gpg: Do not pre-check keys given on the command line.
[gnupg.git] / g10 / gpg.c
index a141164..2b48421 100644 (file)
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -1,6 +1,7 @@
 /* gpg.c - The GnuPG utility (main for gpg)
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
- *               2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+ * Copyright (C) 1998-2011 Free Software Foundation, Inc.
+ * Copyright (C) 1997-2014 Werner Koch
+ * Copyright (C) 2015 g10 Code GmbH
  *
  * This file is part of GnuPG.
  *
 #endif
 #include <fcntl.h>
 #ifdef HAVE_W32_SYSTEM
-#include <windows.h>
+# ifdef HAVE_WINSOCK2_H
+#  include <winsock2.h>
+# endif
+# include <windows.h>
 #endif
 
 #define INCLUDED_BY_MAIN_MODULE 1
@@ -45,7 +49,6 @@
 #include "options.h"
 #include "keydb.h"
 #include "trustdb.h"
-#include "cipher.h"
 #include "filter.h"
 #include "ttyio.h"
 #include "i18n.h"
@@ -56,6 +59,7 @@
 #include "gc-opt-flags.h"
 #include "asshelp.h"
 #include "call-dirmngr.h"
+#include "tofu.h"
 #include "../common/init.h"
 #include "../common/shareddefs.h"
 
@@ -103,13 +107,19 @@ enum cmd_and_opt_values
     aDecryptFiles,
     aClearsign,
     aStore,
+    aQuickKeygen,
+    aFullKeygen,
     aKeygen,
     aSignEncr,
     aSignEncrSym,
     aSignSym,
     aSignKey,
     aLSignKey,
+    aQuickSignKey,
+    aQuickLSignKey,
+    aQuickAddUid,
     aListConfig,
+    aListGcryptConfig,
     aGPGConfList,
     aGPGConfTest,
     aListPackets,
@@ -153,6 +163,7 @@ enum cmd_and_opt_values
     aChangePIN,
     aPasswd,
     aServer,
+    aTOFUPolicy,
 
     oTextmode,
     oNoTextmode,
@@ -170,7 +181,9 @@ enum cmd_and_opt_values
     oNoAskCertLevel,
     oFingerprint,
     oWithFingerprint,
+    oWithICAOSpelling,
     oWithKeygrip,
+    oWithSecret,
     oAnswerYes,
     oAnswerNo,
     oKeyring,
@@ -186,7 +199,7 @@ enum cmd_and_opt_values
     oDebug,
     oDebugLevel,
     oDebugAll,
-    oDebugCCIDDriver,
+    oDebugIOLBF,
     oStatusFD,
     oStatusFile,
     oAttributeFD,
@@ -198,11 +211,9 @@ enum cmd_and_opt_values
     oMaxCertDepth,
     oLoadExtension,
     oGnuPG,
-    oRFC1991,
     oRFC2440,
     oRFC4880,
     oOpenPGP,
-    oPGP2,
     oPGP6,
     oPGP7,
     oPGP8,
@@ -244,8 +255,6 @@ enum cmd_and_opt_values
     oSkipVerify,
     oSkipHiddenRecipients,
     oNoSkipHiddenRecipients,
-    oCompressKeys,
-    oCompressSigs,
     oAlwaysTrust,
     oTrustModel,
     oForceOwnertrust,
@@ -268,10 +277,6 @@ enum cmd_and_opt_values
     oShowPhotos,
     oNoShowPhotos,
     oPhotoViewer,
-    oForceV3Sigs,
-    oNoForceV3Sigs,
-    oForceV4Certs,
-    oNoForceV4Certs,
     oForceMDC,
     oNoForceMDC,
     oDisableMDC,
@@ -298,6 +303,7 @@ enum cmd_and_opt_values
     oEncryptTo,
     oHiddenEncryptTo,
     oNoEncryptTo,
+    oEncryptToDefaultKey,
     oLoggerFD,
     oLoggerFile,
     oUtf8Strings,
@@ -332,8 +338,8 @@ enum cmd_and_opt_values
     oTrustedKey,
     oNoExpensiveTrustChecks,
     oFixedListMode,
+    oLegacyListMode,
     oNoSigCache,
-    oNoSigCreateCheck,
     oAutoCheckTrustDB,
     oNoAutoCheckTrustDB,
     oPreservePermissions,
@@ -343,6 +349,7 @@ enum cmd_and_opt_values
     oPersonalDigestPreferences,
     oPersonalCompressPreferences,
     oAgentProgram,
+    oDirmngrProgram,
     oDisplay,
     oTTYname,
     oTTYtype,
@@ -361,16 +368,31 @@ enum cmd_and_opt_values
     oKeyidFormat,
     oExitOnStatusWriteError,
     oLimitCardInsertTries,
+    oReaderPort,
+    octapiDriver,
+    opcscDriver,
+    oDisableCCID,
     oRequireCrossCert,
     oNoRequireCrossCert,
     oAutoKeyLocate,
     oNoAutoKeyLocate,
     oAllowMultisigVerification,
+    oEnableLargeRSA,
+    oDisableLargeRSA,
     oEnableDSA2,
     oDisableDSA2,
     oAllowMultipleMessages,
     oNoAllowMultipleMessages,
+    oAllowWeakDigestAlgos,
     oFakedSystemTime,
+    oNoAutostart,
+    oPrintPKARecords,
+    oPrintDANERecords,
+    oTOFUDefaultPolicy,
+    oTOFUDBFormat,
+    oWeakDigest,
+    oUnwrap,
+    oOnlySignTextIDs,
 
     oNoop
   };
@@ -397,12 +419,23 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_c (aCheckKeys, "check-sigs",N_("list and check key signatures")),
   ARGPARSE_c (oFingerprint, "fingerprint", N_("list keys and fingerprints")),
   ARGPARSE_c (aListSecretKeys, "list-secret-keys", N_("list secret keys")),
-  ARGPARSE_c (aKeygen,    "gen-key",  N_("generate a new key pair")),
+  ARGPARSE_c (aKeygen,     "gen-key",
+              N_("generate a new key pair")),
+  ARGPARSE_c (aQuickKeygen, "quick-gen-key" ,
+              N_("quickly generate a new key pair")),
+  ARGPARSE_c (aQuickAddUid,  "quick-adduid",
+              N_("quickly add a new user-id")),
+  ARGPARSE_c (aFullKeygen,  "full-gen-key" ,
+              N_("full featured key pair generation")),
   ARGPARSE_c (aGenRevoke, "gen-revoke",N_("generate a revocation certificate")),
   ARGPARSE_c (aDeleteKeys,"delete-keys",
               N_("remove keys from the public keyring")),
   ARGPARSE_c (aDeleteSecretKeys, "delete-secret-keys",
               N_("remove keys from the secret keyring")),
+  ARGPARSE_c (aQuickSignKey,  "quick-sign-key" ,
+              N_("quickly sign a key")),
+  ARGPARSE_c (aQuickLSignKey, "quick-lsign-key",
+              N_("quickly sign a key locally")),
   ARGPARSE_c (aSignKey,  "sign-key"   ,N_("sign a key")),
   ARGPARSE_c (aLSignKey, "lsign-key"  ,N_("sign a key locally")),
   ARGPARSE_c (aEditKey,  "edit-key"   ,N_("sign or edit a key")),
@@ -428,15 +461,20 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_c (aChangePIN,  "change-pin", N_("change a card's PIN")),
 #endif
   ARGPARSE_c (aListConfig, "list-config", "@"),
+  ARGPARSE_c (aListGcryptConfig, "list-gcrypt-config", "@"),
   ARGPARSE_c (aGPGConfList, "gpgconf-list", "@" ),
   ARGPARSE_c (aGPGConfTest, "gpgconf-test", "@" ),
   ARGPARSE_c (aListPackets, "list-packets","@"),
+
+#ifndef NO_TRUST_MODELS
   ARGPARSE_c (aExportOwnerTrust, "export-ownertrust", "@"),
   ARGPARSE_c (aImportOwnerTrust, "import-ownertrust", "@"),
   ARGPARSE_c (aUpdateTrustDB,"update-trustdb",
               N_("update the trust database")),
   ARGPARSE_c (aCheckTrustDB, "check-trustdb", "@"),
   ARGPARSE_c (aFixTrustDB, "fix-trustdb", "@"),
+#endif
+
   ARGPARSE_c (aDeArmor, "dearmor", "@"),
   ARGPARSE_c (aDeArmor, "dearmour", "@"),
   ARGPARSE_c (aEnArmor, "enarmor", "@"),
@@ -445,6 +483,8 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_c (aPrimegen, "gen-prime", "@" ),
   ARGPARSE_c (aGenRandom,"gen-random", "@" ),
   ARGPARSE_c (aServer,   "server",  N_("run in server mode")),
+  ARGPARSE_c (aTOFUPolicy, "tofu-policy",
+             N_("|VALUE|set the TOFU policy for a key (good, unknown, bad, ask, auto)")),
 
   ARGPARSE_group (301, N_("@\nOptions:\n ")),
 
@@ -463,6 +503,7 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_s (oEncryptTo,      "encrypt-to", "@"),
   ARGPARSE_s_n (oNoEncryptTo, "no-encrypt-to", "@"),
   ARGPARSE_s_s (oHiddenEncryptTo, "hidden-encrypt-to", "@"),
+  ARGPARSE_s_n (oEncryptToDefaultKey, "encrypt-to-default-key", "@"),
   ARGPARSE_s_s (oLocalUser, "local-user",
                 N_("|USER-ID|use USER-ID to sign or decrypt")),
 
@@ -499,10 +540,6 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oQuiet,          "quiet",   "@"),
   ARGPARSE_s_n (oNoTTY,   "no-tty",  "@"),
 
-  ARGPARSE_s_n (oForceV3Sigs,      "force-v3-sigs", "@"),
-  ARGPARSE_s_n (oNoForceV3Sigs, "no-force-v3-sigs", "@"),
-  ARGPARSE_s_n (oForceV4Certs,     "force-v4-certs", "@"),
-  ARGPARSE_s_n (oNoForceV4Certs, "no-force-v4-certs", "@"),
   ARGPARSE_s_n (oForceMDC, "force-mdc", "@"),
   ARGPARSE_s_n (oNoForceMDC, "no-force-mdc", "@"),
   ARGPARSE_s_n (oDisableMDC, "disable-mdc", "@"),
@@ -511,10 +548,6 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oDryRun, "dry-run", N_("do not make any changes")),
   ARGPARSE_s_n (oInteractive, "interactive", N_("prompt before overwriting")),
 
-  ARGPARSE_s_n (oUseAgent,      "use-agent", "@"),
-  ARGPARSE_s_n (oNoUseAgent, "no-use-agent", "@"),
-  ARGPARSE_s_s (oGpgAgentInfo, "gpg-agent-info", "@"),
-
   ARGPARSE_s_n (oBatch, "batch", "@"),
   ARGPARSE_s_n (oAnswerYes, "yes", "@"),
   ARGPARSE_s_n (oAnswerNo, "no", "@"),
@@ -535,17 +568,15 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_s (oDisplayCharset, "charset", "@"),
   ARGPARSE_s_s (oOptions, "options", "@"),
 
-  ARGPARSE_p_u (oDebug, "debug", "@"),
+  ARGPARSE_s_s (oDebug, "debug", "@"),
   ARGPARSE_s_s (oDebugLevel, "debug-level", "@"),
   ARGPARSE_s_n (oDebugAll, "debug-all", "@"),
+  ARGPARSE_s_n (oDebugIOLBF, "debug-iolbf", "@"),
   ARGPARSE_s_i (oStatusFD, "status-fd", "@"),
   ARGPARSE_s_s (oStatusFile, "status-file", "@"),
   ARGPARSE_s_i (oAttributeFD, "attribute-fd", "@"),
   ARGPARSE_s_s (oAttributeFile, "attribute-file", "@"),
 
-  ARGPARSE_s_n (oNoop, "sk-comments", "@"),
-  ARGPARSE_s_n (oNoop, "no-sk-comments", "@"),
-
   ARGPARSE_s_i (oCompletesNeeded, "completes-needed", "@"),
   ARGPARSE_s_i (oMarginalsNeeded, "marginals-needed", "@"),
   ARGPARSE_s_i (oMaxCertDepth, "max-cert-depth", "@" ),
@@ -558,11 +589,9 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oGnuPG, "no-pgp6", "@"),
   ARGPARSE_s_n (oGnuPG, "no-pgp7", "@"),
   ARGPARSE_s_n (oGnuPG, "no-pgp8", "@"),
-  ARGPARSE_s_n (oRFC1991, "rfc1991", "@"),
   ARGPARSE_s_n (oRFC2440, "rfc2440", "@"),
   ARGPARSE_s_n (oRFC4880, "rfc4880", "@"),
   ARGPARSE_s_n (oOpenPGP, "openpgp", N_("use strict OpenPGP behavior")),
-  ARGPARSE_s_n (oPGP2, "pgp2", "@"),
   ARGPARSE_s_n (oPGP6, "pgp6", "@"),
   ARGPARSE_s_n (oPGP7, "pgp7", "@"),
   ARGPARSE_s_n (oPGP8, "pgp8", "@"),
@@ -578,15 +607,12 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_s (oCertDigestAlgo, "cert-digest-algo", "@"),
   ARGPARSE_s_s (oCompressAlgo,"compress-algo", "@"),
   ARGPARSE_s_s (oCompressAlgo, "compression-algo", "@"), /* Alias */
-  ARGPARSE_s_n (oThrowKeyids, "throw-keyid", "@"),
   ARGPARSE_s_n (oThrowKeyids, "throw-keyids", "@"),
-  ARGPARSE_s_n (oNoThrowKeyids, "no-throw-keyid", "@"),
   ARGPARSE_s_n (oNoThrowKeyids, "no-throw-keyids", "@"),
   ARGPARSE_s_n (oShowPhotos,   "show-photos", "@"),
   ARGPARSE_s_n (oNoShowPhotos, "no-show-photos", "@"),
   ARGPARSE_s_s (oPhotoViewer,  "photo-viewer", "@"),
   ARGPARSE_s_s (oSetNotation,  "set-notation", "@"),
-  ARGPARSE_s_s (oSetNotation,  "notation-data", "@"), /* Alias */
   ARGPARSE_s_s (oSigNotation,  "sig-notation", "@"),
   ARGPARSE_s_s (oCertNotation, "cert-notation", "@"),
 
