Add new logo.
[gnupg.git] / g10 / gpg.c
index 9485001..000bf1a 100644 (file)
--- a/g10/gpg.c
+++ b/g10/gpg.c
 #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 "status.h"
-#include "g10defs.h"
 #include "keyserver-internal.h"
 #include "exec.h"
-#include "cardglue.h"
-#ifdef ENABLE_CARD_SUPPORT
-#include "ccid-driver.h"
-#endif
+
 
 #if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
 #define MY_O_BINARY  O_BINARY
@@ -82,7 +78,7 @@ enum cmd_and_opt_values
     aDecrypt     = 'd',
     aEncr        = 'e',
     oInteractive  = 'i',
-    oKOption     = 'k',
+    aListKeys    = 'k',
     oDryRun      = 'n',
     oOutput      = 'o',
     oQuiet       = 'q',
@@ -114,18 +110,16 @@ enum cmd_and_opt_values
     aLSignKey,
     aListConfig,
     aGPGConfList,
+    aGPGConfTest,
     aListPackets,
     aEditKey,
     aDeleteKeys,
     aDeleteSecretKeys,
     aDeleteSecretAndPublicKeys,
-    aKMode,
-    aKModeC,
     aImport,
     aFastImport,
     aVerify,
     aVerifyFiles,
-    aListKeys,
     aListSigs,
     aSendKeys,
     aRecvKeys,
@@ -147,16 +141,15 @@ enum cmd_and_opt_values
     aListTrustDB,
     aListTrustPath,
     aExportOwnerTrust,
-    aListOwnerTrust,
     aImportOwnerTrust,
     aDeArmor,
     aEnArmor,
     aGenRandom,
-    aPipeMode,
     aRebuildKeydbCaches,
     aCardStatus,
     aCardEdit,
     aChangePIN,
+    aServer,
 
     oTextmode,
     oNoTextmode,
@@ -186,6 +179,7 @@ enum cmd_and_opt_values
     oNoDefRecipient,
     oOptions,
     oDebug,
+    oDebugLevel,
     oDebugAll,
     oDebugCCIDDriver,
     oStatusFD,
@@ -218,6 +212,7 @@ enum cmd_and_opt_values
     oPasswd,
     oPasswdFD,
     oPasswdFile,
+    oPasswdRepeat,
     oCommandFD,
     oCommandFile,
     oQuickRandom,
@@ -243,7 +238,6 @@ enum cmd_and_opt_values
     oAlwaysTrust,
     oTrustModel,
     oForceOwnertrust,
-    oRunAsShmCP,
     oSetFilename,
     oForYourEyesOnly,
     oNoForYourEyesOnly,
@@ -274,6 +268,7 @@ enum cmd_and_opt_values
     oS2KMode,
     oS2KDigest,
     oS2KCipher,
+    oS2KCount,
     oSimpleSKChecksum,                          
     oDisplayCharset,
     oNotDashEscaped,
@@ -333,9 +328,11 @@ enum cmd_and_opt_values
     oNoAutoCheckTrustDB,
     oPreservePermissions,
     oDefaultPreferenceList,
+    oDefaultKeyserverURL,
     oPersonalCipherPreferences,
     oPersonalDigestPreferences,
     oPersonalCompressPreferences,
+    oAgentProgram,
     oDisplay,
     oTTYname,
     oTTYtype,
@@ -353,15 +350,15 @@ enum cmd_and_opt_values
     oKeyidFormat,
     oExitOnStatusWriteError,
     oLimitCardInsertTries,
-    oReaderPort,
-    octapiDriver,
-    opcscDriver,
-    oDisableCCID,
-    oRequireBacksigs,
-    oNoRequireBacksigs,
+    oRequireCrossCert,
+    oNoRequireCrossCert,
     oAutoKeyLocate,
     oNoAutoKeyLocate,
     oAllowMultisigVerification,
+    oEnableDSA2,
+    oDisableDSA2,
+    oAllowMultipleMessages,
+    oNoAllowMultipleMessages,
 
     oNoop
   };
@@ -416,6 +413,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, "@"},
@@ -429,7 +427,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 ") },
 
