Remove hacks which are not anymore needed since we now require Libgcrypt 1.4
[gnupg.git] / g10 / gpg.c
index c469fdb..9dd1790 100644 (file)
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -1,12 +1,12 @@
 /* gpg.c - The GnuPG utility (main for gpg)
  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- *               2006 Free Software Foundation, Inc.
+ *               2006, 2007, 2008 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
  * GnuPG is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * GnuPG is distributed in the hope that it will be useful,
@@ -15,9 +15,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 #include <ctype.h>
 #include <unistd.h>
 #include <assert.h>
-#ifdef HAVE_DOSISH_SYSTEM
-#include <fcntl.h> /* for setmode() */
-#endif
 #ifdef HAVE_STAT
 #include <sys/stat.h> /* for stat() */
 #endif
 #include <fcntl.h>
+#include <assuan.h>
 #ifdef HAVE_W32_SYSTEM
 #include <windows.h>
 #endif
 
 #define INCLUDED_BY_MAIN_MODULE 1
+#include "gpg.h"
 #include "packet.h"
-#include "iobuf.h"
-#include "memory.h"
+#include "../common/iobuf.h"
 #include "util.h"
 #include "main.h"
 #include "options.h"
 #include "keydb.h"
 #include "trustdb.h"
-#include "mpi.h"
 #include "cipher.h"
 #include "filter.h"
 #include "ttyio.h"
 #include "i18n.h"
+#include "sysutils.h"
 #include "status.h"
-#include "g10defs.h"
 #include "keyserver-internal.h"
 #include "exec.h"
-#include "cardglue.h"
-#ifdef ENABLE_CARD_SUPPORT
-#include "ccid-driver.h"
-#endif
+#include "gc-opt-flags.h"
 
 #if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
 #define MY_O_BINARY  O_BINARY
@@ -82,7 +74,7 @@ enum cmd_and_opt_values
     aDecrypt     = 'd',
     aEncr        = 'e',
     oInteractive  = 'i',
-    oKOption     = 'k',
+    aListKeys    = 'k',
     oDryRun      = 'n',
     oOutput      = 'o',
     oQuiet       = 'q',
@@ -114,21 +106,20 @@ enum cmd_and_opt_values
     aLSignKey,
     aListConfig,
     aGPGConfList,
+    aGPGConfTest,
     aListPackets,
     aEditKey,
     aDeleteKeys,
     aDeleteSecretKeys,
     aDeleteSecretAndPublicKeys,
-    aKMode,
-    aKModeC,
     aImport,
     aFastImport,
     aVerify,
     aVerifyFiles,
-    aListKeys,
     aListSigs,
     aSendKeys,
     aRecvKeys,
+    aLocateKeys,
     aSearchKeys,
     aRefreshKeys,
     aFetchKeys,
@@ -147,16 +138,15 @@ enum cmd_and_opt_values
     aListTrustDB,
     aListTrustPath,
     aExportOwnerTrust,
-    aListOwnerTrust,
     aImportOwnerTrust,
     aDeArmor,
     aEnArmor,
     aGenRandom,
-    aPipeMode,
     aRebuildKeydbCaches,
     aCardStatus,
     aCardEdit,
     aChangePIN,
+    aServer,
 
     oTextmode,
     oNoTextmode,
@@ -186,6 +176,7 @@ enum cmd_and_opt_values
     oNoDefRecipient,
     oOptions,
     oDebug,
+    oDebugLevel,
     oDebugAll,
     oDebugCCIDDriver,
     oStatusFD,
@@ -201,6 +192,7 @@ enum cmd_and_opt_values
     oGnuPG,
     oRFC1991,
     oRFC2440,
+    oRFC4880,
     oOpenPGP,
     oPGP2,
     oPGP6,
@@ -218,6 +210,7 @@ enum cmd_and_opt_values
     oPasswd,
     oPasswdFD,
     oPasswdFile,
+    oPasswdRepeat,
     oCommandFD,
     oCommandFile,
     oQuickRandom,
@@ -237,13 +230,14 @@ enum cmd_and_opt_values
     oHomedir,
     oWithColons,
     oWithKeyData,
+    oWithSigList,
+    oWithSigCheck,
     oSkipVerify,
     oCompressKeys,
     oCompressSigs,
     oAlwaysTrust,
     oTrustModel,
     oForceOwnertrust,
-    oRunAsShmCP,
     oSetFilename,
     oForYourEyesOnly,
     oNoForYourEyesOnly,
@@ -274,6 +268,7 @@ enum cmd_and_opt_values
     oS2KMode,
     oS2KDigest,
     oS2KCipher,
+    oS2KCount,
     oSimpleSKChecksum,                          
     oDisplayCharset,
     oNotDashEscaped,
@@ -333,14 +328,17 @@ enum cmd_and_opt_values
     oNoAutoCheckTrustDB,
     oPreservePermissions,
     oDefaultPreferenceList,
+    oDefaultKeyserverURL,
     oPersonalCipherPreferences,
     oPersonalDigestPreferences,
     oPersonalCompressPreferences,
+    oAgentProgram,
     oDisplay,
     oTTYname,
     oTTYtype,
     oLCctype,
     oLCmessages,
+    oXauthority,
     oGroup,
     oUnGroup,
     oNoGroups,
@@ -353,10 +351,6 @@ enum cmd_and_opt_values
     oKeyidFormat,
     oExitOnStatusWriteError,
     oLimitCardInsertTries,
-    oReaderPort,
-    octapiDriver,
-    opcscDriver,
-    oDisableCCID,
     oRequireCrossCert,
     oNoRequireCrossCert,
     oAutoKeyLocate,
@@ -364,6 +358,8 @@ enum cmd_and_opt_values
     oAllowMultisigVerification,
     oEnableDSA2,
     oDisableDSA2,
+    oAllowMultipleMessages,
+    oNoAllowMultipleMessages,
 
     oNoop
   };
@@ -406,6 +402,7 @@ static ARGPARSE_OPTS opts[] = {
                                     N_("search for keys on a key server") },
     { aRefreshKeys, "refresh-keys", 256,
                                     N_("update all keys from a keyserver")},
+    { aLocateKeys, "locate-keys", 256, "@"},
     { aFetchKeys, "fetch-keys" , 256, "@" },
     { aExportSecret, "export-secret-keys" , 256, "@" },
     { aExportSecretSub, "export-secret-subkeys" , 256, "@" },