@@ -603,7 +629,10 @@ static ARGPARSE_OPTS opts[] = {
 
   /* More hidden commands and options. */
   ARGPARSE_c (aPrintMDs, "print-mds", "@"), /* old */
+#ifndef NO_TRUST_MODELS
   ARGPARSE_c (aListTrustDB, "list-trustdb", "@"),
+#endif
+
   /* Not yet used:
      ARGPARSE_c (aListTrustPath, "list-trust-path", "@"), */
   ARGPARSE_c (aDeleteSecretAndPublicKeys,
@@ -619,7 +648,14 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_s (oCommandFile, "command-file", "@"),
   ARGPARSE_s_n (oQuickRandom, "debug-quick-random", "@"),
   ARGPARSE_s_n (oNoVerbose, "no-verbose", "@"),
+
+#ifndef NO_TRUST_MODELS
   ARGPARSE_s_s (oTrustDBName, "trustdb-name", "@"),
+  ARGPARSE_s_n (oAutoCheckTrustDB, "auto-check-trustdb", "@"),
+  ARGPARSE_s_n (oNoAutoCheckTrustDB, "no-auto-check-trustdb", "@"),
+  ARGPARSE_s_s (oForceOwnertrust, "force-ownertrust", "@"),
+#endif
+
   ARGPARSE_s_n (oNoSecmemWarn, "no-secmem-warning", "@"),
   ARGPARSE_s_n (oRequireSecmem, "require-secmem", "@"),
   ARGPARSE_s_n (oNoRequireSecmem, "no-require-secmem", "@"),
@@ -642,12 +678,11 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oSkipVerify, "skip-verify", "@"),
   ARGPARSE_s_n (oSkipHiddenRecipients, "skip-hidden-recipients", "@"),
   ARGPARSE_s_n (oNoSkipHiddenRecipients, "no-skip-hidden-recipients", "@"),
-  ARGPARSE_s_n (oCompressKeys, "compress-keys", "@"),
-  ARGPARSE_s_n (oCompressSigs, "compress-sigs", "@"),
   ARGPARSE_s_i (oDefCertLevel, "default-cert-check-level", "@"), /* old */
   ARGPARSE_s_n (oAlwaysTrust, "always-trust", "@"),
   ARGPARSE_s_s (oTrustModel, "trust-model", "@"),
-  ARGPARSE_s_s (oForceOwnertrust, "force-ownertrust", "@"),
+  ARGPARSE_s_s (oTOFUDefaultPolicy, "tofu-default-policy", "@"),
+  ARGPARSE_s_s (oTOFUDBFormat, "tofu-db-format", "@"),
   ARGPARSE_s_s (oSetFilename, "set-filename", "@"),
   ARGPARSE_s_n (oForYourEyesOnly, "for-your-eyes-only", "@"),
   ARGPARSE_s_n (oNoForYourEyesOnly, "no-for-your-eyes-only", "@"),
@@ -679,7 +714,9 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oUtf8Strings,      "utf8-strings", "@"),
   ARGPARSE_s_n (oNoUtf8Strings, "no-utf8-strings", "@"),
   ARGPARSE_s_n (oWithFingerprint, "with-fingerprint", "@"),
+  ARGPARSE_s_n (oWithICAOSpelling, "with-icao-spelling", "@"),
   ARGPARSE_s_n (oWithKeygrip,     "with-keygrip", "@"),
+  ARGPARSE_s_n (oWithSecret,      "with-secret", "@"),
   ARGPARSE_s_s (oDisableCipherAlgo,  "disable-cipher-algo", "@"),
   ARGPARSE_s_s (oDisablePubkeyAlgo,  "disable-pubkey-algo", "@"),
   ARGPARSE_s_n (oAllowNonSelfsignedUID,      "allow-non-selfsigned-uid", "@"),
@@ -688,10 +725,12 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oNoAllowFreeformUID, "no-allow-freeform-uid", "@"),
   ARGPARSE_s_n (oNoLiteral, "no-literal", "@"),
   ARGPARSE_p_u (oSetFilesize, "set-filesize", "@"),
-  ARGPARSE_s_n (oHonorHttpProxy, "honor-http-proxy", "@"),
   ARGPARSE_s_n (oFastListMode, "fast-list-mode", "@"),
   ARGPARSE_s_n (oFixedListMode, "fixed-list-mode", "@"),
+  ARGPARSE_s_n (oLegacyListMode, "legacy-list-mode", "@"),
   ARGPARSE_s_n (oListOnly, "list-only", "@"),
+  ARGPARSE_s_n (oPrintPKARecords, "print-pka-records", "@"),
+  ARGPARSE_s_n (oPrintDANERecords, "print-dane-records", "@"),
   ARGPARSE_s_n (oIgnoreTimeConflict, "ignore-time-conflict", "@"),
   ARGPARSE_s_n (oIgnoreValidFrom,    "ignore-valid-from", "@"),
   ARGPARSE_s_n (oIgnoreCrcError, "ignore-crc-error", "@"),
@@ -702,9 +741,6 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oAutoKeyRetrieve, "auto-key-retrieve", "@"),
   ARGPARSE_s_n (oNoAutoKeyRetrieve, "no-auto-key-retrieve", "@"),
   ARGPARSE_s_n (oNoSigCache,         "no-sig-cache", "@"),
-  ARGPARSE_s_n (oNoSigCreateCheck,   "no-sig-create-check", "@"),
-  ARGPARSE_s_n (oAutoCheckTrustDB, "auto-check-trustdb", "@"),
-  ARGPARSE_s_n (oNoAutoCheckTrustDB, "no-auto-check-trustdb", "@"),
   ARGPARSE_s_n (oMergeOnly,      "merge-only", "@" ),
   ARGPARSE_s_n (oAllowSecretKeyImport, "allow-secret-key-import", "@"),
   ARGPARSE_s_n (oTryAllSecrets,  "try-all-secrets", "@"),
@@ -718,13 +754,18 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_s (oPersonalCompressPreferences,
                                          "personal-compress-preferences", "@"),
   ARGPARSE_s_s (oFakedSystemTime, "faked-system-time", "@"),
+  ARGPARSE_s_s (oWeakDigest, "weak-digest","@"),
+  ARGPARSE_s_n (oUnwrap, "unwrap", "@"),
+  ARGPARSE_s_n (oOnlySignTextIDs, "only-sign-text-ids", "@"),
 
   /* Aliases.  I constantly mistype these, and assume other people do
      as well. */
   ARGPARSE_s_s (oPersonalCipherPreferences, "personal-cipher-prefs", "@"),
   ARGPARSE_s_s (oPersonalDigestPreferences, "personal-digest-prefs", "@"),
   ARGPARSE_s_s (oPersonalCompressPreferences, "personal-compress-prefs", "@"),
+
   ARGPARSE_s_s (oAgentProgram, "agent-program", "@"),
+  ARGPARSE_s_s (oDirmngrProgram, "dirmngr-program", "@"),
   ARGPARSE_s_s (oDisplay,    "display",    "@"),
   ARGPARSE_s_s (oTTYname,    "ttyname",    "@"),
   ARGPARSE_s_s (oTTYtype,    "ttytype",    "@"),
@@ -746,10 +787,13 @@ static ARGPARSE_OPTS opts[] = {
 
   ARGPARSE_s_n (oAllowMultisigVerification,
                 "allow-multisig-verification", "@"),
+  ARGPARSE_s_n (oEnableLargeRSA, "enable-large-rsa", "@"),
+  ARGPARSE_s_n (oDisableLargeRSA, "disable-large-rsa", "@"),
   ARGPARSE_s_n (oEnableDSA2, "enable-dsa2", "@"),
   ARGPARSE_s_n (oDisableDSA2, "disable-dsa2", "@"),
   ARGPARSE_s_n (oAllowMultipleMessages,      "allow-multiple-messages", "@"),
   ARGPARSE_s_n (oNoAllowMultipleMessages, "no-allow-multiple-messages", "@"),
+  ARGPARSE_s_n (oAllowWeakDigestAlgos, "allow-weak-digest-algos", "@"),
 
   /* These two are aliases to help users of the PGP command line
      product use gpg with minimal pain.  Many commands are common
@@ -766,11 +810,54 @@ static ARGPARSE_OPTS opts[] = {
   /* New options.  Fixme: Should go more to the top.  */
   ARGPARSE_s_s (oAutoKeyLocate, "auto-key-locate", "@"),
   ARGPARSE_s_n (oNoAutoKeyLocate, "no-auto-key-locate", "@"),
+  ARGPARSE_s_n (oNoAutostart, "no-autostart", "@"),
+
+  /* Dummy options with warnings.  */
+  ARGPARSE_s_n (oUseAgent,      "use-agent", "@"),
+  ARGPARSE_s_n (oNoUseAgent, "no-use-agent", "@"),
+  ARGPARSE_s_s (oGpgAgentInfo, "gpg-agent-info", "@"),
+  ARGPARSE_s_s (oReaderPort, "reader-port", "@"),
+  ARGPARSE_s_s (octapiDriver, "ctapi-driver", "@"),
+  ARGPARSE_s_s (opcscDriver, "pcsc-driver", "@"),
+  ARGPARSE_s_n (oDisableCCID, "disable-ccid", "@"),
+  ARGPARSE_s_n (oHonorHttpProxy, "honor-http-proxy", "@"),
+
+  /* Dummy options.  */
+  ARGPARSE_s_n (oNoop, "sk-comments", "@"),
+  ARGPARSE_s_n (oNoop, "no-sk-comments", "@"),
+  ARGPARSE_s_n (oNoop, "compress-keys", "@"),
+  ARGPARSE_s_n (oNoop, "compress-sigs", "@"),
+  ARGPARSE_s_n (oNoop, "force-v3-sigs", "@"),
+  ARGPARSE_s_n (oNoop, "no-force-v3-sigs", "@"),
+  ARGPARSE_s_n (oNoop, "force-v4-certs", "@"),
+  ARGPARSE_s_n (oNoop, "no-force-v4-certs", "@"),
 
   ARGPARSE_end ()
 };
 
 
+/* The list of supported debug flags.  */
+static struct debug_flags_s debug_flags [] =
+  {
+    { DBG_PACKET_VALUE , "packet"  },
+    { DBG_MPI_VALUE    , "mpi"     },
+    { DBG_CRYPTO_VALUE , "crypto"  },
+    { DBG_FILTER_VALUE , "filter"  },
+    { DBG_IOBUF_VALUE  , "iobuf"   },
+    { DBG_MEMORY_VALUE , "memory"  },
+    { DBG_CACHE_VALUE  , "cache"   },
+    { DBG_MEMSTAT_VALUE, "memstat" },
+    { DBG_TRUST_VALUE  , "trust"   },
+    { DBG_HASHING_VALUE, "hashing" },
+    { DBG_CARD_IO_VALUE, "cardio"  },
+    { DBG_IPC_VALUE    , "ipc"     },
+    { DBG_CLOCK_VALUE  , "clock"   },
+    { DBG_LOOKUP_VALUE , "lookup"  },
+    { DBG_EXTPROG_VALUE, "extprog" },
+    { 0, NULL }
+  };
+
+
 #ifdef ENABLE_SELINUX_HACKS
 #define ALWAYS_ADD_KEYRINGS 1
 #else
@@ -812,6 +899,54 @@ make_libversion (const char *libname, const char *(*getfnc)(const char*))
 }
 
 