@@ -502,6 +501,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, "@"},
@@ -531,6 +531,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, "@"},
@@ -561,19 +562,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, "@" },
@@ -600,7 +599,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, "@" },
@@ -625,7 +623,7 @@ static ARGPARSE_OPTS opts[] = {
     { oLockMultiple, "lock-multiple", 0, "@" },
     { oLockNever, "lock-never", 0, "@" },
     { oLoggerFD, "logger-fd",1, "@" },
-    { oLoggerFile, "logger-file",2, "@" },
+    { oLoggerFile, "log-file",2, "@" },
     { oUseEmbeddedFilename, "use-embedded-filename", 0, "@" },
     { oNoUseEmbeddedFilename, "no-use-embedded-filename", 0, "@" },
     { oUtf8Strings, "utf8-strings", 0, "@" },
@@ -665,6 +663,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, "@"},
@@ -673,6 +672,7 @@ 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, "@" },
@@ -691,14 +691,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
@@ -706,10 +703,13 @@ static ARGPARSE_OPTS opts[] = {
        I'm returning the favor. */
     { oLocalUser, "sign-with", 2, "@" },
     { oRecipient, "user", 2, "@" },
-    { oRequireBacksigs, "require-backsigs", 0, "@"},
-    { oNoRequireBacksigs, "no-require-backsigs", 0, "@"},
+    { 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,9 +734,11 @@ 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;
     const char *p;
@@ -779,31 +781,35 @@ 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', 
+                                 gcry_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;
 
-      default: p = default_strusage(level);
+      default: p = NULL;
     }
     return p;
 }
@@ -818,8 +824,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)) )
@@ -868,12 +874,12 @@ static void
 i18n_init(void)
 {
 #ifdef USE_SIMPLE_GETTEXT
-    set_gettext_file (PACKAGE, "Software\\GNU\\GnuPG");
+  set_gettext_file (PACKAGE_GT, "Software\\GNU\\GnuPG");
 #else
 #ifdef ENABLE_NLS
-    setlocale( LC_ALL, "" );
-    bindtextdomain( PACKAGE, G10_LOCALEDIR );
-    textdomain( PACKAGE );
+  setlocale (LC_ALL, "");
+  bindtextdomain (PACKAGE_GT, LOCALEDIR);
+  textdomain (PACKAGE_GT);
 #endif
 #endif
 }
@@ -900,31 +906,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;
 }
 
 
@@ -933,7 +963,7 @@ set_homedir (char *dir)
 static void
 set_screen_dimensions(void)
 {
-#ifndef _WIN32
+#ifndef HAVE_W32_SYSTEM
   char *str;
 
   str=getenv("COLUMNS");
@@ -1017,8 +1047,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)
@@ -1347,7 +1375,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),':');
@@ -1355,7 +1383,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(";");
                }
@@ -1377,7 +1405,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;
        }
@@ -1385,7 +1413,7 @@ 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;
        }
@@ -1395,7 +1423,7 @@ list_config(char *items)
         || 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;
        }
@@ -1410,7 +1438,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)
@@ -1619,6 +1649,122 @@ parse_trust_model(const char *model)
     log_error("unknown trust model `%s'\n",model);
 }
 
