Changes to make use of code taken from libassuan. This replaces the
[gnupg.git] / g10 / g10.c
index 8c4d36a..fefb8ab 100644 (file)
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -1,5 +1,6 @@
 /* g10.c - The GnuPG utility (main for gpg)
- * Copyright (C) 1998,1999,2000,2001,2002,2003 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
+ *               2004, 2005 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -32,6 +33,7 @@
 #ifdef HAVE_STAT
 #include <sys/stat.h> /* for stat() */
 #endif
+#include <fcntl.h>
 
 #define INCLUDED_BY_MAIN_MODULE 1
 #include "packet.h"
 #include "g10defs.h"
 #include "keyserver-internal.h"
 #include "exec.h"
+#include "cardglue.h"
+#ifdef ENABLE_CARD_SUPPORT
+#include "ccid-driver.h"
+#endif
 
-enum cmd_and_opt_values { aNull = 0,
+#if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
+#define MY_O_BINARY  O_BINARY
+#ifndef S_IRGRP
+# define S_IRGRP 0
+# define S_IWGRP 0
+#endif
+#else
+#define MY_O_BINARY  0
+#endif
+
+
+enum cmd_and_opt_values
+  {
+    aNull = 0,
     oArmor       = 'a',
     aDetachedSign = 'b',
     aSym         = 'c',
     aDecrypt     = 'd',
     aEncr        = 'e',
-    aEncrFiles,
     oInteractive  = 'i',
     oKOption     = 'k',
     oDryRun      = 'n',
@@ -72,21 +90,26 @@ enum cmd_and_opt_values { aNull = 0,
     oVerbose     = 'v',
     oCompress    = 'z',
     oSetNotation  = 'N',
+    aListSecretKeys = 'K',
     oBatch       = 500,
+    oMaxOutput,
     oSigNotation,
     oCertNotation,
     oShowNotation,
     oNoShowNotation,
-    aDecryptFiles,                          
+    aEncrFiles,
+    aEncrSym,
+    aDecryptFiles,
     aClearsign,
     aStore,
     aKeygen,
     aSignEncr,
+    aSignEncrSym,
     aSignSym,
     aSignKey,
     aLSignKey,
-    aNRSignKey,
-    aNRLSignKey,
+    aListConfig,
+    aGPGConfList,
     aListPackets,
     aEditKey,
     aDeleteKeys,
@@ -100,12 +123,10 @@ enum cmd_and_opt_values { aNull = 0,
     aVerifyFiles,
     aListKeys,
     aListSigs,
-    aListSecretKeys,
     aSendKeys,
     aRecvKeys,
     aSearchKeys,
     aExport,
-    aExportAll,
     aExportSecret,
     aExportSecretSub,
     aCheckKeys,
@@ -128,6 +149,9 @@ enum cmd_and_opt_values { aNull = 0,
     aPipeMode,
     aRebuildKeydbCaches,
     aRefreshKeys,
+    aCardStatus,
+    aCardEdit,
+    aChangePIN,
 
     oTextmode,
     oNoTextmode,
@@ -137,11 +161,14 @@ enum cmd_and_opt_values { aNull = 0,
     oNoAskSigExpire,
     oAskCertExpire,
     oNoAskCertExpire,
+    oAskCertLevel,
+    oNoAskCertLevel,
     oFingerprint,
     oWithFingerprint,
     oAnswerYes,
     oAnswerNo,
-    oDefCertCheckLevel,
+    oDefCertLevel,
+    oMinCertLevel,
     oKeyring,
     oPrimaryKeyring,
     oSecretKeyring,
@@ -153,14 +180,11 @@ enum cmd_and_opt_values { aNull = 0,
     oOptions,
     oDebug,
     oDebugAll,
+    oDebugCCIDDriver,
     oStatusFD,
-#ifdef __riscos__
     oStatusFile,
-#endif /* __riscos__ */
     oAttributeFD,
-#ifdef __riscos__
     oAttributeFile,
-#endif /* __riscos__ */
     oSKComments,
     oNoSKComments,
     oEmitVersion,
@@ -177,22 +201,25 @@ enum cmd_and_opt_values { aNull = 0,
     oPGP6,
     oPGP7,
     oPGP8,
+    oRFC2440Text,
+    oNoRFC2440Text,
     oCipherAlgo,
     oDigestAlgo,
     oCertDigestAlgo,
     oCompressAlgo,
+    oCompressLevel,
+    oBZ2CompressLevel,
+    oBZ2DecompressLowmem,
     oPasswdFD,
-#ifdef __riscos__
     oPasswdFile,
-#endif /* __riscos__ */
     oCommandFD,
-#ifdef __riscos__
     oCommandFile,
-#endif /* __riscos__ */
     oQuickRandom,
     oNoVerbose,
     oTrustDBName,
     oNoSecmemWarn,
+    oRequireSecmem,
+    oNoRequireSecmem,
     oNoPermissionWarn,
     oNoMDCWarn,
     oNoArmor,
@@ -210,7 +237,6 @@ enum cmd_and_opt_values { aNull = 0,
     oAlwaysTrust,
     oTrustModel,
     oForceOwnertrust,
-    oEmuChecksumBug,
     oRunAsShmCP,
     oSetFilename,
     oForYourEyesOnly,
@@ -222,10 +248,12 @@ enum cmd_and_opt_values { aNull = 0,
     oNoShowPolicyURL,
     oSigKeyserverURL,
     oUseEmbeddedFilename,
+    oNoUseEmbeddedFilename,
     oComment,
     oDefaultComment,
-    oThrowKeyid,
-    oNoThrowKeyid,
+    oNoComments,
+    oThrowKeyids,
+    oNoThrowKeyids,
     oShowPhotos,
     oNoShowPhotos,
     oPhotoViewer,
@@ -241,7 +269,7 @@ enum cmd_and_opt_values { aNull = 0,
     oS2KDigest,
     oS2KCipher,
     oSimpleSKChecksum,                          
-    oCharset,
+    oDisplayCharset,
     oNotDashEscaped,
     oEscapeFrom,
     oNoEscapeFrom,
@@ -260,9 +288,7 @@ enum cmd_and_opt_values { aNull = 0,
     oHiddenEncryptTo,
     oNoEncryptTo,
     oLoggerFD,
-#ifdef __riscos__
     oLoggerFile,
-#endif /* __riscos__ */
     oUtf8Strings,
     oNoUtf8Strings,
     oDisableCipherAlgo,
@@ -304,19 +330,29 @@ enum cmd_and_opt_values { aNull = 0,
     oPersonalCipherPreferences,
     oPersonalDigestPreferences,
     oPersonalCompressPreferences,
-    oEmuMDEncodeBug,
     oDisplay,
     oTTYname,
     oTTYtype,
     oLCctype,
     oLCmessages,
     oGroup,
+    oUnGroup,
+    oNoGroups,
     oStrict,
     oNoStrict,
     oMangleDosFilenames,
     oNoMangleDosFilenames,
-    oEnableProgressFilter,                          
-aTest };
+    oEnableProgressFilter,
+    oMultifile,
+    oKeyidFormat,
+
+    oReaderPort,
+    octapiDriver,
+    opcscDriver,
+    oDisableCCID,
+
+    aTest
+  };
 
 
 static ARGPARSE_OPTS opts[] = {
@@ -324,20 +360,20 @@ static ARGPARSE_OPTS opts[] = {
     { 300, NULL, 0, N_("@Commands:\n ") },
 
     { aSign, "sign",      256, N_("|[file]|make a signature")},
-    { aClearsign, "clearsign", 256, N_("|[file]|make a clear text signature") },
+    { aClearsign, "clearsign", 256, N_("|[file]|make a clear text signature")},
     { aDetachedSign, "detach-sign", 256, N_("make a detached signature")},
     { aEncr, "encrypt",   256, N_("encrypt data")},
-    { aEncrFiles, "encrypt-files", 256, N_("|[files]|encrypt files")},
+    { aEncrFiles, "encrypt-files", 256, "@"},
     { aSym, "symmetric", 256, N_("encryption only with symmetric cipher")},
-    { aStore, "store",     256, N_("store only")},
+    { aStore, "store",     256, "@"},
     { aDecrypt, "decrypt",   256, N_("decrypt data (default)")},
-    { aDecryptFiles, "decrypt-files", 256, N_("|[files]|decrypt files")},
+    { aDecryptFiles, "decrypt-files", 256, "@"},
     { aVerify, "verify"   , 256, N_("verify a signature")},
     { aVerifyFiles, "verify-files" , 256, "@" },
     { aListKeys, "list-keys", 256, N_("list keys")},
     { aListKeys, "list-public-keys", 256, "@" },
     { aListSigs, "list-sigs", 256, N_("list keys and signatures")},
-    { aCheckKeys, "check-sigs",256, N_("check key signatures")},
+    { aCheckKeys, "check-sigs",256, N_("list and check key signatures")},
     { oFingerprint, "fingerprint", 256, N_("list keys and fingerprints")},
     { aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")},
     { aKeygen,    "gen-key",  256, N_("generate a new key pair")},
@@ -346,8 +382,6 @@ static ARGPARSE_OPTS opts[] = {
                                    N_("remove keys from the secret keyring")},
     { aSignKey,  "sign-key"   ,256, N_("sign a key")},
     { aLSignKey, "lsign-key"  ,256, N_("sign a key locally")},
-    { aNRSignKey, "nrsign-key"  ,256, N_("sign a key non-revocably")},
-    { aNRLSignKey, "nrlsign-key"  ,256, N_("sign a key locally and non-revocably")},
     { aEditKey,  "edit-key"   ,256, N_("sign or edit a key")},
     { aGenRevoke, "gen-revoke",256, N_("generate a revocation certificate")},
     { aDesigRevoke, "desig-revoke",256, "@" },
@@ -358,25 +392,28 @@ static ARGPARSE_OPTS opts[] = {
                                     N_("search for keys on a key server") },
     { aRefreshKeys, "refresh-keys", 256,
                                     N_("update all keys from a keyserver")},
-    { aExportAll, "export-all"    , 256, "@" },
     { aExportSecret, "export-secret-keys" , 256, "@" },
     { aExportSecretSub, "export-secret-subkeys" , 256, "@" },
     { aImport, "import",      256     , N_("import/merge keys")},
     { aFastImport, "fast-import",  256 , "@"},
-    { aListPackets, "list-packets",256,N_("list only the sequence of packets")},
-    { aExportOwnerTrust,
-             "export-ownertrust", 256, N_("export the ownertrust values")},
-    { aImportOwnerTrust,
-             "import-ownertrust", 256, N_("import ownertrust values")},
+#ifdef ENABLE_CARD_SUPPORT
+    { aCardStatus,  "card-status", 256, N_("print the card status")},
+    { aCardEdit,   "card-edit",  256, N_("change data on a card")},
+    { aChangePIN,  "change-pin", 256, N_("change a card's PIN")},
+#endif
+    { aListConfig, "list-config", 256, "@"},
+    { aGPGConfList, "gpgconf-list", 256, "@" },
+    { aListPackets, "list-packets",256, "@"},
+    { aExportOwnerTrust, "export-ownertrust", 256, "@"},
+    { aImportOwnerTrust, "import-ownertrust", 256, "@"},
     { aUpdateTrustDB,
              "update-trustdb",0 , N_("update the trust database")},
-    { aCheckTrustDB,
-             "check-trustdb",0 , N_("unattended trust database update")},
-    { aFixTrustDB, "fix-trustdb",0 , N_("fix a corrupted trust database")},
-    { aDeArmor, "dearmor", 256, N_("De-Armor a file or stdin") },
-    { aDeArmor, "dearmour", 256, "@" },
-    { aEnArmor, "enarmor", 256, N_("En-Armor a file or stdin") },
-    { aEnArmor, "enarmour", 256, "@" },
+    { aCheckTrustDB, "check-trustdb", 0, "@"},
+    { aFixTrustDB, "fix-trustdb", 0, "@"},
+    { aDeArmor, "dearmor", 256, "@"},
+    { aDeArmor, "dearmour", 256, "@"},
+    { aEnArmor, "enarmor", 256, "@"},
+    { aEnArmor, "enarmour", 256, "@"},
     { aPrintMD,  "print-md" , 256, N_("|algo [files]|print message digests")},
     { aPrimegen, "gen-prime" , 256, "@" },
     { aGenRandom, "gen-random" , 256, "@" },
@@ -388,10 +425,8 @@ static ARGPARSE_OPTS opts[] = {
     { oRecipient, "recipient", 2, N_("|NAME|encrypt for NAME")},
     { oHiddenRecipient, "hidden-recipient", 2, "@" },
     { oRecipient, "remote-user", 2, "@"},  /* old option name */
-    { oDefRecipient, "default-recipient" ,2,
-                                 N_("|NAME|use NAME as default recipient")},
-    { oDefRecipientSelf, "default-recipient-self" ,0,
-                               N_("use the default key as default recipient")},
+    { oDefRecipient, "default-recipient", 2, "@"},
+    { oDefRecipientSelf, "default-recipient-self", 0, "@"},
     { oNoDefRecipient, "no-default-recipient", 0, "@" },
     { oTempDir, "temp-directory", 2, "@" },
     { oExecPath, "exec-path", 2, "@" },
@@ -399,7 +434,10 @@ static ARGPARSE_OPTS opts[] = {
     { oHiddenEncryptTo, "hidden-encrypt-to", 2, "@" },
     { oNoEncryptTo, "no-encrypt-to", 0, "@" },
     { oUser, "local-user",2, N_("use this user-id to sign or decrypt")},
-    { oCompress, NULL,       1, N_("|N|set compress level N (0 disables)") },
+    { oCompress, NULL, 1, N_("|N|set compress level N (0 disables)") },
+    { oCompressLevel, "compress-level", 1, "@" },
+    { oBZ2CompressLevel, "bzip2-compress-level", 1, "@" },
+    { oBZ2DecompressLowmem, "bzip2-decompress-lowmem", 0, "@" },
     { oTextmodeShort, NULL,   0, "@"},
     { oTextmode, "textmode",  0, N_("use canonical text mode")},
     { oNoTextmode, "no-textmode",  0, "@"},
@@ -409,82 +447,83 @@ static ARGPARSE_OPTS opts[] = {
     { oNoAskSigExpire, "no-ask-sig-expire",   0, "@"},
     { oAskCertExpire, "ask-cert-expire",   0, "@"},
     { oNoAskCertExpire, "no-ask-cert-expire",   0, "@"},
+    { oAskCertLevel, "ask-cert-level",   0, "@"},
+    { oNoAskCertLevel, "no-ask-cert-level",   0, "@"},
     { oOutput, "output",    2, N_("use as output file")},
+    { oMaxOutput, "max-output", 16|4, "@" },
     { oVerbose, "verbose",   0, N_("verbose") },
-    { oQuiet,  "quiet",   0, N_("be somewhat more quiet") },
-    { oNoTTY, "no-tty", 0, N_("don't use the terminal at all") },
-    { oForceV3Sigs, "force-v3-sigs", 0, N_("force v3 signatures") },
-    { oNoForceV3Sigs, "no-force-v3-sigs", 0, N_("do not force v3 signatures") },
-    { oForceV4Certs, "force-v4-certs", 0, N_("force v4 key signatures") },
-    { oNoForceV4Certs, "no-force-v4-certs", 0, N_("do not force v4 key signatures") },
-    { oForceMDC, "force-mdc", 0, N_("always use a MDC for encryption") },
+    { oQuiet,  "quiet",   0, "@"},
+    { oNoTTY, "no-tty", 0, "@"},
+    { oForceV3Sigs, "force-v3-sigs", 0, "@"},
+    { oNoForceV3Sigs, "no-force-v3-sigs", 0, "@"},
+    { oForceV4Certs, "force-v4-certs", 0, "@"},
+    { oNoForceV4Certs, "no-force-v4-certs", 0, "@"},
+    { oForceMDC, "force-mdc", 0, "@"},
     { oNoForceMDC, "no-force-mdc", 0, "@" },
-    { oDisableMDC, "disable-mdc", 0, N_("never use a MDC for encryption") },
+    { oDisableMDC, "disable-mdc", 0, "@"},
     { oNoDisableMDC, "no-disable-mdc", 0, "@" },
     { oDryRun, "dry-run",   0, N_("do not make any changes") },
     { oInteractive, "interactive", 0, N_("prompt before overwriting") },
-    { oUseAgent, "use-agent",0, N_("use the gpg-agent")},
+    { oUseAgent, "use-agent",0, "@"},
     { oNoUseAgent, "no-use-agent",0, "@"},
     { oGpgAgentInfo, "gpg-agent-info",2, "@"},
-    { oBatch, "batch",     0, N_("batch mode: never ask")},
-    { oAnswerYes, "yes",       0, N_("assume yes on most questions")},
-    { oAnswerNo,  "no",        0, N_("assume no on most questions")},
-    { oKeyring, "keyring"   ,2, N_("add this keyring to the list of keyrings")},
+    { oBatch, "batch", 0, "@"},
+    { oAnswerYes, "yes", 0, "@"},
+    { oAnswerNo, "no", 0, "@"},
+    { oKeyring, "keyring", 2, "@"},
     { oPrimaryKeyring, "primary-keyring",2, "@" },
-    { oSecretKeyring, "secret-keyring" ,2, N_("add this secret keyring to the list")},
-    { oShowKeyring, "show-keyring", 0, N_("show which keyring a listed key is on")},
-    { oDefaultKey, "default-key" ,2, N_("|NAME|use NAME as default secret key")},
-    { oKeyServer, "keyserver",2, N_("|HOST|use this keyserver to lookup keys")},
+    { oSecretKeyring, "secret-keyring", 2, "@"},
+    { oShowKeyring, "show-keyring", 0, "@"},
+    { oDefaultKey, "default-key", 2, "@"},
+    { oKeyServer, "keyserver", 2, "@"},
     { oKeyServerOptions, "keyserver-options",2,"@"},
     { oImportOptions, "import-options",2,"@"},
     { oExportOptions, "export-options",2,"@"},
     { oListOptions, "list-options",2,"@"},
     { oVerifyOptions, "verify-options",2,"@"},
-    { oCharset, "charset"   , 2, N_("|NAME|set terminal charset to NAME") },
-    { oOptions, "options"   , 2, N_("read options from file")},
-
+    { oDisplayCharset, "display-charset", 2, "@"},
+    { oDisplayCharset, "charset", 2, "@"},
+    { oOptions, "options", 2, "@"},
     { oDebug, "debug"     ,4|16, "@"},
     { oDebugAll, "debug-all" ,0, "@"},
-    { oStatusFD, "status-fd" ,1, N_("|FD|write status info to this FD") },
-#ifdef __riscos__
-    { oStatusFile, "status-file" ,2, N_("|[file]|write status info to file") },
-#endif /* __riscos__ */
+    { oStatusFD, "status-fd" ,1, "@"},
+    { oStatusFile, "status-file" ,2, "@"},
     { oAttributeFD, "attribute-fd" ,1, "@" },
-#ifdef __riscos__
     { oAttributeFile, "attribute-file" ,2, "@" },
-#endif /* __riscos__ */
-    { oNoSKComments, "no-comment", 0,   "@"},
     { oNoSKComments, "no-sk-comments", 0,   "@"},
     { oSKComments, "sk-comments", 0,   "@"},
     { oCompletesNeeded, "completes-needed", 1, "@"},
     { oMarginalsNeeded, "marginals-needed", 1, "@"},
     { oMaxCertDepth,   "max-cert-depth", 1, "@" },
-    { oTrustedKey, "trusted-key", 2, N_("|KEYID|ultimately trust this key")},
-    { oLoadExtension, "load-extension" ,2, N_("|FILE|load extension module FILE")},
+    { oTrustedKey, "trusted-key", 2, "@"},
+    { oLoadExtension, "load-extension", 2, "@"},
     { oGnuPG, "gnupg",   0, "@"},
     { oGnuPG, "no-pgp2", 0, "@"},
     { oGnuPG, "no-pgp6", 0, "@"},
     { oGnuPG, "no-pgp7", 0, "@"},
     { oGnuPG, "no-pgp8", 0, "@"},
-    { oRFC1991, "rfc1991",   0, N_("emulate the mode described in RFC1991")},
+    { oRFC1991, "rfc1991",   0, "@"},
     { oRFC2440, "rfc2440", 0, "@" },
-    { oOpenPGP, "openpgp", 0, N_("set all packet, cipher and digest options to OpenPGP behavior")},
-    { oPGP2, "pgp2", 0, N_("set all packet, cipher and digest options to PGP 2.x behavior")},
+    { oOpenPGP, "openpgp", 0, N_("use strict OpenPGP behavior")},
+    { oPGP2, "pgp2", 0, N_("generate PGP 2.x compatible messages")},
     { oPGP6, "pgp6", 0, "@"},
     { oPGP7, "pgp7", 0, "@"},
     { oPGP8, "pgp8", 0, "@"},
-    { oS2KMode, "s2k-mode",  1, N_("|N|use passphrase mode N")},
-    { oS2KDigest, "s2k-digest-algo",2,
-               N_("|NAME|use message digest algorithm NAME for passphrases")},
-    { oS2KCipher, "s2k-cipher-algo",2,
-               N_("|NAME|use cipher algorithm NAME for passphrases")},
+    { oRFC2440Text, "rfc2440-text", 0, "@"},
+    { oNoRFC2440Text, "no-rfc2440-text", 0, "@"},
+    { oS2KMode, "s2k-mode", 1, "@"},
+    { oS2KDigest, "s2k-digest-algo", 2, "@"},
+    { oS2KCipher, "s2k-cipher-algo", 2, "@"},
     { oSimpleSKChecksum, "simple-sk-checksum", 0, "@"},
-    { oCipherAlgo, "cipher-algo", 2 , N_("|NAME|use cipher algorithm NAME")},
-    { oDigestAlgo, "digest-algo", 2 , N_("|NAME|use message digest algorithm NAME")},
+    { oCipherAlgo, "cipher-algo", 2, "@"},
+    { oDigestAlgo, "digest-algo", 2, "@"},
     { oCertDigestAlgo, "cert-digest-algo", 2 , "@" },
-    { oCompressAlgo,"compress-algo",2,N_("|NAME|use compression algorithm NAME")},
-    { oThrowKeyid, "throw-keyid", 0, N_("throw keyid field of encrypted packets")},
-    { oNoThrowKeyid, "no-throw-keyid", 0, "@" },
+    { oCompressAlgo,"compress-algo", 2, "@"},
+    { oCompressAlgo, "compression-algo", 2, "@"}, /* Alias */
+    { oThrowKeyids, "throw-keyid", 0, "@"},
+    { oThrowKeyids, "throw-keyids", 0, "@"},
+    { oNoThrowKeyids, "no-throw-keyid", 0, "@" },
+    { oNoThrowKeyids, "no-throw-keyids", 0, "@" },
     { oShowPhotos,   "show-photos", 0, "@" },
     { oNoShowPhotos, "no-show-photos", 0, "@" },
     { oPhotoViewer,  "photo-viewer", 2, "@" },
@@ -506,7 +545,6 @@ static ARGPARSE_OPTS opts[] = {
 
   /* hidden options */
     { aListOwnerTrust, "list-ownertrust", 256, "@"}, /* deprecated */
-    { oCompressAlgo, "compression-algo", 1, "@"}, /* alias */
     { aPrintMDs, "print-mds" , 256, "@"}, /* old */
     { aListTrustDB, "list-trustdb",0 , "@"},
     /* Not yet used */
@@ -514,17 +552,15 @@ static ARGPARSE_OPTS opts[] = {
     { aPipeMode,  "pipemode", 0, "@" },
     { oKOption, NULL,   0, "@"},
     { oPasswdFD, "passphrase-fd",1, "@" },
-#ifdef __riscos__
     { oPasswdFile, "passphrase-file",2, "@" },
-#endif /* __riscos__ */
     { oCommandFD, "command-fd",1, "@" },
-#ifdef __riscos__
     { oCommandFile, "command-file",2, "@" },
-#endif /* __riscos__ */
     { oQuickRandom, "quick-random", 0, "@"},
     { oNoVerbose, "no-verbose", 0, "@"},
     { oTrustDBName, "trustdb-name", 2, "@" },
-    { oNoSecmemWarn, "no-secmem-warning", 0, "@" }, /* used only by regression tests */
+    { oNoSecmemWarn, "no-secmem-warning", 0, "@" },
+    { oRequireSecmem,"require-secmem", 0, "@" },
+    { oNoRequireSecmem,"no-require-secmem", 0, "@" },
     { oNoPermissionWarn, "no-permission-warning", 0, "@" },
     { oNoMDCWarn, "no-mdc-warning", 0, "@" },
     { oNoArmor, "no-armor",   0, "@"},
@@ -542,11 +578,12 @@ static ARGPARSE_OPTS opts[] = {
     { oSkipVerify, "skip-verify",0, "@" },
     { oCompressKeys, "compress-keys",0, "@"},
     { oCompressSigs, "compress-sigs",0, "@"},
-    { oDefCertCheckLevel, "default-cert-check-level", 1, "@"},
+    { oDefCertLevel, "default-cert-check-level", 1, "@"}, /* Old option */
+    { oDefCertLevel, "default-cert-level", 1, "@"},
+    { oMinCertLevel, "min-cert-level", 1, "@"},
     { oAlwaysTrust, "always-trust", 0, "@"},
     { oTrustModel, "trust-model", 2, "@"},
     { oForceOwnertrust, "force-ownertrust", 2, "@"},
-    { oEmuChecksumBug, "emulate-checksum-bug", 0, "@"},
     { oRunAsShmCP, "run-as-shm-coprocess", 4, "@" },
     { oSetFilename, "set-filename", 2, "@" },
     { oForYourEyesOnly, "for-your-eyes-only", 0, "@" },
@@ -556,11 +593,12 @@ static ARGPARSE_OPTS opts[] = {
     { oCertPolicyURL, "cert-policy-url", 2, "@" },
     { oShowPolicyURL, "show-policy-url", 0, "@" },
     { oNoShowPolicyURL, "no-show-policy-url", 0, "@" },
-    { oSigKeyserverURL, "sig-preferred-keyserver", 2, "@" },
+    { oSigKeyserverURL, "sig-keyserver-url", 2, "@" },
     { oShowNotation, "show-notation", 0, "@" },
     { oNoShowNotation, "no-show-notation", 0, "@" },
     { oComment, "comment", 2, "@" },
     { oDefaultComment, "default-comment", 0, "@" },
+    { oNoComments, "no-comments", 0, "@" },
     { oEmitVersion, "emit-version", 0, "@"},
     { oNoEmitVersion, "no-emit-version", 0, "@"},
     { oNoEmitVersion, "no-version", 0, "@"}, /* alias */
@@ -571,10 +609,9 @@ static ARGPARSE_OPTS opts[] = {
     { oLockMultiple, "lock-multiple", 0, "@" },
     { oLockNever, "lock-never", 0, "@" },
     { oLoggerFD, "logger-fd",1, "@" },
-#ifdef __riscos__
     { oLoggerFile, "logger-file",2, "@" },
-#endif /* __riscos__ */
     { oUseEmbeddedFilename, "use-embedded-filename", 0, "@" },
+    { oNoUseEmbeddedFilename, "no-use-embedded-filename", 0, "@" },
     { oUtf8Strings, "utf8-strings", 0, "@" },
     { oNoUtf8Strings, "no-utf8-strings", 0, "@" },
     { oWithFingerprint, "with-fingerprint", 0, "@" },
@@ -615,20 +652,44 @@ static ARGPARSE_OPTS opts[] = {
     { oPersonalCipherPreferences,  "personal-cipher-preferences", 2, "@"},
     { oPersonalDigestPreferences,  "personal-digest-preferences", 2, "@"},
     { oPersonalCompressPreferences,  "personal-compress-preferences", 2, "@"},
-    { oEmuMDEncodeBug, "emulate-md-encode-bug", 0, "@"},
+    /* Aliases.  I constantly mistype these, and assume other people
+       do as well. */
+    { oPersonalCipherPreferences, "personal-cipher-prefs", 2, "@"},
+    { oPersonalDigestPreferences, "personal-digest-prefs", 2, "@"},
+    { oPersonalCompressPreferences, "personal-compress-prefs", 2, "@"},
     { oDisplay,    "display",     2, "@" },
     { oTTYname,    "ttyname",     2, "@" },
     { oTTYtype,    "ttytype",     2, "@" },
     { oLCctype,    "lc-ctype",    2, "@" },
     { oLCmessages, "lc-messages", 2, "@" },
     { oGroup,      "group",       2, "@" },
+    { oUnGroup,    "ungroup",     2, "@" },
+    { oNoGroups,   "no-groups",    0, "@" },
     { oStrict,     "strict",      0, "@" },
     { oNoStrict,   "no-strict",   0, "@" },
     { oMangleDosFilenames, "mangle-dos-filenames", 0, "@" },
     { oNoMangleDosFilenames, "no-mangle-dos-filenames", 0, "@" },
     { oEnableProgressFilter, "enable-progress-filter", 0, "@" },
-{0} };
+    { oMultifile, "multifile", 0, "@" },
+    { oKeyidFormat, "keyid-format", 2, "@" },
+
+    { 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
 
+    {0,NULL,0,NULL}
+};
+
+
+#ifdef ENABLE_SELINUX_HACKS
+#define ALWAYS_ADD_KEYRINGS 1
+#else
+#define ALWAYS_ADD_KEYRINGS 0
+#endif
 
 
 int g10_errors_seen = 0;
@@ -645,10 +706,6 @@ 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 );
 
-#ifdef __riscos__
-RISCOS_GLOBAL_STATICS("GnuPG Heap")
-#endif /* __riscos__ */
-
 const char *
 strusage( int level )
 {
@@ -662,6 +719,19 @@ strusage( int level )
       case 19: p =
            _("Please report bugs to <gnupg-bugs@gnu.org>.\n");
        break;
+
+#ifdef IS_DEVELOPMENT_VERSION
+      case 20:
+       p="NOTE: THIS IS A DEVELOPMENT VERSION!";
+       break;
+      case 21:
+       p="It is only intended for test purposes and should NOT be";
+       break;
+      case 22:
+       p="used in a production environment or with production keys!";
+       break;
+#endif
+
       case 1:
       case 40: p =
            _("Usage: gpg [options] [files] (-h for help)");
@@ -769,7 +839,7 @@ static void
 i18n_init(void)
 {
 #ifdef USE_SIMPLE_GETTEXT
-    set_gettext_file( PACKAGE );
+    set_gettext_file (PACKAGE, "Software\\GNU\\GnuPG");
 #else
 #ifdef ENABLE_NLS
     setlocale( LC_ALL, "" );
@@ -829,6 +899,76 @@ set_homedir (char *dir)
 }
 
 
+/* We set the screen dimensions for UI purposes.  Do not allow screens
+   smaller than 80x24 for the sake of simplicity. */
+static void
+set_screen_dimensions(void)
+{
+#ifndef _WIN32
+  char *str;
+
+  str=getenv("COLUMNS");
+  if(str)
+    opt.screen_columns=atoi(str);
+
+  str=getenv("LINES");
+  if(str)
+    opt.screen_lines=atoi(str);
+#endif
+
+  if(opt.screen_columns<80 || opt.screen_columns>255)
+    opt.screen_columns=80;
+
+  if(opt.screen_lines<24 || opt.screen_lines>255)
+    opt.screen_lines=24;
+}
+
+
+/* Helper to open a file FNAME either for reading or writing to be
+   used with --status-file etc functions.  Not generally useful but it
+   avoids the riscos specific functions and well some Windows people
+   might like it too.  Prints an error message and returns -1 on
+   error. On success the file descriptor is returned.  */
+static int
+open_info_file (const char *fname, int for_write)
+{
+#ifdef __riscos__
+  return riscos_fdopenfile (fname, for_write);
+#elif defined (ENABLE_SELINUX_HACKS)
+  /* We can't allow these even when testing for a secured filename
+     because files to be secured might not yet been secured.  This is
+     similar to the option file but in that case it is unlikely that
+     sensitive information may be retrieved by means of error
+     messages.  */
+  return -1;
+#else 
+  int fd;
+
+/*   if (is_secured_filename (fname)) */
+/*     { */
+/*       fd = -1; */
+/*       errno = EPERM; */
+/*     } */
+/*   else */
+/*     { */
+      do
+        {
+          if (for_write)
+            fd = open (fname, O_CREAT | O_TRUNC | O_WRONLY,
+                        S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+          else
+            fd = open (fname, O_RDONLY | MY_O_BINARY);
+        }
+      while (fd == -1 && errno == EINTR);
+/*     } */
+  if ( fd == -1)
+    log_error ( for_write? _("can't create `%s': %s\n")
+                         : _("can't open `%s': %s\n"), fname, strerror(errno));
+  
+  return fd;
+#endif
+}
+
 static void
 set_cmd( enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd )
 {
@@ -844,8 +984,18 @@ set_cmd( enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd )
        cmd = aSignSym;
     else if( cmd == aSym && new_cmd == aSign )
        cmd = aSignSym;
+    else if( cmd == aSym && new_cmd == aEncr )
+       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)
+        cmd = aSignEncrSym;
+    else if (cmd == aEncrSym && new_cmd == aSign)
+        cmd = aSignEncrSym;
     else if(   ( cmd == aSign     && new_cmd == aClearsign )
             || ( cmd == aClearsign && new_cmd == aSign )  )
        cmd = aClearsign;
@@ -858,47 +1008,79 @@ set_cmd( enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd )
 }
 
 
-static void add_group(char *string)
+static void
+add_group(char *string)
 {
   char *name,*value;
   struct groupitem *item;
-  STRLIST values=NULL;
 
   /* Break off the group name */
   name=strsep(&string,"=");
   if(string==NULL)
     {
-      log_error(_("no = sign found in group definition \"%s\"\n"),name);
+      log_error(_("no = sign found in group definition `%s'\n"),name);
       return;
     }
 
   trim_trailing_ws(name,strlen(name));
 
+  /* Does this group already exist? */
+  for(item=opt.grouplist;item;item=item->next)
+    if(strcasecmp(item->name,name)==0)
+      break;
+
+  if(!item)
+    {
+      item=m_alloc(sizeof(struct groupitem));
+      item->name=name;
+      item->next=opt.grouplist;
+      item->values=NULL;
+      opt.grouplist=item;
+    }
+
   /* Break apart the values */
   while ((value= strsep(&string," \t")))
     {
       if (*value)
-        add_to_strlist2 (&values,value,utf8_strings);
+        add_to_strlist2(&item->values,value,utf8_strings);
     }
+}
 
-  item=m_alloc(sizeof(struct groupitem));
-  item->name=name;
-  item->values=values;
-  item->next=opt.grouplist;
 
-  opt.grouplist=item;
+static void
+rm_group(char *name)
+{
+  struct groupitem *item,*last=NULL;
+
+  trim_trailing_ws(name,strlen(name));
+
+  for(item=opt.grouplist;item;last=item,item=item->next)
+    {
+      if(strcasecmp(item->name,name)==0)
+       {
+         if(last)
+           last->next=item->next;
+         else
+           opt.grouplist=item->next;
+
+         free_strlist(item->values);
+         m_free(item);
+         break;
+       }
+    }
 }
 
+
 /* We need to check three things.
 
    0) The homedir.  It must be x00, a directory, and owned by the
    user.
 
-   1) The options file.  Okay unless it or its containing directory is
-   group or other writable or not owned by us.  disable exec in this
-   case.
+   1) The options/gpg.conf file.  Okay unless it or its containing
+   directory is group or other writable or not owned by us.  Disable
+   exec in this case.
 
-   2) Extensions.  Same as #2.
+   2) Extensions.  Same as #1.
 
    Returns true if the item is unsafe. */
 static int
@@ -1033,50 +1215,50 @@ check_permissions(const char *path,int item)
       if(own)
        {
          if(item==0)
-           log_info(_("WARNING: unsafe ownership on "
-                      "homedir \"%s\"\n"),tmppath);
+           log_info(_("WARNING: unsafe ownership on"
+                      " homedir `%s'\n"),tmppath);
          else if(item==1)
-           log_info(_("WARNING: unsafe ownership on "
-                      "configuration file \"%s\"\n"),tmppath);
+           log_info(_("WARNING: unsafe ownership on"
+                      " configuration file `%s'\n"),tmppath);
          else
-           log_info(_("WARNING: unsafe ownership on "
-                      "extension \"%s\"\n"),tmppath);
+           log_info(_("WARNING: unsafe ownership on"
+                      " extension `%s'\n"),tmppath);
        }
       if(perm)
        {
          if(item==0)
-           log_info(_("WARNING: unsafe permissions on "
-                      "homedir \"%s\"\n"),tmppath);
+           log_info(_("WARNING: unsafe permissions on"
+                      " homedir `%s'\n"),tmppath);
          else if(item==1)
-           log_info(_("WARNING: unsafe permissions on "
-                      "configuration file \"%s\"\n"),tmppath);
+           log_info(_("WARNING: unsafe permissions on"
+                      " configuration file `%s'\n"),tmppath);
          else
-           log_info(_("WARNING: unsafe permissions on "
-                      "extension \"%s\"\n"),tmppath);
+           log_info(_("WARNING: unsafe permissions on"
+                      " extension `%s'\n"),tmppath);
        }
       if(enc_dir_own)
        {
          if(item==0)
-           log_info(_("WARNING: unsafe enclosing directory ownership on "
-                      "homedir \"%s\"\n"),tmppath);
+           log_info(_("WARNING: unsafe enclosing directory ownership on"
+                      " homedir `%s'\n"),tmppath);
          else if(item==1)
-           log_info(_("WARNING: unsafe enclosing directory ownership on "
-                      "configuration file \"%s\"\n"),tmppath);
+           log_info(_("WARNING: unsafe enclosing directory ownership on"
+                      " configuration file `%s'\n"),tmppath);
          else
-           log_info(_("WARNING: unsafe enclosing directory ownership on "
-                      "extension \"%s\"\n"),tmppath);
+           log_info(_("WARNING: unsafe enclosing directory ownership on"
+                      " extension `%s'\n"),tmppath);
        }
       if(enc_dir_perm)
        {
          if(item==0)
-           log_info(_("WARNING: unsafe enclosing directory permissions on "
-                      "homedir \"%s\"\n"),tmppath);
+           log_info(_("WARNING: unsafe enclosing directory permissions on"
+                      " homedir `%s'\n"),tmppath);
          else if(item==1)
-           log_info(_("WARNING: unsafe enclosing directory permissions on "
-                      "configuration file \"%s\"\n"),tmppath);
+           log_info(_("WARNING: unsafe enclosing directory permissions on"
+                      " configuration file `%s'\n"),tmppath);
          else
-           log_info(_("WARNING: unsafe enclosing directory permissions on "
-                      "extension \"%s\"\n"),tmppath);
+           log_info(_("WARNING: unsafe enclosing directory permissions on"
+                      " extension `%s'\n"),tmppath);
        }
     }
 
@@ -1093,6 +1275,308 @@ check_permissions(const char *path,int item)
   return 0;
 }
 
+
+static void
+print_algo_numbers(int (*checker)(int))
+{
+  int i,first=1;
+
+  for(i=0;i<=110;i++)
+    {
+      if(!checker(i))
+       {
+         if(first)
+           first=0;
+         else
+           printf(";");
+         printf("%d",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
+   for frontends. */
+static void
+list_config(char *items)
+{
+  int show_all=(items==NULL);
+  char *name=NULL;
+
+  if(!opt.with_colons)
+    return;
+
+  while(show_all || (name=strsep(&items," ")))
+    {
+      int any=0;
+
+      if(show_all || ascii_strcasecmp(name,"group")==0)
+       {
+         struct groupitem *iter;
+
+         for(iter=opt.grouplist;iter;iter=iter->next)
+           {
+             STRLIST sl;
+
+             printf("cfg:group:");
+             print_string(stdout,iter->name,strlen(iter->name),':');
+             printf(":");
+
+             for(sl=iter->values;sl;sl=sl->next)
+               {
+                 print_string2(stdout,sl->d,strlen(sl->d),':',';');
+                 if(sl->next)
+                   printf(";");
+               }
+
+             printf("\n");
+           }
+
+         any=1;
+       }
+
+      if(show_all || ascii_strcasecmp(name,"version")==0)
+       {
+         printf("cfg:version:");
+         print_string(stdout,VERSION,strlen(VERSION),':');
+         printf("\n");
+         any=1;
+       }
+
+      if(show_all || ascii_strcasecmp(name,"pubkey")==0)
+       {
+         printf("cfg:pubkey:");
+         print_algo_numbers(check_pubkey_algo);
+         printf("\n");
+         any=1;
+       }
+
+      if(show_all || ascii_strcasecmp(name,"cipher")==0)
+       {
+         printf("cfg:cipher:");
+         print_algo_numbers(check_cipher_algo);
+         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);
+         printf("\n");
+         any=1;
+       }
+
+      if(show_all || ascii_strcasecmp(name,"compress")==0)
+       {
+         printf("cfg:compress:");
+         print_algo_numbers(check_compress_algo);
+         printf("\n");
+         any=1;
+       }
+
+      if(show_all || ascii_strcasecmp(name,"ccid-reader-id")==0)
+       {
+#if defined(ENABLE_CARD_SUPPORT) && defined(HAVE_LIBUSB)
+          char *p, *p2, *list = ccid_get_reader_list ();
+
+          for (p=list; p && (p2 = strchr (p, '\n')); p = p2+1)
+            {
+              *p2 = 0;
+              printf("cfg:ccid-reader-id:%s\n", p);
+            }
+          free (list);
+#endif
+         any=1;
+       }
+
+      if(show_all)
+       break;
+
+      if(!any)
+       log_error(_("unknown configuration item `%s'\n"),name);
+    }
+}
+
+
+/* List options and default values in the GPG Conf format.  This is a
+   new tool distributed with gnupg 1.9.x but we also want some limited
+   support in older gpg versions.  The output is the name of the
+   configuration file and a list of options available for editing by
+   gpgconf.  */
+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)
+
+  printf ("gpgconf-gpg.conf:%lu:\"%s\n",
+          GC_OPT_FLAG_DEFAULT,configfile?configfile:"/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);
+}
+
+
+static int
+parse_subpacket_list(char *list)
+{
+  char *tok;
+  byte subpackets[128],i;
+  int count=0;
+
+  if(!list)
+    {
+      /* No arguments means all subpackets */
+      memset(subpackets+1,1,sizeof(subpackets)-1);
+      count=127;
+    }
+  else
+    {
+      memset(subpackets,0,sizeof(subpackets));
+
+      /* Merge with earlier copy */
+      if(opt.show_subpackets)
+       {
+         byte *in;
+
+         for(in=opt.show_subpackets;*in;in++)
+           {
+             if(*in>127 || *in<1)
+               BUG();
+
+             if(!subpackets[*in])
+               count++;
+             subpackets[*in]=1;
+           }
+       }
+
+      while((tok=strsep(&list," ,")))
+       {
+         if(!*tok)
+           continue;
+
+         i=atoi(tok);
+         if(i>127 || i<1)
+           return 0;
+
+         if(!subpackets[i])
+           count++;
+         subpackets[i]=1;
+       }
+    }
+
+  m_free(opt.show_subpackets);
+  opt.show_subpackets=m_alloc(count+1);
+  opt.show_subpackets[count--]=0;
+
+  for(i=1;i<128 && count>=0;i++)
+    if(subpackets[i])
+      opt.show_subpackets[count--]=i;
+
+  return 1;
+}
+
+
+static int
+parse_list_options(char *str)
+{
+  char *subpackets=""; /* something that isn't NULL */
+  struct parse_options lopts[]=
+    {
+      {"show-photos",LIST_SHOW_PHOTOS,NULL},
+      {"show-policy-urls",LIST_SHOW_POLICY_URLS,NULL},
+      {"show-notations",LIST_SHOW_NOTATIONS,NULL},
+      {"show-std-notations",LIST_SHOW_STD_NOTATIONS,NULL},
+      {"show-standard-notations",LIST_SHOW_STD_NOTATIONS,NULL},
+      {"show-user-notations",LIST_SHOW_USER_NOTATIONS,NULL},
+      {"show-keyserver-urls",LIST_SHOW_KEYSERVER_URLS,NULL},
+      {"show-uid-validity",LIST_SHOW_UID_VALIDITY,NULL},
+      {"show-unusable-uids",LIST_SHOW_UNUSABLE_UIDS,NULL},
+      {"show-unusable-subkeys",LIST_SHOW_UNUSABLE_SUBKEYS,NULL},
+      {"show-keyring",LIST_SHOW_KEYRING,NULL},
+      {"show-sig-expire",LIST_SHOW_SIG_EXPIRE,NULL},
+      {"show-sig-subpackets",LIST_SHOW_SIG_SUBPACKETS,NULL},
+      {NULL,0,NULL}
+    };
+
+  /* C99 allows for non-constant initializers, but we'd like to
+     compile everywhere, so fill in the show-sig-subpackets argument
+     here.  Note that if the parse_options array changes, we'll have
+     to change the subscript here. */
+  lopts[12].value=&subpackets;
+
+  if(parse_options(str,&opt.list_options,lopts,1))
+    {
+      if(opt.list_options&LIST_SHOW_SIG_SUBPACKETS)
+       {
+         /* Unset so users can pass multiple lists in. */
+         opt.list_options&=~LIST_SHOW_SIG_SUBPACKETS;
+         if(!parse_subpacket_list(subpackets))
+           return 0;
+       }
+      else if(subpackets==NULL && opt.show_subpackets)
+       {
+         /* User did 'no-show-subpackets' */
+         m_free(opt.show_subpackets);
+         opt.show_subpackets=NULL;
+       }
+
+      return 1;
+    }
+  else
+    return 0;
+}
+
+
+/* Collapses argc/argv into a single string that must be freed */
+static char *
+collapse_args(int argc,char *argv[])
+{
+  char *str=NULL;
+  int i,first=1,len=0;
+
+  for(i=0;i<argc;i++)
+    {
+      len+=strlen(argv[i])+2;
+      str=m_realloc(str,len);
+      if(first)
+       {
+         str[0]='\0';
+         first=0;
+       }
+      else
+       strcat(str," ");
+
+      strcat(str,argv[i]);
+    }
+
+  return str;
+}
+
+static void
+parse_trust_model(const char *model)
+{
+  if(ascii_strcasecmp(model,"pgp")==0)
+    opt.trust_model=TM_PGP;
+  else if(ascii_strcasecmp(model,"classic")==0)
+    opt.trust_model=TM_CLASSIC;
+  else if(ascii_strcasecmp(model,"always")==0)
+    opt.trust_model=TM_ALWAYS;
+  else if(ascii_strcasecmp(model,"direct")==0)
+    opt.trust_model=TM_DIRECT;
+  else if(ascii_strcasecmp(model,"auto")==0)
+    opt.trust_model=TM_AUTO;
+  else
+    log_error("unknown trust model `%s'\n",model);
+}
+
 int
 main( int argc, char **argv )
 {
@@ -1110,6 +1594,7 @@ main( int argc, char **argv )
     int detached_sig = 0;
     FILE *configfp = NULL;
     char *configname = NULL;
+    char *save_configname = NULL;
     unsigned configlineno;
     int parse_debug = 0;
     int default_config = 1;
@@ -1121,7 +1606,7 @@ main( int argc, char **argv )
     const char *trustdb_name = NULL;
     char *def_cipher_string = NULL;
     char *def_digest_string = NULL;
-    char *def_compress_string = NULL;
+    char *compress_algo_string = NULL;
     char *cert_digest_string = NULL;
     char *s2k_cipher_string = NULL;
     char *s2k_digest_string = NULL;
@@ -1129,15 +1614,16 @@ main( int argc, char **argv )
     char *pers_digest_list = NULL;
     char *pers_compress_list = NULL;
     int eyes_only=0;
+    int multifile=0;
     int pwfd = -1;
     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__
-    riscos_global_defaults();
     opt.lock_once = 1;
 #endif /* __riscos__ */
 
@@ -1154,14 +1640,14 @@ main( int argc, char **argv )
     create_dotlock(NULL); /* register locking cleanup */
     i18n_init();
     opt.command_fd = -1; /* no command fd */
-    opt.compress = -1; /* defaults to standard compress level */
+    opt.compress_level = -1; /* defaults to standard compress level */
+    opt.bz2_compress_level = -1; /* defaults to standard compress level */
     /* note: if you change these lines, look at oOpenPGP */
     opt.def_cipher_algo = 0;
     opt.def_digest_algo = 0;
     opt.cert_digest_algo = 0;
-    opt.def_compress_algo = -1;
+    opt.compress_algo = -1; /* defaults to DEFAULT_COMPRESS_ALGO */
     opt.s2k_mode = 3; /* iterated+salted */
-    opt.s2k_digest_algo = DIGEST_ALGO_SHA1;
 #ifdef USE_CAST5
     opt.s2k_cipher_algo = CIPHER_ALGO_CAST5;
 #else
@@ -1174,27 +1660,28 @@ main( int argc, char **argv )
     opt.force_v3_sigs = 1;
     opt.escape_from = 1;
     opt.import_options=IMPORT_SK2PK;
-    opt.export_options=
-      EXPORT_INCLUDE_NON_RFC|EXPORT_INCLUDE_ATTRIBUTES;
+    opt.export_options=EXPORT_ATTRIBUTES;
     opt.keyserver_options.import_options=IMPORT_REPAIR_PKS_SUBKEY_BUG;
-    opt.keyserver_options.export_options=
-      EXPORT_INCLUDE_NON_RFC|EXPORT_INCLUDE_ATTRIBUTES;
-    opt.keyserver_options.include_subkeys=1;
-    opt.keyserver_options.include_revoked=1;
-    opt.keyserver_options.try_dns_srv=1;
+    opt.keyserver_options.export_options=EXPORT_ATTRIBUTES;
+    opt.keyserver_options.options=
+      KEYSERVER_INCLUDE_SUBKEYS|KEYSERVER_INCLUDE_REVOKED|KEYSERVER_TRY_DNS_SRV|KEYSERVER_HONOR_KEYSERVER_URL;
     opt.verify_options=
-      VERIFY_SHOW_POLICY|VERIFY_SHOW_NOTATION|VERIFY_SHOW_KEYSERVER;
+      VERIFY_SHOW_POLICY_URLS|VERIFY_SHOW_STD_NOTATIONS|VERIFY_SHOW_KEYSERVER_URLS;
     opt.trust_model=TM_AUTO;
-    opt.mangle_dos_filenames = 1;
-
-#if defined (__MINGW32__)
-    set_homedir ( read_w32_registry_string( NULL,
-                                    "Software\\GNU\\GnuPG", "HomeDir" ));
+    opt.mangle_dos_filenames=0;
+    opt.min_cert_level=2;
+    set_screen_dimensions();
+    opt.keyid_format=KF_SHORT;
+    opt.rfc2440_text=1;
+    set_homedir ( default_homedir () );
+
+#ifdef ENABLE_CARD_SUPPORT
+# ifdef _WIN32
+    opt.pcsc_driver = "winscard.dll"; 
 #else
-    set_homedir ( getenv("GNUPGHOME") );
+    opt.pcsc_driver = "libpcsclite.so"; 
 #endif
-    if( !*opt.homedir )
-       set_homedir ( GNUPG_HOMEDIR );
+#endif /*ENABLE_CARD_SUPPORT*/
 
     /* check whether we have a config file on the commandline */
     orig_argc = argc;
@@ -1258,23 +1745,50 @@ main( int argc, char **argv )
     }
 #endif
     /* initialize the secure memory. */
-    secmem_init( 32768 );
+    got_secmem=secmem_init( 32768 );
     maybe_setuid = 0;
     /* Okay, we are now working under our real uid */
 
+#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
+
     set_native_charset (NULL); /* Try to auto set the character set */
 
+    /* Try for a version specific config file first */
     if( default_config )
       {
-       /* Try for a version specific config file first */
-       configname = make_filename(opt.homedir,
-                                  "gpg" EXTSEP_S "conf-" SAFE_VERSION, NULL );
-       if(access(configname,R_OK))
+       char *name=m_strdup("gpg" EXTSEP_S "conf-" SAFE_VERSION);
+       char *ver=&name[strlen("gpg" EXTSEP_S "conf-")];
+
+       do
          {
-           m_free(configname);
-           configname = make_filename(opt.homedir,
-                                      "gpg" EXTSEP_S "conf", NULL );
+           if(configname)
+             {
+               char *tok;
+
+               m_free(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));
+
+       m_free(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 );
@@ -1312,6 +1826,12 @@ main( int argc, char **argv )
 
        configlineno = 0;
        configfp = fopen( configname, "r" );
+        if (configfp && is_secured_file (fileno (configfp)))
+          {
+            fclose (configfp);
+            configfp = NULL;
+            errno = EPERM;
+          }
        if( !configfp ) {
            if( default_config ) {
                if( parse_debug )
@@ -1331,24 +1851,31 @@ main( int argc, char **argv )
     }
 
     while( optfile_parse( configfp, configname, &configlineno,
-                                               &pargs, opts) ) {
-       switch( pargs.r_opt ) {
-         case aCheckKeys: set_cmd( &cmd, aCheckKeys); break;
-         case aListPackets: set_cmd( &cmd, aListPackets); break;
-         case aImport: set_cmd( &cmd, aImport); break;
-         case aFastImport: set_cmd( &cmd, aFastImport); break;
-         case aSendKeys: set_cmd( &cmd, aSendKeys); break;
-         case aRecvKeys: set_cmd( &cmd, aRecvKeys); break;
-         case aSearchKeys: set_cmd( &cmd, aSearchKeys); break;
-         case aRefreshKeys: set_cmd( &cmd, aRefreshKeys); break;
-         case aExport: set_cmd( &cmd, aExport); break;
-         case aExportAll: set_cmd( &cmd, aExportAll); break;
+                                               &pargs, opts) )
+      {
+       switch( pargs.r_opt )
+         {
+         case aCheckKeys: 
+         case aListConfig:
+          case aGPGConfList:
+         case aListPackets:
+         case aImport: 
+         case aFastImport: 
+         case aSendKeys: 
+         case aRecvKeys: 
+         case aSearchKeys:
+         case aRefreshKeys:
+         case aExport: 
+            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 aDeleteSecretKeys: set_cmd( &cmd, aDeleteSecretKeys);
-                                                       greeting=1; break;
+         case aDeleteSecretKeys:
+           set_cmd( &cmd, aDeleteSecretKeys);
+           greeting=1;
+           break;
          case aDeleteSecretAndPublicKeys:
             set_cmd( &cmd, aDeleteSecretAndPublicKeys);
             greeting=1; 
@@ -1358,24 +1885,24 @@ main( int argc, char **argv )
          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;
-          case aDecryptFiles: set_cmd( &cmd, aDecryptFiles); break;
 
+         case aEncrFiles: multifile=1; /* fall through */
          case aEncr: set_cmd( &cmd, aEncr); break;
-         case aEncrFiles: set_cmd( &cmd, aEncrFiles ); break;
+
+         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 aNRSignKey: set_cmd( &cmd, aNRSignKey); break;
-         case aNRLSignKey: set_cmd( &cmd, aNRLSignKey); 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 aVerify: set_cmd( &cmd, aVerify); break;
-         case aVerifyFiles: set_cmd( &cmd, aVerifyFiles); break;
          case aPrimegen: set_cmd( &cmd, aPrimegen); break;
          case aGenRandom: set_cmd( &cmd, aGenRandom); break;
          case aPrintMD: set_cmd( &cmd, aPrintMD); break;
@@ -1395,14 +1922,31 @@ main( int argc, char **argv )
           case aPipeMode: 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);
+            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;
+         case oMaxOutput: opt.max_output = pargs.r.ret_ulong; break;
          case oQuiet: opt.quiet = 1; break;
          case oNoTTY: tty_no_terminal(1); break;
          case oDryRun: opt.dry_run = 1; break;
          case oInteractive: opt.interactive = 1; break;
-         case oVerbose: g10_opt_verbose++;
-                   opt.verbose++; opt.list_sigs=1; break;
+         case oVerbose:
+           g10_opt_verbose++;
+           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;
@@ -1423,40 +1967,45 @@ main( int argc, char **argv )
            sl=append_to_strlist( &nrings, pargs.r.ret_str);
            sl->flags=2;
            break;
-         case oShowKeyring: opt.list_options|=LIST_SHOW_KEYRING; break;
+         case oShowKeyring:
+           deprecated_warning(configname,configlineno,"--show-keyring",
+                              "--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 (1);
+#endif
+            break;
          case oStatusFD:
             set_status_fd( iobuf_translate_file_handle (pargs.r.ret_int, 1) );
             break;
-#ifdef __riscos__
          case oStatusFile:
-            set_status_fd( iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 1), 1) );
+            set_status_fd ( open_info_file (pargs.r.ret_str, 1) );
             break;
-#endif /* __riscos__ */
          case oAttributeFD:
             set_attrib_fd(iobuf_translate_file_handle (pargs.r.ret_int, 1));
             break;
-#ifdef __riscos__
          case oAttributeFile:
-            set_attrib_fd(iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 1), 1) );
+            set_attrib_fd ( open_info_file (pargs.r.ret_str, 1) );
             break;
-#endif /* __riscos__ */
          case oLoggerFD:
             log_set_logfile( NULL,
-                             iobuf_translate_file_handle (pargs.r.ret_int, 1) );
+                             iobuf_translate_file_handle (pargs.r.ret_int, 1));
             break;
-#ifdef __riscos__
          case oLoggerFile:
-            log_set_logfile( NULL,
-                             iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 1), 1) );
+            log_set_logfile( NULL, open_info_file (pargs.r.ret_str, 1) );
             break;
-#endif /* __riscos__ */
+
          case oWithFingerprint:
             opt.with_fingerprint = 1;
             with_fpr=1; /*fall thru*/
          case oFingerprint: opt.fingerprint++; break;
-         case oSecretKeyring: append_to_strlist( &sec_nrings, pargs.r.ret_str); break;
+         case oSecretKeyring:
+            append_to_strlist( &sec_nrings, pargs.r.ret_str);
+            break;
          case oOptions:
            /* config files may not be nested (silently ignore them) */
            if( !configfp ) {
@@ -1467,7 +2016,8 @@ main( int argc, char **argv )
            break;
          case oNoArmor: opt.no_armor=1; opt.armor=0; break;
          case oNoDefKeyring: default_keyring = 0; break;
-          case oDefCertCheckLevel: opt.def_cert_check_level=pargs.r.ret_int; break;
+          case oDefCertLevel: opt.def_cert_level=pargs.r.ret_int; break;
+          case oMinCertLevel: opt.min_cert_level=pargs.r.ret_int; break;
          case oNoGreeting: nogreeting = 1; break;
          case oNoVerbose: g10_opt_verbose = 0;
                           opt.verbose = 0; opt.list_sigs=0; break;
@@ -1507,16 +2057,7 @@ main( int argc, char **argv )
               time. */
          case oAlwaysTrust: opt.trust_model=TM_ALWAYS; break;
          case oTrustModel:
-           if(ascii_strcasecmp(pargs.r.ret_str,"pgp")==0)
-             opt.trust_model=TM_PGP;
-           else if(ascii_strcasecmp(pargs.r.ret_str,"classic")==0)
-             opt.trust_model=TM_CLASSIC;
-           else if(ascii_strcasecmp(pargs.r.ret_str,"always")==0)
-             opt.trust_model=TM_ALWAYS;
-           else if(ascii_strcasecmp(pargs.r.ret_str,"auto")==0)
-             opt.trust_model=TM_AUTO;
-           else
-             log_error("unknown trust model \"%s\"\n",pargs.r.ret_str);
+           parse_trust_model(pargs.r.ret_str);
            break;
          case oForceOwnertrust:
            log_info(_("NOTE: %s is not for normal use!\n"),
@@ -1524,16 +2065,16 @@ main( int argc, char **argv )
            opt.force_ownertrust=string_to_trust_value(pargs.r.ret_str);
            if(opt.force_ownertrust==-1)
              {
-               log_error("invalid ownertrust \"%s\"\n",pargs.r.ret_str);
+               log_error("invalid ownertrust `%s'\n",pargs.r.ret_str);
                opt.force_ownertrust=0;
              }
            break;
          case oLoadExtension:
 #ifndef __riscos__
-#if defined(USE_DYNAMIC_LINKING) || defined(__MINGW32__)
+#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);
+             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);
@@ -1545,27 +2086,26 @@ main( int argc, char **argv )
          case oRFC1991:
            opt.compliance = CO_RFC1991;
            opt.force_v4_certs = 0;
-           opt.disable_mdc = 1;
            opt.escape_from = 1;
            break;
-         case oRFC2440:
          case oOpenPGP:
-           /* TODO: When 2440bis becomes a RFC, these may need
-               changing. */
+         case oRFC2440:
+           /* TODO: When 2440bis becomes a RFC, set new values for
+              oOpenPGP. */
+           opt.rfc2440_text=1;
            opt.compliance = CO_RFC2440;
-           opt.disable_mdc = 1;
            opt.allow_non_selfsigned_uid = 1;
            opt.allow_freeform_uid = 1;
            opt.pgp2_workarounds = 0;
            opt.escape_from = 0;
            opt.force_v3_sigs = 0;
-           opt.compress_keys = 0;          /* not mandated  but we do it */
+           opt.compress_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.def_compress_algo = -1;
+           opt.compress_algo = -1;
             opt.s2k_mode = 3; /* iterated+salted */
            opt.s2k_digest_algo = DIGEST_ALGO_SHA1;
            opt.s2k_cipher_algo = CIPHER_ALGO_3DES;
@@ -1575,8 +2115,9 @@ main( int argc, char **argv )
          case oPGP7:  opt.compliance = CO_PGP7;  break;
          case oPGP8:  opt.compliance = CO_PGP8;  break;
          case oGnuPG: opt.compliance = CO_GNUPG; break;
-         case oEmuMDEncodeBug: opt.emulate_bugs |= EMUBUG_MDENCODE; break;
          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
@@ -1598,24 +2139,51 @@ main( int argc, char **argv )
          case oSigPolicyURL: add_policy_url(pargs.r.ret_str,0); break;
          case oCertPolicyURL: add_policy_url(pargs.r.ret_str,1); break;
           case oShowPolicyURL:
-           opt.list_options|=LIST_SHOW_POLICY;
-           opt.verify_options|=VERIFY_SHOW_POLICY;
+           deprecated_warning(configname,configlineno,"--show-policy-url",
+                              "--list-options ","show-policy-urls");
+           deprecated_warning(configname,configlineno,"--show-policy-url",
+                              "--verify-options ","show-policy-urls");
+           opt.list_options|=LIST_SHOW_POLICY_URLS;
+           opt.verify_options|=VERIFY_SHOW_POLICY_URLS;
            break;
          case oNoShowPolicyURL:
-           opt.list_options&=~LIST_SHOW_POLICY;
-           opt.verify_options&=~VERIFY_SHOW_POLICY;
+           deprecated_warning(configname,configlineno,"--no-show-policy-url",
+                              "--list-options ","no-show-policy-urls");
+           deprecated_warning(configname,configlineno,"--no-show-policy-url",
+                              "--verify-options ","no-show-policy-urls");
+           opt.list_options&=~LIST_SHOW_POLICY_URLS;
+           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 oComment: opt.comment_string = pargs.r.ret_str; break;
-         case oDefaultComment: opt.comment_string = NULL; break;
-         case oThrowKeyid: opt.throw_keyid = 1; break;
-         case oNoThrowKeyid: opt.throw_keyid = 0; break;
-         case oShowPhotos: 
+         case oNoUseEmbeddedFilename: opt.use_embedded_filename = 0; break;
+         case oComment:
+           if(pargs.r.ret_str[0])
+             append_to_strlist(&opt.comments,pargs.r.ret_str);
+           break;
+         case oDefaultComment:
+           deprecated_warning(configname,configlineno,
+                              "--default-comment","--no-comments","");
+           /* fall through */
+         case oNoComments:
+           free_strlist(opt.comments);
+           opt.comments=NULL;
+           break;
+         case oThrowKeyids: opt.throw_keyid = 1; break;
+         case oNoThrowKeyids: opt.throw_keyid = 0; break;
+         case oShowPhotos:
+           deprecated_warning(configname,configlineno,"--show-photos",
+                              "--list-options ","show-photos");
+           deprecated_warning(configname,configlineno,"--show-photos",
+                              "--verify-options ","show-photos");
            opt.list_options|=LIST_SHOW_PHOTOS;
            opt.verify_options|=VERIFY_SHOW_PHOTOS;
            break;
          case oNoShowPhotos:
+           deprecated_warning(configname,configlineno,"--no-show-photos",
+                              "--list-options ","no-show-photos");
+           deprecated_warning(configname,configlineno,"--no-show-photos",
+                              "--verify-options ","no-show-photos");
            opt.list_options&=~LIST_SHOW_PHOTOS;
            opt.verify_options&=~VERIFY_SHOW_PHOTOS;
            break;
@@ -1659,28 +2227,37 @@ main( int argc, char **argv )
          case oNoAskSigExpire: opt.ask_sig_expire = 0; break;
          case oAskCertExpire: opt.ask_cert_expire = 1; break;
          case oNoAskCertExpire: opt.ask_cert_expire = 0; break;
+         case oAskCertLevel: opt.ask_cert_level = 1; break;
+         case oNoAskCertLevel: opt.ask_cert_level = 0; break;
          case oUser: /* store the local users */
            add_to_strlist2( &locusr, pargs.r.ret_str, utf8_strings );
            break;
-         case oCompress: opt.compress = pargs.r.ret_int; break;
+         case oCompress:
+           /* this is the -z command line option */
+           opt.compress_level = opt.bz2_compress_level = pargs.r.ret_int;
+           break;
+         case oCompressLevel: opt.compress_level = pargs.r.ret_int; break;
+         case oBZ2CompressLevel: opt.bz2_compress_level = pargs.r.ret_int; break;
+         case oBZ2DecompressLowmem: opt.bz2_decompress_lowmem=1; break;
          case oPasswdFD:
             pwfd = iobuf_translate_file_handle (pargs.r.ret_int, 0);
+            opt.use_agent = 0;
             break;
-#ifdef __riscos__
          case oPasswdFile:
-            pwfd = iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 0), 0);
+            pwfd = open_info_file (pargs.r.ret_str, 0);
             break;
-#endif /* __riscos__ */
          case oCommandFD:
             opt.command_fd = iobuf_translate_file_handle (pargs.r.ret_int, 0);
             break;
-#ifdef __riscos__
          case oCommandFile:
-            opt.command_fd = iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 0), 0);
+            opt.command_fd = open_info_file (pargs.r.ret_str, 0);
+            break;
+         case oCipherAlgo: 
+            def_cipher_string = m_strdup(pargs.r.ret_str);
+            break;
+         case oDigestAlgo:
+            def_digest_string = m_strdup(pargs.r.ret_str);
             break;
-#endif /* __riscos__ */
-         case oCipherAlgo: def_cipher_string = m_strdup(pargs.r.ret_str); break;
-         case oDigestAlgo: def_digest_string = m_strdup(pargs.r.ret_str); break;
          case oCompressAlgo:
            /* If it is all digits, stick a Z in front of it for
               later.  This is for backwards compatibility with
@@ -1697,22 +2274,24 @@ main( int argc, char **argv )
 
              if(*pt=='\0')
                {
-                 def_compress_string=m_alloc(strlen(pargs.r.ret_str)+2);
-                 strcpy(def_compress_string,"Z");
-                 strcat(def_compress_string,pargs.r.ret_str);
+                 compress_algo_string=m_alloc(strlen(pargs.r.ret_str)+2);
+                 strcpy(compress_algo_string,"Z");
+                 strcat(compress_algo_string,pargs.r.ret_str);
                }
              else
-               def_compress_string = m_strdup(pargs.r.ret_str);
+               compress_algo_string = m_strdup(pargs.r.ret_str);
            }
            break;
          case oCertDigestAlgo: cert_digest_string = m_strdup(pargs.r.ret_str); break;
          case oNoSecmemWarn: secmem_set_flags( secmem_get_flags() | 1 ); break;
+         case oRequireSecmem: require_secmem=1; break;
+         case oNoRequireSecmem: require_secmem=0; break;
          case oNoPermissionWarn: opt.no_perm_warn=1; break;
          case oNoMDCWarn: opt.no_mdc_warn=1; break;
-          case oCharset:
+          case oDisplayCharset:
            if( set_native_charset( pargs.r.ret_str ) )
-               log_error(_("%s is not a valid character set\n"),
-                                                   pargs.r.ret_str);
+               log_error(_("`%s' is not a valid character set\n"),
+                         pargs.r.ret_str);
            break;
          case oNotDashEscaped: opt.not_dash_escaped = 1; break;
          case oEscapeFrom: opt.escape_from = 1; break;
@@ -1727,15 +2306,23 @@ main( int argc, char **argv )
 #endif /* __riscos__ */
             break;
          case oKeyServer:
-           opt.keyserver_uri=m_strdup(pargs.r.ret_str);
-           if(parse_keyserver_uri(pargs.r.ret_str,configname,configlineno))
-             log_error(_("could not parse keyserver URI\n"));
+           opt.keyserver=parse_keyserver_uri(pargs.r.ret_str,0,
+                                             configname,configlineno);
+           if(!opt.keyserver)
+             log_error(_("could not parse keyserver URL\n"));
            break;
          case oKeyServerOptions:
-           parse_keyserver_options(pargs.r.ret_str);
+           if(!parse_keyserver_options(pargs.r.ret_str))
+             {
+               if(configname)
+                 log_error(_("%s:%d: invalid keyserver options\n"),
+                           configname,configlineno);
+               else
+                 log_error(_("invalid keyserver options\n"));
+             }
            break;
          case oImportOptions:
-           if(!parse_import_options(pargs.r.ret_str,&opt.import_options))
+           if(!parse_import_options(pargs.r.ret_str,&opt.import_options,1))
              {
                if(configname)
                  log_error(_("%s:%d: invalid import options\n"),
@@ -1745,7 +2332,7 @@ main( int argc, char **argv )
              }
            break;
          case oExportOptions:
-           if(!parse_export_options(pargs.r.ret_str,&opt.export_options))
+           if(!parse_export_options(pargs.r.ret_str,&opt.export_options,1))
              {
                if(configname)
                  log_error(_("%s:%d: invalid export options\n"),
@@ -1755,42 +2342,32 @@ main( int argc, char **argv )
              }
            break;
          case oListOptions:
-           {
-             struct parse_options lopts[]=
-               {
-                 {"show-photos",LIST_SHOW_PHOTOS},
-                 {"show-policy-url",LIST_SHOW_POLICY},
-                 {"show-notation",LIST_SHOW_NOTATION},
-                 {"show-keyring",LIST_SHOW_KEYRING},
-                 {"show-validity",LIST_SHOW_VALIDITY},
-                 {"show-long-keyid",LIST_SHOW_LONG_KEYID},
-                 {NULL,0}
-               };
-
-             if(!parse_options(pargs.r.ret_str,&opt.list_options,lopts))
-               {
-                 if(configname)
-                   log_error(_("%s:%d: invalid list options\n"),
-                             configname,configlineno);
-                 else
-                   log_error(_("invalid list options\n"));
-               }
-           }
+           if(!parse_list_options(pargs.r.ret_str))
+             {
+               if(configname)
+                 log_error(_("%s:%d: invalid list options\n"),
+                           configname,configlineno);
+               else
+                 log_error(_("invalid list options\n"));
+             }
            break;
          case oVerifyOptions:
            {
              struct parse_options vopts[]=
                {
-                 {"show-photos",VERIFY_SHOW_PHOTOS},
-                 {"show-policy-url",VERIFY_SHOW_POLICY},
-                 {"show-notation",VERIFY_SHOW_NOTATION},
-                 {"show-preferred-keyserver",VERIFY_SHOW_KEYSERVER},
-                 {"show-validity",VERIFY_SHOW_VALIDITY},
-                 {"show-long-keyid",VERIFY_SHOW_LONG_KEYID},
-                 {NULL,0}
+                 {"show-photos",VERIFY_SHOW_PHOTOS,NULL},
+                 {"show-policy-urls",VERIFY_SHOW_POLICY_URLS,NULL},
+                 {"show-notations",VERIFY_SHOW_NOTATIONS,NULL},
+                 {"show-std-notations",VERIFY_SHOW_STD_NOTATIONS,NULL},
+                 {"show-standard-notations",VERIFY_SHOW_STD_NOTATIONS,NULL},
+                 {"show-user-notations",VERIFY_SHOW_USER_NOTATIONS,NULL},
+                 {"show-keyserver-urls",VERIFY_SHOW_KEYSERVER_URLS,NULL},
+                 {"show-uid-validity",VERIFY_SHOW_UID_VALIDITY,NULL},
+                 {"show-unusable-uids",VERIFY_SHOW_UNUSABLE_UIDS,NULL},
+                 {NULL,0,NULL}
                };
 
-             if(!parse_options(pargs.r.ret_str,&opt.verify_options,vopts))
+             if(!parse_options(pargs.r.ret_str,&opt.verify_options,vopts,1))
                {
                  if(configname)
                    log_error(_("%s:%d: invalid verify options\n"),
@@ -1802,7 +2379,7 @@ main( int argc, char **argv )
            break;
          case oTempDir: opt.temp_dir=pargs.r.ret_str; break;
          case oExecPath:
-           if(set_exec_path(pargs.r.ret_str,0))
+           if(set_exec_path(pargs.r.ret_str))
              log_error(_("unable to set exec-path to %s\n"),pargs.r.ret_str);
            else
              opt.exec_path_set=1;
@@ -1814,12 +2391,20 @@ main( int argc, char **argv )
          case oSigNotation: add_notation_data( pargs.r.ret_str, 0 ); break;
          case oCertNotation: add_notation_data( pargs.r.ret_str, 1 ); break;
          case oShowNotation:
-           opt.list_options|=LIST_SHOW_NOTATION;
-           opt.verify_options|=VERIFY_SHOW_NOTATION;
+           deprecated_warning(configname,configlineno,"--show-notation",
+                              "--list-options ","show-notations");
+           deprecated_warning(configname,configlineno,"--show-notation",
+                              "--verify-options ","show-notations");
+           opt.list_options|=LIST_SHOW_NOTATIONS;
+           opt.verify_options|=VERIFY_SHOW_NOTATIONS;
            break;
          case oNoShowNotation:
-           opt.list_options&=~LIST_SHOW_NOTATION;
-           opt.verify_options&=~VERIFY_SHOW_NOTATION;
+           deprecated_warning(configname,configlineno,"--no-show-notation",
+                              "--list-options ","no-show-notations");
+           deprecated_warning(configname,configlineno,"--no-show-notation",
+                              "--verify-options ","no-show-notations");
+           opt.list_options&=~LIST_SHOW_NOTATIONS;
+           opt.verify_options&=~VERIFY_SHOW_NOTATIONS;
            break;
          case oUtf8Strings: utf8_strings = 1; break;
          case oNoUtf8Strings: utf8_strings = 0; break;
@@ -1838,11 +2423,10 @@ main( int argc, char **argv )
          case oNoLiteral: opt.no_literal = 1; break;
          case oSetFilesize: opt.set_filesize = pargs.r.ret_ulong; break;
          case oHonorHttpProxy:
-                opt.keyserver_options.honor_http_proxy = 1;
+               add_to_strlist(&opt.keyserver_options.other,"http-proxy");
                deprecated_warning(configname,configlineno,
                                   "--honor-http-proxy",
-                                  "--keyserver-options ",
-                                  "honor-http-proxy");
+                                  "--keyserver-options ","http-proxy");
                break;
          case oFastListMode: opt.fast_list_mode = 1; break;
          case oFixedListMode: opt.fixed_list_mode = 1; break;
@@ -1854,8 +2438,11 @@ main( int argc, char **argv )
          case oNoRandomSeedFile: use_random_seed = 0; break;
          case oAutoKeyRetrieve:
          case oNoAutoKeyRetrieve:
-               opt.keyserver_options.auto_key_retrieve=
-                                            (pargs.r_opt==oAutoKeyRetrieve);
+               if(pargs.r_opt==oAutoKeyRetrieve)
+                 opt.keyserver_options.options|=KEYSERVER_AUTO_KEY_RETRIEVE;
+               else
+                 opt.keyserver_options.options&=~KEYSERVER_AUTO_KEY_RETRIEVE;
+
                deprecated_warning(configname,configlineno,
                           pargs.r_opt==oAutoKeyRetrieve?"--auto-key-retrieve":
                               "--no-auto-key-retrieve","--keyserver-options ",
@@ -1866,7 +2453,11 @@ main( int argc, char **argv )
          case oOverrideSessionKey:
                opt.override_session_key = pargs.r.ret_str;
                break;
-         case oMergeOnly: opt.merge_only = 1; break;
+         case oMergeOnly:
+               deprecated_warning(configname,configlineno,"--merge-only",
+                                  "--import-options ","merge-only");
+               opt.import_options|=IMPORT_MERGE_ONLY;
+           break;
           case oAllowSecretKeyImport: /* obsolete */ break;
          case oTryAllSecrets: opt.try_all_secrets = 1; break;
           case oTrustedKey: register_trusted_key( pargs.r.ret_str ); break;
@@ -1895,27 +2486,64 @@ main( int argc, char **argv )
           case oLCctype: opt.lc_ctype = pargs.r.ret_str; break;
           case oLCmessages: opt.lc_messages = 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:
+           while(opt.grouplist)
+             {
+               struct groupitem *iter=opt.grouplist;
+               free_strlist(iter->values);
+               opt.grouplist=opt.grouplist->next;
+               m_free(iter);
+             }
+           break;
          case oStrict: opt.strict=1; log_set_strict(1); break;
          case oNoStrict: opt.strict=0; log_set_strict(0); 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;
+         case oMultifile: multifile=1; break;
+         case oKeyidFormat:
+           if(ascii_strcasecmp(pargs.r.ret_str,"short")==0)
+             opt.keyid_format=KF_SHORT;
+           else if(ascii_strcasecmp(pargs.r.ret_str,"long")==0)
+             opt.keyid_format=KF_LONG;
+           else if(ascii_strcasecmp(pargs.r.ret_str,"0xshort")==0)
+             opt.keyid_format=KF_0xSHORT;
+           else if(ascii_strcasecmp(pargs.r.ret_str,"0xlong")==0)
+             opt.keyid_format=KF_0xLONG;
+           else
+             log_error("unknown keyid-format `%s'\n",pargs.r.ret_str);
+           break;
 
          default : pargs.err = configfp? 1:2; break;
-       }
-    }
+         }
+      }
+
 
     if( configfp ) {
        fclose( configfp );
        configfp = NULL;
-       m_free(configname); configname = NULL;
+        /* Remember the first config file name. */
+        if (!save_configname)
+          save_configname = configname;
+        else
+          m_free(configname);
+        configname = NULL;
        goto next_pass;
     }
     m_free( configname ); configname = NULL;
     if( log_get_errorcount(0) )
        g10_exit(2);
+
+    /* The command --gpgconf-list is pretty simple and may be called
+       directly after the option parsing. */
+    if (cmd == aGPGConfList)
+      {
+        gpgconf_list (save_configname);
+        g10_exit (0);
+      }
+    m_free (save_configname);
+
     if( nogreeting )
        greeting = 0;
 
@@ -1925,11 +2553,17 @@ main( int argc, char **argv )
        fprintf(stderr, "%s\n", strusage(15) );
     }
 #ifdef IS_DEVELOPMENT_VERSION
-    if( !opt.batch ) {
-       log_info("NOTE: THIS IS A DEVELOPMENT VERSION!\n");
-       log_info("It is only intended for test purposes and should NOT be\n");
-       log_info("used in a production environment or with production keys!\n");
-    }
+    if( !opt.batch )
+      {
+       const char *s;
+
+       if((s=strusage(20)))
+         log_info("%s\n",s);
+       if((s=strusage(21)))
+         log_info("%s\n",s);
+       if((s=strusage(22)))
+         log_info("%s\n",s);
+      }
 #endif
 
     if (opt.verbose > 2)
@@ -1957,6 +2591,14 @@ 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 )
@@ -1964,6 +2606,13 @@ main( int argc, char **argv )
 
     secmem_set_flags( secmem_get_flags() & ~2 ); /* resume warnings */
 
+    if(require_secmem && !got_secmem)
+      {
+       log_info(_("will not run with insecure memory due to %s\n"),
+                "--require-secmem");
+       g10_exit(2);
+      }
+
     set_debug();
 
     /* Do these after the switch(), so they can override settings. */
@@ -2025,8 +2674,6 @@ main( int argc, char **argv )
          compliance_failure();
        else
          {
-           opt.force_mdc = 0;
-           opt.disable_mdc = 1;
            opt.force_v4_certs = 0;
            opt.sk_comments = 0;
            opt.escape_from = 1;
@@ -2036,7 +2683,9 @@ main( int argc, char **argv )
            opt.ask_cert_expire = 0;
            m_free(def_digest_string);
            def_digest_string = m_strdup("md5");
-           opt.def_compress_algo = 1;
+           m_free(s2k_digest_string);
+           s2k_digest_string = m_strdup("md5");
+           opt.compress_algo = COMPRESS_ALGO_ZIP;
          }
       }
     else if(PGP6)
@@ -2045,8 +2694,6 @@ main( int argc, char **argv )
        opt.escape_from=1;
        opt.force_v3_sigs=1;
        opt.ask_sig_expire=0;
-       opt.force_mdc=0;
-       opt.disable_mdc=1;
       }
     else if(PGP7)
       {
@@ -2078,10 +2725,10 @@ main( int argc, char **argv )
        if( check_digest_algo(opt.def_digest_algo) )
            log_error(_("selected digest algorithm is invalid\n"));
     }
-    if( def_compress_string ) {
-       opt.def_compress_algo = string_to_compress_algo(def_compress_string);
-       m_free(def_compress_string); def_compress_string = NULL;
-       if( check_compress_algo(opt.def_compress_algo) )
+    if( compress_algo_string ) {
+       opt.compress_algo = string_to_compress_algo(compress_algo_string);
+       m_free(compress_algo_string); compress_algo_string = NULL;
+       if( check_compress_algo(opt.compress_algo) )
            log_error(_("selected compression algorithm is invalid\n"));
     }
     if( cert_digest_string ) {
@@ -2103,11 +2750,15 @@ main( int argc, char **argv )
            log_error(_("selected digest algorithm is invalid\n"));
     }
     if( opt.completes_needed < 1 )
-       log_error(_("completes-needed must be greater than 0\n"));
+      log_error(_("completes-needed must be greater than 0\n"));
     if( opt.marginals_needed < 2 )
-       log_error(_("marginals-needed must be greater than 1\n"));
+      log_error(_("marginals-needed must be greater than 1\n"));
     if( opt.max_cert_depth < 1 || opt.max_cert_depth > 255 )
-       log_error(_("max-cert-depth must be in range 1 to 255\n"));
+      log_error(_("max-cert-depth must be in the range from 1 to 255\n"));
+    if(opt.def_cert_level<0 || opt.def_cert_level>3)
+      log_error(_("invalid default-cert-level; must be 0, 1, 2, or 3\n"));
+    if( opt.min_cert_level < 1 || opt.min_cert_level > 3 )
+      log_error(_("invalid min-cert-level; must be 1, 2, or 3\n"));
     switch( opt.s2k_mode ) {
       case 0:
        log_info(_("NOTE: simple S2K mode (0) is strongly discouraged\n"));
@@ -2117,16 +2768,14 @@ main( int argc, char **argv )
        log_error(_("invalid S2K mode; must be 0, 1 or 3\n"));
     }
 
-    if(opt.def_cert_check_level<0 || opt.def_cert_check_level>3)
-      log_error(_("invalid default-check-level; must be 0, 1, 2, or 3\n"));
-
     /* This isn't actually needed, but does serve to error out if the
        string is invalid. */
     if(opt.def_preference_list &&
        keygen_set_std_prefs(opt.def_preference_list,0))
       log_error(_("invalid default preferences\n"));
 
-    /* We provide defaults for the personal digest list */
+    /* We provide defaults for the personal digest list.  This is
+       SHA-1. */
     if(!pers_digest_list)
       pers_digest_list="h2";
 
@@ -2142,9 +2791,46 @@ main( int argc, char **argv )
        keygen_set_std_prefs(pers_compress_list,PREFTYPE_ZIP))
       log_error(_("invalid personal compress preferences\n"));
 
+    /* We don't support all possible commands with multifile yet */
+    if(multifile)
+      {
+       char *cmdname;
+
+       switch(cmd)
+         {
+         case aSign:
+           cmdname="--sign";
+           break;
+         case aClearsign:
+           cmdname="--clearsign";
+           break;
+         case aDetachedSign:
+           cmdname="--detach-sign";
+           break;
+         case aSym:
+           cmdname="--symmetric";
+           break;
+         case aEncrSym:
+           cmdname="--symmetric --encrypt";
+           break;
+         case aStore:
+           cmdname="--store";
+           break;
+         default:
+           cmdname=NULL;
+           break;
+         }
+
+       if(cmdname)
+         log_error(_("%s does not yet work with %s\n"),cmdname,"--multifile");
+      }
+
     if( log_get_errorcount(0) )
        g10_exit(2);
 
+    if(opt.compress_level==0)
+      opt.compress_algo=COMPRESS_ALGO_NONE;
+
     /* Check our chosen algorithms against the list of legal
        algorithms. */
 
@@ -2171,10 +2857,10 @@ main( int argc, char **argv )
            badalg=digest_algo_to_string(opt.cert_digest_algo);
            badtype=PREFTYPE_HASH;
          }
-       else if(opt.def_compress_algo!=-1
-               && !algo_available(PREFTYPE_ZIP,opt.def_compress_algo,NULL))
+       else if(opt.compress_algo!=-1
+               && !algo_available(PREFTYPE_ZIP,opt.compress_algo,NULL))
          {
-           badalg=compress_algo_to_string(opt.def_compress_algo);
+           badalg=compress_algo_to_string(opt.compress_algo);
            badtype=PREFTYPE_ZIP;
          }
 
@@ -2183,18 +2869,18 @@ main( int argc, char **argv )
            switch(badtype)
              {
              case PREFTYPE_SYM:
-               log_info(_("you may not use cipher algorithm \"%s\" "
-                          "while in %s mode\n"),
+               log_info(_("you may not use cipher algorithm `%s'"
+                          " while in %s mode\n"),
                         badalg,compliance_option_string());
                break;
              case PREFTYPE_HASH:
-               log_info(_("you may not use digest algorithm \"%s\" "
-                          "while in %s mode\n"),
+               log_info(_("you may not use digest algorithm `%s'"
+                          " while in %s mode\n"),
                         badalg,compliance_option_string());
                break;
              case PREFTYPE_ZIP:
-               log_info(_("you may not use compression algorithm \"%s\" "
-                          "while in %s mode\n"),
+               log_info(_("you may not use compression algorithm `%s'"
+                          " while in %s mode\n"),
                         badalg,compliance_option_string());
                break;
              default:
@@ -2209,6 +2895,8 @@ main( int argc, char **argv )
     if( use_random_seed ) {
        char *p = make_filename(opt.homedir, "random_seed", NULL );
        set_random_seed_file(p);
+        if (!access (p, F_OK))
+          register_secured_file (p);
        m_free(p);
     }
 
@@ -2231,10 +2919,6 @@ main( int argc, char **argv )
        g10_opt_verbose = opt.verbose;
     }
 
-    /* Compression algorithm 0 means no compression at all */
-    if( opt.def_compress_algo == 0)
-        opt.compress = 0;
-
     /* kludge to let -sat generate a clear text signature */
     if( opt.textmode == 2 && !detached_sig && opt.armor && cmd == aSign )
        cmd = aClearsign;
@@ -2245,21 +2929,26 @@ main( int argc, char **argv )
     /* 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 */
-    if( cmd != aDeArmor && cmd != aEnArmor
-       && !(cmd == aKMode && argc == 2 ) ) 
+       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 )) ) 
       {
-        if (cmd != aCheckKeys && cmd != aListSigs && cmd != aListKeys
-            && cmd != aVerify && cmd != aVerifyFiles
-            && cmd != aSym)
+        if (ALWAYS_ADD_KEYRINGS
+            || (cmd != aCheckKeys && cmd != aListSigs && cmd != aListKeys
+                && cmd != aVerify && cmd != aSym))
           {
             if (!sec_nrings || default_keyring) /* add default secret rings */
-              keydb_add_resource ("secring" EXTSEP_S "gpg", 0, 1);
+              keydb_add_resource ("secring" EXTSEP_S "gpg", 4, 1);
             for (sl = sec_nrings; sl; sl = sl->next)
               keydb_add_resource ( sl->d, 0, 1 );
           }
        if( !nrings || default_keyring )  /* add default ring */
-           keydb_add_resource ("pubring" EXTSEP_S "gpg", 0, 0);
+           keydb_add_resource ("pubring" EXTSEP_S "gpg", 4, 0);
        for(sl = nrings; sl; sl = sl->next )
            keydb_add_resource ( sl->d, sl->flags, 0 );
       }
@@ -2289,7 +2978,8 @@ main( int argc, char **argv )
        log_error(_("failed to initialize the TrustDB: %s\n"), g10_errstr(rc));
 
 
-    switch (cmd) {
+    switch (cmd)
+      {
       case aStore: 
       case aSym:  
       case aSign: 
@@ -2301,35 +2991,59 @@ main( int argc, char **argv )
        break;
       default:
         break;
-    }
+      }
 
-    switch( cmd ) {
+    switch( cmd )
+      {
       case aStore: /* only store the file */
        if( argc > 1 )
            wrong_args(_("--store [filename]"));
        if( (rc = encode_store(fname)) )
-           log_error_f( print_fname_stdin(fname),
-                       "store failed: %s\n", g10_errstr(rc) );
+           log_error ("storing `%s' failed: %s\n",
+                       print_fname_stdin(fname),g10_errstr(rc) );
        break;
       case aSym: /* encrypt the given file only with the symmetric cipher */
        if( argc > 1 )
            wrong_args(_("--symmetric [filename]"));
        if( (rc = encode_symmetric(fname)) )
-           log_error_f(print_fname_stdin(fname),
-                       "symmetric encryption failed: %s\n",g10_errstr(rc) );
+            log_error (_("symmetric encryption of `%s' failed: %s\n"),
+                        print_fname_stdin(fname),g10_errstr(rc) );
        break;
 
       case aEncr: /* encrypt the given file */
+       if(multifile)
+         encode_crypt_files(argc, argv, remusr);
+       else
+         {
+           if( argc > 1 )
+             wrong_args(_("--encrypt [filename]"));
+           if( (rc = encode_crypt(fname,remusr,0)) )
+             log_error("%s: encryption failed: %s\n",
+                       print_fname_stdin(fname), g10_errstr(rc) );
+         }
+       break;
+
+      case aEncrSym:
+       /* This works with PGP 8 in the sense that it acts just like a
+          symmetric message.  It doesn't work at all with 2 or 6.  It
+          might work with 7, but alas, I don't have a copy to test
+          with right now. */
        if( argc > 1 )
-           wrong_args(_("--encrypt [filename]"));
-       if( (rc = encode_crypt(fname,remusr)) )
-           log_error("%s: encryption failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) );
+         wrong_args(_("--symmetric --encrypt [filename]"));
+       else if(opt.s2k_mode==0)
+         log_error(_("you cannot use --symmetric --encrypt"
+                     " with --s2k-mode 0\n"));
+       else if(PGP2 || PGP6 || PGP7 || RFC1991)
+         log_error(_("you cannot use --symmetric --encrypt"
+                     " while in %s mode\n"),compliance_option_string());
+       else
+         {
+           if( (rc = encode_crypt(fname,remusr,1)) )
+             log_error("%s: encryption failed: %s\n",
+                       print_fname_stdin(fname), g10_errstr(rc) );
+         }
        break;
 
-      case aEncrFiles: /* encrypt the given files */
-        encode_crypt_files(argc, argv, remusr);
-       break;
-          
       case aSign: /* sign the given file */
        sl = NULL;
        if( detached_sig ) { /* sign all files */
@@ -2359,10 +3073,36 @@ main( int argc, char **argv )
        else
            sl = NULL;
        if( (rc = sign_file(sl, detached_sig, locusr, 1, remusr, NULL)) )
-           log_error("%s: sign+encrypt failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) );
+           log_error("%s: sign+encrypt failed: %s\n",
+                     print_fname_stdin(fname), g10_errstr(rc) );
        free_strlist(sl);
        break;
 
+      case aSignEncrSym: /* sign and encrypt the given file */
+       if( argc > 1 )
+           wrong_args(_("--symmetric --sign --encrypt [filename]"));
+       else if(opt.s2k_mode==0)
+         log_error(_("you cannot use --symmetric --sign --encrypt"
+                     " with --s2k-mode 0\n"));
+       else if(PGP2 || PGP6 || PGP7 || RFC1991)
+         log_error(_("you cannot use --symmetric --sign --encrypt"
+                     " while in %s mode\n"),compliance_option_string());
+       else
+         {
+           if( argc )
+             {
+               sl = m_alloc_clear( sizeof *sl + strlen(fname));
+               strcpy(sl->d, fname);
+             }
+           else
+             sl = NULL;
+           if( (rc = sign_file(sl, detached_sig, locusr, 2, remusr, NULL)) )
+             log_error("%s: symmetric+sign+encrypt failed: %s\n",
+                       print_fname_stdin(fname), g10_errstr(rc) );
+           free_strlist(sl);
+         }
+       break;
+
       case aSignSym: /* sign and conventionally encrypt the given file */
        if (argc > 1)
            wrong_args(_("--sign --symmetric [filename]"));
@@ -2381,57 +3121,54 @@ main( int argc, char **argv )
        break;
 
       case aVerify:
-       if( (rc = verify_signatures( argc, argv ) ))
-           log_error("verify signatures failed: %s\n", g10_errstr(rc) );
-       break;
-
-      case aVerifyFiles:
-       if( (rc = verify_files( argc, argv ) ))
-           log_error("verify files failed: %s\n", g10_errstr(rc) );
+       if(multifile)
+         {
+           if( (rc = verify_files( argc, argv ) ))
+             log_error("verify files failed: %s\n", g10_errstr(rc) );
+         }
+       else
+         {
+           if( (rc = verify_signatures( argc, argv ) ))
+             log_error("verify signatures failed: %s\n", g10_errstr(rc) );
+         }
        break;
 
       case aDecrypt:
-       if( argc > 1 )
-           wrong_args(_("--decrypt [filename]"));
-       if( (rc = decrypt_message( fname ) ))
-           log_error("decrypt_message failed: %s\n", g10_errstr(rc) );
+        if(multifile)
+         decrypt_messages(argc, argv);
+       else
+         {
+           if( argc > 1 )
+             wrong_args(_("--decrypt [filename]"));
+           if( (rc = decrypt_message( fname ) ))
+             log_error("decrypt_message failed: %s\n", g10_errstr(rc) );
+         }
        break;
-
-      case aDecryptFiles:
-        decrypt_messages(argc, argv);
-        break;
             
-      case aSignKey: /* sign the key given as argument */
+      case aSignKey:
        if( argc != 1 )
-           wrong_args(_("--sign-key user-id"));
-       username = make_username( fname );
-       keyedit_menu(fname, locusr, NULL, 1 );
-       m_free(username);
-       break;
-
+         wrong_args(_("--sign-key user-id"));
+       /* fall through */
       case aLSignKey:
        if( argc != 1 )
-           wrong_args(_("--lsign-key user-id"));
-       username = make_username( fname );
-       keyedit_menu(fname, locusr, NULL, 2 );
-       m_free(username);
-       break;
+         wrong_args(_("--lsign-key user-id"));
+       /* fall through */
 
-      case aNRSignKey:
-       if( argc != 1 )
-           wrong_args(_("--nrsign-key user-id"));
-       username = make_username( fname );
-       keyedit_menu(fname, locusr, NULL, 3 );
-        m_free(username);
-        break;
+       sl=NULL;
 
-      case aNRLSignKey:
-       if( argc != 1 )
-           wrong_args(_("--nrlsign-key user-id"));
+       if(cmd==aSignKey)
+         append_to_strlist(&sl,"sign");
+       else if(cmd==aLSignKey)
+         append_to_strlist(&sl,"lsign");
+       else
+         BUG();
+
+       append_to_strlist( &sl, "save" );
        username = make_username( fname );
-       keyedit_menu(fname, locusr, NULL, 4 );
-        m_free(username);
-        break;
+       keyedit_menu(fname, locusr, sl, 0, 0 );
+       m_free(username);
+       free_strlist(sl);
+       break;
 
       case aEditKey: /* Edit a key signature */
        if( !argc )
@@ -2441,11 +3178,11 @@ main( int argc, char **argv )
            sl = NULL;
            for( argc--, argv++ ; argc; argc--, argv++ )
                append_to_strlist( &sl, *argv );
-           keyedit_menu( username, locusr, sl, 0 );
+           keyedit_menu( username, locusr, sl, 0, 1 );
            free_strlist(sl);
        }
        else
-           keyedit_menu(username, locusr, NULL, 0 );
+           keyedit_menu(username, locusr, NULL, 0, 1 );
        m_free(username);
        break;
 
@@ -2491,7 +3228,7 @@ main( int argc, char **argv )
        }
        else if( argc == 2 ) { /* -kv userid keyring */
            if( access( argv[1], R_OK ) ) {
-               log_error(_("can't open %s: %s\n"),
+               log_error(_("can't open `%s': %s\n"),
                               print_fname_stdin(argv[1]), strerror(errno));
            }
            else {
@@ -2513,23 +3250,22 @@ main( int argc, char **argv )
        if( opt.batch ) {
            if( argc > 1 )
                wrong_args("--gen-key [parameterfile]");
-           generate_keypair( argc? *argv : NULL );
+           generate_keypair( argc? *argv : NULL, NULL, NULL );
        }
        else {
            if( argc )
                wrong_args("--gen-key");
-           generate_keypair(NULL);
+           generate_keypair(NULL, NULL, NULL);
        }
        break;
 
       case aFastImport:
-        opt.import_options |= IMPORT_FAST_IMPORT;
+        opt.import_options |= IMPORT_FAST;
       case aImport:
        import_keys( argc? argv:NULL, argc, NULL, opt.import_options );
        break;
 
       case aExport:
-      case aExportAll:
       case aSendKeys:
       case aRecvKeys:
        sl = NULL;
@@ -2557,7 +3293,6 @@ main( int argc, char **argv )
        sl = NULL;
        for( ; argc; argc--, argv++ )
          append_to_strlist2( &sl, *argv, utf8_strings );
-
        rc=keyserver_search( sl );
        if(rc)
          log_error(_("keyserver search failed: %s\n"),g10_errstr(rc));
@@ -2785,9 +3520,46 @@ main( int argc, char **argv )
       case aRebuildKeydbCaches:
         if (argc)
             wrong_args ("--rebuild-keydb-caches");
-        keydb_rebuild_caches ();
+        keydb_rebuild_caches (1);
+        break;
+
+#ifdef ENABLE_CARD_SUPPORT
+      case aCardStatus:
+        if (argc)
+            wrong_args ("--card-status");
+        card_status (stdout, NULL, 0);
         break;
 
+      case aCardEdit:
+        if (argc) {
+            sl = NULL;
+            for (argc--, argv++ ; argc; argc--, argv++)
+                append_to_strlist (&sl, *argv);
+            card_edit (sl);
+            free_strlist (sl);
+       }
+        else
+            card_edit (NULL);
+        break;
+
+      case aChangePIN:
+        if (!argc)
+            change_pin (0,1);
+        else if (argc == 1)
+            change_pin (atoi (*argv),1);
+        else
+        wrong_args ("--change-pin [no]");
+        break;
+#endif /* ENABLE_CARD_SUPPORT*/
+
+      case aListConfig:
+       {
+         char *str=collapse_args(argc,argv);
+         list_config(str);
+         m_free(str);
+       }
+       break;
+
       case aListPackets:
        opt.list_packets=2;
       default:
@@ -2798,7 +3570,14 @@ main( int argc, char **argv )
                && isatty( fileno(stdout) ) && isatty( fileno(stderr) ) )
            log_info(_("Go ahead and type your message ...\n"));
 
-       if( !(a = iobuf_open(fname)) )
+       a = iobuf_open(fname);
+        if (a && is_secured_file (iobuf_get_fd (a)))
+          {
+            iobuf_close (a);
+            a = NULL;
+            errno = EPERM;
+          }
+       if( !a )
            log_error(_("can't open `%s'\n"), print_fname_stdin(fname));
        else {
 
@@ -2818,7 +3597,7 @@ main( int argc, char **argv )
            iobuf_close(a);
        }
        break;
-    }
+      }
 
     /* cleanup */
     FREE_STRLIST(remusr);
@@ -2831,6 +3610,9 @@ main( int argc, char **argv )
 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");
@@ -2865,8 +3647,6 @@ print_hex( MD_HANDLE md, int algo, const char *fname )
 
   if(algo==DIGEST_ALGO_RMD160)
     indent+=printf("RMD160 = ");
-  else if(algo==DIGEST_ALGO_TIGER)
-    indent+=printf(" TIGER = ");
   else if(algo>0)
     indent+=printf("%6s = ",digest_algo_to_string(algo));
   else
@@ -2970,6 +3750,12 @@ print_mds( const char *fname, int algo )
     }
     else {
        fp = fopen( fname, "rb" );
+        if (fp && is_secured_file (fileno (fp)))
+          {
+            fclose (fp);
+            fp = NULL;
+            errno = EPERM;
+          }
     }
     if( !fp ) {
        log_error("%s: %s\n", fname?fname:"[stdin]", strerror(errno) );
@@ -2983,9 +3769,6 @@ print_mds( const char *fname, int algo )
        md_enable( md, DIGEST_ALGO_MD5 );
        md_enable( md, DIGEST_ALGO_SHA1 );
        md_enable( md, DIGEST_ALGO_RMD160 );
-#ifdef USE_TIGER192
-       md_enable( md, DIGEST_ALGO_TIGER );
-#endif
 #ifdef USE_SHA256
        md_enable( md, DIGEST_ALGO_SHA256 );
 #endif
@@ -3008,9 +3791,6 @@ print_mds( const char *fname, int algo )
                 print_hashline( md, DIGEST_ALGO_MD5, fname );
                 print_hashline( md, DIGEST_ALGO_SHA1, fname );
                 print_hashline( md, DIGEST_ALGO_RMD160, fname );
-#ifdef USE_TIGER192
-               print_hashline( md, DIGEST_ALGO_TIGER, fname );
-#endif
 #ifdef USE_SHA256
                 print_hashline( md, DIGEST_ALGO_SHA256, fname );
 #endif
@@ -3027,9 +3807,6 @@ print_mds( const char *fname, int algo )
                 print_hex( md, DIGEST_ALGO_MD5, fname );
                 print_hex( md, DIGEST_ALGO_SHA1, fname );
                 print_hex( md, DIGEST_ALGO_RMD160, fname );
-#ifdef USE_TIGER192
-               print_hex( md, DIGEST_ALGO_TIGER, fname );
-#endif
 #ifdef USE_SHA256
                 print_hex( md, DIGEST_ALGO_SHA256, fname );
 #endif
@@ -3089,8 +3866,7 @@ add_notation_data( const char *string, int which )
 
     if(!saw_at && !opt.expert)
       {
-       log_error(
-               _("a user notation name must contain the '@' character\n"));
+       log_error(_("a user notation name must contain the '@' character\n"));
        return;
       }
 
@@ -3100,8 +3876,8 @@ add_notation_data( const char *string, int which )
        if ((*s & 0x80))
           highbit = 1;
        else if (iscntrl(*s)) {
-           log_error(_("a notation value must not use "
-                       "any control characters\n") );
+           log_error(_("a notation value must not use"
+                       " any control characters\n") );
            return;
        }
     }
@@ -3118,7 +3894,7 @@ add_notation_data( const char *string, int which )
 static void
 add_policy_url( const char *string, int which )
 {
-  int i,critical=0;
+  unsigned int i,critical=0;
   STRLIST sl;
 
   if(*string=='!')
@@ -3151,7 +3927,7 @@ add_policy_url( const char *string, int which )
 static void
 add_keyserver_url( const char *string, int which )
 {
-  int i,critical=0;
+  unsigned int i,critical=0;
   STRLIST sl;
 
   if(*string=='!')
@@ -3169,8 +3945,7 @@ add_keyserver_url( const char *string, int which )
       if(which)
        BUG();
       else
-       log_error(_("the given signature preferred keyserver "
-                   "URL is invalid\n"));
+       log_error(_("the given preferred keyserver URL is invalid\n"));
     }
 
   if(which)