+static int
+build_list_pk_test_algo (int algo)
+{
+  /* Show only one "RSA" string.  If RSA_E or RSA_S is available RSA
+     is also available.  */
+  if (algo == PUBKEY_ALGO_RSA_E
+      || algo == PUBKEY_ALGO_RSA_S)
+    return GPG_ERR_DIGEST_ALGO;
+
+  return openpgp_pk_test_algo (algo);
+}
+
+static const char *
+build_list_pk_algo_name (int algo)
+{
+  return openpgp_pk_algo_name (algo);
+}
+
+static int
+build_list_cipher_test_algo (int algo)
+{
+  return openpgp_cipher_test_algo (algo);
+}
+
+static const char *
+build_list_cipher_algo_name (int algo)
+{
+  return openpgp_cipher_algo_name (algo);
+}
+
+static int
+build_list_md_test_algo (int algo)
+{
+  /* By default we do not accept MD5 based signatures.  To avoid
+     confusion we do not announce support for it either.  */
+  if (algo == DIGEST_ALGO_MD5)
+    return GPG_ERR_DIGEST_ALGO;
+
+  return openpgp_md_test_algo (algo);
+}
+
+static const char *
+build_list_md_algo_name (int algo)
+{
+  return openpgp_md_algo_name (algo);
+}
+
+
 static const char *
 my_strusage( int level )
 {
@@ -819,7 +954,7 @@ my_strusage( int level )
   const char *p;
 
     switch( level ) {
-      case 11: p = "gpg (GnuPG)";
+      case 11: p = "@GPG@ (@GNUPG@)";
        break;
       case 13: p = VERSION; break;
       case 17: p = PRINTABLE_OS_NAME; break;
@@ -845,10 +980,10 @@ my_strusage( int level )
 
       case 1:
       case 40: p =
-           _("Usage: gpg [options] [files] (-h for help)");
+           _("Usage: @GPG@ [options] [files] (-h for help)");
        break;
       case 41: p =
-           _("Syntax: gpg [options] [files]\n"
+           _("Syntax: @GPG@ [options] [files]\n"
              "Sign, check, encrypt or decrypt\n"
              "Default operation depends on the input data\n");
        break;
@@ -862,23 +997,23 @@ my_strusage( int level )
       case 33: p = _("\nSupported algorithms:\n"); break;
       case 34:
        if (!pubkeys)
-            pubkeys = build_list (_("Pubkey: "), 0,
-                                  openpgp_pk_algo_name,
-                                  openpgp_pk_test_algo );
+            pubkeys = build_list (_("Pubkey: "), 1,
+                                  build_list_pk_algo_name,
+                                  build_list_pk_test_algo );
        p = pubkeys;
        break;
       case 35:
        if( !ciphers )
            ciphers = build_list(_("Cipher: "), 'S',
-                                 openpgp_cipher_algo_name,
-                                 openpgp_cipher_test_algo );
+                                 build_list_cipher_algo_name,
+                                 build_list_cipher_test_algo );
        p = ciphers;
        break;
       case 36:
        if( !digests )
            digests = build_list(_("Hash: "), 'H',
-                                 gcry_md_algo_name,
-                                 openpgp_md_test_algo );
+                                 build_list_md_algo_name,
+                                 build_list_md_test_algo );
        p = digests;
        break;
       case 37:
@@ -908,7 +1043,7 @@ build_list (const char *text, char letter,
   if (maybe_setuid)
     gcry_control (GCRYCTL_INIT_SECMEM, 0, 0);  /* Drop setuid. */
 
-  indent = utf8_charcount (text);
+  indent = utf8_charcount (text, -1);
   len = 0;
   init_membuf (&mb, 512);
 
@@ -932,7 +1067,10 @@ build_list (const char *text, char letter,
           if (opt.verbose && letter)
             {
               char num[20];
-              snprintf (num, sizeof num, " (%c%d)", letter, i);
+              if (letter == 1)
+                snprintf (num, sizeof num, " (%d)", i);
+              else
+                snprintf (num, sizeof num, " (%c%d)", letter, i);
               put_membuf_str (&mb, num);
             }
        }
@@ -949,10 +1087,8 @@ build_list (const char *text, char letter,
 static void
 wrong_args( const char *text)
 {
-    fputs(_("usage: gpg [options] "),stderr);
-    fputs(text,stderr);
-    putc('\n',stderr);
-    g10_exit(2);
+  es_fprintf (es_stderr, _("usage: %s [options] %s\n"), GPG_NAME, text);
+  g10_exit(2);
 }
 
 
@@ -979,6 +1115,7 @@ set_opt_session_env (const char *name, const char *value)
                gpg_strerror (err));
 }
 
+
 /* Setup the debugging.  With a LEVEL of NULL only the active debug
    flags are propagated to the subsystems.  With LEVEL set, a specific
    set of debug flags is set; thus overriding all flags already
@@ -999,7 +1136,7 @@ set_debug (const char *level)
     opt.debug = DBG_MEMSTAT_VALUE|DBG_TRUST_VALUE|DBG_EXTPROG_VALUE;
   else if (!strcmp (level, "expert")  || (numok && numlvl <= 8))
     opt.debug = (DBG_MEMSTAT_VALUE|DBG_TRUST_VALUE|DBG_EXTPROG_VALUE
-                 |DBG_CACHE_VALUE|DBG_FILTER_VALUE|DBG_PACKET_VALUE);
+                 |DBG_CACHE_VALUE|DBG_LOOKUP|DBG_FILTER_VALUE|DBG_PACKET_VALUE);
   else if (!strcmp (level, "guru") || numok)
     {
       opt.debug = ~0;
@@ -1022,28 +1159,14 @@ set_debug (const char *level)
     memory_stat_debug_mode = 1;
   if (opt.debug & DBG_MPI_VALUE)
     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 2);
-  if (opt.debug & DBG_CIPHER_VALUE )
+  if (opt.debug & DBG_CRYPTO_VALUE )
     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1);
   if (opt.debug & DBG_IOBUF_VALUE )
     iobuf_debug_mode = 1;
   gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
 
   if (opt.debug)
-    log_info ("enabled debug flags:%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
-              (opt.debug & DBG_PACKET_VALUE )? " packet":"",
-              (opt.debug & DBG_MPI_VALUE    )? " mpi":"",
-              (opt.debug & DBG_CIPHER_VALUE )? " cipher":"",
-              (opt.debug & DBG_FILTER_VALUE )? " filter":"",
-              (opt.debug & DBG_IOBUF_VALUE  )? " iobuf":"",
-              (opt.debug & DBG_MEMORY_VALUE )? " memory":"",
-              (opt.debug & DBG_CACHE_VALUE  )? " cache":"",
-              (opt.debug & DBG_MEMSTAT_VALUE)? " memstat":"",
-              (opt.debug & DBG_TRUST_VALUE  )? " trust":"",
-              (opt.debug & DBG_HASHING_VALUE)? " hashing":"",
-              (opt.debug & DBG_EXTPROG_VALUE)? " extprog":"",
-              (opt.debug & DBG_CARD_IO_VALUE)? " cardio":"",
-              (opt.debug & DBG_ASSUAN_VALUE )? " assuan":"",
-              (opt.debug & DBG_CLOCK_VALUE  )? " clock":"");
+    parse_debug_flag (NULL, &opt.debug, debug_flags);
 }
 
 
@@ -1487,8 +1610,11 @@ print_algo_names(int (*checker)(int),const char *(*mapper)(int))
 static void
 list_config(char *items)
 {
-  int show_all=(items==NULL);
-  char *name=NULL;
+  int show_all = !items;
+  char *name = NULL;
+  const char *s;
+  struct groupitem *giter;
+  int first, iter;
 
   if(!opt.with_colons)
     return;
@@ -1499,20 +1625,19 @@ list_config(char *items)
 
       if(show_all || ascii_strcasecmp(name,"group")==0)
        {
-         struct groupitem *iter;
-
-         for(iter=opt.grouplist;iter;iter=iter->next)
+         for (giter = opt.grouplist; giter; giter = giter->next)
            {
              strlist_t sl;
 
              es_fprintf (es_stdout, "cfg:group:");
-             es_write_sanitized (es_stdout, iter->name, strlen(iter->name),
+             es_write_sanitized (es_stdout, giter->name, strlen(giter->name),
                                   ":", NULL);
              es_putc (':', es_stdout);
 
-             for(sl=iter->values;sl;sl=sl->next)
+             for(sl=giter->values; sl; sl=sl->next)
                {
-                 print_sanitized_string2 (stdout, sl->d, ':',';');
+                 es_write_sanitized (es_stdout, sl->d, strlen (sl->d),
+                                      ":;", NULL);
                  if(sl->next)
                     es_printf(";");
                }
@@ -1534,7 +1659,16 @@ list_config(char *items)
       if(show_all || ascii_strcasecmp(name,"pubkey")==0)
        {
          es_printf ("cfg:pubkey:");
-         print_algo_numbers (openpgp_pk_test_algo);
+         print_algo_numbers (build_list_pk_test_algo);
+         es_printf ("\n");
+         any=1;
+       }
+
+      if(show_all || ascii_strcasecmp(name,"pubkeyname")==0)
+       {
+         es_printf ("cfg:pubkeyname:");
+         print_algo_names (build_list_pk_test_algo,
+                            build_list_pk_algo_name);
          es_printf ("\n");
          any=1;
        }
@@ -1542,7 +1676,7 @@ list_config(char *items)
       if(show_all || ascii_strcasecmp(name,"cipher")==0)
        {
          es_printf ("cfg:cipher:");
-         print_algo_numbers(openpgp_cipher_test_algo);
+         print_algo_numbers (build_list_cipher_test_algo);
          es_printf ("\n");
          any=1;
        }
@@ -1550,7 +1684,8 @@ list_config(char *items)
       if (show_all || !ascii_strcasecmp (name,"ciphername"))
        {
          es_printf ("cfg:ciphername:");
-         print_algo_names (openpgp_cipher_test_algo,openpgp_cipher_algo_name);
+         print_algo_names (build_list_cipher_test_algo,
+                            build_list_cipher_algo_name);
          es_printf ("\n");
          any = 1;
        }
@@ -1560,7 +1695,7 @@ list_config(char *items)
         || ascii_strcasecmp(name,"hash")==0)
        {
          es_printf ("cfg:digest:");
-         print_algo_numbers(openpgp_md_test_algo);
+         print_algo_numbers (build_list_md_test_algo);
          es_printf ("\n");
          any=1;
        }
@@ -1570,7 +1705,8 @@ list_config(char *items)
           || !ascii_strcasecmp(name,"hashname"))
        {
          es_printf ("cfg:digestname:");
-         print_algo_names (openpgp_md_test_algo, gcry_md_algo_name);
+         print_algo_names (build_list_md_test_algo,
+                            build_list_md_algo_name);
          es_printf ("\n");
          any=1;
        }
@@ -1583,20 +1719,31 @@ list_config(char *items)
          any=1;
        }
 
-      if(show_all || ascii_strcasecmp(name,"ccid-reader-id")==0)
+      if (show_all || !ascii_strcasecmp(name,"ccid-reader-id"))
        {
-#if defined(ENABLE_CARD_SUPPORT) && defined(HAVE_LIBUSB) \
-    && GNUPG_MAJOR_VERSION == 1
+          /* We ignore this for GnuPG 1.4 backward compatibility.  */
+         any=1;
+       }
 
-          char *p, *p2, *list = ccid_get_reader_list ();
+      if (show_all || !ascii_strcasecmp (name,"curve"))
+       {
+         es_printf ("cfg:curve:");
+          for (iter=0, first=1; (s = openpgp_enum_curves (&iter)); first=0)
+            es_printf ("%s%s", first?"":";", s);
+         es_printf ("\n");
+         any=1;
+       }
 
-          for (p=list; p && (p2 = strchr (p, '\n')); p = p2+1)
+      /* Curve OIDs are rarely useful and thus only printed if requested.  */
+      if (name && !ascii_strcasecmp (name,"curveoid"))
+       {
+         es_printf ("cfg:curveoid:");
+          for (iter=0, first=1; (s = openpgp_enum_curves (&iter)); first = 0)
             {
-              *p2 = 0;
-              es_printf ("cfg:ccid-reader-id:%s\n", p);
+              s = openpgp_curve_to_oid (s, NULL);
+              es_printf ("%s%s", first?"":";", s? s:"[?]");
             }
-          free (list);
-#endif
+         es_printf ("\n");
          any=1;
        }
 