+
+
+/* Make sure that the standard file descriptors are opened. Obviously
+   some folks close them before an exec and the next file we open will
+   get one of them assigned and thus any output (i.e. diagnostics) end
+   up in that file (e.g. the trustdb).  Not actually a gpg problem as
+   this will hapenn with almost all utilities when called in a wrong
+   way.  However we try to minimize the damage here and raise
+   awareness of the problem.
+
+   Must be called before we open any files! */
+static void
+reopen_std(void)
+{  
+#if defined(HAVE_STAT) && !defined(HAVE_W32_SYSTEM)
+  struct stat statbuf;
+  int did_stdin=0,did_stdout=0,did_stderr=0;
+  FILE *complain;
+
+  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)
+    {
+      if(open("/dev/null",O_WRONLY)==STDOUT_FILENO)
+       did_stdout=1;
+      else
+       did_stdout=2;
+    }
+
+  if(fstat(STDERR_FILENO,&statbuf)==-1 && errno==EBADF)
+    {
+      if(open("/dev/null",O_WRONLY)==STDERR_FILENO)
+       did_stderr=1;
+      else
+       did_stderr=2;
+    }
+
+  /* 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");
+    }
+
+  if(did_stdin==2 || did_stdout==2 || did_stderr==2)
+    exit(3);
+#endif /* HAVE_STAT && !HAVE_W32_SYSTEM */
+}
+
+/* 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
+gpg_init_default_ctrl (ctrl_t ctrl)
+{
+}
+
+
+/* This function is called to deinitialize a control object.  It is
+   not deallocated. */
+static void
+gpg_deinit_default_ctrl (ctrl_t ctrl)
+{
+}
+
+
+
 int
 main (int argc, char **argv )
 {
@@ -1630,9 +1776,9 @@ 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;
@@ -1643,8 +1789,10 @@ main (int argc, char **argv )
     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;
@@ -1661,26 +1809,44 @@ 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__ */
 
-    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. */
+    reopen_std ();
+    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);
+
+    /* 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 */
@@ -1690,6 +1856,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
@@ -1718,18 +1885,9 @@ main (int argc, char **argv )
     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";
-#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;
@@ -1752,27 +1910,12 @@ main (int argc, char **argv )
            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
@@ -1791,22 +1934,24 @@ 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();
 #endif
+    maybe_setuid = 0;
+
+    /* Okay, we are now working under our real uid */
+
+    /* malloc hooks go here ... */
+    assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
+    assuan_set_assuan_err_source (GPG_ERR_SOURCE_DEFAULT);
 
     set_native_charset (NULL); /* Try to auto set the character set */
 
@@ -1910,6 +2055,7 @@ main (int argc, char **argv )
          case aCheckKeys: 
          case aListConfig:
           case aGPGConfList:
+          case aGPGConfTest:
          case aListPackets:
          case aImport: 
          case aFastImport: 
@@ -1919,24 +2065,50 @@ 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 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;
@@ -1947,49 +2119,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;
@@ -1999,24 +2132,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:
+           obsolete_option (configname, configlineno, "--no-use-agent");
+            break;
+         case oGpgAgentInfo: 
+           obsolete_option (configname, configlineno, "--gpg-agent-info");
             break;
-          case oNoUseAgent: opt.use_agent = 0; break;
-         case oGpgAgentInfo: opt.gpg_agent_info = pargs.r.ret_str; 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;
@@ -2029,13 +2164,11 @@ 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) );
             break;
@@ -2049,11 +2182,10 @@ main (int argc, char **argv )
             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 (iobuf_translate_file_handle (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:
@@ -2074,9 +2206,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;
@@ -2085,17 +2222,17 @@ 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;
@@ -2171,18 +2308,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: opt.set_filename = 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:
@@ -2208,8 +2339,12 @@ main (int argc, char **argv )
            opt.verify_options&=~VERIFY_SHOW_POLICY_URLS;
            break;
          case oSigKeyserverURL: add_keyserver_url(pargs.r.ret_str,0); break;
-         case oUseEmbeddedFilename: opt.use_embedded_filename = 1; break;
-         case oNoUseEmbeddedFilename: opt.use_embedded_filename = 0; break;
+         case oUseEmbeddedFilename:
+           opt.flags.use_embedded_filename=1;
+           break;
+         case oNoUseEmbeddedFilename:
+           opt.flags.use_embedded_filename=0;
+           break;
          case oComment:
            if(pargs.r.ret_str[0])
              append_to_strlist(&opt.comments,pargs.r.ret_str);
@@ -2252,6 +2387,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 */
@@ -2319,11 +2457,11 @@ main (int argc, char **argv )
            break;
          case oPasswdFD:
             pwfd = iobuf_translate_file_handle (pargs.r.ret_int, 0);
-            opt.use_agent = 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);
             break;
@@ -2360,8 +2498,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;
@@ -2377,7 +2521,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__
@@ -2462,7 +2605,9 @@ 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")},
-                 {"pka-lookup",VERIFY_PKA_LOOKUP,NULL,
+                 {"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,
                   N_("elevate the trust of signatures with valid PKA data")},
@@ -2511,11 +2656,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;
@@ -2573,6 +2724,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;
@@ -2582,6 +2746,7 @@ 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;
@@ -2598,8 +2763,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;
@@ -2625,8 +2794,8 @@ main (int argc, char **argv )
             opt.limit_card_insert_tries = pargs.r.ret_int; 
             break;
 
-         case oRequireBacksigs: opt.require_backsigs=1; break;
-         case oNoRequireBacksigs: opt.require_backsigs=0; break;
+         case oRequireCrossCert: opt.flags.require_cross_cert=1; break;
+         case oNoRequireCrossCert: opt.flags.require_cross_cert=0; break;
 
          case oAutoKeyLocate:
            if(!parse_auto_key_locate(pargs.r.ret_str))
@@ -2642,9 +2811,17 @@ main (int argc, char **argv )
            release_akl();
            break;
 
+         case oEnableDSA2: opt.flags.dsa2=1; break;
+         case oDisableDSA2: opt.flags.dsa2=0; break;
+
           case oAllowMultisigVerification:
-            opt.allow_multisig_verification = 1;
-            break;
+         case oAllowMultipleMessages:
+           opt.flags.allow_multiple_messages=1;
+           break;
+
+         case oNoAllowMultipleMessages:
+           opt.flags.allow_multiple_messages=0;
+           break;
 
          case oNoop: break;
 
@@ -2699,6 +2876,16 @@ 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);
+      }
+
     if (opt.verbose > 2)
         log_info ("using character set `%s'\n", get_native_charset ());
 
