gpg: Remove MDC options
[gnupg.git] / g10 / gpg.c
index 7de62fd..1a419f7 100644 (file)
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -1,7 +1,7 @@
 /* gpg.c - The GnuPG utility (main for gpg)
  * Copyright (C) 1998-2011 Free Software Foundation, Inc.
- * Copyright (C) 1997-2016 Werner Koch
- * Copyright (C) 2015-2016 g10 Code GmbH
+ * Copyright (C) 1997-2017 Werner Koch
+ * Copyright (C) 2015-2017 g10 Code GmbH
  *
  * This file is part of GnuPG.
  *
 #include "gpg.h"
 #include <assuan.h>
 #include "../common/iobuf.h"
-#include "util.h"
+#include "../common/util.h"
 #include "packet.h"
-#include "membuf.h"
+#include "../common/membuf.h"
 #include "main.h"
 #include "options.h"
 #include "keydb.h"
 #include "trustdb.h"
 #include "filter.h"
-#include "ttyio.h"
-#include "i18n.h"
-#include "sysutils.h"
-#include "status.h"
+#include "../common/ttyio.h"
+#include "../common/i18n.h"
+#include "../common/sysutils.h"
+#include "../common/status.h"
 #include "keyserver-internal.h"
 #include "exec.h"
-#include "gc-opt-flags.h"
-#include "asshelp.h"
+#include "../common/gc-opt-flags.h"
+#include "../common/asshelp.h"
 #include "call-dirmngr.h"
 #include "tofu.h"
 #include "../common/init.h"
 #include "../common/mbox-util.h"
 #include "../common/shareddefs.h"
+#include "../common/compliance.h"
 
 #if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
 #define MY_O_BINARY  O_BINARY
@@ -73,6 +74,9 @@
 #define MY_O_BINARY  0
 #endif
 
+#ifdef __MINGW32__
+int _dowildcard = -1;
+#endif
 
 enum cmd_and_opt_values
   {
@@ -101,6 +105,7 @@ enum cmd_and_opt_values
     oBatch       = 500,
     oMaxOutput,
     oInputSizeHint,
+    oChunkSize,
     oSigNotation,
     oCertNotation,
     oShowNotation,
@@ -124,6 +129,7 @@ enum cmd_and_opt_values
     aQuickAddKey,
     aQuickRevUid,
     aQuickSetExpire,
+    aQuickSetPrimaryUid,
     aListConfig,
     aListGcryptConfig,
     aGPGConfList,
@@ -192,10 +198,12 @@ enum cmd_and_opt_values
     oWithSubkeyFingerprint,
     oWithICAOSpelling,
     oWithKeygrip,
+    oWithKeyScreening,
     oWithSecret,
     oWithWKDHash,
     oWithColons,
     oWithKeyData,
+    oWithKeyOrigin,
     oWithTofuInfo,
     oWithSigList,
     oWithSigCheck,
@@ -215,6 +223,7 @@ enum cmd_and_opt_values
     oDebugLevel,
     oDebugAll,
     oDebugIOLBF,
+    oDebugSetIobufSize,
     oStatusFD,
     oStatusFile,
     oAttributeFD,
@@ -238,6 +247,7 @@ enum cmd_and_opt_values
     oRFC2440Text,
     oNoRFC2440Text,
     oCipherAlgo,
+    oAEADAlgo,
     oDigestAlgo,
     oCertDigestAlgo,
     oCompressAlgo,
@@ -258,7 +268,6 @@ enum cmd_and_opt_values
     oRequireSecmem,
     oNoRequireSecmem,
     oNoPermissionWarn,
-    oNoMDCWarn,
     oNoArmor,
     oNoDefKeyring,
     oNoKeyring,
@@ -292,10 +301,7 @@ enum cmd_and_opt_values
     oShowPhotos,
     oNoShowPhotos,
     oPhotoViewer,
-    oForceMDC,
-    oNoForceMDC,
-    oDisableMDC,
-    oNoDisableMDC,
+    oForceAEAD,
     oS2KMode,
     oS2KDigest,
     oS2KCipher,
@@ -364,10 +370,12 @@ enum cmd_and_opt_values
     oDefaultPreferenceList,
     oDefaultKeyserverURL,
     oPersonalCipherPreferences,
+    oPersonalAEADPreferences,
     oPersonalDigestPreferences,
     oPersonalCompressPreferences,
     oAgentProgram,
     oDirmngrProgram,
+    oDisableDirmngr,
     oDisplay,
     oTTYname,
     oTTYtype,
@@ -414,6 +422,9 @@ enum cmd_and_opt_values
     oOnlySignTextIDs,
     oDisableSignerUID,
     oSender,
+    oKeyOrigin,
+    oRequestOrigin,
+    oNoSymkeyCache,
 
     oNoop
   };
@@ -424,7 +435,8 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_group (300, N_("@Commands:\n ")),
 
   ARGPARSE_c (aSign, "sign", N_("make a signature")),
-  ARGPARSE_c (aClearsign, "clearsign", N_("make a clear text signature")),
+  ARGPARSE_c (aClearsign, "clear-sign", N_("make a clear text signature")),
+  ARGPARSE_c (aClearsign, "clearsign", "@"),
   ARGPARSE_c (aDetachedSign, "detach-sign", N_("make a detached signature")),
   ARGPARSE_c (aEncr, "encrypt",   N_("encrypt data")),
   ARGPARSE_c (aEncrFiles, "encrypt-files", "@"),
@@ -436,24 +448,36 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_c (aVerifyFiles, "verify-files" , "@" ),
   ARGPARSE_c (aListKeys, "list-keys", N_("list keys")),
   ARGPARSE_c (aListKeys, "list-public-keys", "@" ),
-  ARGPARSE_c (aListSigs, "list-sigs", N_("list keys and signatures")),
-  ARGPARSE_c (aCheckKeys, "check-sigs",N_("list and check key signatures")),
+  ARGPARSE_c (aListSigs, "list-signatures", N_("list keys and signatures")),
+  ARGPARSE_c (aListSigs, "list-sigs", "@"),
+  ARGPARSE_c (aCheckKeys, "check-signatures",
+             N_("list and check key signatures")),
+  ARGPARSE_c (aCheckKeys, "check-sigs", "@"),
   ARGPARSE_c (oFingerprint, "fingerprint", N_("list keys and fingerprints")),
   ARGPARSE_c (aListSecretKeys, "list-secret-keys", N_("list secret keys")),
-  ARGPARSE_c (aKeygen,     "gen-key",
+  ARGPARSE_c (aKeygen,     "generate-key",
               N_("generate a new key pair")),
-  ARGPARSE_c (aQuickKeygen, "quick-gen-key" ,
+  ARGPARSE_c (aKeygen,     "gen-key", "@"),
+  ARGPARSE_c (aQuickKeygen, "quick-generate-key" ,
               N_("quickly generate a new key pair")),
-  ARGPARSE_c (aQuickAddUid,  "quick-adduid",
+  ARGPARSE_c (aQuickKeygen, "quick-gen-key", "@"),
+  ARGPARSE_c (aQuickAddUid,  "quick-add-uid",
               N_("quickly add a new user-id")),
+  ARGPARSE_c (aQuickAddUid,  "quick-adduid", "@"),
+  ARGPARSE_c (aQuickAddKey,  "quick-add-key", "@"),
   ARGPARSE_c (aQuickAddKey,  "quick-addkey", "@"),
-  ARGPARSE_c (aQuickRevUid,  "quick-revuid",
+  ARGPARSE_c (aQuickRevUid,  "quick-revoke-uid",
               N_("quickly revoke a user-id")),
+  ARGPARSE_c (aQuickRevUid,  "quick-revuid", "@"),
   ARGPARSE_c (aQuickSetExpire,  "quick-set-expire",
               N_("quickly set a new expiration date")),
-  ARGPARSE_c (aFullKeygen,  "full-gen-key" ,
+  ARGPARSE_c (aQuickSetPrimaryUid,  "quick-set-primary-uid", "@"),
+  ARGPARSE_c (aFullKeygen,  "full-generate-key" ,
               N_("full featured key pair generation")),
-  ARGPARSE_c (aGenRevoke, "gen-revoke",N_("generate a revocation certificate")),
+  ARGPARSE_c (aFullKeygen,  "full-gen-key", "@"),
+  ARGPARSE_c (aGenRevoke, "generate-revocation",
+             N_("generate a revocation certificate")),
+  ARGPARSE_c (aGenRevoke, "gen-revoke", "@"),
   ARGPARSE_c (aDeleteKeys,"delete-keys",
               N_("remove keys from the public keyring")),
   ARGPARSE_c (aDeleteSecretKeys, "delete-secret-keys",
@@ -466,7 +490,9 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_c (aLSignKey, "lsign-key"  ,N_("sign a key locally")),
   ARGPARSE_c (aEditKey,  "edit-key"   ,N_("sign or edit a key")),
   ARGPARSE_c (aEditKey,  "key-edit"   ,"@"),
-  ARGPARSE_c (aPasswd,   "passwd",     N_("change a passphrase")),
+  ARGPARSE_c (aPasswd,   "change-passphrase", N_("change a passphrase")),
+  ARGPARSE_c (aPasswd,   "passwd", "@"),
+  ARGPARSE_c (aDesigRevoke, "generate-designated-revocation", "@"),
   ARGPARSE_c (aDesigRevoke, "desig-revoke","@" ),
   ARGPARSE_c (aExport, "export"           , N_("export keys") ),
   ARGPARSE_c (aSendKeys, "send-keys"     , N_("export keys to a keyserver") ),
@@ -485,7 +511,8 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_c (aFastImport, "fast-import", "@"),
 #ifdef ENABLE_CARD_SUPPORT
   ARGPARSE_c (aCardStatus,  "card-status", N_("print the card status")),
-  ARGPARSE_c (aCardEdit,   "card-edit",  N_("change data on a card")),
+  ARGPARSE_c (aCardEdit,   "edit-card",  N_("change data on a card")),
+  ARGPARSE_c (aCardEdit,   "card-edit", "@"),
   ARGPARSE_c (aChangePIN,  "change-pin", N_("change a card's PIN")),
 #endif
   ARGPARSE_c (aListConfig, "list-config", "@"),
@@ -568,15 +595,13 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_s (oOutput, "output", N_("|FILE|write output to FILE")),
   ARGPARSE_p_u (oMaxOutput, "max-output", "@"),
   ARGPARSE_s_s (oInputSizeHint, "input-size-hint", "@"),
+  ARGPARSE_s_i (oChunkSize, "chunk-size", "@"),
 
   ARGPARSE_s_n (oVerbose, "verbose", N_("verbose")),
   ARGPARSE_s_n (oQuiet,          "quiet",   "@"),
   ARGPARSE_s_n (oNoTTY,   "no-tty",  "@"),
 
-  ARGPARSE_s_n (oForceMDC, "force-mdc", "@"),
-  ARGPARSE_s_n (oNoForceMDC, "no-force-mdc", "@"),
-  ARGPARSE_s_n (oDisableMDC, "disable-mdc", "@"),
-  ARGPARSE_s_n (oNoDisableMDC, "no-disable-mdc", "@"),
+  ARGPARSE_s_n (oForceAEAD, "force-aead", "@"),
 
   ARGPARSE_s_n (oDisableSignerUID, "disable-signer-uid", "@"),
 
@@ -594,6 +619,7 @@ static ARGPARSE_OPTS opts[] = {
 
   ARGPARSE_s_s (oKeyServer, "keyserver", "@"),
   ARGPARSE_s_s (oKeyServerOptions, "keyserver-options", "@"),
+  ARGPARSE_s_s (oKeyOrigin, "key-origin", "@"),
   ARGPARSE_s_s (oImportOptions, "import-options", "@"),
   ARGPARSE_s_s (oImportFilter,  "import-filter", "@"),
   ARGPARSE_s_s (oExportOptions, "export-options", "@"),
@@ -609,6 +635,7 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_s (oDebugLevel, "debug-level", "@"),
   ARGPARSE_s_n (oDebugAll, "debug-all", "@"),
   ARGPARSE_s_n (oDebugIOLBF, "debug-iolbf", "@"),
+  ARGPARSE_s_u (oDebugSetIobufSize, "debug-set-iobuf-size", "@"),
   ARGPARSE_s_i (oStatusFD, "status-fd", "@"),
   ARGPARSE_s_s (oStatusFile, "status-file", "@"),
   ARGPARSE_s_i (oAttributeFD, "attribute-fd", "@"),
@@ -642,6 +669,7 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_s (oS2KCipher, "s2k-cipher-algo", "@"),
   ARGPARSE_s_i (oS2KCount, "s2k-count", "@"),
   ARGPARSE_s_s (oCipherAlgo, "cipher-algo", "@"),
+  ARGPARSE_s_s (oAEADAlgo,   "aead-algo", "@"),
   ARGPARSE_s_s (oDigestAlgo, "digest-algo", "@"),
   ARGPARSE_s_s (oCertDigestAlgo, "cert-digest-algo", "@"),
   ARGPARSE_s_s (oCompressAlgo,"compress-algo", "@"),
@@ -661,7 +689,7 @@ static ARGPARSE_OPTS opts[] = {
 
   ARGPARSE_group (303, N_("@\nExamples:\n\n"
     " -se -r Bob [file]          sign and encrypt for user Bob\n"
-    " --clearsign [file]         make a clear text signature\n"
+    " --clear-sign [file]        make a clear text signature\n"
     " --detach-sign [file]       make a detached signature\n"
     " --list-keys [names]        show keys\n"
     " --fingerprint [names]      show fingerprints\n")),
@@ -683,6 +711,7 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_s (oPassphraseFile,  "passphrase-file", "@"),
   ARGPARSE_s_i (oPassphraseRepeat,"passphrase-repeat", "@"),
   ARGPARSE_s_s (oPinentryMode,    "pinentry-mode", "@"),
+  ARGPARSE_s_s (oRequestOrigin,   "request-origin", "@"),
   ARGPARSE_s_i (oCommandFD, "command-fd", "@"),
   ARGPARSE_s_s (oCommandFile, "command-file", "@"),
   ARGPARSE_s_n (oQuickRandom, "debug-quick-random", "@"),
@@ -699,7 +728,6 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oRequireSecmem, "require-secmem", "@"),
   ARGPARSE_s_n (oNoRequireSecmem, "no-require-secmem", "@"),
   ARGPARSE_s_n (oNoPermissionWarn, "no-permission-warning", "@"),
-  ARGPARSE_s_n (oNoMDCWarn, "no-mdc-warning", "@"),
   ARGPARSE_s_n (oNoArmor, "no-armor", "@"),
   ARGPARSE_s_n (oNoArmor, "no-armour", "@"),
   ARGPARSE_s_n (oNoDefKeyring, "no-default-keyring", "@"),
@@ -713,9 +741,9 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oWithKeyData,"with-key-data", "@"),
   ARGPARSE_s_n (oWithSigList,"with-sig-list", "@"),
   ARGPARSE_s_n (oWithSigCheck,"with-sig-check", "@"),
-  ARGPARSE_s_n (aListKeys, "list-key", "@"),   /* alias */
-  ARGPARSE_s_n (aListSigs, "list-sig", "@"),   /* alias */
-  ARGPARSE_s_n (aCheckKeys, "check-sig", "@"), /* alias */
+  ARGPARSE_c (aListKeys, "list-key", "@"),   /* alias */
+  ARGPARSE_c (aListSigs, "list-sig", "@"),   /* alias */
+  ARGPARSE_c (aCheckKeys, "check-sig", "@"), /* alias */
   ARGPARSE_s_n (oSkipVerify, "skip-verify", "@"),
   ARGPARSE_s_n (oSkipHiddenRecipients, "skip-hidden-recipients", "@"),
   ARGPARSE_s_n (oNoSkipHiddenRecipients, "no-skip-hidden-recipients", "@"),