@@ -1619,7 +1766,8 @@ gpgconf_list (const char *configfile)
 {
   char *configfile_esc = percent_escape (configfile, NULL);
 
-  es_printf ("gpgconf-gpg.conf:%lu:\"%s\n",
+  es_printf ("%s-%s.conf:%lu:\"%s\n",
+             GPGCONF_NAME, GPG_NAME,
              GC_OPT_FLAG_DEFAULT,
              configfile_esc ? configfile_esc : "/dev/null");
   es_printf ("verbose:%lu:\n", GC_OPT_FLAG_NONE);
@@ -1711,6 +1859,8 @@ parse_list_options(char *str)
     {
       {"show-photos",LIST_SHOW_PHOTOS,NULL,
        N_("display photo IDs during key listings")},
+      {"show-usage",LIST_SHOW_USAGE,NULL,
+       N_("show key usage information during key listings")},
       {"show-policy-urls",LIST_SHOW_POLICY_URLS,NULL,
        N_("show policy URLs during signature listings")},
       {"show-notations",LIST_SHOW_NOTATIONS,NULL,
@@ -1742,7 +1892,7 @@ parse_list_options(char *str)
      compile everywhere, so fill in the show-sig-subpackets argument
      here.  Note that if the parse_options array changes, we'll have
      to change the subscript here. */
-  lopts[12].value=&subpackets;
+  lopts[13].value=&subpackets;
 
   if(parse_options(str,&opt.list_options,lopts,1))
     {
@@ -1792,6 +1942,8 @@ collapse_args(int argc,char *argv[])
   return str;
 }
 
+
+#ifndef NO_TRUST_MODELS
 static void
 parse_trust_model(const char *model)
 {
@@ -1803,14 +1955,78 @@ parse_trust_model(const char *model)
     opt.trust_model=TM_ALWAYS;
   else if(ascii_strcasecmp(model,"direct")==0)
     opt.trust_model=TM_DIRECT;
+#ifdef USE_TOFU
+  else if(ascii_strcasecmp(model,"tofu")==0)
+    opt.trust_model=TM_TOFU;
+  else if(ascii_strcasecmp(model,"tofu+pgp")==0)
+    opt.trust_model=TM_TOFU_PGP;
+#endif /*USE_TOFU*/
   else if(ascii_strcasecmp(model,"auto")==0)
     opt.trust_model=TM_AUTO;
   else
     log_error("unknown trust model '%s'\n",model);
 }
+#endif /*NO_TRUST_MODELS*/
 
 
-/* This fucntion called to initialized a new control object.  It is
+static int
+parse_tofu_policy (const char *policystr)
+{
+#ifdef USE_TOFU
+  struct { const char *keyword; int policy; } list[] = {
+    { "auto",    TOFU_POLICY_AUTO },
+    { "good",    TOFU_POLICY_GOOD },
+    { "unknown", TOFU_POLICY_UNKNOWN },
+    { "bad",     TOFU_POLICY_BAD },
+    { "ask",     TOFU_POLICY_ASK }
+  };
+  int i;
+
+  if (!ascii_strcasecmp (policystr, "help"))
+    {
+      log_info (_("available TOFU policies:\n"));
+      for (i=0; i < DIM (list); i++)
+        log_info ("  %s\n", list[i].keyword);
+      g10_exit (1);
+    }
+
+  for (i=0; i < DIM (list); i++)
+    if (!ascii_strcasecmp (policystr, list[i].keyword))
+      return list[i].policy;
+#endif /*USE_TOFU*/
+
+  log_error (_("unknown TOFU policy '%s'\n"), policystr);
+  if (!opt.quiet)
+    log_info (_("(use \"help\" to list choices)\n"));
+  g10_exit (1);
+}
+
+static int
+parse_tofu_db_format (const char *db_format)
+{
+#ifdef USE_TOFU
+  if (ascii_strcasecmp (db_format, "auto") == 0)
+    return TOFU_DB_AUTO;
+  else if (ascii_strcasecmp (db_format, "split") == 0)
+    return TOFU_DB_SPLIT;
+  else if (ascii_strcasecmp (db_format, "flat") == 0)
+    return TOFU_DB_FLAT;
+  else if (ascii_strcasecmp (db_format, "help") == 0)
+    {
+      log_info ("available TOFU DB fomats: auto, split, flat\n");
+      g10_exit (1);
+    }
+  else
+#endif /*USE_TOFU*/
+    {
+      log_error (_("unknown TOFU DB format '%s'\n"), db_format);
+      if (!opt.quiet)
+        log_info (_("(use \"help\" to list choices)\n"));
+      g10_exit (1);
+    }
+}
+
+/* This function called to initialized a new control object.  It is
    assumed that this object has been zeroed out before calling this
    function. */
 static void
@@ -1833,8 +2049,8 @@ char *
 get_default_configname (void)
 {
   char *configname = NULL;
-  char *name = xstrdup ("gpg" EXTSEP_S "conf-" SAFE_VERSION);
-  char *ver = &name[strlen ("gpg" EXTSEP_S "conf-")];
+  char *name = xstrdup (GPG_NAME EXTSEP_S "conf-" SAFE_VERSION);
+  char *ver = &name[strlen (GPG_NAME EXTSEP_S "conf-")];
 
   do
     {
@@ -1860,13 +2076,13 @@ get_default_configname (void)
   xfree(name);
 
   if (! configname)
-    configname = make_filename (opt.homedir, "gpg" EXTSEP_S "conf", NULL);
+    configname = make_filename (opt.homedir, GPG_NAME EXTSEP_S "conf", NULL);
   if (! access (configname, R_OK))
     {
       /* Print a warning when both config files are present.  */
       char *p = make_filename (opt.homedir, "options", NULL);
       if (! access (p, R_OK))
-       log_info (_("NOTE: old default options file '%s' ignored\n"), p);
+       log_info (_("Note: old default options file '%s' ignored\n"), p);
       xfree (p);
     }
   else
@@ -1886,6 +2102,248 @@ get_default_configname (void)
 }
 
 
+static gpg_error_t
+check_user_ids (strlist_t *sp,
+                int warn_possibly_ambiguous,
+                int error_if_not_found)
+{
+  strlist_t s = *sp;
+  strlist_t s2 = NULL;
+  strlist_t t;
+
+  gpg_error_t rc = 0;
+  gpg_error_t err;
+
+  KEYDB_HANDLE hd = NULL;
+
+  /* A quick check to avoid allocating a new strlist if we can skip
+     all keys.  Handles also the case of !SP.  See below for details.  */
+  for (t = s; t && (!(t->flags & PK_LIST_CONFIG)
+                    && !(t->flags & PK_LIST_ENCRYPT_TO)); t = t->next)
+    ;
+  if (!t)
+    return 0;
+
+  for (t = s; t; t = t->next)
+    {
+      const char *option;
+
+      KEYDB_SEARCH_DESC desc;
+      KBNODE kb;
+      PKT_public_key *pk;
+      char fingerprint_bin[MAX_FINGERPRINT_LEN];
+      size_t fingerprint_bin_len = sizeof (fingerprint_bin);
+      /* We also potentially need a ! at the end.  */
+      char fingerprint[2 * MAX_FINGERPRINT_LEN + 1 + 1];
+
+      /* If the key has been given on the command line and it has not
+         been given by one of the encrypt-to options, we skip the
+         checks.  The reason is that the actual key selection code
+         does its own checks and provides proper status message to the
+         caller to detect the wrong keys.  */
+      if (!(t->flags & PK_LIST_CONFIG) && !(t->flags & PK_LIST_ENCRYPT_TO))
+        {
+          add_to_strlist (&s2, t->d);
+          s2->flags = t->flags;
+          continue;
+        }
+
+      switch (t->flags >> PK_LIST_SHIFT)
+        {
+        case oDefaultKey: option = "--default-key"; break;
+        case oEncryptTo: option = "--encrypt-to"; break;
+        case oHiddenEncryptTo: option = "--hidden-encrypt-to"; break;
+        case oEncryptToDefaultKey: option = "--encrypt-to-default-key"; break;
+        case oRecipient: option = "--recipient"; break;
+        case oHiddenRecipient: option = "--hidden-recipient"; break;
+        case oLocalUser: option = "--local-user"; break;
+        default:
+          log_bug ("Unsupport option: %d\n", (t->flags >> PK_LIST_SHIFT));
+        }
+
+      if (DBG_LOOKUP)
+        {
+          log_debug ("\n");
+          log_debug ("%s: Checking %s=%s\n", __func__, option, t->d);
+        }
+
+      err = classify_user_id (t->d, &desc, 1);
+      if (err)
+        {
+          if (! rc)
+            rc = err;
+
+          log_error (_("key \"%s\" not found: %s\n"),
+                       t->d, gpg_strerror (err));
+          if (!opt.quiet)
+            log_info (_("(check argument of option '%s')\n"), option);
+          continue;
+        }
+
+      if (warn_possibly_ambiguous
+          && ! (desc.mode == KEYDB_SEARCH_MODE_LONG_KID
+                || desc.mode == KEYDB_SEARCH_MODE_FPR16
+                || desc.mode == KEYDB_SEARCH_MODE_FPR20
+                || desc.mode == KEYDB_SEARCH_MODE_FPR))
+        log_info (_("Warning: value '%s' for option '%s'"
+                    " should be a long key ID or a fingerprint\n"),
+                  t->d, option);
+
+      if (! hd)
+        {
+          hd = keydb_new ();
+          if (!hd)
+            {
+              rc = gpg_error_from_syserror ();
+              break;
+            }
+        }
+      else
+        keydb_search_reset (hd);
+
+      err = keydb_search (hd, &desc, 1, NULL);
+      if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
+        {
+          if (DBG_LOOKUP)
+            log_debug ("%s: '%s' not found.\n", __func__, t->d);
+
+          if (error_if_not_found)
+            {
+              if (! rc)
+                rc = err;
+
+              log_error (_("key \"%s\" not found\n"), t->d);
+              if (!opt.quiet)
+                log_info (_("(check argument of option '%s')\n"), option);
+            }
+          continue;
+        }
+      if (err)
+        {
+          if (! rc)
+            rc = err;
+
+          log_error (_("key \"%s\" not found: %s\n"), t->d, gpg_strerror (err));
+          break;
+        }
+
+      err = keydb_get_keyblock (hd, &kb);
+      if (err)
+        {
+          if (! rc)
+            rc = err;
+
+          log_error (_("error reading keyblock: %s\n"), gpg_strerror (err));
+          continue;
+        }
+
+      pk = kb->pkt->pkt.public_key;
+      if ((desc.mode == KEYDB_SEARCH_MODE_SHORT_KID
+           || desc.mode == KEYDB_SEARCH_MODE_LONG_KID
+           || desc.mode == KEYDB_SEARCH_MODE_FPR16
+           || desc.mode == KEYDB_SEARCH_MODE_FPR20)
+          && strchr (t->d, '!'))
+        /* Exact search.  In this case we want to set FINGERPRINT not
+           to the primary key, but the key (primary or sub) that
+           matched the search criteria.  Note: there will always be
+           exactly one match.  */
+        {
+          kbnode_t n = kb;
+          PKT_public_key *match = NULL;
+          int i;
+
+          do
+            {
+              if ((n->flag & 1))
+                /* The matched node.  */
+                {
+                  assert (! match);
+                  match = n->pkt->pkt.public_key;
+                }
+            }
+          while ((n = find_next_kbnode (n, PKT_PUBLIC_SUBKEY)));
+          assert (match);
+
+          fingerprint_from_pk (match, fingerprint_bin, &fingerprint_bin_len);
+          assert (fingerprint_bin_len == sizeof (fingerprint_bin));
+          bin2hex (fingerprint_bin, MAX_FINGERPRINT_LEN, fingerprint);
+
+          i = strlen (fingerprint);
+          fingerprint[i] = '!';
+          fingerprint[i + 1] = '\0';
+        }
+      else
+        {
+          fingerprint_from_pk (pk, fingerprint_bin, &fingerprint_bin_len);
+          assert (fingerprint_bin_len == sizeof (fingerprint_bin));
+          bin2hex (fingerprint_bin, MAX_FINGERPRINT_LEN, fingerprint);
+        }
+
+      add_to_strlist (&s2, fingerprint);
+      s2->flags = s->flags;
+
+      release_kbnode (kb);
+
+      /* Continue the search.  */
+      if (DBG_LOOKUP)
+        log_debug ("%s: Check for duplicates for %s='%s'\n",
+                   __func__, option, t->d);
+      err = keydb_search (hd, &desc, 1, NULL);
+      if (! err)
+        /* Another result!  */
+        {
+          char fingerprint_bin2[MAX_FINGERPRINT_LEN];
+          size_t fingerprint_bin2_len = sizeof (fingerprint_bin2);
+          char fingerprint2[2 * MAX_FINGERPRINT_LEN + 1];
+
+          log_error (_("key specification '%s' is ambiguous\n"), t->d);
+          if (!opt.quiet)
+            log_info (_("(check argument of option '%s')\n"), option);
+
+          if (! rc)
+            rc = GPG_ERR_AMBIGUOUS_NAME;
+
+          err = keydb_get_keyblock (hd, &kb);
+          if (err)
+            log_error (_("error reading keyblock: %s\n"), gpg_strerror (err));
+          else
+            {
+              pk = kb->pkt->pkt.public_key;
+              fingerprint_from_pk (pk, fingerprint_bin2, &fingerprint_bin2_len);
+              assert (fingerprint_bin2_len == sizeof (fingerprint_bin2));
+              bin2hex (fingerprint_bin2, MAX_FINGERPRINT_LEN, fingerprint2);
+
+              /* TRANSLATORS: The %s prints a key specification which
+                 for example has been given at the command line.  Two
+                 lines with fingerprints are printed after this message.  */
+              log_info (_("'%s' matches at least:\n"), t->d);
+              log_info ("  %s\n", fingerprint);
+              log_info ("  %s\n", fingerprint2);
+
+              release_kbnode (kb);
+            }
+        }
+      else if (! (gpg_err_code (err) == GPG_ERR_NOT_FOUND
+                  || gpg_err_code (err) == GPG_ERR_EOF))
+        /* An error (other than "not found").  */
+        {
+          log_error (_("error searching the keyring: %s\n"),
+                     gpg_strerror (err));
+          if (! rc)
+            rc = err;
+        }
+    }
+
+  strlist_rev (&s2);
+
+  keydb_release (hd);
+
+  free_strlist (s);
+  *sp = s2;
+  return rc;
+}
+
+
 int
 main (int argc, char **argv)
 {
@@ -1897,7 +2355,9 @@ main (int argc, char **argv)
     const char *fname;
     char *username;
     int may_coredump;
-    strlist_t sl, remusr= NULL, locusr=NULL;
+    strlist_t sl;
+    strlist_t remusr = NULL;
+    strlist_t locusr = NULL;
     strlist_t nrings = NULL;
     armor_filter_context_t *afx = NULL;
     int detached_sig = 0;
@@ -1915,7 +2375,9 @@ main (int argc, char **argv)
     int use_random_seed = 1;
     enum cmd_and_opt_values cmd = 0;
     const char *debug_level = NULL;
+#ifndef NO_TRUST_MODELS
     const char *trustdb_name = NULL;
+#endif /*!NO_TRUST_MODELS*/
     char *def_cipher_string = NULL;
     char *def_digest_string = NULL;
     char *compress_algo_string = NULL;
@@ -1942,12 +2404,13 @@ main (int argc, char **argv)
     /* Please note that we may running SUID(ROOT), so be very CAREFUL
        when adding any stuff between here and the call to
        secmem_init() somewhere after the option parsing. */
-    gnupg_reopen_std ("gpg");
+    early_system_init ();
+    gnupg_reopen_std (GPG_NAME);
     trap_unaligned ();
     gnupg_rl_initialize ();
     set_strusage (my_strusage);
     gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
-    log_set_prefix ("gpg", 1);
+    log_set_prefix (GPG_NAME, 1);
 
     /* Make sure that our subsystems are ready.  */
     i18n_init();
@@ -1973,6 +2436,7 @@ main (int argc, char **argv)
 
     dotlock_create (NULL, 0); /* Register lock file cleanup. */
 
+    opt.autostart = 1;
     opt.session_env = session_env_new ();
     if (!opt.session_env)
       log_fatal ("error allocating session environment block: %s\n",
@@ -1988,23 +2452,29 @@ main (int argc, char **argv)
     opt.compress_algo = -1; /* defaults to DEFAULT_COMPRESS_ALGO */
     opt.s2k_mode = 3; /* iterated+salted */
     opt.s2k_count = 0; /* Auto-calibrate when needed.  */
-    opt.s2k_cipher_algo = CIPHER_ALGO_CAST5;
+    opt.s2k_cipher_algo = DEFAULT_CIPHER_ALGO;
     opt.completes_needed = 1;
     opt.marginals_needed = 3;
     opt.max_cert_depth = 5;
-    opt.pgp2_workarounds = 1;
     opt.escape_from = 1;
     opt.flags.require_cross_cert = 1;
     opt.import_options = 0;
     opt.export_options = EXPORT_ATTRIBUTES;
     opt.keyserver_options.import_options = IMPORT_REPAIR_PKS_SUBKEY_BUG;
     opt.keyserver_options.export_options = EXPORT_ATTRIBUTES;
-    opt.keyserver_options.options = (KEYSERVER_HONOR_KEYSERVER_URL
-                                     | KEYSERVER_HONOR_PKA_RECORD );
-    opt.verify_options = (VERIFY_SHOW_POLICY_URLS
+    opt.keyserver_options.options = KEYSERVER_HONOR_PKA_RECORD;
+    opt.verify_options = (LIST_SHOW_UID_VALIDITY
+                          | VERIFY_SHOW_POLICY_URLS
                           | VERIFY_SHOW_STD_NOTATIONS
                           | VERIFY_SHOW_KEYSERVER_URLS);
+    opt.list_options   = LIST_SHOW_UID_VALIDITY;
+#ifdef NO_TRUST_MODELS
+    opt.trust_model = TM_ALWAYS;
+#else
     opt.trust_model = TM_AUTO;
+#endif
+    opt.tofu_default_policy = TOFU_POLICY_AUTO;
+    opt.tofu_db_format = TOFU_DB_AUTO;
     opt.mangle_dos_filenames = 0;
     opt.min_cert_level = 2;
     set_screen_dimensions ();
@@ -2013,6 +2483,9 @@ main (int argc, char **argv)
     opt.def_cert_expire = "0";
     set_homedir (default_homedir ());
     opt.passphrase_repeat = 1;
+    opt.emit_version = 1; /* Limit to the major number.  */
+    opt.weak_digests = NULL;
+    additional_weak_digest("MD5");
 
     /* Check whether we have a config file on the command line.  */
     orig_argc = argc;
@@ -2023,6 +2496,8 @@ main (int argc, char **argv)
     while( arg_parse( &pargs, opts) ) {
        if( pargs.r_opt == oDebug || pargs.r_opt == oDebugAll )
            parse_debug++;
+       else if (pargs.r_opt == oDebugIOLBF)
+            es_setvbuf (es_stdout, NULL, _IOLBF, 0);
        else if( pargs.r_opt == oOptions ) {
            /* yes there is one, so we do not try the default one, but
             * read the option file when it is encountered at the commandline
@@ -2066,7 +2541,7 @@ main (int argc, char **argv)
 #endif
 
     /* Initialize the secure memory. */
-    if (!gcry_control (GCRYCTL_INIT_SECMEM, 32768, 0))
+    if (!gcry_control (GCRYCTL_INIT_SECMEM, SECMEM_BUFFER_SIZE, 0))
       got_secmem = 1;
 #if defined(HAVE_GETUID) && defined(HAVE_GETEUID)
     /* There should be no way to get to this spot while still carrying
@@ -2124,7 +2599,7 @@ main (int argc, char **argv)
        if( !configfp ) {
            if( default_config ) {
                if( parse_debug )
-                   log_info(_("NOTE: no default option file '%s'\n"),
+                   log_info(_("Note: no default option file '%s'\n"),
                                                            configname );
            }
            else {
@@ -2146,6 +2621,7 @@ main (int argc, char **argv)
          {
          case aCheckKeys:
          case aListConfig:
+         case aListGcryptConfig:
           case aGPGConfList:
           case aGPGConfTest:
          case aListPackets:
@@ -2183,9 +2659,13 @@ main (int argc, char **argv)
          case aDeArmor:
          case aEnArmor:
          case aSign:
+         case aQuickSignKey:
+         case aQuickLSignKey:
          case aSignKey:
          case aLSignKey:
          case aStore:
+         case aQuickKeygen:
+         case aQuickAddUid:
          case aExportOwnerTrust:
          case aImportOwnerTrust:
           case aRebuildKeydbCaches:
@@ -2193,6 +2673,7 @@ main (int argc, char **argv)
             break;
 
          case aKeygen:
+         case aFullKeygen:
          case aEditKey:
          case aDeleteSecretKeys:
          case aDeleteSecretAndPublicKeys:
@@ -2218,6 +2699,10 @@ main (int argc, char **argv)
             opt.batch = 1;
             break;
 
+          case aTOFUPolicy:
+            set_cmd (&cmd, pargs.r_opt);
+            break;
+
          case oArmor: opt.armor = 1; opt.no_armor=0; break;
          case oOutput: opt.outfile = pargs.r.ret_str; break;
          case oMaxOutput: opt.max_output = pargs.r.ret_ulong; break;
@@ -2239,11 +2724,27 @@ main (int argc, char **argv)
 
           case oUseAgent: /* Dummy. */
             break;
+
           case oNoUseAgent:
-           obsolete_option (configname, configlineno, "--no-use-agent");
+           obsolete_option (configname, configlineno, "no-use-agent");
             break;
          case oGpgAgentInfo:
-           obsolete_option (configname, configlineno, "--gpg-agent-info");
+           obsolete_option (configname, configlineno, "gpg-agent-info");
+            break;
+          case oReaderPort:
+           obsolete_scdaemon_option (configname, configlineno, "reader-port");
+            break;
+          case octapiDriver:
+           obsolete_scdaemon_option (configname, configlineno, "ctapi-driver");
+            break;
+          case opcscDriver:
+           obsolete_scdaemon_option (configname, configlineno, "pcsc-driver");
+            break;
+          case oDisableCCID:
+           obsolete_scdaemon_option (configname, configlineno, "disable-ccid");
+            break;
+          case oHonorHttpProxy:
+           obsolete_option (configname, configlineno, "honor-http-proxy");
             break;
 
          case oAnswerYes: opt.answer_yes = 1; break;
@@ -2259,10 +2760,19 @@ main (int argc, char **argv)
            opt.list_options|=LIST_SHOW_KEYRING;
            break;
 
-         case oDebug: opt.debug |= pargs.r.ret_ulong; break;
+         case oDebug:
+            if (parse_debug_flag (pargs.r.ret_str, &opt.debug, debug_flags))
+              {
+                pargs.r_opt = ARGPARSE_INVALID_ARG;
+                pargs.err = ARGPARSE_PRINT_ERROR;
+              }
+            break;
+
          case oDebugAll: opt.debug = ~0; break;
           case oDebugLevel: debug_level = pargs.r.ret_str; break;
 
+          case oDebugIOLBF: break; /* Already set in pre-parse step.  */
+
          case oStatusFD:
             set_status_fd ( translate_sys2libc_fd_int (pargs.r.ret_int, 1) );
             break;
@@ -2286,6 +2796,9 @@ main (int argc, char **argv)
             opt.with_fingerprint = 1;
             opt.fingerprint++;
             break;
+         case oWithICAOSpelling:
+            opt.with_icao_spelling = 1;
+            break;
          case oFingerprint:
             opt.fingerprint++;
             fpr_maybe_cmd = 1;
@@ -2295,6 +2808,10 @@ main (int argc, char **argv)
             opt.with_keygrip = 1;
             break;
 
+         case oWithSecret:
+            opt.with_secret = 1;
+            break;
+
          case oSecretKeyring:
             /* Ignore this old option.  */
             break;
@@ -2318,16 +2835,26 @@ main (int argc, char **argv)
           case oQuickRandom:
             gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
             break;
-         case oEmitVersion: opt.no_version=0; break;
-         case oNoEmitVersion: opt.no_version=1; break;
+         case oEmitVersion: opt.emit_version++; break;
+         case oNoEmitVersion: opt.emit_version=0; break;
          case oCompletesNeeded: opt.completes_needed = pargs.r.ret_int; break;
          case oMarginalsNeeded: opt.marginals_needed = pargs.r.ret_int; break;
          case oMaxCertDepth: opt.max_cert_depth = pargs.r.ret_int; break;
+
+#ifndef NO_TRUST_MODELS
          case oTrustDBName: trustdb_name = pargs.r.ret_str; break;
-         case oDefaultKey: opt.def_secret_key = pargs.r.ret_str; break;
+
+#endif /*!NO_TRUST_MODELS*/
+         case oDefaultKey:
+            sl = add_to_strlist (&opt.def_secret_key, pargs.r.ret_str);
+            sl->flags = (pargs.r_opt << PK_LIST_SHIFT);
+            break;
          case oDefRecipient:
             if( *pargs.r.ret_str )
-              opt.def_recipient = make_username(pargs.r.ret_str);
+             {
+               xfree (opt.def_recipient);
+               opt.def_recipient = make_username(pargs.r.ret_str);
+             }
             break;
          case oDefRecipientSelf:
             xfree(opt.def_recipient); opt.def_recipient = NULL;
@@ -2352,8 +2879,9 @@ main (int argc, char **argv)
          case oSkipHiddenRecipients: opt.skip_hidden_recipients = 1; break;
          case oNoSkipHiddenRecipients: opt.skip_hidden_recipients = 0; break;
 
-         case oCompressKeys: opt.compress_keys = 1; break;
          case aListSecretKeys: set_cmd( &cmd, aListSecretKeys); break;
+
+#ifndef NO_TRUST_MODELS
            /* There are many programs (like mutt) that call gpg with
               --always-trust so keep this option around for a long
               time. */
@@ -2361,8 +2889,16 @@ main (int argc, char **argv)
          case oTrustModel:
            parse_trust_model(pargs.r.ret_str);
            break;
+#endif /*!NO_TRUST_MODELS*/
+         case oTOFUDefaultPolicy:
+           opt.tofu_default_policy = parse_tofu_policy (pargs.r.ret_str);
+           break;
+         case oTOFUDBFormat:
+           opt.tofu_db_format = parse_tofu_db_format (pargs.r.ret_str);
+           break;
+
          case oForceOwnertrust:
-           log_info(_("NOTE: %s is not for normal use!\n"),
+           log_info(_("Note: %s is not for normal use!\n"),
                     "--force-ownertrust");
            opt.force_ownertrust=string_to_trust_value(pargs.r.ret_str);
            if(opt.force_ownertrust==-1)
@@ -2375,11 +2911,6 @@ main (int argc, char **argv)
             /* Dummy so that gpg 1.4 conf files can work. Should
                eventually be removed.  */
            break;
-         case oRFC1991:
-           opt.compliance = CO_RFC1991;
-           opt.force_v4_certs = 0;
-           opt.escape_from = 1;
-           break;
          case oOpenPGP:
          case oRFC4880:
            /* This is effectively the same as RFC2440, but with
@@ -2391,11 +2922,7 @@ main (int argc, char **argv)
            opt.rfc2440_text = 0;
            opt.allow_non_selfsigned_uid = 1;
            opt.allow_freeform_uid = 1;
-           opt.pgp2_workarounds = 0;
            opt.escape_from = 1;
-           opt.force_v3_sigs = 0;
-           opt.compress_keys = 0;          /* not mandated, but we do it */
-           opt.compress_sigs = 0;          /* ditto. */
            opt.not_dash_escaped = 0;
            opt.def_cipher_algo = 0;
            opt.def_digest_algo = 0;
@@ -2411,11 +2938,7 @@ main (int argc, char **argv)
            opt.rfc2440_text = 1;
            opt.allow_non_selfsigned_uid = 1;
            opt.allow_freeform_uid = 1;
-           opt.pgp2_workarounds = 0;
            opt.escape_from = 0;
-           opt.force_v3_sigs = 0;
-           opt.compress_keys = 0;          /* not mandated, but we do it */
-           opt.compress_sigs = 0;          /* ditto. */
            opt.not_dash_escaped = 0;
            opt.def_cipher_algo = 0;
            opt.def_digest_algo = 0;
@@ -2425,12 +2948,10 @@ main (int argc, char **argv)
            opt.s2k_digest_algo = DIGEST_ALGO_SHA1;
            opt.s2k_cipher_algo = CIPHER_ALGO_3DES;
            break;
-         case oPGP2:  opt.compliance = CO_PGP2;  break;
          case oPGP6:  opt.compliance = CO_PGP6;  break;
          case oPGP7:  opt.compliance = CO_PGP7;  break;
          case oPGP8:  opt.compliance = CO_PGP8;  break;
          case oGnuPG: opt.compliance = CO_GNUPG; break;
-         case oCompressSigs: opt.compress_sigs = 1; break;
          case oRFC2440Text: opt.rfc2440_text=1; break;
          case oNoRFC2440Text: opt.rfc2440_text=0; break;
          case oSetFilename:
@@ -2482,8 +3003,8 @@ main (int argc, char **argv)
            free_strlist(opt.comments);
            opt.comments=NULL;
            break;
-         case oThrowKeyids: opt.throw_keyid = 1; break;
-         case oNoThrowKeyids: opt.throw_keyid = 0; break;
+         case oThrowKeyids: opt.throw_keyids = 1; break;
+         case oNoThrowKeyids: opt.throw_keyids = 0; break;
          case oShowPhotos:
            deprecated_warning(configname,configlineno,"--show-photos",
                               "--list-options ","show-photos");
@@ -2501,10 +3022,7 @@ main (int argc, char **argv)
            opt.verify_options&=~VERIFY_SHOW_PHOTOS;
            break;
          case oPhotoViewer: opt.photo_viewer = pargs.r.ret_str; break;
-         case oForceV3Sigs: opt.force_v3_sigs = 1; break;
-         case oNoForceV3Sigs: opt.force_v3_sigs = 0; break;
-          case oForceV4Certs: opt.force_v4_certs = 1; break;
-          case oNoForceV4Certs: opt.force_v4_certs = 0; break;
+
          case oForceMDC: opt.force_mdc = 1; break;
          case oNoForceMDC: opt.force_mdc = 0; break;
          case oDisableMDC: opt.disable_mdc = 1; break;
@@ -2521,19 +3039,32 @@ main (int argc, char **argv)
          case oNoEncryptTo: opt.no_encrypt_to = 1; break;
          case oEncryptTo: /* store the recipient in the second list */
            sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
-           sl->flags = 1;
+           sl->flags = ((pargs.r_opt << PK_LIST_SHIFT) | PK_LIST_ENCRYPT_TO);
+            if (configfp)
+              sl->flags |= PK_LIST_CONFIG;
            break;
          case oHiddenEncryptTo: /* store the recipient in the second list */
            sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
-           sl->flags = 1|2;
+           sl->flags = ((pargs.r_opt << PK_LIST_SHIFT)
+                         | PK_LIST_ENCRYPT_TO|PK_LIST_HIDDEN);
+            if (configfp)
+              sl->flags |= PK_LIST_CONFIG;
            break;
+          case oEncryptToDefaultKey:
+            opt.encrypt_to_default_key = 1;
+            break;
          case oRecipient: /* store the recipient */
-           add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
+           sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
+           sl->flags = (pargs.r_opt << PK_LIST_SHIFT);
+            if (configfp)
+              sl->flags |= PK_LIST_CONFIG;
             any_explicit_recipient = 1;
            break;
          case oHiddenRecipient: /* store the recipient with a flag */
            sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
-           sl->flags = 2;
+           sl->flags = ((pargs.r_opt << PK_LIST_SHIFT) | PK_LIST_HIDDEN);
+            if (configfp)
+              sl->flags |= PK_LIST_CONFIG;
             any_explicit_recipient = 1;
            break;
 
@@ -2576,7 +3107,10 @@ main (int argc, char **argv)
          case oAskCertLevel: opt.ask_cert_level = 1; break;
          case oNoAskCertLevel: opt.ask_cert_level = 0; break;
          case oLocalUser: /* store the local users */
-           add_to_strlist2( &locusr, pargs.r.ret_str, utf8_strings );
+           sl = add_to_strlist2( &locusr, pargs.r.ret_str, utf8_strings );
+            sl->flags = (pargs.r_opt << PK_LIST_SHIFT);
+            if (configfp)
+              sl->flags |= PK_LIST_CONFIG;
            break;
          case oCompress:
            /* this is the -z command line option */
@@ -2674,13 +3208,18 @@ main (int argc, char **argv)
          case oKeyServer:
            {
              keyserver_spec_t keyserver;
-             keyserver = parse_keyserver_uri (pargs.r.ret_str,0,
-                                               configname,configlineno);
+             keyserver = parse_keyserver_uri (pargs.r.ret_str, 0);
              if (!keyserver)
                log_error (_("could not parse keyserver URL\n"));
              else
                {
-                 keyserver->next = opt.keyserver;
+                 /* We only support a single keyserver.  Later ones
+                    override earlier ones.  (Since we parse the
+                    config file first and then the command line
+                    arguments, the command line takes
+                    precedence.)  */
+                 if (opt.keyserver)
+                   free_keyserver_spec (opt.keyserver);
                  opt.keyserver = keyserver;
                }
            }
@@ -2810,21 +3349,17 @@ main (int argc, char **argv)
             }
             break;
           case oNoSigCache: opt.no_sig_cache = 1; break;
-          case oNoSigCreateCheck: opt.no_sig_create_check = 1; break;
          case oAllowNonSelfsignedUID: opt.allow_non_selfsigned_uid = 1; break;
          case oNoAllowNonSelfsignedUID: opt.allow_non_selfsigned_uid=0; break;
          case oAllowFreeformUID: opt.allow_freeform_uid = 1; break;
          case oNoAllowFreeformUID: opt.allow_freeform_uid = 0; break;
          case oNoLiteral: opt.no_literal = 1; break;
          case oSetFilesize: opt.set_filesize = pargs.r.ret_ulong; break;
-         case oHonorHttpProxy:
-               add_to_strlist(&opt.keyserver_options.other,"http-proxy");
-               deprecated_warning(configname,configlineno,
-                                  "--honor-http-proxy",
-                                  "--keyserver-options ","http-proxy");
-               break;
          case oFastListMode: opt.fast_list_mode = 1; break;
          case oFixedListMode: /* Dummy */ break;
+          case oLegacyListMode: opt.legacy_list_mode = 1; break;
+         case oPrintPKARecords: opt.print_pka_records = 1; break;
+         case oPrintDANERecords: opt.print_dane_records = 1; break;
          case oListOnly: opt.list_only=1; break;
          case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break;
          case oIgnoreValidFrom: opt.ignore_valid_from = 1; break;
@@ -2869,8 +3404,7 @@ main (int argc, char **argv)
          case oDefaultKeyserverURL:
            {
              keyserver_spec_t keyserver;
-             keyserver = parse_keyserver_uri (pargs.r.ret_str,1,
-                                               configname,configlineno);
+             keyserver = parse_keyserver_uri (pargs.r.ret_str,1 );
              if (!keyserver)
                log_error (_("could not parse keyserver URL\n"));
              else
@@ -2889,6 +3423,16 @@ main (int argc, char **argv)
            pers_compress_list=pargs.r.ret_str;
            break;
           case oAgentProgram: opt.agent_program = pargs.r.ret_str;  break;
+          case oDirmngrProgram: opt.dirmngr_program = pargs.r.ret_str; break;
+          case oWeakDigest:
+           additional_weak_digest(pargs.r.ret_str);
+           break;
+          case oUnwrap:
+            opt.unwrap_encryption = 1;
+            break;
+          case oOnlySignTextIDs:
+            opt.only_sign_text_ids = 1;
+            break;
 
           case oDisplay:
             set_opt_session_env ("DISPLAY", pargs.r.ret_str);
@@ -2965,6 +3509,22 @@ main (int argc, char **argv)
            release_akl();
            break;
 
+         case oEnableLargeRSA:
+#if SECMEM_BUFFER_SIZE >= 65536
+            opt.flags.large_rsa=1;
+#else
+            if (configname)
+              log_info("%s:%d: WARNING: gpg not built with large secure "
+                         "memory buffer.  Ignoring enable-large-rsa\n",
+                        configname,configlineno);
+            else
+              log_info("WARNING: gpg not built with large secure "
+                         "memory buffer.  Ignoring --enable-large-rsa\n");
+#endif /* SECMEM_BUFFER_SIZE >= 65536 */
+            break;
+         case oDisableLargeRSA: opt.flags.large_rsa=0;
+            break;
+
          case oEnableDSA2: opt.flags.dsa2=1; break;
          case oDisableDSA2: opt.flags.dsa2=0; break;
 
@@ -2977,6 +3537,10 @@ main (int argc, char **argv)
            opt.flags.allow_multiple_messages=0;
            break;
 
+          case oAllowWeakDigestAlgos:
+            opt.flags.allow_weak_digest_algos = 1;
+            break;
+
           case oFakedSystemTime:
             {
               time_t faked_time = isotime2epoch (pargs.r.ret_str);
@@ -2986,6 +3550,8 @@ main (int argc, char **argv)
             }
             break;
 
+          case oNoAutostart: opt.autostart = 0; break;
+
          case oNoop: break;
 
          default:
@@ -3053,15 +3619,6 @@ main (int argc, char **argv)
         log_set_prefix (NULL, 1|2|4);
       }
 
-    /* Older Libgcrypts fail with an assertion during DSA key
-       generation.  Better disable DSA2 entirely. */
-    if (opt.flags.dsa2 && !gcry_check_version ("1.4.0") )
-      {
-        log_info ("WARNING: "
-                  "DSA2 is only available with Libgcrypt 1.4 and later\n");
-        opt.flags.dsa2 = 0;
-      }
-
     if (opt.verbose > 2)
         log_info ("using character set '%s'\n", get_native_charset ());
 
@@ -3077,7 +3634,7 @@ main (int argc, char **argv)
     }
 
     if (opt.no_literal) {
-       log_info(_("NOTE: %s is not for normal use!\n"), "--no-literal");
+       log_info(_("Note: %s is not for normal use!\n"), "--no-literal");
        if (opt.textmode)
            log_error(_("%s not allowed with %s!\n"),
                       "--textmode", "--no-literal" );
@@ -3089,7 +3646,7 @@ main (int argc, char **argv)
 
 
     if (opt.set_filesize)
-       log_info(_("NOTE: %s is not for normal use!\n"), "--set-filesize");
+       log_info(_("Note: %s is not for normal use!\n"), "--set-filesize");
     if( opt.batch )
        tty_batchmode( 1 );
 
@@ -3110,7 +3667,7 @@ main (int argc, char **argv)
 
         for (i=0; i < argc; i++)
           if (argv[i][0] == '-' && argv[i][1] == '-')
-            log_info (_("NOTE: '%s' is not considered an option\n"), argv[i]);
+            log_info (_("Note: '%s' is not considered an option\n"), argv[i]);
       }
 
 
@@ -3128,87 +3685,19 @@ main (int argc, char **argv)
       log_clock ("start");
 
     /* Do these after the switch(), so they can override settings. */
-    if(PGP2)
-      {
-       int unusable=0;
-
-       if(cmd==aSign && !detached_sig)
-         {
-           log_info(_("you can only make detached or clear signatures "
-                      "while in --pgp2 mode\n"));
-           unusable=1;
-         }
-       else if(cmd==aSignEncr || cmd==aSignSym)
-         {
-           log_info(_("you can't sign and encrypt at the "
-                      "same time while in --pgp2 mode\n"));
-           unusable=1;
-         }
-       else if(argc==0 && (cmd==aSign || cmd==aEncr || cmd==aSym))
-         {
-           log_info(_("you must use files (and not a pipe) when "
-                      "working with --pgp2 enabled.\n"));
-           unusable=1;
-         }
-       else if(cmd==aEncr || cmd==aSym)
-         {
-           /* Everything else should work without IDEA (except using
-              a secret key encrypted with IDEA and setting an IDEA
-              preference, but those have their own error
-              messages). */
-
-           if (openpgp_cipher_test_algo(CIPHER_ALGO_IDEA))
-             {
-               log_info(_("encrypting a message in --pgp2 mode requires "
-                          "the IDEA cipher\n"));
-               unusable=1;
-             }
-           else if(cmd==aSym)
-             {
-               /* This only sets IDEA for symmetric encryption
-                  since it is set via select_algo_from_prefs for
-                  pk encryption. */
-               xfree(def_cipher_string);
-               def_cipher_string = xstrdup("idea");
-             }
-
-           /* PGP2 can't handle the output from the textmode
-              filter, so we disable it for anything that could
-              create a literal packet (only encryption and
-              symmetric encryption, since we disable signing
-              above). */
-           if(!unusable)
-             opt.textmode=0;
-         }
-
-       if(unusable)
-         compliance_failure();
-       else
-         {
-           opt.force_v4_certs = 0;
-           opt.escape_from = 1;
-           opt.force_v3_sigs = 1;
-           opt.pgp2_workarounds = 1;
-           opt.ask_sig_expire = 0;
-           opt.ask_cert_expire = 0;
-           xfree(def_digest_string);
-           def_digest_string = xstrdup("md5");
-           xfree(s2k_digest_string);
-           s2k_digest_string = xstrdup("md5");
-           opt.compress_algo = COMPRESS_ALGO_ZIP;
-         }
-      }
-    else if(PGP6)
+    if(PGP6)
       {
+        /* That does not anymore work because we have no more support
+           for v3 signatures.  */
        opt.disable_mdc=1;
        opt.escape_from=1;
-       opt.force_v3_sigs=1;
        opt.ask_sig_expire=0;
       }
     else if(PGP7)
       {
+        /* That does not anymore work because we have no more support
+           for v3 signatures.  */
        opt.escape_from=1;
-       opt.force_v3_sigs=1;
        opt.ask_sig_expire=0;
       }
     else if(PGP8)
@@ -3265,7 +3754,7 @@ main (int argc, char **argv)
       log_error(_("invalid min-cert-level; must be 1, 2, or 3\n"));
     switch( opt.s2k_mode ) {
       case 0:
-       log_info(_("NOTE: simple S2K mode (0) is strongly discouraged\n"));
+       log_info(_("Note: simple S2K mode (0) is strongly discouraged\n"));
        break;
       case 1: case 3: break;
       default:
@@ -3300,6 +3789,9 @@ main (int argc, char **argv)
          case aSign:
            cmdname="--sign";
            break;
+         case aSignEncr:
+           cmdname="--sign --encrypt";
+           break;
          case aClearsign:
            cmdname="--clearsign";
            break;
@@ -3418,13 +3910,20 @@ main (int argc, char **argv)
         || (cmd != aDeArmor && cmd != aEnArmor && cmd != aGPGConfTest) )
       {
        if (!nrings || default_keyring)  /* Add default ring. */
-           keydb_add_resource ("pubring" EXTSEP_S "gpg",
+           keydb_add_resource ("pubring" EXTSEP_S GPGEXT_GPG,
                                 KEYDB_RESOURCE_FLAG_DEFAULT);
        for (sl = nrings; sl; sl = sl->next )
           keydb_add_resource (sl->d, sl->flags);
       }
     FREE_STRLIST(nrings);
 
+    if (opt.pinentry_mode == PINENTRY_MODE_LOOPBACK)
+      /* In loopback mode, never ask for the password multiple
+        times.  */
+      {
+       opt.passphrase_repeat = 0;
+      }
+
     if (cmd == aGPGConfTest)
       g10_exit(0);
 
@@ -3440,7 +3939,9 @@ main (int argc, char **argv)
     ctrl = xcalloc (1, sizeof *ctrl);
     gpg_init_default_ctrl (ctrl);
 
-    switch( cmd ) {
+#ifndef NO_TRUST_MODELS
+    switch (cmd)
+      {
       case aPrimegen:
       case aPrintMD:
       case aPrintMDs:
@@ -3449,13 +3950,22 @@ main (int argc, char **argv)
       case aEnArmor:
        break;
       case aFixTrustDB:
-      case aExportOwnerTrust: rc = setup_trustdb( 0, trustdb_name ); break;
-      case aListTrustDB: rc = setup_trustdb( argc? 1:0, trustdb_name ); break;
-      default: rc = setup_trustdb(1, trustdb_name ); break;
-    }
-    if( rc )
-       log_error(_("failed to initialize the TrustDB: %s\n"), g10_errstr(rc));
-
+      case aExportOwnerTrust:
+        rc = setup_trustdb (0, trustdb_name);
+        break;
+      case aListTrustDB:
+        rc = setup_trustdb (argc? 1:0, trustdb_name);
+        break;
+      default:
+        /* If we are using TM_ALWAYS, we do not need to create the
+           trustdb.  */
+        rc = setup_trustdb (opt.trust_model != TM_ALWAYS, trustdb_name);
+        break;
+      }
+    if (rc)
+      log_error (_("failed to initialize the TrustDB: %s\n"),
+                 gpg_strerror (rc));
+#endif /*!NO_TRUST_MODELS*/
 
     switch (cmd)
       {
@@ -3472,6 +3982,77 @@ main (int argc, char **argv)
         break;
       }
 
+
+    /* Check for certain command whether we need to migrate a
+       secring.gpg to the gpg-agent. */
+    switch (cmd)
+      {
+      case aListSecretKeys:
+      case aSign:
+      case aSignEncr:
+      case aSignEncrSym:
+      case aSignSym:
+      case aClearsign:
+      case aDecrypt:
+      case aSignKey:
+      case aLSignKey:
+      case aEditKey:
+      case aPasswd:
+      case aDeleteSecretKeys:
+      case aDeleteSecretAndPublicKeys:
+      case aQuickKeygen:
+      case aQuickAddUid:
+      case aFullKeygen:
+      case aKeygen:
+      case aImport:
+      case aExportSecret:
+      case aExportSecretSub:
+      case aGenRevoke:
+      case aDesigRevoke:
+      case aCardEdit:
+      case aChangePIN:
+        migrate_secring (ctrl);
+       break;
+      case aListKeys:
+        if (opt.with_secret)
+          migrate_secring (ctrl);
+        break;
+      default:
+        break;
+      }
+
+    {
+      int have_def_secret_key = opt.def_secret_key != NULL;
+
+      rc = check_user_ids (&locusr, 1, 1);
+      if (rc)
+        g10_exit (1);
+      rc = check_user_ids (&remusr, 0, 1);
+      if (rc)
+        g10_exit (1);
+      rc = check_user_ids (&opt.def_secret_key, 1, 0);
+      if (rc)
+        g10_exit (1);
+
+      if (opt.encrypt_to_default_key)
+        {
+          const char *default_key = parse_def_secret_key (ctrl);
+          if (default_key)
+            {
+              sl = add_to_strlist2 (&remusr, default_key, utf8_strings);
+              sl->flags = ((oEncryptToDefaultKey << PK_LIST_SHIFT)
+                           | PK_LIST_ENCRYPT_TO);
+            }
+          else if (have_def_secret_key)
+            log_info (_("option '%s' given, but no valid default keys given\n"),
+                      "--encrypt-to-default-key");
+          else
+            log_info (_("option '%s' given, but option '%s' not given\n"),
+                      "--encrypt-to-default-key", "--default-key");
+        }
+    }
+
+    /* The command dispatcher.  */
     switch( cmd )
       {
       case aServer:
@@ -3482,15 +4063,21 @@ main (int argc, char **argv)
        if( argc > 1 )
            wrong_args(_("--store [filename]"));
        if( (rc = encrypt_store(fname)) )
+          {
+            write_status_failure ("store", rc);
            log_error ("storing '%s' failed: %s\n",
-                       print_fname_stdin(fname),g10_errstr(rc) );
+                       print_fname_stdin(fname),gpg_strerror (rc) );
+          }
        break;
       case aSym: /* encrypt the given file only with the symmetric cipher */
        if( argc > 1 )
            wrong_args(_("--symmetric [filename]"));
        if( (rc = encrypt_symmetric(fname)) )
+          {
+            write_status_failure ("symencrypt", rc);
             log_error (_("symmetric encryption of '%s' failed: %s\n"),
-                        print_fname_stdin(fname),g10_errstr(rc) );
+                        print_fname_stdin(fname),gpg_strerror (rc) );
+          }
        break;
 
       case aEncr: /* encrypt the given file */
@@ -3501,8 +4088,11 @@ main (int argc, char **argv)
            if( argc > 1 )
              wrong_args(_("--encrypt [filename]"));
            if( (rc = encrypt_crypt (ctrl, -1, fname, remusr, 0, NULL, -1)) )
-             log_error("%s: encryption failed: %s\n",
-                       print_fname_stdin(fname), g10_errstr(rc) );
+              {
+                write_status_failure ("encrypt", rc);
+                log_error("%s: encryption failed: %s\n",
+                          print_fname_stdin(fname), gpg_strerror (rc) );
+              }
          }
        break;
 
@@ -3516,14 +4106,17 @@ main (int argc, char **argv)
        else if(opt.s2k_mode==0)
          log_error(_("you cannot use --symmetric --encrypt"
                      " with --s2k-mode 0\n"));
-       else if(PGP2 || PGP6 || PGP7 || RFC1991)
+       else if(PGP6 || PGP7)
          log_error(_("you cannot use --symmetric --encrypt"
                      " while in %s mode\n"),compliance_option_string());
        else
          {
            if( (rc = encrypt_crypt (ctrl, -1, fname, remusr, 1, NULL, -1)) )
-             log_error("%s: encryption failed: %s\n",
-                       print_fname_stdin(fname), g10_errstr(rc) );
+              {
+                write_status_failure ("encrypt", rc);
+                log_error ("%s: encryption failed: %s\n",
+                           print_fname_stdin(fname), gpg_strerror (rc) );
+              }
          }
        break;
 
@@ -3541,8 +4134,11 @@ main (int argc, char **argv)
                strcpy(sl->d, fname);
            }
        }
-       if( (rc = sign_file (ctrl, sl, detached_sig, locusr, 0, NULL, NULL)) )
-           log_error("signing failed: %s\n", g10_errstr(rc) );
+       if ((rc = sign_file (ctrl, sl, detached_sig, locusr, 0, NULL, NULL)))
+          {
+            write_status_failure ("sign", rc);
+           log_error ("signing failed: %s\n", gpg_strerror (rc) );
+          }
        free_strlist(sl);
        break;
 
@@ -3556,8 +4152,11 @@ main (int argc, char **argv)
        else
            sl = NULL;
        if ((rc = sign_file (ctrl, sl, detached_sig, locusr, 1, remusr, NULL)))
+          {
+            write_status_failure ("sign-encrypt", rc);
            log_error("%s: sign+encrypt failed: %s\n",
-                     print_fname_stdin(fname), g10_errstr(rc) );
+                     print_fname_stdin(fname), gpg_strerror (rc) );
+          }
        free_strlist(sl);
        break;
 
@@ -3567,7 +4166,7 @@ main (int argc, char **argv)
        else if(opt.s2k_mode==0)
          log_error(_("you cannot use --symmetric --sign --encrypt"
                      " with --s2k-mode 0\n"));
-       else if(PGP2 || PGP6 || PGP7 || RFC1991)
+       else if(PGP6 || PGP7)
          log_error(_("you cannot use --symmetric --sign --encrypt"
                      " while in %s mode\n"),compliance_option_string());
        else
@@ -3581,8 +4180,11 @@ main (int argc, char **argv)
              sl = NULL;
            if ((rc = sign_file (ctrl, sl, detached_sig, locusr,
                                  2, remusr, NULL)))
-             log_error("%s: symmetric+sign+encrypt failed: %s\n",
-                       print_fname_stdin(fname), g10_errstr(rc) );
+              {
+                write_status_failure ("sign-encrypt", rc);
+                log_error("%s: symmetric+sign+encrypt failed: %s\n",
+                          print_fname_stdin(fname), gpg_strerror (rc) );
+              }
            free_strlist(sl);
          }
        break;
@@ -3590,31 +4192,40 @@ main (int argc, char **argv)
       case aSignSym: /* sign and conventionally encrypt the given file */
        if (argc > 1)
            wrong_args(_("--sign --symmetric [filename]"));
-       rc = sign_symencrypt_file (fname, locusr);
+       rc = sign_symencrypt_file (ctrl, fname, locusr);
         if (rc)
+          {
+            write_status_failure ("sign-symencrypt", rc);
            log_error("%s: sign+symmetric failed: %s\n",
-                      print_fname_stdin(fname), g10_errstr(rc) );
+                      print_fname_stdin(fname), gpg_strerror (rc) );
+          }
        break;
 
       case aClearsign: /* make a clearsig */
        if( argc > 1 )
            wrong_args(_("--clearsign [filename]"));
-       if( (rc = clearsign_file(fname, locusr, NULL)) )
+       if( (rc = clearsign_file (ctrl, fname, locusr, NULL)) )
+          {
+            write_status_failure ("sign", rc);
            log_error("%s: clearsign failed: %s\n",
-                      print_fname_stdin(fname), g10_errstr(rc) );
+                      print_fname_stdin(fname), gpg_strerror (rc) );
+          }
        break;
 
       case aVerify:
+        rc = 0;
        if (multifile)
          {
            if ((rc = verify_files (ctrl, argc, argv)))
-             log_error("verify files failed: %s\n", g10_errstr(rc) );
+             log_error("verify files failed: %s\n", gpg_strerror (rc) );
          }
        else
          {
            if ((rc = verify_signatures (ctrl, argc, argv)))
-             log_error("verify signatures failed: %s\n", g10_errstr(rc) );
+             log_error("verify signatures failed: %s\n", gpg_strerror (rc) );
          }
+        if (rc)
+          write_status_failure ("verify", rc);
        break;
 
       case aDecrypt:
@@ -3625,10 +4236,29 @@ main (int argc, char **argv)
            if( argc > 1 )
              wrong_args(_("--decrypt [filename]"));
            if( (rc = decrypt_message (ctrl, fname) ))
-             log_error("decrypt_message failed: %s\n", g10_errstr(rc) );
+              {
+                write_status_failure ("decrypt", rc);
+                log_error("decrypt_message failed: %s\n", gpg_strerror (rc) );
+              }
          }
        break;
 