@@ -418,6 +415,7 @@ static ARGPARSE_OPTS opts[] = {
 #endif
     { aListConfig, "list-config", 256, "@"},
     { aGPGConfList, "gpgconf-list", 256, "@" },
+    { aGPGConfTest, "gpgconf-test", 256, "@" },
     { aListPackets, "list-packets",256, "@"},
     { aExportOwnerTrust, "export-ownertrust", 256, "@"},
     { aImportOwnerTrust, "import-ownertrust", 256, "@"},
@@ -431,7 +429,8 @@ static ARGPARSE_OPTS opts[] = {
     { aEnArmor, "enarmour", 256, "@"},
     { aPrintMD,  "print-md" , 256, N_("|algo [files]|print message digests")},
     { aPrimegen, "gen-prime" , 256, "@" },
-    { aGenRandom, "gen-random" , 256, "@" },
+    { aGenRandom, "gen-random", 256, "@" },
+    { aServer,   "server",      256, N_("run in server mode")},
 
     { 301, NULL, 0, N_("@\nOptions:\n ") },
 
@@ -468,7 +467,7 @@ static ARGPARSE_OPTS opts[] = {
     { oMinCertLevel, "min-cert-level", 1, "@"},
     { oAskCertLevel, "ask-cert-level",   0, "@"},
     { oNoAskCertLevel, "no-ask-cert-level",   0, "@"},
-    { oOutput, "output",    2, N_("use as output file")},
+    { oOutput, "output",    2, N_("|FILE|write output to FILE")},
     { oMaxOutput, "max-output", 16|4, "@" },
     { oVerbose, "verbose",   0, N_("verbose") },
     { oQuiet,  "quiet",   0, "@"},
@@ -504,6 +503,7 @@ static ARGPARSE_OPTS opts[] = {
     { oDisplayCharset, "charset", 2, "@"},
     { oOptions, "options", 2, "@"},
     { oDebug, "debug"     ,4|16, "@"},
+    { oDebugLevel, "debug-level" ,2, "@"},
     { oDebugAll, "debug-all" ,0, "@"},
     { oStatusFD, "status-fd" ,1, "@"},
     { oStatusFile, "status-file" ,2, "@"},
@@ -523,6 +523,7 @@ static ARGPARSE_OPTS opts[] = {
     { oGnuPG, "no-pgp8", 0, "@"},
     { oRFC1991, "rfc1991",   0, "@"},
     { oRFC2440, "rfc2440", 0, "@" },
+    { oRFC4880, "rfc4880", 0, "@" },
     { oOpenPGP, "openpgp", 0, N_("use strict OpenPGP behavior")},
     { oPGP2, "pgp2", 0, N_("generate PGP 2.x compatible messages")},
     { oPGP6, "pgp6", 0, "@"},
@@ -533,6 +534,7 @@ static ARGPARSE_OPTS opts[] = {
     { oS2KMode, "s2k-mode", 1, "@"},
     { oS2KDigest, "s2k-digest-algo", 2, "@"},
     { oS2KCipher, "s2k-cipher-algo", 2, "@"},
+    { oS2KCount, "s2k-count", 1, "@"},
     { oSimpleSKChecksum, "simple-sk-checksum", 0, "@"},
     { oCipherAlgo, "cipher-algo", 2, "@"},
     { oDigestAlgo, "digest-algo", 2, "@"},
@@ -563,19 +565,17 @@ static ARGPARSE_OPTS opts[] = {
     " --fingerprint [names]      show fingerprints\n"  ) },
 
   /* hidden options */
-    { aListOwnerTrust, "list-ownertrust", 256, "@"}, /* deprecated */
     { aPrintMDs, "print-mds" , 256, "@"}, /* old */
     { aListTrustDB, "list-trustdb",0 , "@"},
     /* Not yet used */
     /* { aListTrustPath, "list-trust-path",0, "@"}, */
-    { aPipeMode,  "pipemode", 0, "@" },
-    { oKOption, NULL,   0, "@"},
     { oPasswd, "passphrase",2, "@" },
     { oPasswdFD, "passphrase-fd",1, "@" },
     { oPasswdFile, "passphrase-file",2, "@" },
+    { oPasswdRepeat, "passphrase-repeat", 1, "@"},
     { oCommandFD, "command-fd",1, "@" },
     { oCommandFile, "command-file",2, "@" },
-    { oQuickRandom, "quick-random", 0, "@"},
+    { oQuickRandom, "debug-quick-random", 0, "@"},
     { oNoVerbose, "no-verbose", 0, "@"},
     { oTrustDBName, "trustdb-name", 2, "@" },
     { oNoSecmemWarn, "no-secmem-warning", 0, "@" },
@@ -592,6 +592,8 @@ static ARGPARSE_OPTS opts[] = {
     { oNoBatch, "no-batch", 0, "@" },
     { oWithColons, "with-colons", 0, "@"},
     { oWithKeyData,"with-key-data", 0, "@"},
+    { oWithSigList,"with-sig-list", 0, "@"},
+    { oWithSigCheck,"with-sig-check", 0, "@"},
     { aListKeys, "list-key", 0, "@" }, /* alias */
     { aListSigs, "list-sig", 0, "@" }, /* alias */
     { aCheckKeys, "check-sig",0, "@" }, /* alias */
@@ -602,7 +604,6 @@ static ARGPARSE_OPTS opts[] = {
     { oAlwaysTrust, "always-trust", 0, "@"},
     { oTrustModel, "trust-model", 2, "@"},
     { oForceOwnertrust, "force-ownertrust", 2, "@"},
-    { oRunAsShmCP, "run-as-shm-coprocess", 4, "@" },
     { oSetFilename, "set-filename", 2, "@" },
     { oForYourEyesOnly, "for-your-eyes-only", 0, "@" },
     { oNoForYourEyesOnly, "no-for-your-eyes-only", 0, "@" },
@@ -627,7 +628,8 @@ static ARGPARSE_OPTS opts[] = {
     { oLockMultiple, "lock-multiple", 0, "@" },
     { oLockNever, "lock-never", 0, "@" },
     { oLoggerFD, "logger-fd",1, "@" },
-    { oLoggerFile, "logger-file",2, "@" },
+    { oLoggerFile, "log-file",2, "@" },
+    { oLoggerFile, "logger-file",2, "@" },  /* For 1.4 compatibility.  */
     { oUseEmbeddedFilename, "use-embedded-filename", 0, "@" },
     { oNoUseEmbeddedFilename, "no-use-embedded-filename", 0, "@" },
     { oUtf8Strings, "utf8-strings", 0, "@" },
@@ -667,6 +669,7 @@ static ARGPARSE_OPTS opts[] = {
     { aRebuildKeydbCaches, "rebuild-keydb-caches", 256, "@"},
     { oPreservePermissions, "preserve-permissions", 0, "@"},
     { oDefaultPreferenceList,  "default-preference-list", 2, "@"},
+    { oDefaultKeyserverURL,  "default-keyserver-url", 2, "@"},
     { oPersonalCipherPreferences,  "personal-cipher-preferences", 2, "@"},
     { oPersonalDigestPreferences,  "personal-digest-preferences", 2, "@"},
     { oPersonalCompressPreferences,  "personal-compress-preferences", 2, "@"},
@@ -675,11 +678,13 @@ static ARGPARSE_OPTS opts[] = {
     { oPersonalCipherPreferences, "personal-cipher-prefs", 2, "@"},
     { oPersonalDigestPreferences, "personal-digest-prefs", 2, "@"},
     { oPersonalCompressPreferences, "personal-compress-prefs", 2, "@"},
+    { oAgentProgram, "agent-program", 2 , "@" },
     { oDisplay,    "display",     2, "@" },
     { oTTYname,    "ttyname",     2, "@" },
     { oTTYtype,    "ttytype",     2, "@" },
     { oLCctype,    "lc-ctype",    2, "@" },
     { oLCmessages, "lc-messages", 2, "@" },
+    { oXauthority, "xauthority",  2, "@" },
     { oGroup,      "group",       2, "@" },
     { oUnGroup,    "ungroup",     2, "@" },
     { oNoGroups,   "no-groups",    0, "@" },
@@ -693,16 +698,11 @@ static ARGPARSE_OPTS opts[] = {
     { oExitOnStatusWriteError, "exit-on-status-write-error", 0, "@" },
     { oLimitCardInsertTries, "limit-card-insert-tries", 1, "@"},
 
-    { oReaderPort, "reader-port",    2, "@"},
-    { octapiDriver, "ctapi-driver",  2, "@"},
-    { opcscDriver, "pcsc-driver",    2, "@"},
-    { oDisableCCID, "disable-ccid", 0, "@"},
-#if defined(ENABLE_CARD_SUPPORT) && defined(HAVE_LIBUSB)
-    { oDebugCCIDDriver, "debug-ccid-driver", 0, "@"},
-#endif
     { oAllowMultisigVerification, "allow-multisig-verification", 0, "@"},
     { oEnableDSA2, "enable-dsa2", 0, "@"},
     { oDisableDSA2, "disable-dsa2", 0, "@"},
+    { oAllowMultipleMessages, "allow-multiple-messages", 0, "@"},
+    { oNoAllowMultipleMessages, "no-allow-multiple-messages", 0, "@"},
 
     /* These two are aliases to help users of the PGP command line
        product use gpg with minimal pain.  Many commands are common
@@ -710,12 +710,14 @@ static ARGPARSE_OPTS opts[] = {
        I'm returning the favor. */
     { oLocalUser, "sign-with", 2, "@" },
     { oRecipient, "user", 2, "@" },
+
     { oRequireCrossCert, "require-backsigs", 0, "@"},
     { oRequireCrossCert, "require-cross-certification", 0, "@"},
     { oNoRequireCrossCert, "no-require-backsigs", 0, "@"},
     { oNoRequireCrossCert, "no-require-cross-certification", 0, "@"},
     { oAutoKeyLocate, "auto-key-locate", 2, "@"},
     { oNoAutoKeyLocate, "no-auto-key-locate", 0, "@"},
+
     {0,NULL,0,NULL}
 };
 
@@ -734,17 +736,20 @@ static int maybe_setuid = 1;
 
 static char *build_list( const char *text, char letter,
                         const char *(*mapf)(int), int (*chkf)(int) );
+static char *build_lib_list (const char *text);
 static void set_cmd( enum cmd_and_opt_values *ret_cmd,
                        enum cmd_and_opt_values new_cmd );
 static void print_mds( const char *fname, int algo );
 static void add_notation_data( const char *string, int which );
 static void add_policy_url( const char *string, int which );
 static void add_keyserver_url( const char *string, int which );
+static void emergency_cleanup (void);
 
-const char *
-strusage( int level )
+
+static const char *
+my_strusage( int level )
 {
-  static char *digests, *pubkeys, *ciphers, *zips;
+  static char *digests, *pubkeys, *ciphers, *zips, *libs;
     const char *p;
     switch( level ) {
       case 11: p = "gpg (GnuPG)";
@@ -785,31 +790,40 @@ strusage( int level )
 #endif /* __riscos__ */
       case 33: p = _("\nSupported algorithms:\n"); break;
       case 34:
-       if( !pubkeys )
-           pubkeys = build_list(_("Pubkey: "), 0, pubkey_algo_to_string,
-                                                       check_pubkey_algo );
+       if (!pubkeys)
+            pubkeys = build_list (_("Pubkey: "), 0,
+                                  gcry_pk_algo_name,
+                                  openpgp_pk_test_algo );
        p = pubkeys;
        break;
       case 35:
        if( !ciphers )
-           ciphers = build_list(_("Cipher: "), 'S', cipher_algo_to_string,
-                                                       check_cipher_algo );
+           ciphers = build_list(_("Cipher: "), 'S', 
+                                 openpgp_cipher_algo_name,
+                                 openpgp_cipher_test_algo );
        p = ciphers;
        break;
       case 36:
        if( !digests )
-           digests = build_list(_("Hash: "), 'H', digest_algo_to_string,
-                                                       check_digest_algo );
+           digests = build_list(_("Hash: "), 'H', 
+                                 gcry_md_algo_name,
+                                 openpgp_md_test_algo );
        p = digests;
        break;
       case 37:
        if( !zips )
-           zips = build_list(_("Compression: "),'Z',compress_algo_to_string,
-                                                       check_compress_algo);
+           zips = build_list(_("Compression: "),'Z',
+                              compress_algo_to_string,
+                              check_compress_algo);
        p = zips;
        break;
+      case 38:
+       if (!libs)
+          libs = build_lib_list(_("Used libraries:"));
+       p = libs;
+       break;
 
-      default: p = default_strusage(level);
+      default: p = NULL;
     }
     return p;
 }
@@ -824,8 +838,8 @@ build_list( const char *text, char letter,
     size_t n=strlen(text)+2;
     char *list, *p, *line=NULL;
 
-    if( maybe_setuid )
-       secmem_init( 0 );    /* drop setuid */
+    if (maybe_setuid)
+      gcry_control (GCRYCTL_INIT_SECMEM, 0, 0);  /* Drop setuid. */
 
     for(i=0; i <= 110; i++ )
        if( !chkf(i) && (s=mapf(i)) )
@@ -870,20 +884,46 @@ build_list( const char *text, char letter,
 }
 
 
-static void
-i18n_init(void)
+static char *
+build_lib_list (const char *text)
 {
-#ifdef USE_SIMPLE_GETTEXT
-    set_gettext_file (PACKAGE, "Software\\GNU\\GnuPG");
-#else
-#ifdef ENABLE_NLS
-    setlocale( LC_ALL, "" );
-    bindtextdomain( PACKAGE, G10_LOCALEDIR );
-    textdomain( PACKAGE );
-#endif
-#endif
+  struct { const char *name; const char *version; } array[3];
+  int idx;
+  size_t n;
+  char *list, *p;
+
+  if (maybe_setuid)
+    gcry_control (GCRYCTL_INIT_SECMEM, 0, 0);  /* Drop setuid. */
+
+  idx = 0;
+  array[idx].name = "gcrypt";
+  array[idx++].version = gcry_check_version (NULL);
+  array[idx].name = NULL;
+  array[idx++].version = NULL;
+
+  n = strlen (text) + 1;
+  for (idx=0; array[idx].name; idx++)
+    {
+      n += 2 + strlen (array[idx].name);
+      if (array[idx].version)
+        n += 1 + strlen (array[idx].version) + 1;
+    }
+  n++;
+  list = xmalloc (n+1);
+  p = stpcpy (stpcpy (list, text), " ");
+  for (idx=0; array[idx].name; idx++)
+    {
+      if (idx)
+        p = stpcpy (p, ", ");
+      p = stpcpy (p, array[idx].name);
+      if (array[idx].version)
+        p = stpcpy (stpcpy (stpcpy (p, "("), array[idx].version), ")");
+    }
+  strcpy (p, "\n");
+  return list;
 }
 
+
 static void
 wrong_args( const char *text)
 {
@@ -906,31 +946,55 @@ make_username( const char *string )
 }
 
 
+/* 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
+   set. */
 static void
-set_debug(void)
+set_debug (const char *level)
 {
-    if( opt.debug & DBG_MEMORY_VALUE )
-       memory_debug_mode = 1;
-    if( opt.debug & DBG_MEMSTAT_VALUE )
-       memory_stat_debug_mode = 1;
-    if( opt.debug & DBG_MPI_VALUE )
-       mpi_debug_mode = 1;
-    if( opt.debug & DBG_CIPHER_VALUE )
-       g10c_debug_mode = 1;
-    if( opt.debug & DBG_IOBUF_VALUE )
-       iobuf_debug_mode = 1;
+  if (!level)
+    ;
+  else if (!strcmp (level, "none"))
+    opt.debug = 0;
+  else if (!strcmp (level, "basic"))
+    opt.debug = DBG_MEMSTAT_VALUE;
+  else if (!strcmp (level, "advanced"))
+    opt.debug = DBG_MEMSTAT_VALUE|DBG_TRUST_VALUE|DBG_EXTPROG_VALUE;
+  else if (!strcmp (level, "expert"))
+    opt.debug = (DBG_MEMSTAT_VALUE|DBG_TRUST_VALUE|DBG_EXTPROG_VALUE
+                 |DBG_CACHE_VALUE|DBG_FILTER_VALUE|DBG_PACKET_VALUE);
+  else if (!strcmp (level, "guru"))
+    opt.debug = ~0;
+  else
+    {
+      log_error (_("invalid debug-level `%s' given\n"), level);
+      g10_exit (2);
+    }
 
+  if (opt.debug & DBG_MEMORY_VALUE )
+    memory_debug_mode = 1;
+  if (opt.debug & DBG_MEMSTAT_VALUE )
+    memory_stat_debug_mode = 1;
+  if (opt.debug & DBG_MPI_VALUE)
+    gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 2);
+  if (opt.debug & DBG_CIPHER_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);
 }
 
 
+
 /* We need the home directory also in some other directories, so make
    sure that both variables are always in sync. */
 static void
-set_homedir (char *dir)
+set_homedir (const char *dir)
 {
   if (!dir)
     dir = "";
-  g10_opt_homedir = opt.homedir = dir;
+  opt.homedir = dir;
 }
 
 
@@ -939,7 +1003,7 @@ set_homedir (char *dir)
 static void
 set_screen_dimensions(void)
 {
-#ifndef _WIN32
+#ifndef HAVE_W32_SYSTEM
   char *str;
 
   str=getenv("COLUMNS");
@@ -1023,8 +1087,6 @@ set_cmd( enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd )
        cmd = aEncrSym;
     else if( cmd == aEncr && new_cmd == aSym )
        cmd = aEncrSym;
-    else if( cmd == aKMode && new_cmd == aSym )
-       cmd = aKModeC;
     else if (cmd == aSignEncr && new_cmd == aSym)
         cmd = aSignEncrSym;
     else if (cmd == aSignSym && new_cmd == aEncr)
@@ -1139,7 +1201,7 @@ check_permissions(const char *path,int item)
       if(strchr(path,DIRSEP_C))
        tmppath=make_filename(path,NULL);
       else
-       tmppath=make_filename(GNUPG_LIBDIR,path,NULL);
+       tmppath=make_filename(gnupg_libdir (),path,NULL);
     }
   else
     tmppath=xstrdup(path);
@@ -1330,6 +1392,24 @@ print_algo_numbers(int (*checker)(int))
 }
 
 
+static void
+print_algo_names(int (*checker)(int),const char *(*mapper)(int))
+{
+  int i,first=1;
+
+  for(i=0;i<=110;i++)
+    {
+      if(!checker(i))
+       {
+         if(first)
+           first=0;
+         else
+           printf(";");
+         printf("%s",mapper(i));
+       }
+    }
+}
+
 /* In the future, we can do all sorts of interesting configuration
    output here.  For now, just give "group" as the Enigmail folks need
    it, and pubkey, cipher, hash, and compress as they may be useful
@@ -1353,7 +1433,7 @@ list_config(char *items)
 
          for(iter=opt.grouplist;iter;iter=iter->next)
            {
-             STRLIST sl;
+             strlist_t sl;
 
              printf("cfg:group:");
              print_string(stdout,iter->name,strlen(iter->name),':');
@@ -1361,7 +1441,7 @@ list_config(char *items)
 
              for(sl=iter->values;sl;sl=sl->next)
                {
-                 print_string2(stdout,sl->d,strlen(sl->d),':',';');
+                 print_sanitized_string2 (stdout, sl->d, ':',';');
                  if(sl->next)
                    printf(";");
                }
@@ -1383,7 +1463,7 @@ list_config(char *items)
       if(show_all || ascii_strcasecmp(name,"pubkey")==0)
        {
          printf("cfg:pubkey:");
-         print_algo_numbers(check_pubkey_algo);
+         print_algo_numbers (openpgp_pk_test_algo);
          printf("\n");
          any=1;
        }
@@ -1391,21 +1471,39 @@ list_config(char *items)
       if(show_all || ascii_strcasecmp(name,"cipher")==0)
        {
          printf("cfg:cipher:");
-         print_algo_numbers(check_cipher_algo);
+         print_algo_numbers(openpgp_cipher_test_algo);
          printf("\n");
          any=1;
        }
 
+      if (show_all || !ascii_strcasecmp (name,"ciphername"))
+       {
+         printf ("cfg:ciphername:");
+         print_algo_names (openpgp_cipher_test_algo,openpgp_cipher_algo_name);
+         printf ("\n");
+         any = 1;
+       }
+
       if(show_all
         || ascii_strcasecmp(name,"digest")==0
         || ascii_strcasecmp(name,"hash")==0)
        {
          printf("cfg:digest:");
-         print_algo_numbers(check_digest_algo);
+         print_algo_numbers(openpgp_md_test_algo);
          printf("\n");
          any=1;
        }
 
+      if (show_all
+          || !ascii_strcasecmp(name,"digestname")
+          || !ascii_strcasecmp(name,"hashname"))
+       {
+         printf ("cfg:digestname:");
+         print_algo_names (openpgp_md_test_algo, gcry_md_algo_name);
+         printf("\n");
+         any=1;
+       }
+      
       if(show_all || ascii_strcasecmp(name,"compress")==0)
        {
          printf("cfg:compress:");
@@ -1416,7 +1514,9 @@ list_config(char *items)
 
       if(show_all || ascii_strcasecmp(name,"ccid-reader-id")==0)
        {
-#if defined(ENABLE_CARD_SUPPORT) && defined(HAVE_LIBUSB)
+#if defined(ENABLE_CARD_SUPPORT) && defined(HAVE_LIBUSB) \
+    && GNUPG_MAJOR_VERSION == 1
+
           char *p, *p2, *list = ccid_get_reader_list ();
 
           for (p=list; p && (p2 = strchr (p, '\n')); p = p2+1)
@@ -1446,16 +1546,23 @@ list_config(char *items)
 static void
 gpgconf_list (const char *configfile)
 {
-  /* The following definitions are taken from gnupg/tools/gpgconf-comp.c.  */
-#define GC_OPT_FLAG_NONE       0UL
-#define GC_OPT_FLAG_DEFAULT    (1UL << 4)
+  char *configfile_esc = percent_escape (configfile, NULL);
 
   printf ("gpgconf-gpg.conf:%lu:\"%s\n",
-          GC_OPT_FLAG_DEFAULT,configfile?configfile:"/dev/null");
+          GC_OPT_FLAG_DEFAULT, configfile_esc ? configfile_esc : "/dev/null");
   printf ("verbose:%lu:\n", GC_OPT_FLAG_NONE);
   printf ("quiet:%lu:\n",   GC_OPT_FLAG_NONE);
   printf ("keyserver:%lu:\n", GC_OPT_FLAG_NONE);
   printf ("reader-port:%lu:\n", GC_OPT_FLAG_NONE);
+  printf ("default-key:%lu:\n", GC_OPT_FLAG_NONE);
+  printf ("encrypt-to:%lu:\n", GC_OPT_FLAG_NONE);
+  printf ("auto-key-locate:%lu:\n", GC_OPT_FLAG_NONE);
+  printf ("allow-pka-lookup:%lu:\n", GC_OPT_FLAG_NONE);
+  printf ("log-file:%lu:\n", GC_OPT_FLAG_NONE);
+  printf ("debug-level:%lu:\"none:\n", GC_OPT_FLAG_DEFAULT);
+  printf ("group:%lu:\n", GC_OPT_FLAG_NONE);
+
+  xfree (configfile_esc);
 }
 
 
@@ -1625,69 +1732,110 @@ parse_trust_model(const char *model)
     log_error("unknown trust model `%s'\n",model);
 }
 
-/* Must be called before we open any files. */
+
+/* Pack an s2k iteration count into the form specified in 2440.  If
+   we're in between valid values, round up. */
+static unsigned char
+encode_s2k_iterations(int iterations)
+{
+  unsigned char c=0,result;
+  unsigned int count;
+
+  if(iterations<=1024)
+    return 0;
+
+  if(iterations>=65011712)
+    return 255;
+
+  /* Need count to be in the range 16-31 */
+  for(count=iterations>>6;count>=32;count>>=1)
+    c++;
+
+  result=(c<<4)|(count-16);
+
+  if(S2K_DECODE_COUNT(result)<iterations)
+    result++;
+
+  return result;
+}
+
+
+/* This fucntion called to initialized a new control object.  It is
+   assumed that this object has been zeroed out before calling this
+   function. */
 static void
-reopen_std(void)
-{  
-#ifdef HAVE_STAT
-  struct stat statbuf;
-  int did_stdin=0,did_stdout=0,did_stderr=0;
-  FILE *complain;
+gpg_init_default_ctrl (ctrl_t ctrl)
+{
+}
 
-  if(fstat(STDIN_FILENO,&statbuf)==-1 && errno==EBADF)
-    {
-      if(open("/dev/null",O_RDONLY)==STDIN_FILENO)
-       did_stdin=1;
-      else
-       did_stdin=2;
-    }
 
-  if(fstat(STDOUT_FILENO,&statbuf)==-1 && errno==EBADF)
+/* This function is called to deinitialize a control object.  It is
+   not deallocated. */
+static void
+gpg_deinit_default_ctrl (ctrl_t ctrl)
+{
+}
+
+
+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-")];
+
+  do
     {
-      if(open("/dev/null",O_WRONLY)==STDOUT_FILENO)
-       did_stdout=1;
-      else
-       did_stdout=2;
+      if (configname)
+       {
+         char *tok;
+         
+         xfree (configname);
+         configname = NULL;
+
+         if ((tok = strrchr (ver, SAFE_VERSION_DASH)))
+           *tok='\0';
+         else if ((tok = strrchr (ver, SAFE_VERSION_DOT)))
+           *tok='\0';
+         else
+           break;
+       }
+      
+      configname = make_filename (opt.homedir, name, NULL);
     }
+  while (access (configname, R_OK));
 
-  if(fstat(STDERR_FILENO,&statbuf)==-1 && errno==EBADF)
+  xfree(name);
+  
+  if (! configname)
+    configname = make_filename (opt.homedir, "gpg" EXTSEP_S "conf", NULL);
+  if (! access (configname, R_OK))
     {
-      if(open("/dev/null",O_WRONLY)==STDERR_FILENO)
-       did_stderr=1;
-      else
-       did_stderr=2;
+      /* 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);
+      xfree (p);
     }
-
-  /* It's hard to log this sort of thing since the filehandle we would
-     complain to may be closed... */
-  if(did_stderr==0)
-    complain=stderr;
-  else if(did_stdout==0)
-    complain=stdout;
   else
-    complain=NULL;
-
-  if(complain)
     {
-      if(did_stdin==1)
-       fprintf(complain,"gpg: WARNING: standard input reopened\n");
-      if(did_stdout==1)
-       fprintf(complain,"gpg: WARNING: standard output reopened\n");
-      if(did_stderr==1)
-       fprintf(complain,"gpg: WARNING: standard error reopened\n");
-
-      if(did_stdin==2 || did_stdout==2 || did_stderr==2)
-       fprintf(complain,"gpg: fatal: unable to reopen standard input,"
-               " output, or error\n");
+      /* Use the old default only if it exists.  */
+      char *p = make_filename (opt.homedir, "options", NULL);
+      if (!access (p, R_OK))
+       {
+         xfree (configname);
+         configname = p;
+       }
+      else
+       xfree (p);
     }
 
-  if(did_stdin==2 || did_stdout==2 || did_stderr==2)
-    exit(3);
-#endif
+  return configname;
 }
 
+
 int
-main (int argc, char **argv )
+main (int argc, char **argv)
 {
     ARGPARSE_ARGS pargs;
     IOBUF a;
@@ -1697,21 +1845,24 @@ main (int argc, char **argv )
     const char *fname;
     char *username;
     int may_coredump;
-    STRLIST sl, remusr= NULL, locusr=NULL;
-    STRLIST nrings=NULL, sec_nrings=NULL;
-    armor_filter_context_t afx;
+    strlist_t sl, remusr= NULL, locusr=NULL;
+    strlist_t nrings=NULL, sec_nrings=NULL;
+    armor_filter_context_t *afx = NULL;
     int detached_sig = 0;
     FILE *configfp = NULL;
     char *configname = NULL;
     char *save_configname = NULL;
+    char *default_configname = NULL;
     unsigned configlineno;
     int parse_debug = 0;
     int default_config = 1;
     int default_keyring = 1;
     int greeting = 0;
     int nogreeting = 0;
+    char *logfile = NULL;
     int use_random_seed = 1;
     enum cmd_and_opt_values cmd = 0;
+    const char *debug_level = NULL;
     const char *trustdb_name = NULL;
     char *def_cipher_string = NULL;
     char *def_digest_string = NULL;
@@ -1728,27 +1879,47 @@ main (int argc, char **argv )
     int with_fpr = 0; /* make an option out of --fingerprint */
     int any_explicit_recipient = 0;
     int require_secmem=0,got_secmem=0;
-#ifdef USE_SHM_COPROCESSING
-    ulong requested_shm_size=0;
-#endif
 
 #ifdef __riscos__
     opt.lock_once = 1;
 #endif /* __riscos__ */
 
-    reopen_std();
-    trap_unaligned();
-    secmem_set_flags( secmem_get_flags() | 2 ); /* suspend warnings */
+
     /* 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
-     */
-    log_set_name("gpg");
-    secure_randoxmalloc(); /* put random number into secure memory */
+       when adding any stuff between here and the call to
+       secmem_init() somewhere after the option parsing. */
+    gnupg_reopen_std ("gpg");
+    trap_unaligned ();
+    gnupg_rl_initialize ();
+    set_strusage (my_strusage);
+    gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
+    /* We don't need any locking in libgcrypt unless we use any kind of
+       threading. */
+    gcry_control (GCRYCTL_DISABLE_INTERNAL_LOCKING);
+    log_set_prefix ("gpg", 1);
+
+    /* Make sure that our subsystems are ready.  */
+    init_common_subsystems ();
+
+    /* Check that the libraries are suitable.  Do it right here because the
+       option parsing may need services of the library.  */
+    if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
+      {
+        log_fatal ( _("libgcrypt is too old (need %s, have %s)\n"),
+                    NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
+      }
+
+    /* Put random number into secure memory */
+    gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
+
     may_coredump = disable_core_dumps();
-    init_signals();
-    create_dotlock(NULL); /* register locking cleanup */
+
+    gnupg_init_signals (0, emergency_cleanup);
+
+    create_dotlock(NULL); /* Register locking cleanup. */
+
     i18n_init();
+
     opt.command_fd = -1; /* no command fd */
     opt.compress_level = -1; /* defaults to standard compress level */
     opt.bz2_compress_level = -1; /* defaults to standard compress level */
@@ -1758,6 +1929,7 @@ main (int argc, char **argv )
     opt.cert_digest_algo = 0;
     opt.compress_algo = -1; /* defaults to DEFAULT_COMPRESS_ALGO */
     opt.s2k_mode = 3; /* iterated+salted */
+    opt.s2k_count = 96; /* 65536 iterations */
 #ifdef USE_CAST5
     opt.s2k_cipher_algo = CIPHER_ALGO_CAST5;
 #else
@@ -1767,8 +1939,8 @@ main (int argc, char **argv )
     opt.marginals_needed = 3;
     opt.max_cert_depth = 5;
     opt.pgp2_workarounds = 1;
-    opt.force_v3_sigs = 1;
     opt.escape_from = 1;
+    opt.flags.require_cross_cert = 1;
     opt.import_options=IMPORT_SK2PK;
     opt.export_options=EXPORT_ATTRIBUTES;
     opt.keyserver_options.import_options=IMPORT_REPAIR_PKS_SUBKEY_BUG;
@@ -1782,24 +1954,12 @@ main (int argc, char **argv )
     opt.min_cert_level=2;
     set_screen_dimensions();
     opt.keyid_format=KF_SHORT;
-    opt.rfc2440_text=1;
     opt.def_sig_expire="0";
     opt.def_cert_expire="0";
     set_homedir ( default_homedir () );
+    opt.passwd_repeat=1;
 
-#ifdef ENABLE_CARD_SUPPORT
-#if defined(_WIN32) || defined(__CYGWIN__)
-    opt.pcsc_driver = "winscard.dll";
-#elif defined(__APPLE__)
-    opt.pcsc_driver = "/System/Library/Frameworks/PCSC.framework/PCSC";
-#elif defined(__GLIBC__)
-    opt.pcsc_driver = "libpcsclite.so.1"; 
-#else
-    opt.pcsc_driver = "libpcsclite.so"; 
-#endif
-#endif /*ENABLE_CARD_SUPPORT*/
-
-    /* check whether we have a config file on the commandline */
+    /* Check whether we have a config file on the command line.  */
     orig_argc = argc;
     orig_argv = argv;
     pargs.argc = &argc;
@@ -1815,34 +1975,22 @@ main (int argc, char **argv )
            default_config = 0;
        }
        else if( pargs.r_opt == oNoOptions )
+          {
            default_config = 0; /* --no-options */
-       else if( pargs.r_opt == oHomedir )
+            opt.no_homedir_creation = 1;
+          }
+        else if( pargs.r_opt == oHomedir )
            set_homedir ( pargs.r.ret_str );
        else if( pargs.r_opt == oNoPermissionWarn )
            opt.no_perm_warn=1;
        else if (pargs.r_opt == oStrict )
          {
-           opt.strict=1;
-           log_set_strict(1);
+           /* Not used */
          }
        else if (pargs.r_opt == oNoStrict )
          {
-           opt.strict=0;
-           log_set_strict(0);
+           /* Not used */
          }
-#ifdef USE_SHM_COPROCESSING
-       else if( pargs.r_opt == oRunAsShmCP ) {
-           /* does not make sense in a options file, we do it here,
-            * so that we are the able to drop setuid as soon as possible */
-           opt.shm_coprocess = 1;
-           requested_shm_size = pargs.r.ret_ulong;
-       }
-       else if ( pargs.r_opt == oStatusFD ) {
-           /* this is needed to ensure that the status-fd filedescriptor is
-            * initialized when init_shm_coprocessing() is called */
-           set_status_fd( iobuf_translate_file_handle (pargs.r.ret_int, 1) );
-       }
-#endif
     }
 
 #ifdef HAVE_DOSISH_SYSTEM
@@ -1861,69 +2009,30 @@ main (int argc, char **argv )
         set_homedir (buf);
     }
 #endif
-#ifdef USE_SHM_COPROCESSING
-    if( opt.shm_coprocess ) {
-       init_shm_coprocessing(requested_shm_size, 1 );
-    }
-#endif
-    /* initialize the secure memory. */
-    got_secmem=secmem_init( 32768 );
-    maybe_setuid = 0;
-    /* Okay, we are now working under our real uid */
 
+    /* Initialize the secure memory. */
+    if (!gcry_control (GCRYCTL_INIT_SECMEM, 32768, 0))
+      got_secmem = 1; 
 #if defined(HAVE_GETUID) && defined(HAVE_GETEUID)
     /* There should be no way to get to this spot while still carrying
        setuid privs.  Just in case, bomb out if we are. */
-    if(getuid()!=geteuid())
-      BUG();
+    if ( getuid () != geteuid () )
+      BUG ();
 #endif
+    maybe_setuid = 0;
 
-    set_native_charset (NULL); /* Try to auto set the character set */
-
-    /* Try for a version specific config file first */
-    if( default_config )
-      {
-       char *name=xstrdup("gpg" EXTSEP_S "conf-" SAFE_VERSION);
-       char *ver=&name[strlen("gpg" EXTSEP_S "conf-")];
-
-       do
-         {
-           if(configname)
-             {
-               char *tok;
+    /* Okay, we are now working under our real uid */
 
-               xfree(configname);
-               configname=NULL;
+    /* malloc hooks go here ... */
+    assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
+    assuan_set_assuan_err_source (GPG_ERR_SOURCE_DEFAULT);
 
-               if((tok=strrchr(ver,SAFE_VERSION_DASH)))
-                 *tok='\0';
-               else if((tok=strrchr(ver,SAFE_VERSION_DOT)))
-                 *tok='\0';
-               else
-                 break;
-             }
+    /* Try for a version specific config file first */
+    default_configname = get_default_configname ();
+    if (default_config)
+      configname = xstrdup (default_configname);
 
-           configname = make_filename(opt.homedir,name,NULL);
-         }
-       while(access(configname,R_OK));
-
-       xfree(name);
-
-       if(!configname)
-         configname=make_filename(opt.homedir, "gpg" 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);
-            xfree (p);
-          }
-        else
-          { /* Keep on using the old default one. */
-            xfree (configname);
-            configname = make_filename(opt.homedir, "options", NULL );
-          }
-      }
     argc = orig_argc;
     argv = orig_argv;
     pargs.argc = &argc;
@@ -1980,6 +2089,7 @@ main (int argc, char **argv )
          case aCheckKeys: 
          case aListConfig:
           case aGPGConfList:
+          case aGPGConfTest:
          case aListPackets:
          case aImport: 
          case aFastImport: 
@@ -1989,24 +2099,51 @@ main (int argc, char **argv )
          case aRefreshKeys:
          case aFetchKeys:
          case aExport: 
+#ifdef ENABLE_CARD_SUPPORT
+          case aCardStatus:
+          case aCardEdit: 
+          case aChangePIN:
+#endif /* ENABLE_CARD_SUPPORT*/
+         case aListKeys: 
+         case aLocateKeys:
+         case aListSigs: 
+         case aExportSecret: 
+         case aExportSecretSub: 
+         case aSym:
+         case aClearsign: 
+         case aGenRevoke: 
+         case aDesigRevoke: 
+         case aPrimegen: 
+         case aGenRandom:
+         case aPrintMD:
+         case aPrintMDs: 
+         case aListTrustDB: 
+         case aCheckTrustDB:
+         case aUpdateTrustDB: 
+         case aFixTrustDB: 
+         case aListTrustPath: 
+         case aDeArmor: 
+         case aEnArmor: 
+         case aSign: 
+         case aSignKey: 
+         case aLSignKey:
+         case aStore: 
+         case aExportOwnerTrust: 
+         case aImportOwnerTrust: 
+          case aRebuildKeydbCaches:
             set_cmd (&cmd, pargs.r_opt);
             break;
-         case aListKeys: set_cmd( &cmd, aListKeys); break;
-         case aListSigs: set_cmd( &cmd, aListSigs); break;
-         case aExportSecret: set_cmd( &cmd, aExportSecret); break;
-         case aExportSecretSub: set_cmd( &cmd, aExportSecretSub); break;
+
+         case aKeygen: 
+         case aEditKey:
          case aDeleteSecretKeys:
-           set_cmd( &cmd, aDeleteSecretKeys);
-           greeting=1;
-           break;
          case aDeleteSecretAndPublicKeys:
-            set_cmd( &cmd, aDeleteSecretAndPublicKeys);
-            greeting=1; 
+         case aDeleteKeys:
+            set_cmd (&cmd, pargs.r_opt);
+            greeting=1;
             break;
-         case aDeleteKeys: set_cmd( &cmd, aDeleteKeys); greeting=1; break;
 
          case aDetachedSign: detached_sig = 1; set_cmd( &cmd, aSign ); break;
-         case aSym: set_cmd( &cmd, aSym); break;
 
          case aDecryptFiles: multifile=1; /* fall through */
          case aDecrypt: set_cmd( &cmd, aDecrypt); break;
@@ -2017,49 +2154,10 @@ main (int argc, char **argv )
          case aVerifyFiles: multifile=1; /* fall through */
          case aVerify: set_cmd( &cmd, aVerify); break;
 
-         case aSign: set_cmd( &cmd, aSign );  break;
-         case aKeygen: set_cmd( &cmd, aKeygen); greeting=1; break;
-         case aSignKey: set_cmd( &cmd, aSignKey); break;
-         case aLSignKey: set_cmd( &cmd, aLSignKey); break;
-         case aStore: set_cmd( &cmd, aStore); break;
-         case aEditKey: set_cmd( &cmd, aEditKey); greeting=1; break;
-         case aClearsign: set_cmd( &cmd, aClearsign); break;
-         case aGenRevoke: set_cmd( &cmd, aGenRevoke); break;
-         case aDesigRevoke: set_cmd( &cmd, aDesigRevoke); break;
-         case aPrimegen: set_cmd( &cmd, aPrimegen); break;
-         case aGenRandom: set_cmd( &cmd, aGenRandom); break;
-         case aPrintMD: set_cmd( &cmd, aPrintMD); break;
-         case aPrintMDs: set_cmd( &cmd, aPrintMDs); break;
-         case aListTrustDB: set_cmd( &cmd, aListTrustDB); break;
-         case aCheckTrustDB: set_cmd( &cmd, aCheckTrustDB); break;
-         case aUpdateTrustDB: set_cmd( &cmd, aUpdateTrustDB); break;
-         case aFixTrustDB: set_cmd( &cmd, aFixTrustDB); break;
-         case aListTrustPath: set_cmd( &cmd, aListTrustPath); break;
-         case aDeArmor: set_cmd( &cmd, aDeArmor); break;
-         case aEnArmor: set_cmd( &cmd, aEnArmor); break;
-         case aListOwnerTrust:
-           deprecated_warning(configname,configlineno,
-                              "--list-ownertrust","--export-ownertrust","");
-         case aExportOwnerTrust: set_cmd( &cmd, aExportOwnerTrust); break;
-         case aImportOwnerTrust: set_cmd( &cmd, aImportOwnerTrust); break;
-          case aPipeMode:
-           deprecated_command ("--pipemode");
-            set_cmd( &cmd, aPipeMode);
-            break;
-
-          case aRebuildKeydbCaches: set_cmd( &cmd, aRebuildKeydbCaches); break;
-
-#ifdef ENABLE_CARD_SUPPORT
-          case aCardStatus: set_cmd (&cmd, aCardStatus); break;
-          case aCardEdit: set_cmd (&cmd, aCardEdit); break;
-          case aChangePIN: set_cmd (&cmd, aChangePIN); break;
-          case oReaderPort:
-            card_set_reader_port (pargs.r.ret_str);
+          case aServer:
+            set_cmd (&cmd, pargs.r_opt);
+            opt.batch = 1;
             break;
-          case octapiDriver: opt.ctapi_driver = pargs.r.ret_str; break;
-          case opcscDriver: opt.pcsc_driver = pargs.r.ret_str; break;
-          case oDisableCCID: opt.disable_ccid = 1; break;
-#endif /* ENABLE_CARD_SUPPORT*/
 
          case oArmor: opt.armor = 1; opt.no_armor=0; break;
          case oOutput: opt.outfile = pargs.r.ret_str; break;
@@ -2069,24 +2167,26 @@ main (int argc, char **argv )
          case oDryRun: opt.dry_run = 1; break;
          case oInteractive: opt.interactive = 1; break;
          case oVerbose:
-           g10_opt_verbose++;
            opt.verbose++;
+            gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
            opt.list_options|=LIST_SHOW_UNUSABLE_UIDS;
            opt.list_options|=LIST_SHOW_UNUSABLE_SUBKEYS;
            break;
-         case oKOption: set_cmd( &cmd, aKMode ); break;
 
-         case oBatch: opt.batch = 1; nogreeting = 1; break;
-          case oUseAgent:
-#ifndef __riscos__
-            opt.use_agent = 1;
-#else /* __riscos__ */
-            opt.use_agent = 0;
-            riscos_not_implemented("use-agent");
-#endif /* __riscos__ */
+         case oBatch:
+            opt.batch = 1;
+            nogreeting = 1;
+            break;
+
+          case oUseAgent: /* Dummy. */
             break;
-          case oNoUseAgent: opt.use_agent = 0; break;
-         case oGpgAgentInfo: opt.gpg_agent_info = pargs.r.ret_str; break;
+          case oNoUseAgent:
+           obsolete_option (configname, configlineno, "--no-use-agent");
+            break;
+         case oGpgAgentInfo: 
+           obsolete_option (configname, configlineno, "--gpg-agent-info");
+            break;
+
          case oAnswerYes: opt.answer_yes = 1; break;
          case oAnswerNo: opt.answer_no = 1; break;
          case oKeyring: append_to_strlist( &nrings, pargs.r.ret_str); break;
@@ -2099,31 +2199,28 @@ main (int argc, char **argv )
                               "--list-options ","show-keyring");
            opt.list_options|=LIST_SHOW_KEYRING;
            break;
+
          case oDebug: opt.debug |= pargs.r.ret_ulong; break;
          case oDebugAll: opt.debug = ~0; break;
-          case oDebugCCIDDriver: 
-#if defined(ENABLE_CARD_SUPPORT) && defined(HAVE_LIBUSB)
-            ccid_set_debug_level (ccid_set_debug_level (1)+1);
-#endif
-            break;
+          case oDebugLevel: debug_level = pargs.r.ret_str; break;
+
          case oStatusFD:
-            set_status_fd( iobuf_translate_file_handle (pargs.r.ret_int, 1) );
+            set_status_fd( translate_sys2libc_fd_int (pargs.r.ret_int, 1) );
             break;
          case oStatusFile:
             set_status_fd ( open_info_file (pargs.r.ret_str, 1) );
             break;
          case oAttributeFD:
-            set_attrib_fd(iobuf_translate_file_handle (pargs.r.ret_int, 1));
+            set_attrib_fd(translate_sys2libc_fd_int (pargs.r.ret_int, 1));
             break;
          case oAttributeFile:
             set_attrib_fd ( open_info_file (pargs.r.ret_str, 1) );
             break;
          case oLoggerFD:
-            log_set_logfile( NULL,
-                             iobuf_translate_file_handle (pargs.r.ret_int, 1));
+            log_set_fd (translate_sys2libc_fd_int (pargs.r.ret_int, 1));
             break;
-         case oLoggerFile:
-            log_set_logfile( NULL, open_info_file (pargs.r.ret_str, 1) );
+          case oLoggerFile:
+            logfile = pargs.r.ret_str;
             break;
 
          case oWithFingerprint:
@@ -2144,9 +2241,14 @@ main (int argc, char **argv )
          case oNoArmor: opt.no_armor=1; opt.armor=0; break;
          case oNoDefKeyring: default_keyring = 0; break;
          case oNoGreeting: nogreeting = 1; break;
-         case oNoVerbose: g10_opt_verbose = 0;
-                          opt.verbose = 0; opt.list_sigs=0; break;
-         case oQuickRandom: quick_random_gen(1); break;
+         case oNoVerbose: 
+            opt.verbose = 0;
+            gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
+            opt.list_sigs=0;
+            break;
+          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 oCompletesNeeded: opt.completes_needed = pargs.r.ret_int; break;
@@ -2155,23 +2257,27 @@ main (int argc, char **argv )
          case oTrustDBName: trustdb_name = pargs.r.ret_str; break;
          case oDefaultKey: opt.def_secret_key = pargs.r.ret_str; break;
          case oDefRecipient:
-                   if( *pargs.r.ret_str )
-                       opt.def_recipient = make_username(pargs.r.ret_str);
-                   break;
+            if( *pargs.r.ret_str )
+              opt.def_recipient = make_username(pargs.r.ret_str);
+            break;
          case oDefRecipientSelf:
-                   xfree(opt.def_recipient); opt.def_recipient = NULL;
-                   opt.def_recipient_self = 1;
-                   break;
+            xfree(opt.def_recipient); opt.def_recipient = NULL;
+            opt.def_recipient_self = 1;
+            break;
          case oNoDefRecipient:
-                   xfree(opt.def_recipient); opt.def_recipient = NULL;
-                   opt.def_recipient_self = 0;
-                   break;
+            xfree(opt.def_recipient); opt.def_recipient = NULL;
+            opt.def_recipient_self = 0;
+            break;
          case oNoOptions: opt.no_homedir_creation = 1; break; /* no-options */
          case oHomedir: break;
          case oNoBatch: opt.batch = 0; break;
-         case oWithKeyData: opt.with_key_data=1; /* fall thru */
+
+         case oWithKeyData: opt.with_key_data=1; /*FALLTHRU*/
          case oWithColons: opt.with_colons=':'; break;
 
+          case oWithSigCheck: opt.check_sigs = 1; /*FALLTHRU*/
+          case oWithSigList: opt.list_sigs = 1; break;  
+
          case oSkipVerify: opt.skip_verify=1; break;
          case oCompressKeys: opt.compress_keys = 1; break;
          case aListSecretKeys: set_cmd( &cmd, aListSecretKeys); break;
@@ -2193,18 +2299,8 @@ main (int argc, char **argv )
              }
            break;
          case oLoadExtension:
-#ifndef __riscos__
-#if defined(USE_DYNAMIC_LINKING) || defined(_WIN32)
-           if(check_permissions(pargs.r.ret_str,2))
-             log_info(_("cipher extension `%s' not loaded due to"
-                        " unsafe permissions\n"),pargs.r.ret_str);
-           else
-             register_cipher_extension(orig_argc? *orig_argv:NULL,
-                                       pargs.r.ret_str);
-#endif
-#else /* __riscos__ */
-            riscos_not_implemented("load-extension");
-#endif /* __riscos__ */
+            /* Dummy so that gpg 1.4 conf files can work. Should
+               eventually be removed.  */
            break;
          case oRFC1991:
            opt.compliance = CO_RFC1991;
@@ -2212,11 +2308,34 @@ main (int argc, char **argv )
            opt.escape_from = 1;
            break;
          case oOpenPGP:
+         case oRFC4880:
+           /* This is effectively the same as RFC2440, but with
+              "--enable-dsa2 --no-rfc2440-text --escape-from-lines
+              --require-cross-certification". */
+           opt.compliance = CO_RFC4880;
+           opt.flags.dsa2 = 1;
+           opt.flags.require_cross_cert = 1;
+           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;
+           opt.cert_digest_algo = 0;
+           opt.compress_algo = -1;
+            opt.s2k_mode = 3; /* iterated+salted */
+           opt.s2k_digest_algo = DIGEST_ALGO_SHA1;
+           opt.s2k_cipher_algo = CIPHER_ALGO_3DES;
+           break;
          case oRFC2440:
-           /* TODO: When 2440bis becomes a RFC, set new values for
-              oOpenPGP. */
-           opt.rfc2440_text=1;
            opt.compliance = CO_RFC2440;
+           opt.flags.dsa2 = 0;
+           opt.rfc2440_text = 1;
            opt.allow_non_selfsigned_uid = 1;
            opt.allow_freeform_uid = 1;
            opt.pgp2_workarounds = 0;
@@ -2241,23 +2360,12 @@ main (int argc, char **argv )
          case oCompressSigs: opt.compress_sigs = 1; break;
          case oRFC2440Text: opt.rfc2440_text=1; break;
          case oNoRFC2440Text: opt.rfc2440_text=0; break;
-         case oRunAsShmCP:
-#ifndef __riscos__
-# ifndef USE_SHM_COPROCESSING
-           /* not possible in the option file,
-            * but we print the warning here anyway */
-           log_error("shared memory coprocessing is not available\n");
-# endif
-#else /* __riscos__ */
-            riscos_not_implemented("run-as-shm-coprocess");
-#endif /* __riscos__ */
-           break;
-         case oSetFilename:
-           if(utf8_strings)
-             opt.set_filename = pargs.r.ret_str;
-           else
-             opt.set_filename = native_to_utf8(pargs.r.ret_str);
-           break;
+         case oSetFilename:
+            if(utf8_strings)
+              opt.set_filename = pargs.r.ret_str;
+            else
+              opt.set_filename = native_to_utf8(pargs.r.ret_str);
+           break;
          case oForYourEyesOnly: eyes_only = 1; break;
          case oNoForYourEyesOnly: eyes_only = 0; break;
          case oSetPolicyURL:
@@ -2331,6 +2439,9 @@ main (int argc, char **argv )
          case oS2KMode:   opt.s2k_mode = pargs.r.ret_int; break;
          case oS2KDigest: s2k_digest_string = xstrdup(pargs.r.ret_str); break;
          case oS2KCipher: s2k_cipher_string = xstrdup(pargs.r.ret_str); break;
+         case oS2KCount:
+           opt.s2k_count=encode_s2k_iterations(pargs.r.ret_int);
+           break;
           case oSimpleSKChecksum: opt.simple_sk_checksum = 1; break;
          case oNoEncryptTo: opt.no_encrypt_to = 1; break;
          case oEncryptTo: /* store the recipient in the second list */
@@ -2397,14 +2508,14 @@ main (int argc, char **argv )
            set_passphrase_from_string(pargs.r.ret_str);
            break;
          case oPasswdFD:
-            pwfd = iobuf_translate_file_handle (pargs.r.ret_int, 0);
-            opt.use_agent = 0;
+            pwfd = translate_sys2libc_fd_int (pargs.r.ret_int, 0);
             break;
          case oPasswdFile:
             pwfd = open_info_file (pargs.r.ret_str, 0);
             break;
+         case oPasswdRepeat: opt.passwd_repeat=pargs.r.ret_int; break;
          case oCommandFD:
-            opt.command_fd = iobuf_translate_file_handle (pargs.r.ret_int, 0);
+            opt.command_fd = translate_sys2libc_fd_int (pargs.r.ret_int, 0);
             break;
          case oCommandFile:
             opt.command_fd = open_info_file (pargs.r.ret_str, 0);
@@ -2439,8 +2550,14 @@ main (int argc, char **argv )
                compress_algo_string = xstrdup(pargs.r.ret_str);
            }
            break;
-         case oCertDigestAlgo: cert_digest_string = xstrdup(pargs.r.ret_str); break;
-         case oNoSecmemWarn: secmem_set_flags( secmem_get_flags() | 1 ); break;
+         case oCertDigestAlgo: 
+            cert_digest_string = xstrdup(pargs.r.ret_str);
+            break;
+
+         case oNoSecmemWarn: 
+            gcry_control (GCRYCTL_DISABLE_SECMEM_WARN); 
+            break;
+
          case oRequireSecmem: require_secmem=1; break;
          case oNoRequireSecmem: require_secmem=0; break;
          case oNoPermissionWarn: opt.no_perm_warn=1; break;
@@ -2456,7 +2573,6 @@ main (int argc, char **argv )
          case oLockOnce: opt.lock_once = 1; break;
          case oLockNever:
             disable_dotlock ();
-            random_disable_locking ();
             break;
          case oLockMultiple:
 #ifndef __riscos__
@@ -2541,6 +2657,8 @@ main (int argc, char **argv )
                   N_("show user ID validity during signature verification")},
                  {"show-unusable-uids",VERIFY_SHOW_UNUSABLE_UIDS,NULL,
                   N_("show revoked and expired user IDs in signature verification")},
+                 {"show-primary-uid-only",VERIFY_SHOW_PRIMARY_UID_ONLY,NULL,
+                  N_("show only the primary user ID in signature verification")},
                  {"pka-lookups",VERIFY_PKA_LOOKUPS,NULL,
                   N_("validate signatures with PKA data")},
                  {"pka-trust-increase",VERIFY_PKA_TRUST_INCREASE,NULL,
@@ -2590,11 +2708,17 @@ main (int argc, char **argv )
          case oUtf8Strings: utf8_strings = 1; break;
          case oNoUtf8Strings: utf8_strings = 0; break;
          case oDisableCipherAlgo:
-               disable_cipher_algo( string_to_cipher_algo(pargs.r.ret_str) );
-               break;
+            {
+              int algo = string_to_cipher_algo (pargs.r.ret_str);
+              gcry_cipher_ctl (NULL, GCRYCTL_DISABLE_ALGO, &algo, sizeof algo);
+            }
+            break;
          case oDisablePubkeyAlgo:
-               disable_pubkey_algo( string_to_pubkey_algo(pargs.r.ret_str) );
-               break;
+            {
+              int algo = gcry_pk_map_name (pargs.r.ret_str);
+              gcry_pk_ctl (GCRYCTL_DISABLE_ALGO, &algo, sizeof algo);
+            }
+            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;
@@ -2610,7 +2734,7 @@ main (int argc, char **argv )
                                   "--keyserver-options ","http-proxy");
                break;
          case oFastListMode: opt.fast_list_mode = 1; break;
-         case oFixedListMode: opt.fixed_list_mode = 1; break;
+         case oFixedListMode: /* Dummy */ break;
          case oListOnly: opt.list_only=1; break;
          case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break;
          case oIgnoreValidFrom: opt.ignore_valid_from = 1; break;
@@ -2652,6 +2776,19 @@ main (int argc, char **argv )
           case oDefaultPreferenceList:
            opt.def_preference_list = pargs.r.ret_str;
            break;
+         case oDefaultKeyserverURL:
+           {
+             struct keyserver_spec *keyserver;
+             keyserver=parse_keyserver_uri(pargs.r.ret_str,1,
+                                           configname,configlineno);
+             if(!keyserver)
+               log_error(_("could not parse keyserver URL\n"));
+             else
+               free_keyserver_spec(keyserver);
+
+             opt.def_keyserver_url = pargs.r.ret_str;
+           }
+           break;
           case oPersonalCipherPreferences:
            pers_cipher_list=pargs.r.ret_str;
            break;
@@ -2661,11 +2798,13 @@ main (int argc, char **argv )
           case oPersonalCompressPreferences:
            pers_compress_list=pargs.r.ret_str;
            break;
+          case oAgentProgram: opt.agent_program = pargs.r.ret_str;  break;
           case oDisplay: opt.display = pargs.r.ret_str; break;
           case oTTYname: opt.ttyname = pargs.r.ret_str; break;
           case oTTYtype: opt.ttytype = pargs.r.ret_str; break;
           case oLCctype: opt.lc_ctype = pargs.r.ret_str; break;
           case oLCmessages: opt.lc_messages = pargs.r.ret_str; break;
+          case oXauthority: opt.xauthority = pargs.r.ret_str; break;
          case oGroup: add_group(pargs.r.ret_str); break;
          case oUnGroup: rm_group(pargs.r.ret_str); break;
          case oNoGroups:
@@ -2677,8 +2816,12 @@ main (int argc, char **argv )
                xfree(iter);
              }
            break;