@@ -760,8 +788,10 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oWithSubkeyFingerprint, "with-subkey-fingerprints", "@"),
   ARGPARSE_s_n (oWithICAOSpelling, "with-icao-spelling", "@"),
   ARGPARSE_s_n (oWithKeygrip,     "with-keygrip", "@"),
+  ARGPARSE_s_n (oWithKeyScreening,"with-key-screening", "@"),
   ARGPARSE_s_n (oWithSecret,      "with-secret", "@"),
   ARGPARSE_s_n (oWithWKDHash,     "with-wkd-hash", "@"),
+  ARGPARSE_s_n (oWithKeyOrigin,   "with-key-origin", "@"),
   ARGPARSE_s_s (oDisableCipherAlgo,  "disable-cipher-algo", "@"),
   ARGPARSE_s_s (oDisablePubkeyAlgo,  "disable-pubkey-algo", "@"),
   ARGPARSE_s_n (oAllowNonSelfsignedUID,      "allow-non-selfsigned-uid", "@"),
@@ -796,6 +826,7 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_s (oDefaultPreferenceList,  "default-preference-list", "@"),
   ARGPARSE_s_s (oDefaultKeyserverURL,  "default-keyserver-url", "@"),
   ARGPARSE_s_s (oPersonalCipherPreferences, "personal-cipher-preferences","@"),