+      case aQuickSignKey:
+      case aQuickLSignKey:
+        {
+          const char *fpr;
+
+          if (argc < 1)
+            wrong_args ("--quick-[l]sign-key fingerprint [userids]");
+          fpr = *argv++; argc--;
+          sl = NULL;
+          for( ; argc; argc--, argv++)
+           append_to_strlist2 (&sl, *argv, utf8_strings);
+          keyedit_quick_sign (ctrl, fpr, sl, locusr, (cmd == aQuickLSignKey));
+          free_strlist (sl);
+        }
+       break;
+
       case aSignKey:
        if( argc != 1 )
          wrong_args(_("--sign-key user-id"));
@@ -3720,19 +4350,63 @@ main (int argc, char **argv)
        free_strlist (sl);
        break;
 
+      case aQuickKeygen:
+        if (argc != 1 )
+          wrong_args("--gen-key user-id");
+        username = make_username (fname);
+        quick_generate_keypair (ctrl, username);
+        xfree (username);
+        break;
+
       case aKeygen: /* generate a key */
        if( opt.batch ) {
            if( argc > 1 )
                wrong_args("--gen-key [parameterfile]");
-           generate_keypair (ctrl, argc? *argv : NULL, NULL, 0);
+           generate_keypair (ctrl, 0, argc? *argv : NULL, NULL, 0);
        }
        else {
-           if( argc )
-               wrong_args("--gen-key");
-           generate_keypair (ctrl, NULL, NULL, 0);
+            if (opt.command_fd != -1 && argc)
+              {
+                if( argc > 1 )
+                  wrong_args("--gen-key [parameterfile]");
+
+                opt.batch = 1;
+                generate_keypair (ctrl, 0, argc? *argv : NULL, NULL, 0);
+              }
+            else if (argc)
+              wrong_args ("--gen-key");
+            else
+              generate_keypair (ctrl, 0, NULL, NULL, 0);
        }
        break;
 