@@ -2724,20 +2911,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)
       {
@@ -2746,7 +2926,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)
@@ -2778,7 +2958,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"));
@@ -2837,47 +3017,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"));
@@ -2972,26 +3151,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 = gcry_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)
@@ -3021,10 +3200,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);
@@ -3034,39 +3213,29 @@ 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 )
+      {
+        log_info ("compatibility note:\n");
+        log_info ("\"-sat\" won't generate clear signed messages in "
+                  "future versions\n");
+        log_info ("Use \"--clearsign\" instead of \"-sat\"\n");
        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
@@ -3085,12 +3254,18 @@ 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;
 
+    if(fname && utf8_strings)
+      opt.flags.utf8_filename=1;
+
     switch( cmd ) {
       case aPrimegen:
       case aPrintMD:
@@ -3125,6 +3300,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]"));
@@ -3348,34 +3533,6 @@ main (int argc, char **argv )
        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]") );
-       break;
-
       case aKeygen: /* generate a key */
        if( opt.batch ) {
            if( argc > 1 )
@@ -3395,12 +3552,17 @@ main (int argc, char **argv )
        import_keys( argc? argv:NULL, argc, NULL, opt.import_options );
        break;
 
+       /* TODO: There are a number of command that use this same
+          "make strlist, call function, report error, free strlist"
+          pattern.  Join them together here and avoid all that
+          duplicated code. */
+
       case aExport:
       case aSendKeys:
       case aRecvKeys:
        sl = NULL;
        for( ; argc; argc--, argv++ )
-           add_to_strlist2( &sl, *argv, utf8_strings );
+           append_to_strlist2( &sl, *argv, utf8_strings );
        if( cmd == aSendKeys )
            rc=keyserver_export( sl );
        else if( cmd == aRecvKeys )
@@ -3432,7 +3594,7 @@ main (int argc, char **argv )
       case aRefreshKeys:
        sl = NULL;
        for( ; argc; argc--, argv++ )
-           add_to_strlist2( &sl, *argv, utf8_strings );
+           append_to_strlist2( &sl, *argv, utf8_strings );
        rc=keyserver_refresh(sl);
        if(rc)
          log_error(_("keyserver refresh failed: %s\n"),g10_errstr(rc));
@@ -3442,7 +3604,7 @@ main (int argc, char **argv )
       case aFetchKeys:
        sl = NULL;
        for( ; argc; argc--, argv++ )
-           add_to_strlist2( &sl, *argv, utf8_strings );
+           append_to_strlist2( &sl, *argv, utf8_strings );
        rc=keyserver_fetch(sl);
        if(rc)
          log_error("key fetch failed: %s\n",g10_errstr(rc));
@@ -3499,6 +3661,7 @@ main (int argc, char **argv )
 
 
       case aPrimegen:
+#if 0 /*FIXME*/
        {   int mode = argc < 2 ? 0 : atoi(*argv);
 
            if( mode == 1 && argc == 2 ) {
@@ -3530,6 +3693,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:
@@ -3549,7 +3714,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
@@ -3578,7 +3743,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 );
@@ -3651,12 +3816,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");
@@ -3723,8 +3882,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 ) {
@@ -3740,6 +3899,7 @@ main (int argc, char **argv )
       }
 
     /* cleanup */
+    release_armor_context (afx);
     FREE_STRLIST(remusr);
     FREE_STRLIST(locusr);
     g10_exit(0);
@@ -3747,23 +3907,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);
 }
 
 