+  ARGPARSE_s_s (oPersonalAEADPreferences, "personal-aead-preferences","@"),
   ARGPARSE_s_s (oPersonalDigestPreferences, "personal-digest-preferences","@"),
   ARGPARSE_s_s (oPersonalCompressPreferences,
                                          "personal-compress-preferences", "@"),
@@ -807,11 +838,13 @@ static ARGPARSE_OPTS opts[] = {
   /* Aliases.  I constantly mistype these, and assume other people do
      as well. */
   ARGPARSE_s_s (oPersonalCipherPreferences, "personal-cipher-prefs", "@"),
+  ARGPARSE_s_s (oPersonalAEADPreferences,   "personal-aead-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_n (oDisableDirmngr, "disable-dirmngr", "@"),
   ARGPARSE_s_s (oDisplay,    "display",    "@"),
   ARGPARSE_s_s (oTTYname,    "ttyname",    "@"),
   ARGPARSE_s_s (oTTYtype,    "ttytype",    "@"),
@@ -859,6 +892,7 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_s (oAutoKeyLocate, "auto-key-locate", "@"),
   ARGPARSE_s_n (oNoAutoKeyLocate, "no-auto-key-locate", "@"),
   ARGPARSE_s_n (oNoAutostart, "no-autostart", "@"),
+  ARGPARSE_s_n (oNoSymkeyCache, "no-symkey-cache", "@"),
 
   /* Dummy options with warnings.  */
   ARGPARSE_s_n (oUseAgent,      "use-agent", "@"),
@@ -880,6 +914,12 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oNoop, "no-force-v3-sigs", "@"),
   ARGPARSE_s_n (oNoop, "force-v4-certs", "@"),
   ARGPARSE_s_n (oNoop, "no-force-v4-certs", "@"),
+  ARGPARSE_s_n (oNoop, "no-mdc-warning", "@"),
+  ARGPARSE_s_n (oNoop, "force-mdc", "@"),
+  ARGPARSE_s_n (oNoop, "no-force-mdc", "@"),
+  ARGPARSE_s_n (oNoop, "disable-mdc", "@"),
+  ARGPARSE_s_n (oNoop, "no-disable-mdc", "@"),
+
 
   ARGPARSE_end ()
 };
@@ -898,7 +938,6 @@ static struct debug_flags_s debug_flags [] =
     { 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"  },
@@ -918,6 +957,8 @@ int g10_errors_seen = 0;
 
 static int utf8_strings = 0;
 static int maybe_setuid = 1;
+static unsigned int opt_set_iobuf_size;
+static unsigned int opt_set_iobuf_size_used;
 
 static char *build_list( const char *text, char letter,
                         const char *(*mapf)(int), int (*chkf)(int) );
@@ -980,6 +1021,18 @@ build_list_cipher_algo_name (int algo)
 }
 
 static int
+build_list_aead_test_algo (int algo)
+{
+  return openpgp_aead_test_algo (algo);
+}
+
+static const char *
+build_list_aead_algo_name (int algo)
+{
+  return openpgp_aead_algo_name (algo);
+}
+
+static int
 build_list_md_test_algo (int algo)
 {
   /* By default we do not accept MD5 based signatures.  To avoid
@@ -1000,7 +1053,7 @@ build_list_md_algo_name (int algo)
 static const char *
 my_strusage( int level )
 {
-  static char *digests, *pubkeys, *ciphers, *zips, *ver_gcry;
+  static char *digests, *pubkeys, *ciphers, *zips, *aeads, *ver_gcry;
   const char *p;
 
     switch( level ) {
@@ -1060,13 +1113,20 @@ my_strusage( int level )
        p = ciphers;
        break;
       case 36:
+       if (!aeads)
+          aeads = build_list ("AEAD: ", 'A',
+                              build_list_aead_algo_name,
+                              build_list_aead_test_algo);
+       p = aeads;
+       break;
+      case 37:
        if( !digests )
            digests = build_list(_("Hash: "), 'H',
                                  build_list_md_algo_name,
                                  build_list_md_test_algo );
        p = digests;
        break;
-      case 37:
+      case 38:
        if( !zips )
            zips = build_list(_("Compression: "),'Z',
                               compress_algo_to_string,
@@ -1087,6 +1147,7 @@ build_list (const char *text, char letter,
   membuf_t mb;
   int indent;
   int i, j, len;
+  int limit;
   const char *s;
   char *string;
 
@@ -1097,7 +1158,8 @@ build_list (const char *text, char letter,
   len = 0;
   init_membuf (&mb, 512);
 
-  for (i=0; i <= 110; i++ )
+  limit = (letter == 'A')? 4 : 110;
+  for (i=0; i <= limit; i++ )
     {
       if (!chkf (i) && (s = mapf (i)))
         {
@@ -1138,6 +1200,7 @@ static void
 wrong_args( const char *text)
 {
   es_fprintf (es_stderr, _("usage: %s [options] %s\n"), GPG_NAME, text);
+  log_inc_errorcount ();
   g10_exit(2);
 }
 
@@ -1217,6 +1280,10 @@ set_debug (const char *level)
 
   if (opt.debug)
     parse_debug_flag (NULL, &opt.debug, debug_flags);
+
+  if (opt_set_iobuf_size || opt_set_iobuf_size_used)
+    log_debug ("iobuf buffer size is %uk\n",
+               iobuf_set_buffer_size (opt_set_iobuf_size));
 }
 
 
@@ -1826,9 +1893,17 @@ gpgconf_list (const char *configfile)
   es_printf ("encrypt-to:%lu:\n", GC_OPT_FLAG_NONE);
   es_printf ("try-secret-key:%lu:\n", GC_OPT_FLAG_NONE);
   es_printf ("auto-key-locate:%lu:\n", GC_OPT_FLAG_NONE);
+  es_printf ("auto-key-retrieve:%lu:\n", GC_OPT_FLAG_NONE);
   es_printf ("log-file:%lu:\n", GC_OPT_FLAG_NONE);
   es_printf ("debug-level:%lu:\"none:\n", GC_OPT_FLAG_DEFAULT);
   es_printf ("group:%lu:\n", GC_OPT_FLAG_NONE);
+  es_printf ("compliance:%lu:\"%s:\n", GC_OPT_FLAG_DEFAULT, "gnupg");
+  es_printf ("default-new-key-algo:%lu:\n", GC_OPT_FLAG_NONE);
+  es_printf ("trust-model:%lu:\n", GC_OPT_FLAG_NONE);
+  es_printf ("disable-dirmngr:%lu:\n", GC_OPT_FLAG_NONE);
+  es_printf ("max-cert-depth:%lu:\n", GC_OPT_FLAG_NONE);
+  es_printf ("completes-needed:%lu:\n", GC_OPT_FLAG_NONE);
+  es_printf ("marginals-needed:%lu:\n", GC_OPT_FLAG_NONE);
 
   /* The next one is an info only item and should match the macros at
      the top of keygen.c  */
@@ -2050,11 +2125,8 @@ parse_tofu_policy (const char *policystr)
 }
 
 
