See ChangeLog: Mon Jul 26 09:34:46 CEST 1999 Werner Koch
[gnupg.git] / g10 / g10.c
index 9d4f20d..02d7202 100644 (file)
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -1,14 +1,14 @@
 /* g10.c - The GnuPG utility (main for gpg)
- *     Copyright (C) 1998 Free Software Foundation, Inc.
+ *     Copyright (C) 1998, 1999 Free Software Foundation, Inc.
  *
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
  *
- * GNUPG is free software; you can redistribute it and/or modify
+ * GnuPG is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
- * GNUPG is distributed in the hope that it will be useful,
+ * GnuPG is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -23,9 +23,9 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
 #include <unistd.h>
 
-/* #define MAINTAINER_OPTIONS */
 
 #include "packet.h"
 #include "iobuf.h"
 #include "main.h"
 #include "options.h"
 #include "keydb.h"
+#include "trustdb.h"
 #include "mpi.h"
 #include "cipher.h"
 #include "filter.h"
-#include "trustdb.h"
 #include "ttyio.h"
 #include "i18n.h"
 #include "status.h"
 #include "g10defs.h"
-
-#ifndef IS_G10MAINT
-  #define IS_G10 1
-#endif
+#include "hkp.h"
 
 
 enum cmd_and_opt_values { aNull = 0,
@@ -54,22 +51,25 @@ enum cmd_and_opt_values { aNull = 0,
     aSym         = 'c',
     aDecrypt     = 'd',
     aEncr        = 'e',
+    oInteractive  = 'i',
     oKOption     = 'k',
     oDryRun      = 'n',
     oOutput      = 'o',
     oQuiet       = 'q',
-    oRemote      = 'r',
+    oRecipient   = 'r',
     aSign        = 's',
     oTextmodeShort= 't',
     oUser        = 'u',
     oVerbose     = 'v',
     oCompress    = 'z',
+    oNotation    = 'N',
     oBatch       = 500,
     aClearsign,
     aStore,
     aKeygen,
     aSignEncr,
     aSignKey,
+    aLSignKey,
     aListPackets,
     aEditKey,
     aDeleteKey,
@@ -82,7 +82,10 @@ enum cmd_and_opt_values { aNull = 0,
     aListKeys,
     aListSigs,
     aListSecretKeys,
+    aSendKeys,
+    aRecvKeys,
     aExport,
+    aExportAll,
     aExportSecret,
     aCheckKeys,
     aGenRevoke,
@@ -102,20 +105,28 @@ enum cmd_and_opt_values { aNull = 0,
 
     oTextmode,
     oFingerprint,
+    oWithFingerprint,
     oAnswerYes,
     oAnswerNo,
     oKeyring,
     oSecretKeyring,
     oDefaultKey,
+    oDefRecipient,
+    oDefRecipientSelf,
+    oNoDefRecipient,
     oOptions,
     oDebug,
     oDebugAll,
     oStatusFD,
     oNoComment,
+    oNoVersion,
+    oEmitVersion,
     oCompletesNeeded,
     oMarginalsNeeded,
+    oMaxCertDepth,
     oLoadExtension,
     oRFC1991,
+    oOpenPGP,
     oCipherAlgo,
     oDigestAlgo,
     oCompressAlgo,
@@ -127,10 +138,12 @@ enum cmd_and_opt_values { aNull = 0,
     oNoArmor,
     oNoDefKeyring,
     oNoGreeting,
+    oNoTTY,
     oNoOptions,
     oNoBatch,
     oHomedir,
     oWithColons,
+    oWithKeyData,
     oSkipVerify,
     oCompressKeys,
     oCompressSigs,
@@ -138,12 +151,32 @@ enum cmd_and_opt_values { aNull = 0,
     oEmuChecksumBug,
     oRunAsShmCP,
     oSetFilename,
+    oSetPolicyURL,
+    oUseEmbeddedFilename,
     oComment,
+    oDefaultComment,
     oThrowKeyid,
     oForceV3Sigs,
+    oForceMDC,
     oS2KMode,
     oS2KDigest,
     oS2KCipher,
+    oCharset,
+    oNotDashEscaped,
+    oEscapeFrom,
+    oLockOnce,
+    oLockMultiple,
+    oKeyServer,
+    oEncryptTo,
+    oNoEncryptTo,
+    oLoggerFD,
+    oUtf8Strings,
+    oNoUtf8Strings,
+    oDisableCipherAlgo,
+    oDisablePubkeyAlgo,
+    oAllowNonSelfsignedUID,
+    oNoLiteral,
+    oSetFilesize,
 aTest };
 
 
@@ -151,7 +184,6 @@ static ARGPARSE_OPTS opts[] = {
 
     { 300, NULL, 0, N_("@Commands:\n ") },
 
-  #ifdef IS_G10
     { aSign, "sign",      256, N_("|[file]|make a signature")},
     { aClearsign, "clearsign", 256, N_("|[file]|make a clear text signature") },
     { aDetachedSign, "detach-sign", 256, N_("make a detached signature")},
@@ -160,66 +192,73 @@ static ARGPARSE_OPTS opts[] = {
     { aStore, "store",     256, N_("store only")},
     { aDecrypt, "decrypt",   256, N_("decrypt data (default)")},
     { aVerify, "verify"   , 256, N_("verify a signature")},
-  #endif
     { 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")},
     { oFingerprint, "fingerprint", 256, N_("list keys and fingerprints")},
     { aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")},
-  #ifdef IS_G10
-    { aKeygen, "gen-key",   256, N_("generate a new key pair")},
-  #endif
+    { aKeygen,    "gen-key",  256, N_("generate a new key pair")},
     { aDeleteKey, "delete-key",256, N_("remove key from the public keyring")},
-  #ifdef IS_G10
-    { aEditKey, "edit-key"  ,256, N_("sign or edit a key")},
+    { aSignKey,  "sign-key"   ,256, N_("sign a key")},
+    { aLSignKey, "lsign-key"  ,256, N_("sign a key locally")},
+    { aEditKey,  "edit-key"   ,256, N_("sign or edit a key")},
     { aGenRevoke, "gen-revoke",256, N_("generate a revocation certificate")},
-  #endif
-    { aExport, "export"          , 256, N_("export keys") },
+    { aExport, "export"           , 256, N_("export keys") },
+    { aSendKeys, "send-keys"     , 256, N_("export keys to a key server") },
+    { aRecvKeys, "recv-keys"     , 256, N_("import keys from a key server") },
+    { aExportAll, "export-all"    , 256, "@" },
     { aExportSecret, "export-secret-keys" , 256, "@" },
     { aImport, "import",      256     , N_("import/merge keys")},
     { aFastImport, "fast-import",  256 , "@"},
     { aListPackets, "list-packets",256,N_("list only the sequence of packets")},
-  #ifdef IS_G10MAINT
     { aExportOwnerTrust,
              "export-ownertrust", 256, N_("export the ownertrust values")},
     { aImportOwnerTrust,
              "import-ownertrust", 256 , N_("import ownertrust values")},
     { aUpdateTrustDB,
-             "update-trustdb",0 , N_("|[NAMES]|update the trust database")},
+             "update-trustdb",0 , N_("update the trust database")},
     { aCheckTrustDB,
              "check-trustdb",0 , N_("|[NAMES]|check the trust database")},
     { aFixTrustDB, "fix-trustdb",0 , N_("fix a corrupted trust database")},
     { aDeArmor, "dearmor", 256, N_("De-Armor a file or stdin") },
     { aEnArmor, "enarmor", 256, N_("En-Armor a file or stdin") },
     { aPrintMD,  "print-md" , 256, N_("|algo [files]|print message digests")},
-    { aPrintMDs, "print-mds" , 256, N_("print all message digests")},
-    #ifdef MAINTAINER_OPTIONS
     { aPrimegen, "gen-prime" , 256, "@" },
     { aGenRandom, "gen-random" , 256, "@" },
-    #endif
-  #endif
 
     { 301, NULL, 0, N_("@\nOptions:\n ") },
 
     { oArmor, "armor",     0, N_("create ascii armored output")},
-  #ifdef IS_G10
+    { oRecipient, "recipient", 2, N_("|NAME|encrypt for NAME")},
+    { 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")},
+    { oNoDefRecipient, "no-default-recipient", 0, "@" },
+    { oEncryptTo, "encrypt-to", 2, "@" },
+    { oNoEncryptTo, "no-encrypt-to", 0, "@" },
     { oUser, "local-user",2, N_("use this user-id to sign or decrypt")},
-    { oRemote, "remote-user", 2, N_("use this user-id for encryption")},
     { oCompress, NULL,       1, N_("|N|set compress level N (0 disables)") },
     { oTextmodeShort, NULL,   0, "@"},
     { oTextmode, "textmode",  0, N_("use canonical text mode")},
-  #endif
     { oOutput, "output",    2, N_("use as output file")},
     { 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") },
- /* { oDryRun, "dry-run",   0, N_("do not make any changes") }, */
+    { oForceMDC, "force-mdc", 0, N_("always use a MDC for encryption") },
+    { oDryRun, "dry-run",   0, N_("do not make any changes") },
+  /*{ oInteractive, "interactive", 0, N_("prompt before overwriting") }, */
     { 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")},
     { oSecretKeyring, "secret-keyring" ,2, N_("add this secret keyring to the list")},
     { oDefaultKey, "default-key" ,2, N_("|NAME|use NAME as default secret key")},
+    { oKeyServer, "keyserver",2, N_("|HOST|use this keyserver to lookup keys")},
+    { oCharset, "charset"   , 2, N_("|NAME|set terminal charset to NAME") },
     { oOptions, "options"   , 2, N_("read options from file")},
 
     { oDebug, "debug"     ,4|16, N_("set debugging flags")},
@@ -228,46 +267,35 @@ static ARGPARSE_OPTS opts[] = {
     { oNoComment, "no-comment", 0,   N_("do not write comment packets")},
     { oCompletesNeeded, "completes-needed", 1, N_("(default is 1)")},
     { oMarginalsNeeded, "marginals-needed", 1, N_("(default is 3)")},
+    { oMaxCertDepth,   "max-cert-depth", 1, "@" },
     { oLoadExtension, "load-extension" ,2, N_("|FILE|load extension module FILE")},
     { oRFC1991, "rfc1991",   0, N_("emulate the mode described in RFC1991")},
+    { oOpenPGP, "openpgp", 0, N_("set all packet, cipher and digest options to OpenPGP behavior")},
     { 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")},
-  #ifdef IS_G10
     { oCipherAlgo, "cipher-algo", 2 , N_("|NAME|use cipher algorithm NAME")},
     { oDigestAlgo, "digest-algo", 2 , N_("|NAME|use message digest algorithm NAME")},
     { oCompressAlgo, "compress-algo", 1 , N_("|N|use compress algorithm N")},
     { oThrowKeyid, "throw-keyid", 0, N_("throw keyid field of encrypted packets")},
-  #else /* some dummies */
-    { oCipherAlgo, "cipher-algo", 2 , "@"},
-    { oDigestAlgo, "digest-algo", 2 , "@"},
-    { oCompressAlgo, "compress-algo", 1 , "@"},
-  #endif
+    { oNotation,   "notation-data", 2, N_("|NAME=VALUE|use this notation data")},
 
-  #ifdef IS_G10
     { 302, NULL, 0, N_("@\nExamples:\n\n"
     " -se -r Bob [file]          sign and encrypt for user Bob\n"
     " --clearsign [file]         make a clear text signature\n"
     " --detach-sign [file]       make a detached signature\n"
     " --list-keys [names]        show keys\n"
     " --fingerprint [names]      show fingerprints\n"  ) },
-  #endif
 
   /* hidden options */
-  #ifdef IS_G10MAINT
-    { aTest, "test"      , 0, "@" },
     { aExportOwnerTrust, "list-ownertrust",0 , "@"},  /* alias */
+    { aPrintMDs, "print-mds" , 256, "@"}, /* old */
     { aListTrustDB, "list-trustdb",0 , "@"},
     { aListTrustPath, "list-trust-path",0, "@"},
-  #endif
-  #ifdef IS_G10
     { oKOption, NULL,   0, "@"},
-    { aEditKey, "edit-sig"  ,0, "@"}, /* alias for edit-key */
     { oPasswdFD, "passphrase-fd",1, "@" },
-    { aSignKey, "sign-key"  ,256, "@" }, /* alias for edit-key */
-  #endif
     { aDeleteSecretKey, "delete-secret-key",0, "@" },
     { oQuickRandom, "quick-random", 0, "@"},
     { oNoVerbose, "no-verbose", 0, "@"},
@@ -280,6 +308,7 @@ static ARGPARSE_OPTS opts[] = {
     { oHomedir, "homedir", 2, "@" },   /* defaults to "~/.gnupg" */
     { oNoBatch, "no-batch", 0, "@" },
     { oWithColons, "with-colons", 0, "@"},
+    { oWithKeyData,"with-key-data", 0, "@"},
     { aListKeys, "list-key", 0, "@" }, /* alias */
     { aListSigs, "list-sig", 0, "@" }, /* alias */
     { aCheckKeys, "check-sig",0, "@" }, /* alias */
@@ -290,21 +319,42 @@ static ARGPARSE_OPTS opts[] = {
     { oEmuChecksumBug, "emulate-checksum-bug", 0, "@"},
     { oRunAsShmCP, "run-as-shm-coprocess", 4, "@" },
     { oSetFilename, "set-filename", 2, "@" },
+    { oSetPolicyURL, "set-policy-url", 2, "@" },
     { oComment, "comment", 2, "@" },
+    { oDefaultComment, "default-comment", 0, "@" },
+    { oNoVersion, "no-version", 0, "@"},
+    { oEmitVersion, "emit-version", 0, "@"},
+    { oNotDashEscaped, "not-dash-escaped", 0, "@" },
+    { oEscapeFrom, "escape-from-lines", 0, "@" },
+    { oLockOnce, "lock-once", 0, "@" },
+    { oLockMultiple, "lock-multiple", 0, "@" },
+    { oLoggerFD, "logger-fd",1, "@" },
+    { oUseEmbeddedFilename, "use-embedded-filename", 0, "@" },
+    { oUtf8Strings, "utf8-strings", 0, "@" },
+    { oNoUtf8Strings, "no-utf8-strings", 0, "@" },
+    { oWithFingerprint, "with-fingerprint", 0, "@" },
+    { oDisableCipherAlgo,  "disable-cipher-algo", 2, "@" },
+    { oDisablePubkeyAlgo,  "disable-pubkey-algo", 2, "@" },
+    { oAllowNonSelfsignedUID, "allow-non-selfsigned-uid", 0, "@" },
+    { oNoLiteral, "no-literal", 0, "@" },
+    { oSetFilesize, "set-filesize", 20, "@" },
 {0} };
 
 
 
+int g10_errors_seen = 0;
+
+static int utf8_strings = 0;
 static int maybe_setuid = 1;
 
 static char *build_list( const char *text,
                         const char *(*mapf)(int), int (*chkf)(int) );
 static void set_cmd( enum cmd_and_opt_values *ret_cmd,
                        enum cmd_and_opt_values new_cmd );
-#ifdef IS_G10MAINT
 static void print_hex( byte *p, size_t n );
 static void print_mds( const char *fname, int algo );
-#endif
+static void add_notation_data( const char *string );
+static int  check_policy_url( const char *s );
 
 const char *
 strusage( int level )
@@ -312,12 +362,7 @@ strusage( int level )
   static char *digests, *pubkeys, *ciphers;
     const char *p;
     switch( level ) {
-      case 11: p =
-         #ifdef IS_G10MAINT
-           "gpgm (GnuPG)";
-         #else
-           "gpg (GnuPG)";
-         #endif
+      case 11: p = "gpg (GnuPG)";
        break;
       case 13: p = VERSION; break;
       case 17: p = PRINTABLE_OS_NAME; break;
@@ -326,21 +371,12 @@ strusage( int level )
        break;
       case 1:
       case 40: p =
-         #ifdef IS_G10MAINT
-           _("Usage: gpgm [options] [files] (-h for help)");
-         #else
            _("Usage: gpg [options] [files] (-h for help)");
-         #endif
        break;
       case 41: p =
-         #ifdef IS_G10MAINT
-           _("Syntax: gpgm [options] [files]\n"
-             "GnuPG maintenance utility\n");
-         #else
            _("Syntax: gpg [options] [files]\n"
              "sign, check, encrypt or decrypt\n"
              "default operation depends on the input data\n");
-         #endif
        break;
 
       case 31: p = _("\nSupported algorithms:\n"); break;
@@ -417,16 +453,25 @@ i18n_init(void)
 static void
 wrong_args( const char *text)
 {
-  #ifdef IS_G10MAINT
-    fputs(_("usage: gpgm [options] "),stderr);
-  #else
     fputs(_("usage: gpg [options] "),stderr);
-  #endif
     fputs(text,stderr);
     putc('\n',stderr);
     g10_exit(2);
 }
 
+
+static char *
+make_username( const char *string )
+{
+    char *p;
+    if( utf8_strings )
+       p = native_to_utf8( string );
+    else
+       p = m_strdup(string);
+    return p;
+}
+
+
 static void
 set_debug(void)
 {
@@ -479,6 +524,7 @@ main( int argc, char **argv )
     int orig_argc;
     char **orig_argv;
     const char *fname;
+    char *username;
     STRLIST sl, remusr= NULL, locusr=NULL;
     STRLIST nrings=NULL, sec_nrings=NULL;
     armor_filter_context_t afx;
@@ -488,9 +534,9 @@ main( int argc, char **argv )
     unsigned configlineno;
     int parse_debug = 0;
     int default_config =1;
-    int errors=0;
     int default_keyring = 1;
-    int greeting = 1;
+    int greeting = 0;
+    int nogreeting = 0;
     enum cmd_and_opt_values cmd = 0;
     const char *trustdb_name = NULL;
     char *def_cipher_string = NULL;
@@ -498,17 +544,13 @@ main( int argc, char **argv )
     char *s2k_cipher_string = NULL;
     char *s2k_digest_string = NULL;
     int pwfd = -1;
+    int with_fpr = 0; /* make an option out of --fingerprint */
   #ifdef USE_SHM_COPROCESSING
     ulong requested_shm_size=0;
   #endif
 
     trap_unaligned();
     secmem_set_flags( secmem_get_flags() | 2 ); /* suspend warnings */
-  #ifdef IS_G10MAINT
-    secmem_init( 0 );     /* disable use of secmem */
-    maybe_setuid = 0;
-    log_set_name("gpgm");
-  #else
     /* Please note that we may running SUID(ROOT), so be very CAREFUL
      * when adding any stuff between here and the call to
      * secmem_init()  somewhere after the option parsing
@@ -516,22 +558,23 @@ main( int argc, char **argv )
     log_set_name("gpg");
     secure_random_alloc(); /* put random number into secure memory */
     disable_core_dumps();
-  #endif
     init_signals();
+    create_dotlock(NULL); /* register locking cleanup */
     i18n_init();
     opt.compress = -1; /* defaults to standard compress level */
-    /* fixme: set the next two to zero and decide where used */
+    /* note: if you change these lines, look at oOpenPGP */
     opt.def_cipher_algo = 0;
     opt.def_digest_algo = 0;
     opt.def_compress_algo = 2;
-    opt.s2k_mode = 1; /* salted */
+    opt.s2k_mode = 3; /* iterated+salted */
     opt.s2k_digest_algo = DIGEST_ALGO_RMD160;
     opt.s2k_cipher_algo = CIPHER_ALGO_BLOWFISH;
     opt.completes_needed = 1;
     opt.marginals_needed = 3;
+    opt.max_cert_depth = 5;
     opt.homedir = getenv("GNUPGHOME");
     if( !opt.homedir || !*opt.homedir ) {
-      #ifdef __MINGW32__
+      #ifdef HAVE_DRIVE_LETTERS
        opt.homedir = "c:/gnupg";
       #else
        opt.homedir = "~/.gnupg";
@@ -564,25 +607,24 @@ main( int argc, char **argv )
            opt.shm_coprocess = 1;
            requested_shm_size = pargs.r.ret_ulong;
        }
+       else if ( pargs.r_opt == oStatusFD ) {
+           /* this is needed to ensure that the status-fd filedescriptor is
+            * initialized when init_shm_coprocessing() is called */
+           set_status_fd( pargs.r.ret_int );
+       }
       #endif
     }
 
 
   #ifdef USE_SHM_COPROCESSING
     if( opt.shm_coprocess ) {
-      #ifdef IS_G10
        init_shm_coprocessing(requested_shm_size, 1 );
-      #else
-       init_shm_coprocessing(requested_shm_size, 0 );
-      #endif
     }
   #endif
-  #ifdef IS_G10
     /* initialize the secure memory. */
     secmem_init( 16384 );
     maybe_setuid = 0;
     /* Okay, we are now working under our real uid */
-  #endif
 
     if( default_config )
        configname = make_filename(opt.homedir, "options", NULL );
@@ -599,18 +641,18 @@ main( int argc, char **argv )
        if( !configfp ) {
            if( default_config ) {
                if( parse_debug )
-                   log_info(_("note: no default option file '%s'\n"),
+                   log_info(_("NOTE: no default option file `%s'\n"),
                                                            configname );
            }
            else {
-               log_error(_("option file '%s': %s\n"),
+               log_error(_("option file `%s': %s\n"),
                                    configname, strerror(errno) );
                g10_exit(2);
            }
            m_free(configname); configname = NULL;
        }
        if( parse_debug && configname )
-           log_info(_("reading options from '%s'\n"), configname );
+           log_info(_("reading options from `%s'\n"), configname );
        default_config = 0;
     }
 
@@ -621,32 +663,32 @@ main( int argc, char **argv )
          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 aExport: set_cmd( &cmd, aExport); break;
+         case aExportAll: set_cmd( &cmd, aExportAll); break;
          case aListKeys: set_cmd( &cmd, aListKeys); break;
          case aListSigs: set_cmd( &cmd, aListSigs); break;
          case aExportSecret: set_cmd( &cmd, aExportSecret); break;
-         case aDeleteSecretKey: set_cmd( &cmd, aDeleteSecretKey); break;
-         case aDeleteKey: set_cmd( &cmd, aDeleteKey); break;
+         case aDeleteSecretKey: set_cmd( &cmd, aDeleteSecretKey);
+                                                       greeting=1; break;
+         case aDeleteKey: set_cmd( &cmd, aDeleteKey); greeting=1; break;
 
-       #ifdef IS_G10
          case aDetachedSign: detached_sig = 1; set_cmd( &cmd, aSign ); break;
          case aSym: set_cmd( &cmd, aSym); break;
          case aDecrypt: set_cmd( &cmd, aDecrypt); break;
          case aEncr: set_cmd( &cmd, aEncr); break;
          case aSign: set_cmd( &cmd, aSign );  break;
-         case aKeygen: set_cmd( &cmd, aKeygen); break;
+         case aKeygen: set_cmd( &cmd, aKeygen); greeting=1; break;
          case aSignKey: set_cmd( &cmd, aSignKey); break;
+         case aLSignKey: set_cmd( &cmd, aLSignKey); break;
          case aStore: set_cmd( &cmd, aStore); break;
-         case aEditKey: set_cmd( &cmd, aEditKey); 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 aVerify: set_cmd( &cmd, aVerify); break;
-       #else
-         #ifdef MAINTAINER_OPTIONS
-           case aPrimegen: set_cmd( &cmd, aPrimegen); break;
-           case aTest: set_cmd( &cmd, aTest); break;
-           case aGenRandom: set_cmd( &cmd, aGenRandom); break;
-         #endif
+         case aPrimegen: set_cmd( &cmd, aPrimegen); break;
+         case aGenRandom: set_cmd( &cmd, aGenRandom); break;
          case aPrintMD: set_cmd( &cmd, aPrintMD); break;
          case aPrintMDs: set_cmd( &cmd, aPrintMDs); break;
          case aListTrustDB: set_cmd( &cmd, aListTrustDB); break;
@@ -658,13 +700,13 @@ main( int argc, char **argv )
          case aEnArmor: set_cmd( &cmd, aEnArmor); break;
          case aExportOwnerTrust: set_cmd( &cmd, aExportOwnerTrust); break;
          case aImportOwnerTrust: set_cmd( &cmd, aImportOwnerTrust); break;
-       #endif /* IS_G10MAINT */
-
-
 
          case oArmor: opt.armor = 1; opt.no_armor=0; break;
          case oOutput: opt.outfile = pargs.r.ret_str; break;
          case oQuiet: opt.quiet = 1; break;
+         case oNoTTY: opt.quiet = 1; 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 oKOption: set_cmd( &cmd, aKMode ); break;
@@ -676,6 +718,9 @@ main( int argc, char **argv )
          case oDebug: opt.debug |= pargs.r.ret_ulong; break;
          case oDebugAll: opt.debug = ~0; break;
          case oStatusFD: set_status_fd( pargs.r.ret_int ); break;
+         case oLoggerFD: log_set_logfile( NULL, pargs.r.ret_int ); break;
+         case oWithFingerprint:
+               with_fpr=1; /*fall thru*/
          case oFingerprint: opt.fingerprint++; break;
          case oSecretKeyring: append_to_strlist( &sec_nrings, pargs.r.ret_str); break;
          case oOptions:
@@ -688,18 +733,34 @@ main( int argc, char **argv )
            break;
          case oNoArmor: opt.no_armor=1; opt.armor=0; break;
          case oNoDefKeyring: default_keyring = 0; break;
-         case oNoGreeting: greeting = 0; break;
+         case oNoGreeting: nogreeting = 1; break;
          case oNoVerbose: g10_opt_verbose = 0;
                           opt.verbose = 0; opt.list_sigs=0; break;
          case oQuickRandom: quick_random_gen(1); break;
          case oNoComment: opt.no_comment=1; break;
+         case oNoVersion: opt.no_version=1; break;
+         case oEmitVersion: opt.no_version=0; break;
          case oCompletesNeeded: opt.completes_needed = pargs.r.ret_int; break;
          case oMarginalsNeeded: opt.marginals_needed = pargs.r.ret_int; break;
+         case oMaxCertDepth: opt.max_cert_depth = pargs.r.ret_int; break;
          case oTrustDBName: trustdb_name = pargs.r.ret_str; break;
          case oDefaultKey: opt.def_secret_key = pargs.r.ret_str; break;
+         case oDefRecipient:
+                   if( *pargs.r.ret_str )
+                       opt.def_recipient = make_username(pargs.r.ret_str);
+                   break;
+         case oDefRecipientSelf:
+                   m_free(opt.def_recipient); opt.def_recipient = NULL;
+                   opt.def_recipient_self = 1;
+                   break;
+         case oNoDefRecipient:
+                   m_free(opt.def_recipient); opt.def_recipient = NULL;
+                   opt.def_recipient_self = 0;
+                   break;
          case oNoOptions: break; /* no-options */
          case oHomedir: opt.homedir = pargs.r.ret_str; break;
          case oNoBatch: opt.batch = 0; break;
+         case oWithKeyData: opt.with_key_data=1; /* fall thru */
          case oWithColons: opt.with_colons=':'; break;
 
          case oSkipVerify: opt.skip_verify=1; break;
@@ -711,7 +772,25 @@ main( int argc, char **argv )
            register_cipher_extension(orig_argc? *orig_argv:NULL,
                                      pargs.r.ret_str);
            break;
-         case oRFC1991: opt.rfc1991 = 1; opt.no_comment = 1; break;
+         case oRFC1991:
+           opt.rfc1991 = 1;
+           opt.no_comment = 1;
+           opt.escape_from = 1;
+           break;
+         case oOpenPGP:
+           opt.rfc1991 = 0;
+           opt.escape_from = 0;
+           opt.force_v3_sigs = 0;
+           opt.compress_keys = 0;          /* not mandated  but we do it */
+           opt.compress_sigs = 0;          /* ditto. */
+           opt.not_dash_escaped = 0;
+           opt.def_cipher_algo = 0;
+           opt.def_digest_algo = 0;
+           opt.def_compress_algo = 2;
+           opt.s2k_mode = 3; /* iterated+salted */
+           opt.s2k_digest_algo = DIGEST_ALGO_RMD160;
+           opt.s2k_cipher_algo = CIPHER_ALGO_BLOWFISH;
+           break;
          case oEmuChecksumBug: opt.emulate_bugs |= EMUBUG_GPGCHKSUM; break;
          case oCompressSigs: opt.compress_sigs = 1; break;
          case oRunAsShmCP:
@@ -722,41 +801,65 @@ main( int argc, char **argv )
          #endif
            break;
          case oSetFilename: opt.set_filename = pargs.r.ret_str; break;
+         case oSetPolicyURL: opt.set_policy_url = pargs.r.ret_str; 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 oForceV3Sigs: opt.force_v3_sigs = 1; break;
+         case oForceMDC: opt.force_mdc = 1; break;
          case oS2KMode:   opt.s2k_mode = pargs.r.ret_int; break;
          case oS2KDigest: s2k_digest_string = m_strdup(pargs.r.ret_str); break;
          case oS2KCipher: s2k_cipher_string = m_strdup(pargs.r.ret_str); break;
 
-       #ifdef IS_G10
-         case oRemote: /* store the remote users */
-           sl = m_alloc( sizeof *sl + strlen(pargs.r.ret_str));
-           strcpy(sl->d, pargs.r.ret_str);
-           sl->next = remusr;
-           remusr = sl;
+         case oNoEncryptTo: opt.no_encrypt_to = 1; break;
+         case oEncryptTo: /* store the recipient in the second list */
+           sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
+           sl->flags = 1;
+           break;
+         case oRecipient: /* store the recipient */
+           add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
            break;
          case oTextmodeShort: opt.textmode = 2; break;
          case oTextmode: opt.textmode=1;  break;
          case oUser: /* store the local users */
-           sl = m_alloc( sizeof *sl + strlen(pargs.r.ret_str));
-           strcpy(sl->d, pargs.r.ret_str);
-           sl->next = locusr;
-           locusr = sl;
+           add_to_strlist2( &locusr, pargs.r.ret_str, utf8_strings );
            break;
          case oCompress: opt.compress = pargs.r.ret_int; break;
          case oPasswdFD: pwfd = pargs.r.ret_int; 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;
          case oNoSecmemWarn: secmem_set_flags( secmem_get_flags() | 1 ); break;
-       #else
-         case oCipherAlgo:
-         case oDigestAlgo:
-         case oNoSecmemWarn:
-           break;  /* dummies */
-       #endif
-
-         default : errors++; pargs.err = configfp? 1:2; break;
+         case oCharset:
+           if( set_native_charset( 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;
+         case oLockOnce: opt.lock_once = 1; break;
+         case oLockMultiple: opt.lock_once = 0; break;
+         case oKeyServer: opt.keyserver_name = pargs.r.ret_str; break;
+         case oNotation: add_notation_data( pargs.r.ret_str ); break;
+         case oUtf8Strings: utf8_strings = 1; break;
+         case oNoUtf8Strings: utf8_strings = 0; break;
+         case oDisableCipherAlgo:
+               disable_cipher_algo( string_to_cipher_algo(pargs.r.ret_str) );
+               break;
+         case oDisablePubkeyAlgo:
+               disable_pubkey_algo( string_to_pubkey_algo(pargs.r.ret_str) );
+               break;
+         case oAllowNonSelfsignedUID:
+               opt.allow_non_selfsigned_uid = 1;
+               break;
+         case oNoLiteral:
+               opt.no_literal = 1;
+               break;
+         case oSetFilesize:
+               opt.set_filesize = pargs.r.ret_ulong;
+               break;
+
+         default : pargs.err = configfp? 1:2; break;
        }
     }
     if( configfp ) {
@@ -768,15 +871,41 @@ main( int argc, char **argv )
     m_free( configname ); configname = NULL;
     if( log_get_errorcount(0) )
        g10_exit(2);
+    if( nogreeting )
+       greeting = 0;
 
     if( greeting ) {
-       tty_printf("%s %s; %s\n", strusage(11), strusage(13), strusage(14) );
-       tty_printf("%s\n", strusage(15) );
+       fprintf(stderr, "%s %s; %s\n",
+                       strusage(11), strusage(13), strusage(14) );
+       fprintf(stderr, "%s\n", strusage(15) );
+    }
+  #ifdef IS_DEVELOPMENT_VERSION
+    if( !opt.batch )
+       log_info("NOTE: this is a development version!\n");
+  #endif
+    if( opt.force_mdc ) {
+       log_info("--force-mdc ignored because"
+                " the OpenPGP WG has not yet aggreed on MDCs\n");
+       opt.force_mdc = 0;
     }
+    if (opt.no_literal) {
+       log_info(_("NOTE: %s is not for normal use!\n"), "--no-literal");
+       if (opt.textmode)
+           log_error(_("%s not allowed with %s!\n"),
+                      "--textmode", "--no-literal" );
+       if (opt.set_filename)
+           log_error(_("%s makes no sense with %s!\n"),
+                       "--set-filename", "--no-literal" );
+    }
+    if (opt.set_filesize)
+       log_info(_("NOTE: %s is not for normal use!\n"), "--set-filesize");
+    if( opt.batch )
+       tty_batchmode( 1 );
 
     secmem_set_flags( secmem_get_flags() & ~2 ); /* resume warnings */
 
     set_debug();
+    g10_opt_homedir = opt.homedir;
 
     /* must do this after dropping setuid, because string_to...
      * may try to load an module */
@@ -804,25 +933,32 @@ main( int argc, char **argv )
        if( check_digest_algo(opt.s2k_digest_algo) )
            log_error(_("selected digest algorithm is invalid\n"));
     }
+    if( opt.set_policy_url ) {
+       if( check_policy_url( opt.set_policy_url ) )
+           log_error(_("the given policy URL is invalid\n"));
+    }
     if( opt.def_compress_algo < 1 || opt.def_compress_algo > 2 )
        log_error(_("compress algorithm must be in range %d..%d\n"), 1, 2);
     if( opt.completes_needed < 1 )
        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"));
+    if( opt.max_cert_depth < 1 || opt.max_cert_depth > 255 )
+       log_error(_("max-cert-depth must be in range 1 to 255\n"));
     switch( opt.s2k_mode ) {
       case 0:
-       log_info(_("note: simple S2K mode (0) is strongly discouraged\n"));
+       log_info(_("NOTE: simple S2K mode (0) is strongly discouraged\n"));
        break;
       case 1: case 3: break;
       default:
        log_error(_("invalid S2K mode; must be 0, 1 or 3\n"));
     }
 
+
     if( log_get_errorcount(0) )
        g10_exit(2);
 
-    if( !cmd && opt.fingerprint )
+    if( !cmd && opt.fingerprint && !with_fpr )
        set_cmd( &cmd, aListKeys);
 
     if( cmd == aKMode || cmd == aKModeC ) { /* kludge to be compatible to pgp */
@@ -853,11 +989,11 @@ main( int argc, char **argv )
     if( cmd != aDeArmor && cmd != aEnArmor
        && !(cmd == aKMode && argc == 2 ) ) {
 
-       if( !sec_nrings || default_keyring )  /* add default secret rings */
+       if( !sec_nrings && default_keyring )  /* add default secret rings */
            add_keyblock_resource("secring.gpg", 0, 1);
        for(sl = sec_nrings; sl; sl = sl->next )
            add_keyblock_resource( sl->d, 0, 1 );
-       if( !nrings || default_keyring )  /* add default ring */
+       if( !nrings && default_keyring )  /* add default ring */
            add_keyblock_resource("pubring.gpg", 0, 0);
        for(sl = nrings; sl; sl = sl->next )
            add_keyblock_resource( sl->d, 0, 0 );
@@ -885,11 +1021,11 @@ main( int argc, char **argv )
       case aListSecretKeys:
       case aCheckKeys:
        if( opt.with_colons ) /* need this to list the trust */
-           rc = init_trustdb(1, trustdb_name );
+           rc = setup_trustdb(1, trustdb_name );
        break;
-      case aExportOwnerTrust: rc = init_trustdb( 0, trustdb_name ); break;
-      case aListTrustDB: rc = init_trustdb( argc? 1:0, trustdb_name ); break;
-      default: rc = init_trustdb(1, trustdb_name ); break;
+      case aExportOwnerTrust: rc = setup_trustdb( 0, trustdb_name ); break;
+      case aListTrustDB: rc = setup_trustdb( argc? 1:0, trustdb_name ); break;
+      default: rc = setup_trustdb(1, trustdb_name ); break;
     }
     if( rc )
        log_error(_("failed to initialize the TrustDB: %s\n"), g10_errstr(rc));
@@ -903,7 +1039,6 @@ main( int argc, char **argv )
            log_error_f( print_fname_stdin(fname),
                        "store failed: %s\n", g10_errstr(rc) );
        break;
-    #ifdef IS_G10
       case aSym: /* encrypt the given file only with the symmetric cipher */
        if( argc > 1 )
            wrong_args(_("--symmetric [filename]"));
@@ -973,23 +1108,47 @@ main( int argc, char **argv )
 
 
       case aSignKey: /* sign the key given as argument */
-      case aEditKey: /* Edit a key signature */
        if( argc != 1 )
-           wrong_args(_("--edit-key username"));
-       keyedit_menu(fname, locusr );
+           wrong_args(_("--sign-key user-id"));
+       username = make_username( fname );
+       keyedit_menu(fname, locusr, NULL, 1 );
+       m_free(username);
+       break;
+
+      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;
 
-      #endif /* IS_G10 */
+      case aEditKey: /* Edit a key signature */
+       if( !argc )
+           wrong_args(_("--edit-key user-id [commands]"));
+       username = make_username( fname );
+       if( argc > 1 ) {
+           sl = NULL;
+           for( argc--, argv++ ; argc; argc--, argv++ )
+               append_to_strlist( &sl, *argv );
+           keyedit_menu( username, locusr, sl, 0 );
+           free_strlist(sl);
+       }
+       else
+           keyedit_menu(username, locusr, NULL, 0 );
+       m_free(username);
+       break;
 
       case aDeleteSecretKey:
        if( argc != 1 )
-           wrong_args(_("--delete-secret-key username"));
+           wrong_args(_("--delete-secret-key user-id"));
       case aDeleteKey:
        if( argc != 1 )
-           wrong_args(_("--delete-key username"));
-       /* note: fname is the user id! */
-       if( (rc = delete_key(fname, cmd==aDeleteSecretKey)) )
-           log_error("%s: delete key failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) );
+           wrong_args(_("--delete-key user-id"));
+       username = make_username( fname );
+       if( (rc = delete_key(username, cmd==aDeleteSecretKey)) )
+           log_error("%s: delete key failed: %s\n", username, g10_errstr(rc) );
+       m_free(username);
        break;
 
 
@@ -1004,7 +1163,7 @@ main( int argc, char **argv )
        secret_key_list( argc, argv );
        break;
 
-      case aKMode: /* list keyring */
+      case aKMode: /* list keyring -- NOTE: This will be removed soon */
        if( argc < 2 )  /* -kv [userid] */
            public_key_list( (argc && **argv)? 1:0, argv );
        else if( argc == 2 ) { /* -kv userid keyring */
@@ -1020,16 +1179,14 @@ main( int argc, char **argv )
            }
        }
        else
-           wrong_args(_("-k[v][v][v][c] [userid] [keyring]") );
+           wrong_args(_("-k[v][v][v][c] [user-id] [keyring]") );
        break;
 
-    #ifdef IS_G10
       case aKeygen: /* generate a key (interactive) */
        if( argc )
            wrong_args("--gen-key");
        generate_keypair();
        break;
-    #endif
 
       case aFastImport:
       case aImport:
@@ -1041,36 +1198,43 @@ main( int argc, char **argv )
        for( ; argc; argc--, argv++ ) {
            rc = import_keys( *argv, (cmd == aFastImport) );
            if( rc )
-               log_error("import from '%s' failed: %s\n",
+               log_error("import from `%s' failed: %s\n",
                                                *argv, g10_errstr(rc) );
        }
        break;
 
       case aExport:
+      case aExportAll:
+      case aSendKeys:
+      case aRecvKeys:
        sl = NULL;
        for( ; argc; argc--, argv++ )
-           add_to_strlist( &sl, *argv );
-       export_pubkeys( sl );
+           add_to_strlist2( &sl, *argv, utf8_strings );
+       if( cmd == aSendKeys )
+           hkp_export( sl );
+       else if( cmd == aRecvKeys )
+           hkp_import( sl );
+       else
+           export_pubkeys( sl, (cmd == aExport) );
        free_strlist(sl);
        break;
 
       case aExportSecret:
        sl = NULL;
        for( ; argc; argc--, argv++ )
-           add_to_strlist( &sl, *argv );
+           add_to_strlist2( &sl, *argv, utf8_strings );
        export_seckeys( sl );
        free_strlist(sl);
        break;
 
-    #ifdef IS_G10
       case aGenRevoke:
        if( argc != 1 )
            wrong_args("--gen-revoke user-id");
-       gen_revoke( *argv );
+       username =  make_username(*argv);
+       gen_revoke( username );
+       m_free( username );
        break;
-    #endif
 
-    #ifdef IS_G10MAINT
       case aDeArmor:
        if( argc > 1 )
            wrong_args("--dearmor [file]");
@@ -1088,64 +1252,71 @@ main( int argc, char **argv )
        break;
 
 
-     #ifdef MAINTAINER_OPTIONS
       case aPrimegen:
-       if( argc == 1 ) {
-           mpi_print( stdout, generate_public_prime( atoi(argv[0]) ), 1);
-           putchar('\n');
-       }
-       else if( argc == 2 ) {
-           mpi_print( stdout, generate_elg_prime( 0, atoi(argv[0]),
-                                                  atoi(argv[1]), NULL,NULL ), 1);
-           putchar('\n');
-       }
-       else if( argc == 3 ) {
-           MPI g = mpi_alloc(1);
-           mpi_print( stdout, generate_elg_prime( 0, atoi(argv[0]),
-                                                  atoi(argv[1]), g, NULL ), 1);
-           printf("\nGenerator: ");
-           mpi_print( stdout, g, 1 );
-           putchar('\n');
-           mpi_free(g);
-       }
-       else if( argc == 4 ) {
-           mpi_print( stdout, generate_elg_prime( 1, atoi(argv[0]),
-                                                  atoi(argv[1]), NULL,NULL ), 1);
+       {   int mode = argc < 2 ? 0 : atoi(*argv);
+
+           if( mode == 1 && argc == 2 ) {
+               mpi_print( stdout, generate_public_prime( atoi(argv[1]) ), 1);
+           }
+           else if( mode == 2 && argc == 3 ) {
+               mpi_print( stdout, generate_elg_prime(
+                                            0, atoi(argv[1]),
+                                            atoi(argv[2]), NULL,NULL ), 1);
+           }
+           else if( mode == 3 && argc == 3 ) {
+               MPI *factors;
+               mpi_print( stdout, generate_elg_prime(
+                                            1, atoi(argv[1]),
+                                            atoi(argv[2]), NULL,&factors ), 1);
+               putchar('\n');
+               mpi_print( stdout, factors[0], 1 ); /* print q */
+           }
+           else if( mode == 4 && argc == 3 ) {
+               MPI g = mpi_alloc(1);
+               mpi_print( stdout, generate_elg_prime(
+                                                0, atoi(argv[1]),
+                                                atoi(argv[2]), g, NULL ), 1);
+               putchar('\n');
+               mpi_print( stdout, g, 1 );
+               mpi_free(g);
+           }
+           else
+               wrong_args("--gen-prime mode bits [qbits] ");
            putchar('\n');
        }
-       else
-           usage(1);
        break;
-      #endif /* MAINTAINER OPTIONS */
 
-      #ifdef MAINTAINER_OPTIONS
       case aGenRandom:
-       if( argc < 1 || argc > 2 )
-           wrong_args("--gen-random level [hex]");
        {
-           int level = atoi(*argv);
-           for(;;) {
-               byte *p = get_random_bits( 8, level, 0);
-               if( argc == 1 ) {
-                   printf("%02x", *p );
-                   fflush(stdout);
-               }
-               else
-                   putchar(c&0xff);
+           int level = argc ? atoi(*argv):0;
+           int count = argc > 1 ? atoi(argv[1]): 0;
+           int endless = !count;
+
+           if( argc < 1 || argc > 2 || level < 0 || level > 2 || count < 0 )
+               wrong_args("--gen-random 0|1|2 [count]");
+
+           while( endless || count ) {
+               byte *p;
+               size_t n = !endless && count < 100? count : 100;
+
+               p = get_random_bits( n*8, level, 0);
+               fwrite( p, n, 1, stdout );
                m_free(p);
+               if( !endless )
+                   count -= n;
            }
        }
        break;
-      #endif /* MAINTAINER OPTIONS */
 
       case aPrintMD:
        if( argc < 1)
-           wrong_args("--print-md algo [file]");
-       else {
-           int algo = string_to_digest_algo(*argv);
+           wrong_args("--print-md algo [files]");
+       {
+           int all_algos = (**argv=='*' && !(*argv)[1]);
+           int algo = all_algos? 0 : string_to_digest_algo(*argv);
 
-           if( !algo )
-               log_error(_("invalid hash algorithm '%s'\n"), *argv );
+           if( !algo && !all_algos )
+               log_error(_("invalid hash algorithm `%s'\n"), *argv );
            else {
                argc--; argv++;
                if( !argc )
@@ -1158,7 +1329,7 @@ main( int argc, char **argv )
        }
        break;
 
-      case aPrintMDs:
+      case aPrintMDs: /* old option */
        if( !argc )
            print_mds(NULL,0);
        else {
@@ -1167,10 +1338,6 @@ main( int argc, char **argv )
        }
        break;
 
-     #ifdef MAINTAINER_OPTIONS
-      case aTest: do_test( argc? atoi(*argv): 1 ); break;
-      #endif /* MAINTAINER OPTIONS */
-
       case aListTrustDB:
        if( !argc )
            list_trustdb(NULL);
@@ -1190,8 +1357,11 @@ main( int argc, char **argv )
        if( !argc )
            check_trustdb(NULL);
        else {
-           for( ; argc; argc--, argv++ )
-               check_trustdb( *argv );
+           for( ; argc; argc--, argv++ ) {
+               username = make_username( *argv );
+               check_trustdb( username );
+               m_free(username);
+           }
        }
        break;
 
@@ -1202,9 +1372,13 @@ main( int argc, char **argv )
        break;
 
       case aListTrustPath:
-       if( argc != 2 )
-           wrong_args("--list-trust-path [-- -]<maxdepth> <username>");
-       list_trust_path( atoi(*argv), argv[1] );
+       if( !argc )
+           wrong_args("--list-trust-path <user-ids>");
+       for( ; argc; argc--, argv++ ) {
+           username = make_username( *argv );
+           list_trust_path( username );
+           m_free(username);
+       }
        break;
 
       case aExportOwnerTrust:
@@ -1219,18 +1393,20 @@ main( int argc, char **argv )
        import_ownertrust( argc? *argv:NULL );
        break;
 
-     #endif /* IS_G10MAINT */
-
-
       case aListPackets:
        opt.list_packets=1;
       default:
-       /* fixme: g10maint should do regular maintenace tasks here */
        if( argc > 1 )
            wrong_args(_("[filename]"));
+       /* Issue some output for the unix newbie */
+       if( !fname && !opt.outfile && isatty( fileno(stdin) )
+               && isatty( fileno(stdout) ) && isatty( fileno(stderr) ) )
+           log_info(_("Go ahead and type your message ...\n"));
+
        if( !(a = iobuf_open(fname)) )
-           log_error(_("can't open '%s'\n"), print_fname_stdin(fname));
+           log_error(_("can't open `%s'\n"), print_fname_stdin(fname));
        else {
+
            if( !opt.no_armor ) {
                if( use_armor_filter( a ) ) {
                    memset( &afx, 0, sizeof afx);
@@ -1241,7 +1417,9 @@ main( int argc, char **argv )
                set_packet_list_mode(1);
                opt.list_packets=1;
            }
-           proc_packets( a );
+           rc = proc_packets(NULL, a );
+           if( rc )
+               log_error("processing message failed: %s\n", g10_errstr(rc) );
            iobuf_close(a);
        }
        break;
@@ -1258,31 +1436,22 @@ main( int argc, char **argv )
 void
 g10_exit( int rc )
 {
-    if( opt.debug & DBG_MEMSTAT_VALUE )
+    if( opt.debug & DBG_MEMSTAT_VALUE ) {
        m_print_stats("on exit");
+       random_dump_stats();
+    }
     if( opt.debug )
        secmem_dump_stats();
     secmem_term();
-    rc = rc? rc : log_get_errorcount(0)? 2:0;
+    rc = rc? rc : log_get_errorcount(0)? 2 :
+                       g10_errors_seen? 1 : 0;
     /*write_status( STATUS_LEAVE );*/
     exit(rc );
 }
 
 
-void
-do_not_use_RSA()
-{
-    static int did_rsa_note = 0;
-
-    if( !did_rsa_note ) {
-       did_rsa_note = 1;
-       log_info(_("RSA keys are deprecated; please consider "
-                  "creating a new key and use this key in the future\n"));
-    }
-}
 
 
-#ifdef IS_G10MAINT
 static void
 print_hex( byte *p, size_t n )
 {
@@ -1384,13 +1553,75 @@ print_mds( const char *fname, int algo )
 }
 
 
-
-#ifdef MAINTAINER_OPTIONS
+/****************
+ * Check the supplied name,value string and add it to the notation
+ * data to be used for signatures.
+ */
 static void
-do_test(int times)
+add_notation_data( const char *string )
+{
+    const char *s;
+    const char *s2;
+    STRLIST sl;
+    int critical=0;
+    int highbit=0;
+
+    if( *string == '!' ) {
+       critical = 1;
+       string++;
+    }
+    s = string;
+
+    if( !*s || (*s & 0x80) || (!isalpha(*s) && *s != '_') ) {
+       log_error(_("the first character of a notation name "
+                   "must be a letter or an underscore\n") );
+       return;
+    }
+    for(s++; *s != '='; s++ ) {
+       if( !*s || (*s & 0x80) || (!isalnum(*s) && *s != '_' && *s != '.' ) ) {
+           log_error(_("a notation name must have only letters, "
+                       "digits, dots or underscores and end with an '='\n") );
+           return;
+       }
+    }
+    if( s[-1] == '.' || ((s2=strstr(string, "..")) && s2 < s ) ) {
+       log_error(_("dots in a notation name must be surrounded "
+                   "by other characters\n") );
+       return;
+    }
+    /* we do only support printabe text - therefore we enforce the use
+     * of only printable characters (an empty value is valid) */
+    for( s++; *s ; s++ ) {
+       if( iscntrl(*s) ) {
+           log_error(_("a notation value must not use "
+                       "any control characters\n") );
+           return;
+       }
+       else if( *s & 0x80 )
+           highbit = 1;
+    }
+
+    if( highbit )   /* must use UTF8 encoding */
+       sl = add_to_strlist2( &opt.notation_data, string, utf8_strings );
+    else
+       sl = add_to_strlist( &opt.notation_data, string );
+
+    if( critical )
+       sl->flags |= 1;
+}
+
+
+static int
+check_policy_url( const char *s )
 {
-    m_check(NULL);
+    if( *s == '!' )
+       s++;
+    if( !*s )
+       return -1;
+    for(; *s ; s++ ) {
+       if( (*s & 0x80) || iscntrl(*s) )
+           return -1;
+    }
+    return 0;
 }
-#endif /* MAINTAINER OPTIONS */
-#endif /* IS_G10MAINT */