-         case oStrict: opt.strict=1; log_set_strict(1); break;
-         case oNoStrict: opt.strict=0; log_set_strict(0); break;
+
+         case oStrict: 
+         case oNoStrict: 
+           /* Not used */
+            break;
+
           case oMangleDosFilenames: opt.mangle_dos_filenames = 1; break;
           case oNoMangleDosFilenames: opt.mangle_dos_filenames = 0; break;
           case oEnableProgressFilter: opt.enable_progress_filter = 1; break;
@@ -2721,13 +2864,18 @@ main (int argc, char **argv )
            release_akl();
            break;
 
-          case oAllowMultisigVerification:
-            opt.allow_multisig_verification = 1;
-            break;
-
          case oEnableDSA2: opt.flags.dsa2=1; break;
          case oDisableDSA2: opt.flags.dsa2=0; break;
 
+          case oAllowMultisigVerification:
+         case oAllowMultipleMessages:
+           opt.flags.allow_multiple_messages=1;
+           break;
+
+         case oNoAllowMultipleMessages:
+           opt.flags.allow_multiple_messages=0;
+           break;
+
          case oNoop: break;
 
          default : pargs.err = configfp? 1:2; break;
@@ -2754,10 +2902,11 @@ main (int argc, char **argv )
        directly after the option parsing. */
     if (cmd == aGPGConfList)
       {
-        gpgconf_list (save_configname);
+        gpgconf_list (save_configname ? save_configname : default_configname);
         g10_exit (0);
       }
     xfree (save_configname);