-/* Parse the value of --compliance.  */
-static int
-parse_compliance_option (const char *string)
-{
-  struct { const char *keyword; enum cmd_and_opt_values option; } list[] = {
+static struct gnupg_compliance_option compliance_options[] =
+  {
     { "gnupg",      oGnuPG },
     { "openpgp",    oOpenPGP },
     { "rfc4880bis", oRFC4880bis },
@@ -2065,29 +2137,9 @@ parse_compliance_option (const char *string)
     { "pgp8",       oPGP8 },
     { "de-vs",      oDE_VS }
   };
-  int i;
-
-  if (!ascii_strcasecmp (string, "help"))
-    {
-      log_info (_("valid values for option '%s':\n"), "--compliance");
-      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 (string, list[i].keyword))
-      return list[i].option;
-
-  log_error (_("invalid value for option '%s'\n"), "--compliance");
-  if (!opt.quiet)
-    log_info (_("(use \"help\" to list choices)\n"));
-  g10_exit (1);
-}
 
 
-
-/* Helper to set compliance related options.  This is a separte
+/* Helper to set compliance related options.  This is a separate
  * function so that it can also be used by the --compliance option
  * parser.  */
 static void
@@ -2112,6 +2164,7 @@ set_compliance_option (enum cmd_and_opt_values option)
       opt.escape_from = 1;
       opt.not_dash_escaped = 0;
       opt.def_cipher_algo = 0;
+      opt.def_aead_algo = 0;
       opt.def_digest_algo = 0;
       opt.cert_digest_algo = 0;
       opt.compress_algo = -1;
@@ -2128,6 +2181,7 @@ set_compliance_option (enum cmd_and_opt_values option)
       opt.escape_from = 0;
       opt.not_dash_escaped = 0;
       opt.def_cipher_algo = 0;
+      opt.def_aead_algo = 0;
       opt.def_digest_algo = 0;
       opt.cert_digest_algo = 0;
       opt.compress_algo = -1;
@@ -2143,6 +2197,7 @@ set_compliance_option (enum cmd_and_opt_values option)
     case oDE_VS:
       set_compliance_option (oOpenPGP);
       opt.compliance = CO_DE_VS;
+      opt.def_aead_algo = 0;
       /* Fixme: Change other options.  */
       break;
 
@@ -2162,7 +2217,7 @@ set_compliance_option (enum cmd_and_opt_values option)
 static void
 gpg_init_default_ctrl (ctrl_t ctrl)
 {
-  (void)ctrl;
+  ctrl->magic = SERVER_CONTROL_MAGIC;
 }
 
 
@@ -2175,6 +2230,8 @@ gpg_deinit_default_ctrl (ctrl_t ctrl)
   tofu_closedbs (ctrl);
 #endif
   gpg_dirmngr_deinit_session_data (ctrl);
+
+  keydb_release (ctrl->cached_getkey_kdb);
 }
 
 
@@ -2270,12 +2327,14 @@ main (int argc, char **argv)
     const char *trustdb_name = NULL;
 #endif /*!NO_TRUST_MODELS*/
     char *def_cipher_string = NULL;
+    char *def_aead_string = NULL;
     char *def_digest_string = NULL;
     char *compress_algo_string = NULL;
     char *cert_digest_string = NULL;
     char *s2k_cipher_string = NULL;
     char *s2k_digest_string = NULL;
     char *pers_cipher_list = NULL;
+    char *pers_aead_list = NULL;
     char *pers_digest_list = NULL;
     char *pers_compress_list = NULL;
     int eyes_only=0;
@@ -2284,6 +2343,7 @@ main (int argc, char **argv)
     int ovrseskeyfd = -1;
     int fpr_maybe_cmd = 0; /* --fingerprint maybe a command.  */
     int any_explicit_recipient = 0;
+    int default_akl = 1;
     int require_secmem = 0;
     int got_secmem = 0;
     struct assuan_malloc_hooks malloc_hooks;
@@ -2324,6 +2384,9 @@ main (int argc, char **argv)
 
     dotlock_create (NULL, 0); /* Register lock file cleanup. */
 
+    /* Tell the compliance module who we are.  */
+    gnupg_initialize_compliance (GNUPG_MODULE_NAME_GPG);
+
     opt.autostart = 1;
     opt.session_env = session_env_new ();
     if (!opt.session_env)
@@ -2335,6 +2398,7 @@ main (int argc, char **argv)
     opt.bz2_compress_level = -1; /* defaults to standard compress level */
     /* note: if you change these lines, look at oOpenPGP */
     opt.def_cipher_algo = 0;
+    opt.def_aead_algo = 0;
     opt.def_digest_algo = 0;
     opt.cert_digest_algo = 0;
     opt.compress_algo = -1; /* defaults to DEFAULT_COMPRESS_ALGO */
@@ -2346,9 +2410,10 @@ main (int argc, char **argv)
     opt.max_cert_depth = 5;
     opt.escape_from = 1;
     opt.flags.require_cross_cert = 1;
-    opt.import_options = 0;
+    opt.import_options = IMPORT_REPAIR_KEYS;
     opt.export_options = EXPORT_ATTRIBUTES;