+      case aFullKeygen: /* Generate a key with all options. */
+       if (opt.batch)
+          {
+           if (argc > 1)
+              wrong_args ("--full-gen-key [parameterfile]");
+           generate_keypair (ctrl, 1, argc? *argv : NULL, NULL, 0);
+          }
+       else
+          {
+           if (argc)
+              wrong_args("--full-gen-key");
+           generate_keypair (ctrl, 1, NULL, NULL, 0);
+       }
+       break;
+
+      case aQuickAddUid:
+        {
+          const char *uid, *newuid;
+
+          if (argc != 2)
+            wrong_args ("--quick-adduid USER-ID NEW-USER-ID");
+          uid = *argv++; argc--;
+          newuid = *argv++; argc--;
+          keyedit_quick_adduid (ctrl, uid, newuid);
+        }
+       break;
+
       case aFastImport:
         opt.import_options |= IMPORT_FAST;
       case aImport:
@@ -3755,15 +4429,30 @@ main (int argc, char **argv)
        else if( cmd == aRecvKeys )
             rc = keyserver_import (ctrl, sl );
        else
-            rc = export_pubkeys (ctrl, sl, opt.export_options);
+          {
+            export_stats_t stats = export_new_stats ();
+            rc = export_pubkeys (ctrl, sl, opt.export_options, stats);
+            export_print_stats (stats);
+            export_release_stats (stats);
+          }
        if(rc)
          {
            if(cmd==aSendKeys)
-             log_error(_("keyserver send failed: %s\n"),g10_errstr(rc));
+              {
+                write_status_failure ("send-keys", rc);
+                log_error(_("keyserver send failed: %s\n"),gpg_strerror (rc));
+              }
            else if(cmd==aRecvKeys)
-             log_error(_("keyserver receive failed: %s\n"),g10_errstr(rc));
+              {
+                write_status_failure ("recv-keys", rc);
+                log_error (_("keyserver receive failed: %s\n"),
+                           gpg_strerror (rc));
+              }
            else
-             log_error(_("key export failed: %s\n"),g10_errstr(rc));
+              {
+                write_status_failure ("export", rc);
+                log_error (_("key export failed: %s\n"), gpg_strerror (rc));
+              }
          }
        free_strlist(sl);
        break;