+    xfree (default_configname);
 
     if( nogreeting )
        greeting = 0;
@@ -2781,6 +2930,34 @@ main (int argc, char **argv )
       }
 #endif
 
+    /* FIXME: We should use logging to a file only in server mode;
+       however we have not yet implemetyed that.  Thus we try to get
+       away with --batch as indication for logging to file
+       required. */
+    if (logfile && opt.batch)
+      {
+        log_set_file (logfile);
+        log_set_prefix (NULL, 1|2|4);
+      }
+
+#ifdef USE_CAMELLIA    
+    /* We better also print a runtime warning if people build it with
+       support for Camellia (which is not yet defined by OpenPGP). */
+    log_info ("WARNING: This version has been built with support for the "
+              "Camellia cipher.\n");
+    log_info ("         It is for testing only and is NOT for production "
+              "use!\n");
+#endif
+
+    /* 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 ());
 
@@ -2806,20 +2983,13 @@ main (int argc, char **argv )
                        "--no-literal" );
     }
 
-#ifndef ENABLE_AGENT_SUPPORT   
-    if (opt.use_agent) {
-      log_info(_("NOTE: %s is not available in this version\n"),
-               "--use-agent");
-      opt.use_agent = 0;
-    }
-#endif /*!ENABLE_AGENT_SUPPORT*/
 
     if (opt.set_filesize)
        log_info(_("NOTE: %s is not for normal use!\n"), "--set-filesize");
     if( opt.batch )
        tty_batchmode( 1 );
 