-    opt.keyserver_options.import_options = IMPORT_REPAIR_PKS_SUBKEY_BUG;
+    opt.keyserver_options.import_options = (IMPORT_REPAIR_KEYS
+                                           | IMPORT_REPAIR_PKS_SUBKEY_BUG);
     opt.keyserver_options.export_options = EXPORT_ATTRIBUTES;
     opt.keyserver_options.options = KEYSERVER_HONOR_PKA_RECORD;
     opt.verify_options = (LIST_SHOW_UID_VALIDITY
@@ -2373,7 +2438,6 @@ main (int argc, char **argv)
     opt.passphrase_repeat = 1;
     opt.emit_version = 0;
     opt.weak_digests = NULL;
-    additional_weak_digest("MD5");
 
     /* Check whether we have a config file on the command line.  */
     orig_argc = argc;
@@ -2449,6 +2513,10 @@ main (int argc, char **argv)
     assuan_set_gpg_err_source (GPG_ERR_SOURCE_DEFAULT);
     setup_libassuan_logging (&opt.debug, NULL);
 
+    /* Set default options which require that malloc stuff is ready.  */
+    additional_weak_digest ("MD5");
+    parse_auto_key_locate ("local,wkd");
+
     /* Try for a version specific config file first */
     default_configname = get_default_configname ();
     if (default_config)
@@ -2563,6 +2631,7 @@ main (int argc, char **argv)
          case aQuickAddKey:
          case aQuickRevUid:
          case aQuickSetExpire:
+         case aQuickSetPrimaryUid:
          case aExportOwnerTrust:
          case aImportOwnerTrust:
           case aRebuildKeydbCaches:
@@ -2609,6 +2678,10 @@ main (int argc, char **argv)
             opt.input_size_hint = string_to_u64 (pargs.r.ret_str);
             break;
 
+          case oChunkSize:
+            opt.chunk_size = pargs.r.ret_int;
+            break;
+
          case oQuiet: opt.quiet = 1; break;
          case oNoTTY: tty_no_terminal(1); break;
          case oDryRun: opt.dry_run = 1; break;
@@ -2676,6 +2749,11 @@ main (int argc, char **argv)
 
           case oDebugIOLBF: break; /* Already set in pre-parse step.  */
 
+          case oDebugSetIobufSize:
+            opt_set_iobuf_size = pargs.r.ret_ulong;
+            opt_set_iobuf_size_used = 1;
+            break;
+
          case oStatusFD:
             set_status_fd ( translate_sys2libc_fd_int (pargs.r.ret_int, 1) );
             break;
@@ -2714,6 +2792,10 @@ main (int argc, char **argv)
             opt.with_keygrip = 1;
             break;
 
+         case oWithKeyScreening:
+            opt.with_key_screening = 1;
+            break;
+
          case oWithSecret:
             opt.with_secret = 1;
             break;
@@ -2722,6 +2804,10 @@ main (int argc, char **argv)
             opt.with_wkd_hash = 1;
             break;
 
+         case oWithKeyOrigin:
+            opt.with_key_origin = 1;
+            break;
+
          case oSecretKeyring:
             /* Ignore this old option.  */
             break;
@@ -2835,7 +2921,15 @@ main (int argc, char **argv)
            break;
 
           case oCompliance:
-            set_compliance_option (parse_compliance_option (pargs.r.ret_str));
+           {
+             int compliance = gnupg_parse_compliance_option
+                (pargs.r.ret_str,
+                 compliance_options, DIM (compliance_options),
+                 opt.quiet);
+             if (compliance < 0)
+               g10_exit (1);
+             set_compliance_option (compliance);
+           }
             break;
           case oOpenPGP:
           case oRFC2440:
@@ -2920,10 +3014,7 @@ main (int argc, char **argv)
            break;
          case oPhotoViewer: opt.photo_viewer = pargs.r.ret_str; break;
 
-         case oForceMDC: opt.force_mdc = 1; break;
-         case oNoForceMDC: opt.force_mdc = 0; break;
-         case oDisableMDC: opt.disable_mdc = 1; break;
-         case oNoDisableMDC: opt.disable_mdc = 0; break;
+         case oForceAEAD: opt.force_aead = 1; break;
 
           case oDisableSignerUID: opt.flags.disable_signer_uid = 1; break;
 
@@ -3061,8 +3152,16 @@ main (int argc, char **argv)
               log_error (_("invalid pinentry mode '%s'\n"), pargs.r.ret_str);
            break;
 
+          case oRequestOrigin:
+           opt.request_origin = parse_request_origin (pargs.r.ret_str);
+           if (opt.request_origin == -1)
+              log_error (_("invalid request origin '%s'\n"), pargs.r.ret_str);
+           break;
+
          case oCommandFD:
             opt.command_fd = translate_sys2libc_fd_int (pargs.r.ret_int, 0);
+           if (! gnupg_fd_valid (opt.command_fd))
+             log_error ("command-fd is invalid: %s\n", strerror (errno));
             break;
          case oCommandFile:
             opt.command_fd = open_info_file (pargs.r.ret_str, 0, 1);
@@ -3070,6 +3169,9 @@ main (int argc, char **argv)
          case oCipherAlgo:
             def_cipher_string = xstrdup(pargs.r.ret_str);
             break;
+         case oAEADAlgo:
+            def_aead_string = xstrdup (pargs.r.ret_str);
+            break;
          case oDigestAlgo:
             def_digest_string = xstrdup(pargs.r.ret_str);
             break;
@@ -3108,7 +3210,6 @@ main (int argc, char **argv)
          case oRequireSecmem: require_secmem=1; break;
          case oNoRequireSecmem: require_secmem=0; break;
          case oNoPermissionWarn: opt.no_perm_warn=1; break;
-         case oNoMDCWarn: opt.no_mdc_warn=1; break;
           case oDisplayCharset:
            if( set_native_charset( pargs.r.ret_str ) )
                log_error(_("'%s' is not a valid character set\n"),
@@ -3299,13 +3400,14 @@ main (int argc, char **argv)
          case oIgnoreCrcError: opt.ignore_crc_error = 1; break;
          case oIgnoreMDCError: opt.ignore_mdc_error = 1; break;
          case oNoRandomSeedFile: use_random_seed = 0; break;
+
          case oAutoKeyRetrieve:
+            opt.keyserver_options.options |= KEYSERVER_AUTO_KEY_RETRIEVE;
+            break;
          case oNoAutoKeyRetrieve:
-               if(pargs.r_opt==oAutoKeyRetrieve)
-                 opt.keyserver_options.options|=KEYSERVER_AUTO_KEY_RETRIEVE;
-               else
-                 opt.keyserver_options.options&=~KEYSERVER_AUTO_KEY_RETRIEVE;
-               break;
+            opt.keyserver_options.options &= ~KEYSERVER_AUTO_KEY_RETRIEVE;
+            break;
+
          case oShowSessionKey: opt.show_session_key = 1; break;
          case oOverrideSessionKey:
                opt.override_session_key = pargs.r.ret_str;
@@ -3348,6 +3450,9 @@ main (int argc, char **argv)
           case oPersonalCipherPreferences:
            pers_cipher_list=pargs.r.ret_str;
            break;
+          case oPersonalAEADPreferences:
+           pers_aead_list = pargs.r.ret_str;
+           break;
           case oPersonalDigestPreferences:
            pers_digest_list=pargs.r.ret_str;
            break;
@@ -3356,6 +3461,7 @@ main (int argc, char **argv)
            break;
           case oAgentProgram: opt.agent_program = pargs.r.ret_str;  break;
           case oDirmngrProgram: opt.dirmngr_program = pargs.r.ret_str; break;
+         case oDisableDirmngr: opt.disable_dirmngr = 1;  break;
           case oWeakDigest:
            additional_weak_digest(pargs.r.ret_str);
            break;
@@ -3430,6 +3536,13 @@ main (int argc, char **argv)
          case oNoRequireCrossCert: opt.flags.require_cross_cert=0; break;
 
          case oAutoKeyLocate:
+            if (default_akl)
+              {
+                /* This is the first time --aito-key-locate is seen.
+                 * We need to reset the default akl.  */
+                default_akl = 0;
+                release_akl();
+              }
            if(!parse_auto_key_locate(pargs.r.ret_str))
              {
                if(configname)
@@ -3443,6 +3556,12 @@ main (int argc, char **argv)
            release_akl();
            break;
 
+         case oKeyOrigin:
+           if(!parse_key_origin (pargs.r.ret_str))
+              log_error (_("invalid argument for option \"%.50s\"\n"),
+                         "--key-origin");
+           break;
+
          case oEnableLargeRSA:
 #if SECMEM_BUFFER_SIZE >= 65536
             opt.flags.large_rsa=1;
@@ -3477,14 +3596,25 @@ main (int argc, char **argv)
 
           case oFakedSystemTime:
             {
-              time_t faked_time = isotime2epoch (pargs.r.ret_str);
+              size_t len = strlen (pargs.r.ret_str);
+              int freeze = 0;
+              time_t faked_time;
+
+              if (len > 0 && pargs.r.ret_str[len-1] == '!')
+                {
+                  freeze = 1;
+                  pargs.r.ret_str[len-1] = '\0';
+                }
+
+              faked_time = isotime2epoch (pargs.r.ret_str);
               if (faked_time == (time_t)(-1))
                 faked_time = (time_t)strtoul (pargs.r.ret_str, NULL, 10);
-              gnupg_set_time (faked_time, 0);
+              gnupg_set_time (faked_time, freeze);
             }
             break;
 
           case oNoAutostart: opt.autostart = 0; break;
+          case oNoSymkeyCache: opt.no_symkey_cache = 1; break;
 
          case oDefaultNewKeyAlgo:
             opt.def_new_key_algo = pargs.r.ret_str;
@@ -3493,7 +3623,16 @@ main (int argc, char **argv)
          case oNoop: break;
 
          default:
-            pargs.err = configfp? ARGPARSE_PRINT_WARNING:ARGPARSE_PRINT_ERROR;
+            if (configfp)
+              pargs.err = ARGPARSE_PRINT_WARNING;
+            else
+              {
+                pargs.err = ARGPARSE_PRINT_ERROR;
+                /* The argparse fucntion calls a plain exit and thus
+                 * we need to print a status here.  */
+                write_status_failure ("option-parser",
+                                      gpg_error(GPG_ERR_GENERAL));
+              }
             break;
          }
       }
@@ -3512,7 +3651,10 @@ main (int argc, char **argv)
       }
     xfree(configname); configname = NULL;
     if (log_get_errorcount (0))
-      g10_exit(2);
+      {
+        write_status_failure ("option-parser", gpg_error(GPG_ERR_GENERAL));
+        g10_exit(2);
+      }
 
     /* The command --gpgconf-list is pretty simple and may be called
        directly after the option parsing. */
@@ -3533,7 +3675,10 @@ main (int argc, char **argv)
                  "--print-pks-records",
                  "--export-options export-pka");
     if (log_get_errorcount (0))
-      g10_exit(2);
+      {
+        write_status_failure ("option-checking", gpg_error(GPG_ERR_GENERAL));
+        g10_exit(2);
+      }
 
 
     if( nogreeting )
@@ -3634,6 +3779,7 @@ main (int argc, char **argv)
       {
        log_info(_("will not run with insecure memory due to %s\n"),
                 "--require-secmem");
+        write_status_failure ("option-checking", gpg_error(GPG_ERR_GENERAL));
        g10_exit(2);
       }
 
@@ -3646,7 +3792,6 @@ main (int argc, char **argv)
       {
         /* That does not anymore work because we have no more support
            for v3 signatures.  */
-       opt.disable_mdc=1;
        opt.escape_from=1;
        opt.ask_sig_expire=0;
       }
@@ -3669,6 +3814,13 @@ main (int argc, char **argv)
        if ( openpgp_cipher_test_algo (opt.def_cipher_algo) )
            log_error(_("selected cipher algorithm is invalid\n"));
     }
+    if (def_aead_string)
+      {
+       opt.def_aead_algo = string_to_aead_algo (def_aead_string);
+       xfree (def_aead_string); def_aead_string = NULL;
+       if (openpgp_aead_test_algo (opt.def_aead_algo))
+          log_error(_("selected AEAD algorithm is invalid\n"));
+      }
     if( def_digest_string ) {
        opt.def_digest_algo = string_to_digest_algo (def_digest_string);
        xfree(def_digest_string); def_digest_string = NULL;
@@ -3728,6 +3880,9 @@ main (int argc, char **argv)
        keygen_set_std_prefs(pers_cipher_list,PREFTYPE_SYM))
       log_error(_("invalid personal cipher preferences\n"));
 
+    if (pers_aead_list && keygen_set_std_prefs (pers_aead_list, PREFTYPE_AEAD))
+      log_error(_("invalid personal AEAD preferences\n"));
+
     if(pers_digest_list &&
        keygen_set_std_prefs(pers_digest_list,PREFTYPE_HASH))
       log_error(_("invalid personal digest preferences\n"));