@@ -3774,7 +4463,10 @@ main (int argc, char **argv)
          append_to_strlist2 (&sl, *argv, utf8_strings);
        rc = keyserver_search (ctrl, sl);
        if (rc)
-         log_error (_("keyserver search failed: %s\n"), gpg_strerror (rc));
+          {
+            write_status_failure ("search-keys", rc);
+            log_error (_("keyserver search failed: %s\n"), gpg_strerror (rc));
+          }
        free_strlist (sl);
        break;
 
@@ -3784,7 +4476,10 @@ main (int argc, char **argv)
            append_to_strlist2( &sl, *argv, utf8_strings );
        rc = keyserver_refresh (ctrl, sl);
        if(rc)
-         log_error(_("keyserver refresh failed: %s\n"),g10_errstr(rc));
+          {
+            write_status_failure ("refresh-keys", rc);
+            log_error (_("keyserver refresh failed: %s\n"),gpg_strerror (rc));
+          }
        free_strlist(sl);
        break;
 
@@ -3794,7 +4489,10 @@ main (int argc, char **argv)
            append_to_strlist2( &sl, *argv, utf8_strings );
        rc = keyserver_fetch (ctrl, sl);
        if(rc)
-         log_error("key fetch failed: %s\n",g10_errstr(rc));
+          {
+            write_status_failure ("fetch-keys", rc);
+            log_error ("key fetch failed: %s\n",gpg_strerror (rc));
+          }
        free_strlist(sl);
        break;
 
@@ -3802,7 +4500,12 @@ main (int argc, char **argv)
        sl = NULL;
        for( ; argc; argc--, argv++ )
            add_to_strlist2( &sl, *argv, utf8_strings );
-       export_seckeys (ctrl, sl);
+        {
+          export_stats_t stats = export_new_stats ();
+          export_seckeys (ctrl, sl, stats);
+          export_print_stats (stats);
+          export_release_stats (stats);
+        }
        free_strlist(sl);
        break;
 
@@ -3810,7 +4513,12 @@ main (int argc, char **argv)
        sl = NULL;
        for( ; argc; argc--, argv++ )
            add_to_strlist2( &sl, *argv, utf8_strings );
-       export_secsubkeys (ctrl, sl);
+        {
+          export_stats_t stats = export_new_stats ();
+          export_secsubkeys (ctrl, sl, stats);
+          export_print_stats (stats);
+          export_release_stats (stats);
+        }
        free_strlist(sl);
        break;
 
@@ -3823,11 +4531,11 @@ main (int argc, char **argv)
        break;
 
       case aDesigRevoke:
-       if( argc != 1 )
-           wrong_args("--desig-revoke user-id");
-       username =  make_username(*argv);
-       gen_desig_revoke( username, locusr );
-       xfree( username );
+       if (argc != 1)
+           wrong_args ("--desig-revoke user-id");
+       username = make_username (*argv);
+       gen_desig_revoke (ctrl, username, locusr);
+       xfree (username);
        break;
 
       case aDeArmor:
@@ -3835,7 +4543,10 @@ main (int argc, char **argv)
            wrong_args("--dearmor [file]");
        rc = dearmor_file( argc? *argv: NULL );
        if( rc )
-           log_error(_("dearmoring failed: %s\n"), g10_errstr(rc));
+          {
+            write_status_failure ("dearmor", rc);
+            log_error (_("dearmoring failed: %s\n"), gpg_strerror (rc));
+          }
        break;
 
       case aEnArmor:
@@ -3843,7 +4554,10 @@ main (int argc, char **argv)
            wrong_args("--enarmor [file]");
        rc = enarmor_file( argc? *argv: NULL );
        if( rc )
-           log_error(_("enarmoring failed: %s\n"), g10_errstr(rc));
+          {
+            write_status_failure ("enarmor", rc);
+           log_error (_("enarmoring failed: %s\n"), gpg_strerror (rc));
+          }
        break;
 
 
@@ -3865,7 +4579,7 @@ main (int argc, char **argv)
                mpi_print (es_stdout, generate_elg_prime(
                                             1, atoi(argv[1]),
                                             atoi(argv[2]), NULL,&factors ), 1);