-    secmem_set_flags( secmem_get_flags() & ~2 ); /* resume warnings */
+    gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
 
     if(require_secmem && !got_secmem)
       {
@@ -2828,7 +2998,7 @@ main (int argc, char **argv )
        g10_exit(2);
       }
 
-    set_debug();
+    set_debug (debug_level);
 
     /* Do these after the switch(), so they can override settings. */
     if(PGP2)
@@ -2860,7 +3030,7 @@ main (int argc, char **argv )
               preference, but those have their own error
               messages). */
 
-           if(check_cipher_algo(CIPHER_ALGO_IDEA))
+           if (openpgp_cipher_test_algo(CIPHER_ALGO_IDEA))
              {
                log_info(_("encrypting a message in --pgp2 mode requires "
                           "the IDEA cipher\n"));
@@ -2919,47 +3089,46 @@ main (int argc, char **argv )
        opt.escape_from=1;
       }
 
-    /* must do this after dropping setuid, because string_to...
-     * may try to load an module */
+
     if( def_cipher_string ) {
-       opt.def_cipher_algo = string_to_cipher_algo(def_cipher_string);
+       opt.def_cipher_algo = string_to_cipher_algo (def_cipher_string);
        if(opt.def_cipher_algo==0 &&
           (ascii_strcasecmp(def_cipher_string,"idea")==0
            || ascii_strcasecmp(def_cipher_string,"s1")==0))
          idea_cipher_warn(1);
        xfree(def_cipher_string); def_cipher_string = NULL;
-       if( check_cipher_algo(opt.def_cipher_algo) )
+       if ( openpgp_cipher_test_algo (opt.def_cipher_algo) )
            log_error(_("selected cipher algorithm is invalid\n"));
     }
     if( def_digest_string ) {
-       opt.def_digest_algo = string_to_digest_algo(def_digest_string);
+       opt.def_digest_algo = string_to_digest_algo (def_digest_string);
        xfree(def_digest_string); def_digest_string = NULL;
-       if( check_digest_algo(opt.def_digest_algo) )
+       if ( openpgp_md_test_algo (opt.def_digest_algo) )
            log_error(_("selected digest algorithm is invalid\n"));
     }
     if( compress_algo_string ) {
        opt.compress_algo = string_to_compress_algo(compress_algo_string);
        xfree(compress_algo_string); compress_algo_string = NULL;
        if( check_compress_algo(opt.compress_algo) )
-           log_error(_("selected compression algorithm is invalid\n"));
+          log_error(_("selected compression algorithm is invalid\n"));
     }
     if( cert_digest_string ) {
-       opt.cert_digest_algo = string_to_digest_algo(cert_digest_string);
+       opt.cert_digest_algo = string_to_digest_algo (cert_digest_string);
        xfree(cert_digest_string); cert_digest_string = NULL;
-       if( check_digest_algo(opt.cert_digest_algo) )
-           log_error(_("selected certification digest algorithm is invalid\n"));
+       if (openpgp_md_test_algo(opt.cert_digest_algo))
+          log_error(_("selected certification digest algorithm is invalid\n"));
     }
     if( s2k_cipher_string ) {
-       opt.s2k_cipher_algo = string_to_cipher_algo(s2k_cipher_string);
+       opt.s2k_cipher_algo = string_to_cipher_algo (s2k_cipher_string);
        xfree(s2k_cipher_string); s2k_cipher_string = NULL;
-       if( check_cipher_algo(opt.s2k_cipher_algo) )
-           log_error(_("selected cipher algorithm is invalid\n"));
+       if (openpgp_cipher_test_algo (opt.s2k_cipher_algo))
+          log_error(_("selected cipher algorithm is invalid\n"));
     }
     if( s2k_digest_string ) {
-       opt.s2k_digest_algo = string_to_digest_algo(s2k_digest_string);
+       opt.s2k_digest_algo = string_to_digest_algo (s2k_digest_string);
        xfree(s2k_digest_string); s2k_digest_string = NULL;
-       if( check_digest_algo(opt.s2k_digest_algo) )
-           log_error(_("selected digest algorithm is invalid\n"));
+       if (openpgp_md_test_algo(opt.s2k_digest_algo))
+          log_error(_("selected digest algorithm is invalid\n"));
     }
     if( opt.completes_needed < 1 )
       log_error(_("completes-needed must be greater than 0\n"));