@@ -3771,7 +3938,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;
@@ -3788,16 +3955,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++)
     {
@@ -3851,7 +4018,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;
@@ -3866,8 +4033,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(':');
@@ -3880,7 +4047,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;
@@ -3902,62 +4069,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_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 (DIGEST_ALGO_SHA224))
+          gcry_md_enable (md, DIGEST_ALGO_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_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 (DIGEST_ALGO_SHA224))
+                    print_hashline (md, DIGEST_ALGO_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_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 (DIGEST_ALGO_SHA224))
+                    print_hex (md, DIGEST_ALGO_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);
@@ -3972,76 +4142,29 @@ print_mds( const char *fname, int algo )
 static void
 add_notation_data( const char *string, int which )
 {
-    const char *s;
-    STRLIST sl,*notation_data;
-    int critical=0;
-    int highbit=0;
-    int saw_at=0;
+  struct notation *notation;
 
-    if(which)
-      notation_data=&opt.cert_notation_data;
-    else
-      notation_data=&opt.sig_notation_data;
-
-    if( *string == '!' ) {
-       critical = 1;
-       string++;
-    }
-
-    /* If and when the IETF assigns some official name tags, we'll
-       have to add them here. */
-
-    for( s=string ; *s != '='; s++ )
-      {
-       if( *s=='@')
-         saw_at++;
-
-       if( !*s || !isascii (*s) || (!isgraph(*s) && !isspace(*s)) )
-         {
-           log_error(_("a notation name must have only printable characters "
-                       "or spaces, and end with an '='\n") );
-           return;
-         }
-      }
-
-    if(!saw_at && !opt.expert)
-      {
-       log_error(_("a user notation name must contain the '@' character\n"));
-       return;
-      }
-    if (saw_at > 1)
-      {
-       log_error(_("a notation name must not contain more than "
-                    "one '@' character\n"));
-       return;
-      }
-
-    /* we only support printable text - therefore we enforce the use
-     * of only printable characters (an empty value is valid) */
-    for( s++; *s ; s++ ) {
-       if ( !isascii (*s) )
-          highbit = 1;
-       else if (iscntrl(*s)) {
-           log_error(_("a notation value must not use"
-                       " any control characters\n") );
-           return;
+  notation=string_to_notation(string,utf8_strings);
+  if(notation)
+    {
+      if(which)
+       {
+         notation->next=opt.cert_notations;
+         opt.cert_notations=notation;
+       }
+      else
+       {
+         notation->next=opt.sig_notations;
+         opt.sig_notations=notation;
        }
     }
-
-    if( highbit )   /* must use UTF8 encoding */
-       sl = add_to_strlist2( notation_data, string, utf8_strings );
-    else
-       sl = add_to_strlist( notation_data, string );
-
-    if( critical )
-       sl->flags |= 1;
 }
 
 static void
 add_policy_url( const char *string, int which )
 {
   unsigned int i,critical=0;
-  STRLIST sl;
+  strlist_t sl;
 
   if(*string=='!')
     {
@@ -4074,7 +4197,7 @@ static void
 add_keyserver_url( const char *string, int which )
 {
   unsigned int i,critical=0;
-  STRLIST sl;
+  strlist_t sl;
 
   if(*string=='!')
     {
@@ -4102,3 +4225,4 @@ add_keyserver_url( const char *string, int which )
   if(critical)
     sl->flags |= 1;    
 }
+