-               putchar('\n');
+               es_putc ('\n', es_stdout);
                mpi_print (es_stdout, factors[0], 1 ); /* print q */
            }
            else if( mode == 4 && argc == 3 ) {
@@ -3873,13 +4587,13 @@ main (int argc, char **argv)
                mpi_print (es_stdout, generate_elg_prime(
                                                 0, atoi(argv[1]),
                                                 atoi(argv[2]), g, NULL ), 1);
-               putchar('\n');
+               es_putc ('\n', es_stdout);
                mpi_print (es_stdout, g, 1 );
                mpi_free (g);
            }
            else
                wrong_args("--gen-prime mode bits [qbits] ");
-           putchar('\n');
+           es_putc ('\n', es_stdout);
        }
 #endif
         wrong_args("--gen-prime not yet supported ");
@@ -3908,21 +4622,21 @@ main (int argc, char **argv)
 #endif
                 if (opt.armor) {
                     char *tmp = make_radix64_string (p, n);
-                    fputs (tmp, stdout);
+                    es_fputs (tmp, es_stdout);
                     xfree (tmp);
                     if (n%3 == 1)
-                      putchar ('=');
+                      es_putc ('=', es_stdout);
                     if (n%3)
-                      putchar ('=');
+                      es_putc ('=', es_stdout);
                 } else {
-                    fwrite( p, n, 1, stdout );
+                    es_fwrite( p, n, 1, es_stdout );
                 }
                xfree(p);
                if( !endless )
                    count -= n;
            }
             if (opt.armor)
-                putchar ('\n');
+              es_putc ('\n', es_stdout);
        }
        break;
 
@@ -3956,12 +4670,13 @@ main (int argc, char **argv)
        }
        break;
 
+#ifndef NO_TRUST_MODELS
       case aListTrustDB:
        if( !argc )
-           list_trustdb(NULL);
+          list_trustdb (es_stdout, NULL);
        else {
            for( ; argc; argc--, argv++ )
-               list_trustdb( *argv );
+              list_trustdb (es_stdout, *argv );
        }
        break;
 
@@ -4001,6 +4716,7 @@ main (int argc, char **argv)
            wrong_args("--import-ownertrust [file]");
        import_ownertrust( argc? *argv:NULL );
        break;
+#endif /*!NO_TRUST_MODELS*/
 
       case aRebuildKeydbCaches:
         if (argc)
@@ -4033,7 +4749,7 @@ main (int argc, char **argv)
         else if (argc == 1)
             change_pin (atoi (*argv),1);
         else
-        wrong_args ("--change-pin [no]");
+            wrong_args ("--change-pin [no]");
         break;
 #endif /* ENABLE_CARD_SUPPORT*/
 
@@ -4045,6 +4761,92 @@ main (int argc, char **argv)
        }
        break;
 
+      case aListGcryptConfig:
+        /* Fixme: It would be nice to integrate that with
+           --list-config but unfortunately there is no way yet to have
+           libgcrypt print it to an estream for further parsing.  */
+        gcry_control (GCRYCTL_PRINT_CONFIG, stdout);
+        break;
+
+      case aTOFUPolicy:
+#ifdef USE_TOFU
+       {
+         int policy;
+         int i;
+         KEYDB_HANDLE hd;
+
+         if (argc < 2)
+           wrong_args ("--tofu-policy POLICY KEYID [KEYID...]");
+
+         policy = parse_tofu_policy (argv[0]);
+
+         hd = keydb_new ();
+         if (! hd)
+            g10_exit (1);
+
+         for (i = 1; i < argc; i ++)
+           {
+             KEYDB_SEARCH_DESC desc;
+             kbnode_t kb;
+
+             rc = classify_user_id (argv[i], &desc, 0);
+             if (rc)
+               {
+                 log_error (_("error parsing key specification '%s': %s\n"),
+                             argv[i], gpg_strerror (rc));
+                 g10_exit (1);
+               }
+
+             if (! (desc.mode == KEYDB_SEARCH_MODE_SHORT_KID
+                    || desc.mode == KEYDB_SEARCH_MODE_LONG_KID
+                    || desc.mode == KEYDB_SEARCH_MODE_FPR16
+                    || desc.mode == KEYDB_SEARCH_MODE_FPR20
+                    || desc.mode == KEYDB_SEARCH_MODE_FPR
+                    || desc.mode == KEYDB_SEARCH_MODE_KEYGRIP))
+               {
+                 log_error (_("'%s' does not appear to be a valid"
+                              " key ID, fingerprint or keygrip\n"),
+                            argv[i]);
+                 g10_exit (1);
+               }
+
+             rc = keydb_search_reset (hd);
+             if (rc)
+               {
+                  /* This should not happen, thus no need to tranalate
+                     the string.  */
+                  log_error ("keydb_search_reset failed: %s\n",
+                             gpg_strerror (rc));
+                 g10_exit (1);
+               }
+
+             rc = keydb_search (hd, &desc, 1, NULL);
+             if (rc)
+               {
+                 log_error (_("key \"%s\" not found: %s\n"), argv[i],
+                             gpg_strerror (rc));
+                 g10_exit (1);
+               }
+
+             rc = keydb_get_keyblock (hd, &kb);
+             if (rc)
+               {
+                 log_error (_("error reading keyblock: %s\n"),
+                             gpg_strerror (rc));
+                 g10_exit (1);
+               }
+
+             merge_keys_and_selfsig (kb);
+             if (tofu_set_policy (kb, policy))
+               g10_exit (1);
+           }
+
+         keydb_release (hd);
+
+       }
+#endif /*USE_TOFU*/
+       break;
+
       case aListPackets:
        opt.list_packets=2;
       default:
@@ -4080,7 +4882,11 @@ main (int argc, char **argv)
            }
            rc = proc_packets (ctrl, NULL, a );
            if( rc )
-               log_error("processing message failed: %s\n", g10_errstr(rc) );
+              {
+                write_status_failure ("-", rc);
+                log_error ("processing message failed: %s\n",
+                           gpg_strerror (rc));
+              }
            iobuf_close(a);
        }
        break;
@@ -4111,8 +4917,10 @@ g10_exit( int rc )
   gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE);
   if (DBG_CLOCK)
     log_clock ("stop");
+
   if ( (opt.debug & DBG_MEMSTAT_VALUE) )
     {
+      keydb_dump_stats ();
       gcry_control (GCRYCTL_DUMP_MEMORY_STATS);
       gcry_control (GCRYCTL_DUMP_RANDOM_STATS);
     }
@@ -4140,7 +4948,7 @@ print_hex (gcry_md_hd_t md, int algo, const char *fname)
 
   if (indent>40)
     {
-      printf("\n");
+      es_printf ("\n");
       indent=0;
     }
 
@@ -4234,98 +5042,111 @@ print_hashline( gcry_md_hd_t md, int algo, const char *fname )
   es_fputs (":\n", es_stdout);
 }
 
+
 static void
 print_mds( const char *fname, int algo )
 {
-    FILE *fp;
-    char buf[1024];
-    size_t n;
-    gcry_md_hd_t md;
+  estream_t fp;
+  char buf[1024];
+  size_t n;
+  gcry_md_hd_t md;
 
-    if( !fname ) {
-       fp = stdin;
-#ifdef HAVE_DOSISH_SYSTEM
-       setmode ( fileno(fp) , O_BINARY );
-#endif
+  if (!fname)
+    {
+      fp = es_stdin;
+      es_set_binary (fp);
     }
-    else {
-       fp = fopen( fname, "rb" );
-        if (fp && is_secured_file (fileno (fp)))
-          {
-            fclose (fp);
-            fp = NULL;
-            gpg_err_set_errno (EPERM);
-          }
+  else
+    {
+      fp = es_fopen (fname, "rb" );
+      if (fp && is_secured_file (es_fileno (fp)))
+        {
+          es_fclose (fp);
+          fp = NULL;
+          gpg_err_set_errno (EPERM);
+        }
     }
-    if( !fp ) {
-       log_error("%s: %s\n", fname?fname:"[stdin]", strerror(errno) );
-       return;
+  if (!fp)
+    {
+      log_error("%s: %s\n", fname?fname:"[stdin]", strerror(errno) );
+      return;
     }
 
-    gcry_md_open (&md, 0, 0);
-    if( algo )
-        gcry_md_enable (md, algo);
-    else {
-       gcry_md_enable (md, GCRY_MD_MD5);
-       gcry_md_enable (md, GCRY_MD_SHA1);
-       gcry_md_enable (md, GCRY_MD_RMD160);
-        if (!openpgp_md_test_algo (GCRY_MD_SHA224))
-          gcry_md_enable (md, GCRY_MD_SHA224);
-        if (!openpgp_md_test_algo (GCRY_MD_SHA256))
-          gcry_md_enable (md, GCRY_MD_SHA256);
-        if (!openpgp_md_test_algo (GCRY_MD_SHA384))
-          gcry_md_enable (md, GCRY_MD_SHA384);
-        if (!openpgp_md_test_algo (GCRY_MD_SHA512))
-          gcry_md_enable (md, GCRY_MD_SHA512);
+  gcry_md_open (&md, 0, 0);
+  if (algo)
+    gcry_md_enable (md, algo);
+  else
+    {
+      if (!gcry_md_test_algo (GCRY_MD_MD5))
+        gcry_md_enable (md, GCRY_MD_MD5);
+      gcry_md_enable (md, GCRY_MD_SHA1);
+      if (!gcry_md_test_algo (GCRY_MD_RMD160))
+        gcry_md_enable (md, GCRY_MD_RMD160);
+      if (!gcry_md_test_algo (GCRY_MD_SHA224))
+        gcry_md_enable (md, GCRY_MD_SHA224);
+      if (!gcry_md_test_algo (GCRY_MD_SHA256))
+        gcry_md_enable (md, GCRY_MD_SHA256);
+      if (!gcry_md_test_algo (GCRY_MD_SHA384))
+        gcry_md_enable (md, GCRY_MD_SHA384);
+      if (!gcry_md_test_algo (GCRY_MD_SHA512))
+        gcry_md_enable (md, GCRY_MD_SHA512);
     }
 
-    while( (n=fread( buf, 1, DIM(buf), fp )) )
-       gcry_md_write (md, buf, n);
-    if( ferror(fp) )
-       log_error("%s: %s\n", fname?fname:"[stdin]", strerror(errno) );
-    else {
-       gcry_md_final (md);
-        if ( opt.with_colons ) {
-            if ( algo )
-                print_hashline( md, algo, fname );
-            else {
+  while ((n=es_fread (buf, 1, DIM(buf), fp)))
+    gcry_md_write (md, buf, n);
+
+  if (es_ferror(fp))
+    log_error ("%s: %s\n", fname?fname:"[stdin]", strerror(errno));
+  else
+    {
+      gcry_md_final (md);
+      if (opt.with_colons)
+        {
+          if ( algo )
+            print_hashline (md, algo, fname);
+          else
+            {
+              if (!gcry_md_test_algo (GCRY_MD_MD5))
                 print_hashline( md, GCRY_MD_MD5, fname );
-                print_hashline( md, GCRY_MD_SHA1, fname );
-                if (!gcry_md_test_algo (GCRY_MD_RMD160))
-                    print_hashline( md, GCRY_MD_RMD160, fname );
-                if (!gcry_md_test_algo (GCRY_MD_SHA224))
-                    print_hashline (md, GCRY_MD_SHA224, fname);
-                if (!gcry_md_test_algo (GCRY_MD_SHA256))
-                    print_hashline( md, GCRY_MD_SHA256, fname );
-                if (!gcry_md_test_algo (GCRY_MD_SHA384))
-                    print_hashline ( md, GCRY_MD_SHA384, fname );
-                if (!gcry_md_test_algo (GCRY_MD_SHA512))
-                    print_hashline ( md, GCRY_MD_SHA512, fname );
+              print_hashline( md, GCRY_MD_SHA1, fname );
+              if (!gcry_md_test_algo (GCRY_MD_RMD160))
+                print_hashline( md, GCRY_MD_RMD160, fname );
+              if (!gcry_md_test_algo (GCRY_MD_SHA224))
+                print_hashline (md, GCRY_MD_SHA224, fname);
+              if (!gcry_md_test_algo (GCRY_MD_SHA256))
+                print_hashline( md, GCRY_MD_SHA256, fname );
+              if (!gcry_md_test_algo (GCRY_MD_SHA384))
+                print_hashline ( md, GCRY_MD_SHA384, fname );
+              if (!gcry_md_test_algo (GCRY_MD_SHA512))
+                print_hashline ( md, GCRY_MD_SHA512, fname );
             }
         }
-        else {
-            if( algo )
-              print_hex(md,-algo,fname);
-            else {
-                print_hex( md, GCRY_MD_MD5, fname );
-                print_hex( md, GCRY_MD_SHA1, fname );
-                if (!gcry_md_test_algo (GCRY_MD_RMD160))
-                    print_hex( md, GCRY_MD_RMD160, fname );
-                if (!gcry_md_test_algo (GCRY_MD_SHA224))
-                    print_hex (md, GCRY_MD_SHA224, fname);
-                if (!gcry_md_test_algo (GCRY_MD_SHA256))
-                    print_hex( md, GCRY_MD_SHA256, fname );
-                if (!gcry_md_test_algo (GCRY_MD_SHA384))
-                    print_hex( md, GCRY_MD_SHA384, fname );
-                if (!gcry_md_test_algo (GCRY_MD_SHA512))
-                    print_hex( md, GCRY_MD_SHA512, fname );
+      else
+        {
+          if (algo)
+            print_hex (md, -algo, fname);
+          else
+            {
+              if (!gcry_md_test_algo (GCRY_MD_MD5))
+                print_hex (md, GCRY_MD_MD5, fname);
+              print_hex (md, GCRY_MD_SHA1, fname );
+              if (!gcry_md_test_algo (GCRY_MD_RMD160))
+                print_hex (md, GCRY_MD_RMD160, fname );
+              if (!gcry_md_test_algo (GCRY_MD_SHA224))
+                print_hex (md, GCRY_MD_SHA224, fname);
+              if (!gcry_md_test_algo (GCRY_MD_SHA256))
+                print_hex (md, GCRY_MD_SHA256, fname );
+              if (!gcry_md_test_algo (GCRY_MD_SHA384))
+                print_hex (md, GCRY_MD_SHA384, fname );
+              if (!gcry_md_test_algo (GCRY_MD_SHA512))
+                print_hex (md, GCRY_MD_SHA512, fname );
             }
         }
     }
-    gcry_md_close(md);
+  gcry_md_close (md);
 
-    if( fp != stdin )
-       fclose(fp);
+  if (fp != es_stdin)
+    es_fclose (fp);
 }