@@ -3054,26 +3223,26 @@ main (int argc, char **argv )
        if(opt.def_cipher_algo
           && !algo_available(PREFTYPE_SYM,opt.def_cipher_algo,NULL))
          {
-           badalg=cipher_algo_to_string(opt.def_cipher_algo);
-           badtype=PREFTYPE_SYM;
+           badalg = openpgp_cipher_algo_name (opt.def_cipher_algo);
+           badtype = PREFTYPE_SYM;
          }
        else if(opt.def_digest_algo
                && !algo_available(PREFTYPE_HASH,opt.def_digest_algo,NULL))
          {
-           badalg=digest_algo_to_string(opt.def_digest_algo);
-           badtype=PREFTYPE_HASH;
+           badalg = gcry_md_algo_name (opt.def_digest_algo);
+           badtype = PREFTYPE_HASH;
          }
        else if(opt.cert_digest_algo
                && !algo_available(PREFTYPE_HASH,opt.cert_digest_algo,NULL))
          {
-           badalg=digest_algo_to_string(opt.cert_digest_algo);
-           badtype=PREFTYPE_HASH;
+           badalg = gcry_md_algo_name (opt.cert_digest_algo);
+           badtype = PREFTYPE_HASH;
          }
        else if(opt.compress_algo!=-1
                && !algo_available(PREFTYPE_ZIP,opt.compress_algo,NULL))
          {
-           badalg=compress_algo_to_string(opt.compress_algo);
-           badtype=PREFTYPE_ZIP;
+           badalg = compress_algo_to_string(opt.compress_algo);
+           badtype = PREFTYPE_ZIP;
          }
 
        if(badalg)
