See ChangeLog: Mon Jul 26 09:34:46 CEST 1999 Werner Koch
[gnupg.git] / g10 / g10.c
index 3ebcbe9..02d7202 100644 (file)
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -26,7 +26,6 @@
 #include <ctype.h>
 #include <unistd.h>
 
-#define MAINTAINER_OPTIONS
 
 #include "packet.h"
 #include "iobuf.h"
@@ -52,6 +51,7 @@ enum cmd_and_opt_values { aNull = 0,
     aSym         = 'c',
     aDecrypt     = 'd',
     aEncr        = 'e',
+    oInteractive  = 'i',
     oKOption     = 'k',
     oDryRun      = 'n',
     oOutput      = 'o',
@@ -62,12 +62,14 @@ enum cmd_and_opt_values { aNull = 0,
     oUser        = 'u',
     oVerbose     = 'v',
     oCompress    = 'z',
+    oNotation    = 'N',
     oBatch       = 500,
     aClearsign,
     aStore,
     aKeygen,
     aSignEncr,
     aSignKey,
+    aLSignKey,
     aListPackets,
     aEditKey,
     aDeleteKey,
@@ -103,22 +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,
@@ -130,10 +138,12 @@ enum cmd_and_opt_values { aNull = 0,
     oNoArmor,
     oNoDefKeyring,
     oNoGreeting,
+    oNoTTY,
     oNoOptions,
     oNoBatch,
     oHomedir,
     oWithColons,
+    oWithKeyData,
     oSkipVerify,
     oCompressKeys,
     oCompressSigs,
@@ -141,9 +151,13 @@ enum cmd_and_opt_values { aNull = 0,
     oEmuChecksumBug,
     oRunAsShmCP,
     oSetFilename,
+    oSetPolicyURL,
+    oUseEmbeddedFilename,
     oComment,
+    oDefaultComment,
     oThrowKeyid,
     oForceV3Sigs,
+    oForceMDC,
     oS2KMode,
     oS2KDigest,
     oS2KCipher,
@@ -151,9 +165,18 @@ enum cmd_and_opt_values { aNull = 0,
     oNotDashEscaped,
     oEscapeFrom,
     oLockOnce,
+    oLockMultiple,
     oKeyServer,
     oEncryptTo,
     oNoEncryptTo,
+    oLoggerFD,
+    oUtf8Strings,
+    oNoUtf8Strings,
+    oDisableCipherAlgo,
+    oDisablePubkeyAlgo,
+    oAllowNonSelfsignedUID,
+    oNoLiteral,
+    oSetFilesize,
 aTest };
 
 
@@ -175,9 +198,11 @@ static ARGPARSE_OPTS opts[] = {
     { 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")},
-    { aKeygen, "gen-key",   256, N_("generate a new key pair")},
+    { aKeygen,    "gen-key",  256, N_("generate a new key pair")},
     { aDeleteKey, "delete-key",256, N_("remove key from the public keyring")},
-    { 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")},
     { aExport, "export"           , 256, N_("export keys") },
     { aSendKeys, "send-keys"     , 256, N_("export keys to a key server") },
@@ -192,24 +217,26 @@ static ARGPARSE_OPTS opts[] = {
     { 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
 
     { 301, NULL, 0, N_("@\nOptions:\n ") },
 
     { oArmor, "armor",     0, N_("create ascii armored output")},
     { 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")},
@@ -219,8 +246,11 @@ static ARGPARSE_OPTS opts[] = {
     { 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") },
+    { 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")},
@@ -240,6 +270,7 @@ static ARGPARSE_OPTS opts[] = {
     { 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")},
@@ -249,6 +280,7 @@ static ARGPARSE_OPTS opts[] = {
     { 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")},
+    { oNotation,   "notation-data", 2, N_("|NAME=VALUE|use this notation data")},
 
     { 302, NULL, 0, N_("@\nExamples:\n\n"
     " -se -r Bob [file]          sign and encrypt for user Bob\n"
@@ -259,11 +291,11 @@ static ARGPARSE_OPTS opts[] = {
 
   /* hidden options */
     { aExportOwnerTrust, "list-ownertrust",0 , "@"},  /* alias */
+    { aPrintMDs, "print-mds" , 256, "@"}, /* old */
     { aListTrustDB, "list-trustdb",0 , "@"},
     { aListTrustPath, "list-trust-path",0, "@"},
     { oKOption, NULL,   0, "@"},
     { oPasswdFD, "passphrase-fd",1, "@" },
-    { aSignKey, "sign-key"  ,256, "@" }, /* alias for edit-key */
     { aDeleteSecretKey, "delete-secret-key",0, "@" },
     { oQuickRandom, "quick-random", 0, "@"},
     { oNoVerbose, "no-verbose", 0, "@"},
@@ -276,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 */
@@ -286,18 +319,32 @@ 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, "@" },
-    { oNoVersion, "no-version", 0,   "@"},
+    { 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,
@@ -306,6 +353,8 @@ static void set_cmd( enum cmd_and_opt_values *ret_cmd,
                        enum cmd_and_opt_values new_cmd );
 static void print_hex( byte *p, size_t n );
 static void print_mds( const char *fname, int algo );
+static void add_notation_data( const char *string );
+static int  check_policy_url( const char *s );
 
 const char *
 strusage( int level )
@@ -410,6 +459,19 @@ wrong_args( const char *text)
     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)
 {
@@ -462,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;
@@ -472,7 +535,8 @@ main( int argc, char **argv )
     int parse_debug = 0;
     int default_config =1;
     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;
@@ -480,6 +544,7 @@ 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
@@ -497,11 +562,11 @@ main( int argc, char **argv )
     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;
@@ -542,6 +607,11 @@ 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
     }
 
@@ -600,25 +670,25 @@ main( int argc, char **argv )
          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;
 
          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;
-       #ifdef MAINTAINER_OPTIONS
          case aPrimegen: set_cmd( &cmd, aPrimegen); break;
          case aGenRandom: set_cmd( &cmd, aGenRandom); break;
-       #endif
          case aPrintMD: set_cmd( &cmd, aPrintMD); break;
          case aPrintMDs: set_cmd( &cmd, aPrintMDs); break;
          case aListTrustDB: set_cmd( &cmd, aListTrustDB); break;
@@ -626,15 +696,17 @@ main( int argc, char **argv )
          case aUpdateTrustDB: set_cmd( &cmd, aUpdateTrustDB); break;
          case aFixTrustDB: set_cmd( &cmd, aFixTrustDB); break;
          case aListTrustPath: set_cmd( &cmd, aListTrustPath); break;
-         case aDeArmor: set_cmd( &cmd, aDeArmor); greeting = 0; break;
-         case aEnArmor: set_cmd( &cmd, aEnArmor); greeting = 0; break;
+         case aDeArmor: set_cmd( &cmd, aDeArmor); break;
+         case aEnArmor: set_cmd( &cmd, aEnArmor); break;
          case aExportOwnerTrust: set_cmd( &cmd, aExportOwnerTrust); break;
          case aImportOwnerTrust: set_cmd( &cmd, aImportOwnerTrust); break;
 
          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;
@@ -646,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:
@@ -658,20 +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;
@@ -688,6 +777,20 @@ main( int argc, char **argv )
            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:
@@ -698,25 +801,29 @@ 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;
 
          case oNoEncryptTo: opt.no_encrypt_to = 1; break;
          case oEncryptTo: /* store the recipient in the second list */
-           sl = add_to_strlist( &remusr, pargs.r.ret_str );
+           sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
            sl->flags = 1;
            break;
          case oRecipient: /* store the recipient */
-           add_to_strlist( &remusr, pargs.r.ret_str );
+           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 */
-           add_to_strlist( &locusr, pargs.r.ret_str );
+           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;
@@ -731,7 +838,26 @@ main( int argc, char **argv )
          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;
        }
@@ -745,15 +871,34 @@ main( int argc, char **argv )
     m_free( configname ); configname = NULL;
     if( log_get_errorcount(0) )
        g10_exit(2);
+    if( nogreeting )
+       greeting = 0;
 
     if( greeting ) {
        fprintf(stderr, "%s %s; %s\n",
                        strusage(11), strusage(13), strusage(14) );
        fprintf(stderr, "%s\n", strusage(15) );
-      #ifdef IS_DEVELOPMENT_VERSION
+    }
+  #ifdef IS_DEVELOPMENT_VERSION
+    if( !opt.batch )
        log_info("NOTE: this is a development version!\n");
-      #endif
+  #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 );
 
@@ -788,6 +933,10 @@ 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 )
@@ -809,7 +958,7 @@ main( int argc, char **argv )
     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 */
@@ -840,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 );
@@ -959,29 +1108,47 @@ main( int argc, char **argv )
 
 
       case aSignKey: /* sign the key given as argument */
+       if( argc != 1 )
+           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;
+
       case aEditKey: /* Edit a key signature */
        if( !argc )
-           wrong_args(_("--edit-key username [commands]"));
+           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( fname, locusr, sl );
+           keyedit_menu( username, locusr, sl, 0 );
            free_strlist(sl);
        }
        else
-           keyedit_menu(fname, locusr, NULL );
+           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;
 
 
@@ -996,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 */
@@ -1012,7 +1179,7 @@ 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;
 
       case aKeygen: /* generate a key (interactive) */
@@ -1042,7 +1209,7 @@ main( int argc, char **argv )
       case aRecvKeys:
        sl = NULL;
        for( ; argc; argc--, argv++ )
-           add_to_strlist( &sl, *argv );
+           add_to_strlist2( &sl, *argv, utf8_strings );
        if( cmd == aSendKeys )
            hkp_export( sl );
        else if( cmd == aRecvKeys )
@@ -1055,7 +1222,7 @@ main( int argc, char **argv )
       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;
@@ -1063,7 +1230,9 @@ main( int argc, char **argv )
       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;
 
       case aDeArmor:
@@ -1083,68 +1252,70 @@ 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 c;
-           int level = atoi(*argv);
-           for(;;) {
+           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;
-               if( argc == 2 ) {
-                   p = get_random_bits( 8, level, 0);
-                   printf("%02x", *p );
-                   fflush(stdout);
-               }
-               else {
-                   p = get_random_bits( 800, level, 0);
-                   for(c=0; c < 100; c++ )
-                       putchar( p[c] );
-               }
+               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 )
+           if( !algo && !all_algos )
                log_error(_("invalid hash algorithm `%s'\n"), *argv );
            else {
                argc--; argv++;
@@ -1158,7 +1329,7 @@ main( int argc, char **argv )
        }
        break;
 
-      case aPrintMDs:
+      case aPrintMDs: /* old option */
        if( !argc )
            print_mds(NULL,0);
        else {
@@ -1186,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;
 
@@ -1199,9 +1373,12 @@ main( int argc, char **argv )
 
       case aListTrustPath:
        if( !argc )
-           wrong_args("--list-trust-path <usernames>");
-       for( ; argc; argc--, argv++ )
-           list_trust_path( *argv );
+           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:
@@ -1240,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;
@@ -1257,8 +1436,10 @@ 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();
@@ -1371,3 +1552,76 @@ print_mds( const char *fname, int algo )
        fclose(fp);
 }
 
+
+/****************
+ * Check the supplied name,value string and add it to the notation
+ * data to be used for signatures.
+ */
+static void
+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 )
+{
+    if( *s == '!' )
+       s++;
+    if( !*s )
+       return -1;
+    for(; *s ; s++ ) {
+       if( (*s & 0x80) || iscntrl(*s) )
+           return -1;
+    }
+    return 0;
+}
+