@@ -3736,6 +3891,21 @@ main (int argc, char **argv)
        keygen_set_std_prefs(pers_compress_list,PREFTYPE_ZIP))
       log_error(_("invalid personal compress preferences\n"));
 
+    /* Check chunk size.  Please fix also the man page if you chnage
+     * the default.  The limits are given by the specs.  */
+    if (!opt.chunk_size)
+      opt.chunk_size = 30; /* Default to 1 GiB chunks.  */
+    else if (opt.chunk_size < 6)
+      {
+        opt.chunk_size = 6;
+        log_info (_("chunk size invalid - using %d\n"), opt.chunk_size);
+      }
+    else if (opt.chunk_size > 62)
+      {
+        opt.chunk_size = 62;
+        log_info (_("chunk size invalid - using %d\n"), opt.chunk_size);
+      }
+
     /* We don't support all possible commands with multifile yet */
     if(multifile)
       {
@@ -3750,7 +3920,7 @@ main (int argc, char **argv)
            cmdname="--sign --encrypt";
            break;
          case aClearsign:
-           cmdname="--clearsign";
+           cmdname="--clear-sign";
            break;
          case aDetachedSign:
            cmdname="--detach-sign";
@@ -3774,7 +3944,11 @@ main (int argc, char **argv)
       }
 
     if( log_get_errorcount(0) )
-       g10_exit(2);
+      {
+        write_status_failure ("option-postprocessing",
+                              gpg_error(GPG_ERR_GENERAL));
+       g10_exit (2);
+      }
 
     if(opt.compress_level==0)
       opt.compress_algo=COMPRESS_ALGO_NONE;
@@ -3782,7 +3956,7 @@ main (int argc, char **argv)
     /* Check our chosen algorithms against the list of legal
        algorithms. */
 
-    if(!GNUPG)
+    if(!GNUPG && !opt.flags.rfc4880bis)
       {
        const char *badalg=NULL;
        preftype_t badtype=PREFTYPE_NONE;
@@ -3793,6 +3967,12 @@ main (int argc, char **argv)
            badalg = openpgp_cipher_algo_name (opt.def_cipher_algo);
            badtype = PREFTYPE_SYM;
          }
+       else if(opt.def_aead_algo
+          && !algo_available(PREFTYPE_AEAD, opt.def_aead_algo, NULL))
+         {
+           badalg = openpgp_aead_algo_name (opt.def_aead_algo);
+           badtype = PREFTYPE_AEAD;
+         }
        else if(opt.def_digest_algo
                && !algo_available(PREFTYPE_HASH,opt.def_digest_algo,NULL))
          {
@@ -3817,19 +3997,28 @@ main (int argc, char **argv)
            switch(badtype)
              {
              case PREFTYPE_SYM:
-               log_info(_("you may not use cipher algorithm '%s'"
-                          " while in %s mode\n"),
-                        badalg,compliance_option_string());
+               log_info (_("cipher algorithm '%s'"
+                            " may not be used in %s mode\n"),
+                        badalg,
+                          gnupg_compliance_option_string (opt.compliance));
+               break;
+             case PREFTYPE_AEAD:
+               log_info (_("AEAD algorithm '%s'"
+                            " may not be used in %s mode\n"),
+                          badalg,
+                          gnupg_compliance_option_string (opt.compliance));
                break;
              case PREFTYPE_HASH:
-               log_info(_("you may not use digest algorithm '%s'"
-                          " while in %s mode\n"),
-                        badalg,compliance_option_string());
+               log_info (_("digest algorithm '%s'"
+                            " may not be used in %s mode\n"),
+                          badalg,
+                          gnupg_compliance_option_string (opt.compliance));
                break;
              case PREFTYPE_ZIP:
-               log_info(_("you may not use compression algorithm '%s'"
-                          " while in %s mode\n"),
-                        badalg,compliance_option_string());
+               log_info (_("compression algorithm '%s'"
+                            " may not be used in %s mode\n"),
+                          badalg,
+                          gnupg_compliance_option_string (opt.compliance));
                break;
              default:
                BUG();
@@ -3839,6 +4028,45 @@ main (int argc, char **argv)
          }
       }
 