@@ -3103,10 +3272,10 @@ main (int argc, char **argv )
          }
       }
 
-    /* set the random seed file */
+    /* Set the random seed file. */
     if( use_random_seed ) {
        char *p = make_filename(opt.homedir, "random_seed", NULL );
-       set_random_seed_file(p);
+       gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p);
         if (!access (p, F_OK))
           register_secured_file (p);
        xfree(p);
@@ -3116,43 +3285,24 @@ main (int argc, char **argv )
        set_cmd( &cmd, aListKeys);
     }
 
-    if( cmd == aKMode || cmd == aKModeC ) { /* kludge to be compatible to pgp */
-       if( cmd == aKModeC ) {
-           opt.fingerprint = 1;
-           cmd = aKMode;
-       }
-       opt.list_sigs = 0;
-       if( opt.verbose > 2 )
-           opt.check_sigs++;
-       if( opt.verbose > 1 )
-           opt.list_sigs++;
-
-       opt.verbose = opt.verbose > 1;
-       g10_opt_verbose = opt.verbose;
-    }
-
-    /* kludge to let -sat generate a clear text signature */
-    if( opt.textmode == 2 && !detached_sig && opt.armor && cmd == aSign )
-       cmd = aClearsign;
 
     if( opt.verbose > 1 )
        set_packet_list_mode(1);
 
-    /* Add the keyrings, but not for some special commands and not in
-       case of "-kvv userid keyring".  Also avoid adding the secret
-       keyring for a couple of commands to avoid unneeded access in
-       case the secrings are stored on a floppy.
+    /* Add the keyrings, but not for some special commands.  Also
+       avoid adding the secret keyring for a couple of commands to
+       avoid unneeded access in case the secrings are stored on a
+       floppy.
        
        We always need to add the keyrings if we are running under
        SELinux, this is so that the rings are added to the list of
        secured files. */
     if( ALWAYS_ADD_KEYRINGS 
-        || (cmd != aDeArmor && cmd != aEnArmor
-            && !(cmd == aKMode && argc == 2 )) ) 
+        || (cmd != aDeArmor && cmd != aEnArmor && cmd != aGPGConfTest) ) 
       {
         if (ALWAYS_ADD_KEYRINGS
             || (cmd != aCheckKeys && cmd != aListSigs && cmd != aListKeys
-                && cmd != aVerify && cmd != aSym))
+                && cmd != aVerify && cmd != aSym && cmd != aLocateKeys))
           {
             if (!sec_nrings || default_keyring) /* add default secret rings */
               keydb_add_resource ("secring" EXTSEP_S "gpg", 4, 1);
@@ -3167,8 +3317,11 @@ main (int argc, char **argv )
     FREE_STRLIST(nrings);
     FREE_STRLIST(sec_nrings);
 
+    if (cmd == aGPGConfTest)
+      g10_exit(0);
+
 
-    if( pwfd != -1 )  /* read the passphrase now. */
+    if( pwfd != -1 )  /* Read the passphrase now. */
        read_passphrase_from_fd( pwfd );
 
     fname = argc? *argv : NULL;
@@ -3210,6 +3363,16 @@ main (int argc, char **argv )
 
     switch( cmd )
       {
+      case aServer:
+        {
+          ctrl_t ctrl = xtrycalloc (1, sizeof *ctrl);
+          gpg_init_default_ctrl (ctrl);
+          gpg_server (ctrl);
+          gpg_deinit_default_ctrl (ctrl);
+          xfree (ctrl);
+        }
+        break;
+
       case aStore: /* only store the file */
        if( argc > 1 )
            wrong_args(_("--store [filename]"));
@@ -3422,7 +3585,7 @@ main (int argc, char **argv )
        sl = NULL;
        for( ; argc; argc--, argv++ )
            add_to_strlist2( &sl, *argv, utf8_strings );
-       public_key_list( sl );
+       public_key_list( sl, 0 );
        free_strlist(sl);
        break;
       case aListSecretKeys:
@@ -3432,33 +3595,12 @@ main (int argc, char **argv )
        secret_key_list( sl );
        free_strlist(sl);
        break;
-
-      case aKMode: /* list keyring -- NOTE: This will be removed soon */
-       if( argc < 2 ) { /* -kv [userid] */
-           sl = NULL;
-           if (argc && **argv)
-               add_to_strlist2( &sl, *argv, utf8_strings );
-           public_key_list( sl );
-           free_strlist(sl);
-       }
-       else if( argc == 2 ) { /* -kv userid keyring */
-           if( access( argv[1], R_OK ) ) {
-               log_error(_("can't open `%s': %s\n"),
-                              print_fname_stdin(argv[1]), strerror(errno));
-           }
-           else {
-               /* add keyring (default keyrings are not registered in this
-                * special case */
-               keydb_add_resource( argv[1], 0, 0 );
-               sl = NULL;
-               if (**argv)
-                   add_to_strlist2( &sl, *argv, utf8_strings );
-               public_key_list( sl );
-               free_strlist(sl);
-           }
-       }
-       else
-           wrong_args(_("-k[v][v][v][c] [user-id] [keyring]") );
+      case aLocateKeys:
+       sl = NULL;
+       for (; argc; argc--, argv++)
+          add_to_strlist2( &sl, *argv, utf8_strings );
+       public_key_list (sl, 1);
+       free_strlist (sl);
        break;
 
       case aKeygen: /* generate a key */
@@ -3589,6 +3731,7 @@ main (int argc, char **argv )
 
 
       case aPrimegen:
+#if 0 /*FIXME*/
        {   int mode = argc < 2 ? 0 : atoi(*argv);
 
            if( mode == 1 && argc == 2 ) {
@@ -3620,6 +3763,8 @@ main (int argc, char **argv )
                wrong_args("--gen-prime mode bits [qbits] ");
            putchar('\n');
        }
+#endif
+        wrong_args("--gen-prime not yet supported ");
        break;
 
       case aGenRandom:
@@ -3639,7 +3784,7 @@ main (int argc, char **argv )
                    other tools */
                size_t n = !endless && count < 99? count : 99;
 
-               p = get_random_bits( n*8, level, 0);
+               p = gcry_random_bytes (n, level);
 #ifdef HAVE_DOSISH_SYSTEM
                setmode ( fileno(stdout), O_BINARY );
 #endif
@@ -3668,7 +3813,7 @@ main (int argc, char **argv )
            wrong_args("--print-md algo [files]");
        {
            int all_algos = (**argv=='*' && !(*argv)[1]);
-           int algo = all_algos? 0 : string_to_digest_algo(*argv);
+           int algo = all_algos? 0 : gcry_md_map_name (*argv);
 
            if( !algo && !all_algos )
                log_error(_("invalid hash algorithm `%s'\n"), *argv );
@@ -3741,12 +3886,6 @@ main (int argc, char **argv )
        import_ownertrust( argc? *argv:NULL );
        break;
       
-      case aPipeMode:
-        if ( argc )
-            wrong_args ("--pipemode");
-        run_in_pipemode ();
-        break;
-
       case aRebuildKeydbCaches:
         if (argc)
             wrong_args ("--rebuild-keydb-caches");
@@ -3813,8 +3952,8 @@ main (int argc, char **argv )
 
            if( !opt.no_armor ) {
                if( use_armor_filter( a ) ) {
-                   memset( &afx, 0, sizeof afx);
-                   iobuf_push_filter( a, armor_filter, &afx );
+                   afx = new_armor_context ();
+                   push_armor_filter (afx, a);
                }
            }
            if( cmd == aListPackets ) {
@@ -3830,6 +3969,7 @@ main (int argc, char **argv )
       }
 
     /* cleanup */
+    release_armor_context (afx);
     FREE_STRLIST(remusr);
     FREE_STRLIST(locusr);
     g10_exit(0);
@@ -3837,23 +3977,30 @@ main (int argc, char **argv )
 }
 
 
+/* Note: This function is used by signal handlers!. */
+static void
+emergency_cleanup (void)
+{
+  gcry_control (GCRYCTL_TERM_SECMEM );
+}
+
+
 void
 g10_exit( int rc )
 {
-#ifdef ENABLE_CARD_SUPPORT
-    card_close ();
-#endif
-    update_random_seed_file();
-    if( opt.debug & DBG_MEMSTAT_VALUE ) {
-       m_print_stats("on exit");
-       random_dump_stats();
+  gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE);
+  if ( (opt.debug & DBG_MEMSTAT_VALUE) )
+    {
+      gcry_control (GCRYCTL_DUMP_MEMORY_STATS);
+      gcry_control (GCRYCTL_DUMP_RANDOM_STATS);
     }
-    if( opt.debug )
-       secmem_dump_stats();
-    secmem_term();
-    rc = rc? rc : log_get_errorcount(0)? 2 :
-                       g10_errors_seen? 1 : 0;
-    exit(rc );
+  if (opt.debug)
+    gcry_control (GCRYCTL_DUMP_SECMEM_STATS );
+
+  emergency_cleanup ();
+  
+  rc = rc? rc : log_get_errorcount(0)? 2 : g10_errors_seen? 1 : 0;
+  exit (rc);
 }
 
 
@@ -3861,7 +4008,7 @@ g10_exit( int rc )
    display, but there are a few other similar assumptions in the
    display code. */
 static void
-print_hex( MD_HANDLE md, int algo, const char *fname )
+print_hex( gcry_md_hd_t md, int algo, const char *fname )
 {
   int i,n,count,indent=0;
   const byte *p;
@@ -3878,16 +4025,16 @@ print_hex( MD_HANDLE md, int algo, const char *fname )
   if(algo==DIGEST_ALGO_RMD160)
     indent+=printf("RMD160 = ");
   else if(algo>0)
-    indent+=printf("%6s = ",digest_algo_to_string(algo));
+    indent+=printf("%6s = ", gcry_md_algo_name (algo));
   else
     algo=abs(algo);
 
   count=indent;
 
-  p = md_read( md, algo );
-  n = md_digest_length(algo);
+  p = gcry_md_read (md, algo);
+  n = gcry_md_get_algo_dlen (algo);
 
-  count+=printf("%02X",*p++);
+  count += printf ("%02X",*p++);
 
   for(i=1;i<n;i++,p++)
     {
@@ -3941,7 +4088,7 @@ print_hex( MD_HANDLE md, int algo, const char *fname )
 }
 
 static void
-print_hashline( MD_HANDLE md, int algo, const char *fname )
+print_hashline( gcry_md_hd_t md, int algo, const char *fname )
 {
     int i, n;
     const byte *p;
@@ -3956,8 +4103,8 @@ print_hashline( MD_HANDLE md, int algo, const char *fname )
     }
     putchar(':');
     printf("%d:", algo );
-    p = md_read( md, algo );
-    n = md_digest_length(algo);
+    p = gcry_md_read (md, algo);
+    n = gcry_md_get_algo_dlen (algo);
     for(i=0; i < n ; i++, p++ ) 
         printf("%02X", *p );
     putchar(':');
@@ -3970,7 +4117,7 @@ print_mds( const char *fname, int algo )
     FILE *fp;
     char buf[1024];
     size_t n;
-    MD_HANDLE md;
+    gcry_md_hd_t md;
 
     if( !fname ) {
        fp = stdin;
@@ -3992,65 +4139,65 @@ print_mds( const char *fname, int algo )
        return;
     }
 
-    md = md_open( 0, 0 );
+    gcry_md_open (&md, 0, 0);
     if( algo )
-       md_enable( md, algo );
+        gcry_md_enable (md, algo);
     else {
-       md_enable( md, DIGEST_ALGO_MD5 );
-       md_enable( md, DIGEST_ALGO_SHA1 );
-       md_enable( md, DIGEST_ALGO_RMD160 );
-#ifdef USE_SHA256
-       md_enable( md, DIGEST_ALGO_SHA224 );
-       md_enable( md, DIGEST_ALGO_SHA256 );
-#endif
-#ifdef USE_SHA512
-       md_enable( md, DIGEST_ALGO_SHA384 );
-       md_enable( md, DIGEST_ALGO_SHA512 );
-#endif
+       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);
     }
 
     while( (n=fread( buf, 1, DIM(buf), fp )) )
-       md_write( md, buf, n );
+       gcry_md_write (md, buf, n);
     if( ferror(fp) )
        log_error("%s: %s\n", fname?fname:"[stdin]", strerror(errno) );
     else {
-       md_final(md);
+       gcry_md_final (md);
         if ( opt.with_colons ) {
             if ( algo ) 
                 print_hashline( md, algo, fname );
             else {
-                print_hashline( md, DIGEST_ALGO_MD5, fname );
-                print_hashline( md, DIGEST_ALGO_SHA1, fname );
-                print_hashline( md, DIGEST_ALGO_RMD160, fname );
-#ifdef USE_SHA256
-                print_hashline( md, DIGEST_ALGO_SHA224, fname );
-                print_hashline( md, DIGEST_ALGO_SHA256, fname );
-#endif
-#ifdef USE_SHA512
-               print_hashline( md, DIGEST_ALGO_SHA384, fname );
-               print_hashline( md, DIGEST_ALGO_SHA512, fname );
-#endif
+                print_hashline( md, GCRY_MD_MD5, fname );
+                print_hashline( md, GCRY_MD_SHA1, fname );
+                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, DIGEST_ALGO_MD5, fname );
-                print_hex( md, DIGEST_ALGO_SHA1, fname );
-                print_hex( md, DIGEST_ALGO_RMD160, fname );
-#ifdef USE_SHA256
-                print_hex( md, DIGEST_ALGO_SHA224, fname );
-                print_hex( md, DIGEST_ALGO_SHA256, fname );
-#endif
-#ifdef USE_SHA512
-               print_hex( md, DIGEST_ALGO_SHA384, fname );
-               print_hex( md, DIGEST_ALGO_SHA512, fname );
-#endif
+                print_hex( md, GCRY_MD_MD5, fname );
+                print_hex( md, GCRY_MD_SHA1, fname );
+                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 );
             }
         }
     }
-    md_close(md);
+    gcry_md_close(md);
 
     if( fp != stdin )
        fclose(fp);
@@ -4087,7 +4234,7 @@ static void
 add_policy_url( const char *string, int which )
 {
   unsigned int i,critical=0;
-  STRLIST sl;
+  strlist_t sl;
 
   if(*string=='!')
     {
@@ -4120,7 +4267,7 @@ static void
 add_keyserver_url( const char *string, int which )
 {
   unsigned int i,critical=0;
-  STRLIST sl;
+  strlist_t sl;
 
   if(*string=='!')
     {
@@ -4148,3 +4295,4 @@ add_keyserver_url( const char *string, int which )
   if(critical)
     sl->flags |= 1;    
 }
+