+    /* Check our chosen algorithms against the list of allowed
+     * algorithms in the current compliance mode, and fail hard if it
+     * is not.  This is us being nice to the user informing her early
+     * that the chosen algorithms are not available.  We also check
+     * and enforce this right before the actual operation.  */
+    /* FIXME: We also need to check the AEAD algo. */
+    if (opt.def_cipher_algo
+       && ! gnupg_cipher_is_allowed (opt.compliance,
+                                     cmd == aEncr
+                                     || cmd == aSignEncr
+                                     || cmd == aEncrSym
+                                     || cmd == aSym
+                                     || cmd == aSignSym
+                                     || cmd == aSignEncrSym,
+                                     opt.def_cipher_algo,
+                                     GCRY_CIPHER_MODE_NONE))
+      log_error (_("cipher algorithm '%s' may not be used in %s mode\n"),
+                openpgp_cipher_algo_name (opt.def_cipher_algo),
+                gnupg_compliance_option_string (opt.compliance));
+
+    if (opt.def_digest_algo
+       && ! gnupg_digest_is_allowed (opt.compliance,
+                                     cmd == aSign
+                                     || cmd == aSignEncr
+                                     || cmd == aSignEncrSym
+                                     || cmd == aSignSym
+                                     || cmd == aClearsign,
+                                     opt.def_digest_algo))
+      log_error (_("digest algorithm '%s' may not be used in %s mode\n"),
+                gcry_md_algo_name (opt.def_digest_algo),
+                gnupg_compliance_option_string (opt.compliance));
+
+    /* Fail hard.  */
+    if (log_get_errorcount (0))
+      {
+        write_status_failure ("option-checking", gpg_error(GPG_ERR_GENERAL));
+       g10_exit (2);
+      }
+
     /* Set the random seed file. */
     if( use_random_seed ) {
       char *p = make_filename (gnupg_homedir (), "random_seed", NULL );
@@ -3919,6 +4147,11 @@ main (int argc, char **argv)
       case aListTrustDB:
         rc = setup_trustdb (argc? 1:0, trustdb_name);
         break;
+      case aKeygen:
+      case aFullKeygen:
+      case aQuickKeygen:
+        rc = setup_trustdb (1, trustdb_name);
+        break;
       default:
         /* If we are using TM_ALWAYS, we do not need to create the
            trustdb.  */
@@ -3967,6 +4200,7 @@ main (int argc, char **argv)
       case aQuickAddUid:
       case aQuickAddKey:
       case aQuickRevUid:
+      case aQuickSetPrimaryUid:
       case aFullKeygen:
       case aKeygen:
       case aImport:
@@ -3995,7 +4229,7 @@ main (int argc, char **argv)
 
       case aStore: /* only store the file */
        if( argc > 1 )
-           wrong_args(_("--store [filename]"));
+           wrong_args("--store [filename]");
        if( (rc = encrypt_store(fname)) )
           {
             write_status_failure ("store", rc);
@@ -4005,7 +4239,7 @@ main (int argc, char **argv)
        break;
       case aSym: /* encrypt the given file only with the symmetric cipher */
        if( argc > 1 )
-           wrong_args(_("--symmetric [filename]"));
+           wrong_args("--symmetric [filename]");
        if( (rc = encrypt_symmetric(fname)) )
           {
             write_status_failure ("symencrypt", rc);
@@ -4020,7 +4254,7 @@ main (int argc, char **argv)
        else
          {
            if( argc > 1 )
-             wrong_args(_("--encrypt [filename]"));
+             wrong_args("--encrypt [filename]");
            if( (rc = encrypt_crypt (ctrl, -1, fname, remusr, 0, NULL, -1)) )
               {
                 write_status_failure ("encrypt", rc);
@@ -4036,13 +4270,14 @@ main (int argc, char **argv)
           might work with 7, but alas, I don't have a copy to test
           with right now. */
        if( argc > 1 )
-         wrong_args(_("--symmetric --encrypt [filename]"));
+         wrong_args("--symmetric --encrypt [filename]");
        else if(opt.s2k_mode==0)
          log_error(_("you cannot use --symmetric --encrypt"
                      " with --s2k-mode 0\n"));
        else if(PGP6 || PGP7)
          log_error(_("you cannot use --symmetric --encrypt"
-                     " while in %s mode\n"),compliance_option_string());
+                     " in %s mode\n"),
+                   gnupg_compliance_option_string (opt.compliance));
        else
          {
            if( (rc = encrypt_crypt (ctrl, -1, fname, remusr, 1, NULL, -1)) )
@@ -4062,7 +4297,7 @@ main (int argc, char **argv)
        }
        else {
            if( argc > 1 )
-               wrong_args(_("--sign [filename]"));
+               wrong_args("--sign [filename]");
            if( argc ) {
                sl = xmalloc_clear( sizeof *sl + strlen(fname));
                strcpy(sl->d, fname);
@@ -4078,7 +4313,7 @@ main (int argc, char **argv)
 
       case aSignEncr: /* sign and encrypt the given file */
        if( argc > 1 )
-           wrong_args(_("--sign --encrypt [filename]"));
+           wrong_args("--sign --encrypt [filename]");
        if( argc ) {
            sl = xmalloc_clear( sizeof *sl + strlen(fname));
            strcpy(sl->d, fname);
@@ -4096,13 +4331,14 @@ main (int argc, char **argv)
 
       case aSignEncrSym: /* sign and encrypt the given file */
        if( argc > 1 )
-           wrong_args(_("--symmetric --sign --encrypt [filename]"));
+           wrong_args("--symmetric --sign --encrypt [filename]");
        else if(opt.s2k_mode==0)
          log_error(_("you cannot use --symmetric --sign --encrypt"
                      " with --s2k-mode 0\n"));
        else if(PGP6 || PGP7)
          log_error(_("you cannot use --symmetric --sign --encrypt"
-                     " while in %s mode\n"),compliance_option_string());
+                     " in %s mode\n"),
+                   gnupg_compliance_option_string (opt.compliance));
        else
          {
            if( argc )
@@ -4125,7 +4361,7 @@ main (int argc, char **argv)
 
       case aSignSym: /* sign and conventionally encrypt the given file */
        if (argc > 1)
-           wrong_args(_("--sign --symmetric [filename]"));
+           wrong_args("--sign --symmetric [filename]");
        rc = sign_symencrypt_file (ctrl, fname, locusr);
         if (rc)
           {
@@ -4137,11 +4373,11 @@ main (int argc, char **argv)
 
       case aClearsign: /* make a clearsig */
        if( argc > 1 )
-           wrong_args(_("--clearsign [filename]"));
+           wrong_args("--clear-sign [filename]");
        if( (rc = clearsign_file (ctrl, fname, locusr, NULL)) )
           {
             write_status_failure ("sign", rc);
-           log_error("%s: clearsign failed: %s\n",
+           log_error("%s: clear-sign failed: %s\n",
                       print_fname_stdin(fname), gpg_strerror (rc) );
           }
        break;
@@ -4167,7 +4403,7 @@ main (int argc, char **argv)
        else
          {
            if( argc > 1 )
-             wrong_args(_("--decrypt [filename]"));
+             wrong_args("--decrypt [filename]");
            if( (rc = decrypt_message (ctrl, fname) ))
               {
                 write_status_failure ("decrypt", rc);
@@ -4194,11 +4430,11 @@ main (int argc, char **argv)
 
       case aSignKey:
        if( argc != 1 )
-         wrong_args(_("--sign-key user-id"));
+         wrong_args("--sign-key user-id");
        /* fall through */
       case aLSignKey:
        if( argc != 1 )
-         wrong_args(_("--lsign-key user-id"));
+         wrong_args("--lsign-key user-id");
        /* fall through */
 
        sl=NULL;
@@ -4219,7 +4455,7 @@ main (int argc, char **argv)
 
       case aEditKey: /* Edit a key signature */
        if( !argc )
-           wrong_args(_("--edit-key user-id [commands]"));
+           wrong_args("--edit-key user-id [commands]");
        username = make_username( fname );
        if( argc > 1 ) {
            sl = NULL;
@@ -4235,7 +4471,7 @@ main (int argc, char **argv)
 
       case aPasswd:
         if (argc != 1)
-          wrong_args (_("--passwd <user-id>"));
+          wrong_args("--change-passphrase <user-id>");
         else
           {
             username = make_username (fname);
@@ -4253,14 +4489,15 @@ main (int argc, char **argv)
            proper order :) */
        for( ; argc; argc-- )
          add_to_strlist2( &sl, argv[argc-1], utf8_strings );
-       delete_keys(sl,cmd==aDeleteSecretKeys,cmd==aDeleteSecretAndPublicKeys);
+       delete_keys (ctrl, sl,
+                     cmd==aDeleteSecretKeys, cmd==aDeleteSecretAndPublicKeys);
        free_strlist(sl);
        break;
 
       case aCheckKeys:
-       opt.check_sigs = 1;
+       opt.check_sigs = 1; /* fall through */
       case aListSigs:
-       opt.list_sigs = 1;
+       opt.list_sigs = 1; /* fall through */
       case aListKeys:
        sl = NULL;
        for( ; argc; argc--, argv++ )
@@ -4288,7 +4525,7 @@ main (int argc, char **argv)
           const char *x_algo, *x_usage, *x_expire;
 
           if (argc < 1 || argc > 4)
-            wrong_args("--quick-gen-key USER-ID [ALGO [USAGE [EXPIRE]]]");
+            wrong_args("--quick-generate-key USER-ID [ALGO [USAGE [EXPIRE]]]");
           username = make_username (fname);
           argv++, argc--;
           x_algo = "";
@@ -4314,20 +4551,20 @@ main (int argc, char **argv)
       case aKeygen: /* generate a key */
        if( opt.batch ) {
            if( argc > 1 )
-               wrong_args("--gen-key [parameterfile]");
+               wrong_args("--generate-key [parameterfile]");
            generate_keypair (ctrl, 0, argc? *argv : NULL, NULL, 0);
        }
        else {
             if (opt.command_fd != -1 && argc)
               {
                 if( argc > 1 )
-                  wrong_args("--gen-key [parameterfile]");
+                  wrong_args("--generate-key [parameterfile]");
 
                 opt.batch = 1;
                 generate_keypair (ctrl, 0, argc? *argv : NULL, NULL, 0);
               }
             else if (argc)
-              wrong_args ("--gen-key");
+              wrong_args ("--generate-key");
             else
               generate_keypair (ctrl, 0, NULL, NULL, 0);
        }
@@ -4337,13 +4574,13 @@ main (int argc, char **argv)
        if (opt.batch)
           {
            if (argc > 1)
-              wrong_args ("--full-gen-key [parameterfile]");
+              wrong_args ("--full-generate-key [parameterfile]");
            generate_keypair (ctrl, 1, argc? *argv : NULL, NULL, 0);
           }
        else
           {
            if (argc)
-              wrong_args("--full-gen-key");
+              wrong_args("--full-generate-key");
            generate_keypair (ctrl, 1, NULL, NULL, 0);
        }
        break;
@@ -4353,7 +4590,7 @@ main (int argc, char **argv)
           const char *uid, *newuid;
 
           if (argc != 2)
-            wrong_args ("--quick-adduid USER-ID NEW-USER-ID");
+            wrong_args ("--quick-add-uid USER-ID NEW-USER-ID");
           uid = *argv++; argc--;
           newuid = *argv++; argc--;
           keyedit_quick_adduid (ctrl, uid, newuid);
@@ -4365,7 +4602,7 @@ main (int argc, char **argv)
           const char *x_fpr, *x_algo, *x_usage, *x_expire;
 
           if (argc < 1 || argc > 4)
-            wrong_args ("--quick-addkey FINGERPRINT [ALGO [USAGE [EXPIRE]]]");
+            wrong_args ("--quick-add-key FINGERPRINT [ALGO [USAGE [EXPIRE]]]");
           x_fpr = *argv++; argc--;
           x_algo = "";
           x_usage = "";
@@ -4391,7 +4628,7 @@ main (int argc, char **argv)
           const char *uid, *uidtorev;
 
           if (argc != 2)
-            wrong_args ("--quick-revuid USER-ID USER-ID-TO-REVOKE");
+            wrong_args ("--quick-revoke-uid USER-ID USER-ID-TO-REVOKE");
           uid = *argv++; argc--;
           uidtorev = *argv++; argc--;
           keyedit_quick_revuid (ctrl, uid, uidtorev);
@@ -4402,18 +4639,31 @@ main (int argc, char **argv)
         {
           const char *x_fpr, *x_expire;
 
-          if (argc != 2)
-            wrong_args ("--quick-set-exipre FINGERPRINT EXPIRE");
+          if (argc < 2)
+            wrong_args ("--quick-set-exipre FINGERPRINT EXPIRE [SUBKEY-FPRS]");
           x_fpr = *argv++; argc--;
           x_expire = *argv++; argc--;
-          keyedit_quick_set_expire (ctrl, x_fpr, x_expire);
+          keyedit_quick_set_expire (ctrl, x_fpr, x_expire, argv);
+        }
+       break;
+
+      case aQuickSetPrimaryUid:
+        {
+          const char *uid, *primaryuid;
+
+          if (argc != 2)
+            wrong_args ("--quick-set-primary-uid USER-ID PRIMARY-USER-ID");
+          uid = *argv++; argc--;
+          primaryuid = *argv++; argc--;
+          keyedit_quick_set_primary (ctrl, uid, primaryuid);
         }
        break;
 
       case aFastImport:
-        opt.import_options |= IMPORT_FAST;
+        opt.import_options |= IMPORT_FAST; /* fall through */
       case aImport:
-       import_keys (ctrl, argc? argv:NULL, argc, NULL, opt.import_options);
+       import_keys (ctrl, argc? argv:NULL, argc, NULL,
+                     opt.import_options, opt.key_origin, opt.key_origin_url);
        break;
 
        /* TODO: There are a number of command that use this same
@@ -4501,7 +4751,7 @@ main (int argc, char **argv)
        sl = NULL;
        for( ; argc; argc--, argv++ )
            append_to_strlist2( &sl, *argv, utf8_strings );
-       rc = keyserver_fetch (ctrl, sl);
+       rc = keyserver_fetch (ctrl, sl, opt.key_origin);
        if(rc)
           {
             write_status_failure ("fetch-keys", rc);
@@ -4516,7 +4766,7 @@ main (int argc, char **argv)
            add_to_strlist2( &sl, *argv, utf8_strings );
         {
           export_stats_t stats = export_new_stats ();
-          export_seckeys (ctrl, sl, stats);
+          export_seckeys (ctrl, sl, opt.export_options, stats);
           export_print_stats (stats);
           export_release_stats (stats);
         }
@@ -4529,7 +4779,7 @@ main (int argc, char **argv)
            add_to_strlist2( &sl, *argv, utf8_strings );
         {
           export_stats_t stats = export_new_stats ();
-          export_secsubkeys (ctrl, sl, stats);
+          export_secsubkeys (ctrl, sl, opt.export_options, stats);
           export_print_stats (stats);
           export_release_stats (stats);
         }
@@ -4538,15 +4788,15 @@ main (int argc, char **argv)
 
       case aGenRevoke:
        if( argc != 1 )
-           wrong_args("--gen-revoke user-id");
+           wrong_args("--generate-revocation user-id");
        username =  make_username(*argv);
-       gen_revoke( username );
+       gen_revoke (ctrl, username );
        xfree( username );
        break;
 
       case aDesigRevoke:
        if (argc != 1)
-           wrong_args ("--desig-revoke user-id");
+           wrong_args ("--generate-designated-revocation user-id");
        username = make_username (*argv);
        gen_desig_revoke (ctrl, username, locusr);
        xfree (username);
@@ -4687,10 +4937,10 @@ main (int argc, char **argv)
 #ifndef NO_TRUST_MODELS
       case aListTrustDB:
        if( !argc )
-          list_trustdb (es_stdout, NULL);
+          list_trustdb (ctrl, es_stdout, NULL);
        else {
            for( ; argc; argc--, argv++ )
-              list_trustdb (es_stdout, *argv );
+              list_trustdb (ctrl, es_stdout, *argv );
        }
        break;
 
@@ -4722,27 +4972,30 @@ main (int argc, char **argv)
       case aExportOwnerTrust:
        if( argc )
            wrong_args("--export-ownertrust");
-       export_ownertrust();
+       export_ownertrust (ctrl);
        break;
 
       case aImportOwnerTrust:
        if( argc > 1 )
            wrong_args("--import-ownertrust [file]");
-       import_ownertrust( argc? *argv:NULL );
+       import_ownertrust (ctrl, argc? *argv:NULL );
        break;
 #endif /*!NO_TRUST_MODELS*/
 
       case aRebuildKeydbCaches:
         if (argc)
             wrong_args ("--rebuild-keydb-caches");
-        keydb_rebuild_caches (1);
+        keydb_rebuild_caches (ctrl, 1);
         break;
 
 #ifdef ENABLE_CARD_SUPPORT
       case aCardStatus:
-        if (argc)
-            wrong_args ("--card-status");
-        card_status (es_stdout, NULL, 0);
+        if (argc == 0)
+            card_status (ctrl, es_stdout, NULL);
+        else if (argc == 1)
+            card_status (ctrl, es_stdout, *argv);
+        else
+            wrong_args ("--card-status [serialno]");
         break;
 
       case aCardEdit:
@@ -4796,7 +5049,10 @@ main (int argc, char **argv)
 
          hd = keydb_new ();
          if (! hd)
-            g10_exit (1);
+            {
+              write_status_failure ("tofu-driver", gpg_error(GPG_ERR_GENERAL));
+              g10_exit (1);
+            }
 
           tofu_begin_batch_update (ctrl);
 
@@ -4810,6 +5066,7 @@ main (int argc, char **argv)
                {
                  log_error (_("error parsing key specification '%s': %s\n"),
                              argv[i], gpg_strerror (rc));
+                  write_status_failure ("tofu-driver", rc);
                  g10_exit (1);
                }
 
@@ -4823,6 +5080,8 @@ main (int argc, char **argv)
                  log_error (_("'%s' does not appear to be a valid"
                               " key ID, fingerprint or keygrip\n"),
                             argv[i]);
+                  write_status_failure ("tofu-driver",
+                                        gpg_error(GPG_ERR_GENERAL));
                  g10_exit (1);
                }
 
@@ -4833,6 +5092,7 @@ main (int argc, char **argv)
                      the string.  */
                   log_error ("keydb_search_reset failed: %s\n",
                              gpg_strerror (rc));
+                  write_status_failure ("tofu-driver", rc);
                  g10_exit (1);
                }
 
@@ -4841,6 +5101,7 @@ main (int argc, char **argv)
                {
                  log_error (_("key \"%s\" not found: %s\n"), argv[i],
                              gpg_strerror (rc));
+                  write_status_failure ("tofu-driver", rc);
                  g10_exit (1);
                }
 
@@ -4849,12 +5110,16 @@ main (int argc, char **argv)
                {
                  log_error (_("error reading keyblock: %s\n"),
                              gpg_strerror (rc));
+                  write_status_failure ("tofu-driver", rc);
                  g10_exit (1);
                }
 
-             merge_keys_and_selfsig (kb);
+             merge_keys_and_selfsig (ctrl, kb);
              if (tofu_set_policy (ctrl, kb, policy))
-               g10_exit (1);
+                {
+                  write_status_failure ("tofu-driver", rc);
+                  g10_exit (1);
+                }
 
               release_kbnode (kb);
            }
@@ -4866,10 +5131,14 @@ main (int argc, char **argv)
 #endif /*USE_TOFU*/
        break;
 
-      case aListPackets:
       default:
+        if (!opt.quiet)
+          log_info (_("WARNING: no command supplied."
+                      "  Trying to guess what you mean ...\n"));
+        /*FALLTHRU*/
+      case aListPackets:
        if( argc > 1 )
-           wrong_args(_("[filename]"));
+           wrong_args("[filename]");
        /* Issue some output for the unix newbie */
        if (!fname && !opt.outfile
             && gnupg_isatty (fileno (stdin))
@@ -4932,6 +5201,12 @@ emergency_cleanup (void)
 void
 g10_exit( int rc )
 {
+  /* If we had an error but not printed an error message, do it now.
+   * Note that write_status_failure will never print a second failure
+   * status line. */
+  if (rc)
+    write_status_failure ("gpg-exit", gpg_error (GPG_ERR_GENERAL));
+
   gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE);
   if (DBG_CLOCK)
     log_clock ("stop");
@@ -4939,6 +5214,7 @@ g10_exit( int rc )
   if ( (opt.debug & DBG_MEMSTAT_VALUE) )
     {
       keydb_dump_stats ();
+      sig_check_dump_stats ();
       gcry_control (GCRYCTL_DUMP_MEMORY_STATS);
       gcry_control (GCRYCTL_DUMP_RANDOM_STATS);
     }
@@ -5267,6 +5543,9 @@ read_sessionkey_from_fd (int fd)
   int i, len;
   char *line;
 
+  if (! gnupg_fd_valid (fd))
+    log_fatal ("override-session-key-fd is invalid: %s\n", strerror (errno));
+
   for (line = NULL, i = len = 100; ; i++ )
     {
       if (i >= len-1 )