Remove hacks which are not anymore needed since we now require Libgcrypt 1.4
[gnupg.git] / g10 / gpg.c
index 624816c..9dd1790 100644 (file)
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -1,12 +1,12 @@
 /* gpg.c - The GnuPG utility (main for gpg)
  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- *               2006 Free Software Foundation, Inc.
+ *               2006, 2007, 2008 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
  * GnuPG is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * GnuPG is distributed in the hope that it will be useful,
@@ -15,9 +15,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
@@ -28,9 +26,6 @@
 #include <ctype.h>
 #include <unistd.h>
 #include <assert.h>
-#ifdef HAVE_DOSISH_SYSTEM
-#include <fcntl.h> /* for setmode() */
-#endif
 #ifdef HAVE_STAT
 #include <sys/stat.h> /* for stat() */
 #endif
 #include "filter.h"
 #include "ttyio.h"
 #include "i18n.h"
+#include "sysutils.h"
 #include "status.h"
 #include "keyserver-internal.h"
 #include "exec.h"
-
+#include "gc-opt-flags.h"
 
 #if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
 #define MY_O_BINARY  O_BINARY
@@ -123,6 +119,7 @@ enum cmd_and_opt_values
     aListSigs,
     aSendKeys,
     aRecvKeys,
+    aLocateKeys,
     aSearchKeys,
     aRefreshKeys,
     aFetchKeys,
@@ -149,6 +146,7 @@ enum cmd_and_opt_values
     aCardStatus,
     aCardEdit,
     aChangePIN,
+    aServer,
 
     oTextmode,
     oNoTextmode,
@@ -194,6 +192,7 @@ enum cmd_and_opt_values
     oGnuPG,
     oRFC1991,
     oRFC2440,
+    oRFC4880,
     oOpenPGP,
     oPGP2,
     oPGP6,
@@ -211,6 +210,7 @@ enum cmd_and_opt_values
     oPasswd,
     oPasswdFD,
     oPasswdFile,
+    oPasswdRepeat,
     oCommandFD,
     oCommandFile,
     oQuickRandom,
@@ -230,6 +230,8 @@ enum cmd_and_opt_values
     oHomedir,
     oWithColons,
     oWithKeyData,
+    oWithSigList,
+    oWithSigCheck,
     oSkipVerify,
     oCompressKeys,
     oCompressSigs,
@@ -336,6 +338,7 @@ enum cmd_and_opt_values
     oTTYtype,
     oLCctype,
     oLCmessages,
+    oXauthority,
     oGroup,
     oUnGroup,
     oNoGroups,
@@ -355,6 +358,8 @@ enum cmd_and_opt_values
     oAllowMultisigVerification,
     oEnableDSA2,
     oDisableDSA2,
+    oAllowMultipleMessages,
+    oNoAllowMultipleMessages,
 
     oNoop
   };
@@ -397,6 +402,7 @@ static ARGPARSE_OPTS opts[] = {
                                     N_("search for keys on a key server") },
     { aRefreshKeys, "refresh-keys", 256,
                                     N_("update all keys from a keyserver")},
+    { aLocateKeys, "locate-keys", 256, "@"},
     { aFetchKeys, "fetch-keys" , 256, "@" },
     { aExportSecret, "export-secret-keys" , 256, "@" },
     { aExportSecretSub, "export-secret-subkeys" , 256, "@" },
@@ -423,7 +429,8 @@ static ARGPARSE_OPTS opts[] = {
     { aEnArmor, "enarmour", 256, "@"},
     { aPrintMD,  "print-md" , 256, N_("|algo [files]|print message digests")},
     { aPrimegen, "gen-prime" , 256, "@" },
-    { aGenRandom, "gen-random" , 256, "@" },
+    { aGenRandom, "gen-random", 256, "@" },
+    { aServer,   "server",      256, N_("run in server mode")},
 
     { 301, NULL, 0, N_("@\nOptions:\n ") },
 
@@ -460,7 +467,7 @@ static ARGPARSE_OPTS opts[] = {
     { oMinCertLevel, "min-cert-level", 1, "@"},
     { oAskCertLevel, "ask-cert-level",   0, "@"},
     { oNoAskCertLevel, "no-ask-cert-level",   0, "@"},
-    { oOutput, "output",    2, N_("use as output file")},
+    { oOutput, "output",    2, N_("|FILE|write output to FILE")},
     { oMaxOutput, "max-output", 16|4, "@" },
     { oVerbose, "verbose",   0, N_("verbose") },
     { oQuiet,  "quiet",   0, "@"},
@@ -516,6 +523,7 @@ static ARGPARSE_OPTS opts[] = {
     { oGnuPG, "no-pgp8", 0, "@"},
     { oRFC1991, "rfc1991",   0, "@"},
     { oRFC2440, "rfc2440", 0, "@" },
+    { oRFC4880, "rfc4880", 0, "@" },
     { oOpenPGP, "openpgp", 0, N_("use strict OpenPGP behavior")},
     { oPGP2, "pgp2", 0, N_("generate PGP 2.x compatible messages")},
     { oPGP6, "pgp6", 0, "@"},
@@ -564,6 +572,7 @@ static ARGPARSE_OPTS opts[] = {
     { oPasswd, "passphrase",2, "@" },
     { oPasswdFD, "passphrase-fd",1, "@" },
     { oPasswdFile, "passphrase-file",2, "@" },
+    { oPasswdRepeat, "passphrase-repeat", 1, "@"},
     { oCommandFD, "command-fd",1, "@" },
     { oCommandFile, "command-file",2, "@" },
     { oQuickRandom, "debug-quick-random", 0, "@"},
@@ -583,6 +592,8 @@ static ARGPARSE_OPTS opts[] = {
     { oNoBatch, "no-batch", 0, "@" },
     { oWithColons, "with-colons", 0, "@"},
     { oWithKeyData,"with-key-data", 0, "@"},
+    { oWithSigList,"with-sig-list", 0, "@"},
+    { oWithSigCheck,"with-sig-check", 0, "@"},
     { aListKeys, "list-key", 0, "@" }, /* alias */
     { aListSigs, "list-sig", 0, "@" }, /* alias */
     { aCheckKeys, "check-sig",0, "@" }, /* alias */
@@ -618,6 +629,7 @@ static ARGPARSE_OPTS opts[] = {
     { oLockNever, "lock-never", 0, "@" },
     { oLoggerFD, "logger-fd",1, "@" },
     { oLoggerFile, "log-file",2, "@" },
+    { oLoggerFile, "logger-file",2, "@" },  /* For 1.4 compatibility.  */
     { oUseEmbeddedFilename, "use-embedded-filename", 0, "@" },
     { oNoUseEmbeddedFilename, "no-use-embedded-filename", 0, "@" },
     { oUtf8Strings, "utf8-strings", 0, "@" },
@@ -672,6 +684,7 @@ static ARGPARSE_OPTS opts[] = {
     { oTTYtype,    "ttytype",     2, "@" },
     { oLCctype,    "lc-ctype",    2, "@" },
     { oLCmessages, "lc-messages", 2, "@" },
+    { oXauthority, "xauthority",  2, "@" },
     { oGroup,      "group",       2, "@" },
     { oUnGroup,    "ungroup",     2, "@" },
     { oNoGroups,   "no-groups",    0, "@" },
@@ -688,6 +701,8 @@ static ARGPARSE_OPTS opts[] = {
     { oAllowMultisigVerification, "allow-multisig-verification", 0, "@"},
     { oEnableDSA2, "enable-dsa2", 0, "@"},
     { oDisableDSA2, "disable-dsa2", 0, "@"},
+    { oAllowMultipleMessages, "allow-multiple-messages", 0, "@"},
+    { oNoAllowMultipleMessages, "no-allow-multiple-messages", 0, "@"},
 
     /* These two are aliases to help users of the PGP command line
        product use gpg with minimal pain.  Many commands are common
@@ -695,6 +710,7 @@ static ARGPARSE_OPTS opts[] = {
        I'm returning the favor. */
     { oLocalUser, "sign-with", 2, "@" },
     { oRecipient, "user", 2, "@" },
+
     { oRequireCrossCert, "require-backsigs", 0, "@"},
     { oRequireCrossCert, "require-cross-certification", 0, "@"},
     { oNoRequireCrossCert, "no-require-backsigs", 0, "@"},
@@ -720,6 +736,7 @@ static int maybe_setuid = 1;
 
 static char *build_list( const char *text, char letter,
                         const char *(*mapf)(int), int (*chkf)(int) );
+static char *build_lib_list (const char *text);
 static void set_cmd( enum cmd_and_opt_values *ret_cmd,
                        enum cmd_and_opt_values new_cmd );
 static void print_mds( const char *fname, int algo );
@@ -732,7 +749,7 @@ static void emergency_cleanup (void);
 static const char *
 my_strusage( int level )
 {
-  static char *digests, *pubkeys, *ciphers, *zips;
+  static char *digests, *pubkeys, *ciphers, *zips, *libs;
     const char *p;
     switch( level ) {
       case 11: p = "gpg (GnuPG)";
@@ -782,7 +799,7 @@ my_strusage( int level )
       case 35:
        if( !ciphers )
            ciphers = build_list(_("Cipher: "), 'S', 
-                                 gcry_cipher_algo_name,
+                                 openpgp_cipher_algo_name,
                                  openpgp_cipher_test_algo );
        p = ciphers;
        break;
@@ -800,6 +817,11 @@ my_strusage( int level )
                               check_compress_algo);
        p = zips;
        break;
+      case 38:
+       if (!libs)
+          libs = build_lib_list(_("Used libraries:"));
+       p = libs;
+       break;
 
       default: p = NULL;
     }
@@ -862,20 +884,46 @@ build_list( const char *text, char letter,
 }
 
 
-static void
-i18n_init(void)
+static char *
+build_lib_list (const char *text)
 {
-#ifdef USE_SIMPLE_GETTEXT
-  set_gettext_file (PACKAGE_GT, "Software\\GNU\\GnuPG");
-#else
-#ifdef ENABLE_NLS
-  setlocale (LC_ALL, "");
-  bindtextdomain (PACKAGE_GT, LOCALEDIR);
-  textdomain (PACKAGE_GT);
-#endif
-#endif
+  struct { const char *name; const char *version; } array[3];
+  int idx;
+  size_t n;
+  char *list, *p;
+
+  if (maybe_setuid)
+    gcry_control (GCRYCTL_INIT_SECMEM, 0, 0);  /* Drop setuid. */
+
+  idx = 0;
+  array[idx].name = "gcrypt";
+  array[idx++].version = gcry_check_version (NULL);
+  array[idx].name = NULL;
+  array[idx++].version = NULL;
+
+  n = strlen (text) + 1;
+  for (idx=0; array[idx].name; idx++)
+    {
+      n += 2 + strlen (array[idx].name);
+      if (array[idx].version)
+        n += 1 + strlen (array[idx].version) + 1;
+    }
+  n++;
+  list = xmalloc (n+1);
+  p = stpcpy (stpcpy (list, text), " ");
+  for (idx=0; array[idx].name; idx++)
+    {
+      if (idx)
+        p = stpcpy (p, ", ");
+      p = stpcpy (p, array[idx].name);
+      if (array[idx].version)
+        p = stpcpy (stpcpy (stpcpy (p, "("), array[idx].version), ")");
+    }
+  strcpy (p, "\n");
+  return list;
 }
 
+
 static void
 wrong_args( const char *text)
 {
@@ -1153,7 +1201,7 @@ check_permissions(const char *path,int item)
       if(strchr(path,DIRSEP_C))
        tmppath=make_filename(path,NULL);
       else
-       tmppath=make_filename(GNUPG_LIBDIR,path,NULL);
+       tmppath=make_filename(gnupg_libdir (),path,NULL);
     }
   else
     tmppath=xstrdup(path);
@@ -1344,6 +1392,24 @@ print_algo_numbers(int (*checker)(int))
 }
 
 
+static void
+print_algo_names(int (*checker)(int),const char *(*mapper)(int))
+{
+  int i,first=1;
+
+  for(i=0;i<=110;i++)
+    {
+      if(!checker(i))
+       {
+         if(first)
+           first=0;
+         else
+           printf(";");
+         printf("%s",mapper(i));
+       }
+    }
+}
+
 /* In the future, we can do all sorts of interesting configuration
    output here.  For now, just give "group" as the Enigmail folks need
    it, and pubkey, cipher, hash, and compress as they may be useful
@@ -1410,6 +1476,14 @@ list_config(char *items)
          any=1;
        }
 
+      if (show_all || !ascii_strcasecmp (name,"ciphername"))
+       {
+         printf ("cfg:ciphername:");
+         print_algo_names (openpgp_cipher_test_algo,openpgp_cipher_algo_name);
+         printf ("\n");
+         any = 1;
+       }
+
       if(show_all
         || ascii_strcasecmp(name,"digest")==0
         || ascii_strcasecmp(name,"hash")==0)
@@ -1420,6 +1494,16 @@ list_config(char *items)
          any=1;
        }
 
+      if (show_all
+          || !ascii_strcasecmp(name,"digestname")
+          || !ascii_strcasecmp(name,"hashname"))
+       {
+         printf ("cfg:digestname:");
+         print_algo_names (openpgp_md_test_algo, gcry_md_algo_name);
+         printf("\n");
+         any=1;
+       }
+      
       if(show_all || ascii_strcasecmp(name,"compress")==0)
        {
          printf("cfg:compress:");
@@ -1462,16 +1546,23 @@ list_config(char *items)
 static void
 gpgconf_list (const char *configfile)
 {
-  /* The following definitions are taken from gnupg/tools/gpgconf-comp.c.  */
-#define GC_OPT_FLAG_NONE       0UL
-#define GC_OPT_FLAG_DEFAULT    (1UL << 4)
+  char *configfile_esc = percent_escape (configfile, NULL);
 
   printf ("gpgconf-gpg.conf:%lu:\"%s\n",
-          GC_OPT_FLAG_DEFAULT,configfile?configfile:"/dev/null");
+          GC_OPT_FLAG_DEFAULT, configfile_esc ? configfile_esc : "/dev/null");
   printf ("verbose:%lu:\n", GC_OPT_FLAG_NONE);
   printf ("quiet:%lu:\n",   GC_OPT_FLAG_NONE);
   printf ("keyserver:%lu:\n", GC_OPT_FLAG_NONE);
   printf ("reader-port:%lu:\n", GC_OPT_FLAG_NONE);
+  printf ("default-key:%lu:\n", GC_OPT_FLAG_NONE);
+  printf ("encrypt-to:%lu:\n", GC_OPT_FLAG_NONE);
+  printf ("auto-key-locate:%lu:\n", GC_OPT_FLAG_NONE);
+  printf ("allow-pka-lookup:%lu:\n", GC_OPT_FLAG_NONE);
+  printf ("log-file:%lu:\n", GC_OPT_FLAG_NONE);
+  printf ("debug-level:%lu:\"none:\n", GC_OPT_FLAG_DEFAULT);
+  printf ("group:%lu:\n", GC_OPT_FLAG_NONE);
+
+  xfree (configfile_esc);
 }
 
 
@@ -1642,76 +1733,6 @@ parse_trust_model(const char *model)
 }
 
 
-
-/* Make sure that the standard file descriptors are opened. Obviously
-   some folks close them before an exec and the next file we open will
-   get one of them assigned and thus any output (i.e. diagnostics) end
-   up in that file (e.g. the trustdb).  Not actually a gpg problem as
-   this will hapenn with almost all utilities when called in a wrong
-   way.  However we try to minimize the damage here and raise
-   awareness of the problem.
-
-   Must be called before we open any files! */
-static void
-reopen_std(void)
-{  
-#if defined(HAVE_STAT) && !defined(HAVE_W32_SYSTEM)
-  struct stat statbuf;
-  int did_stdin=0,did_stdout=0,did_stderr=0;
-  FILE *complain;
-
-  if(fstat(STDIN_FILENO,&statbuf)==-1 && errno==EBADF)
-    {
-      if(open("/dev/null",O_RDONLY)==STDIN_FILENO)
-       did_stdin=1;
-      else
-       did_stdin=2;
-    }
-
-  if(fstat(STDOUT_FILENO,&statbuf)==-1 && errno==EBADF)
-    {
-      if(open("/dev/null",O_WRONLY)==STDOUT_FILENO)
-       did_stdout=1;
-      else
-       did_stdout=2;
-    }
-
-  if(fstat(STDERR_FILENO,&statbuf)==-1 && errno==EBADF)
-    {
-      if(open("/dev/null",O_WRONLY)==STDERR_FILENO)
-       did_stderr=1;
-      else
-       did_stderr=2;
-    }
-
-  /* It's hard to log this sort of thing since the filehandle we would
-     complain to may be closed... */
-  if(did_stderr==0)
-    complain=stderr;
-  else if(did_stdout==0)
-    complain=stdout;
-  else
-    complain=NULL;
-
-  if(complain)
-    {
-      if(did_stdin==1)
-       fprintf(complain,"gpg: WARNING: standard input reopened\n");
-      if(did_stdout==1)
-       fprintf(complain,"gpg: WARNING: standard output reopened\n");
-      if(did_stderr==1)
-       fprintf(complain,"gpg: WARNING: standard error reopened\n");
-
-      if(did_stdin==2 || did_stdout==2 || did_stderr==2)
-       fprintf(complain,"gpg: fatal: unable to reopen standard input,"
-               " output, or error\n");
-    }
-
-  if(did_stdin==2 || did_stdout==2 || did_stderr==2)
-    exit(3);
-#endif /* HAVE_STAT && !HAVE_W32_SYSTEM */
-}
-
 /* Pack an s2k iteration count into the form specified in 2440.  If
    we're in between valid values, round up. */
 static unsigned char
@@ -1738,8 +1759,83 @@ encode_s2k_iterations(int iterations)
   return result;
 }
 
+
+/* This fucntion called to initialized a new control object.  It is
+   assumed that this object has been zeroed out before calling this
+   function. */
+static void
+gpg_init_default_ctrl (ctrl_t ctrl)
+{
+}
+
+
+/* This function is called to deinitialize a control object.  It is
+   not deallocated. */
+static void
+gpg_deinit_default_ctrl (ctrl_t ctrl)
+{
+}
+
+
+char *
+get_default_configname (void)
+{
+  char *configname = NULL;
+  char *name = xstrdup ("gpg" EXTSEP_S "conf-" SAFE_VERSION);
+  char *ver = &name[strlen ("gpg" EXTSEP_S "conf-")];
+
+  do
+    {
+      if (configname)
+       {
+         char *tok;
+         
+         xfree (configname);
+         configname = NULL;
+
+         if ((tok = strrchr (ver, SAFE_VERSION_DASH)))
+           *tok='\0';
+         else if ((tok = strrchr (ver, SAFE_VERSION_DOT)))
+           *tok='\0';
+         else
+           break;
+       }
+      
+      configname = make_filename (opt.homedir, name, NULL);
+    }
+  while (access (configname, R_OK));
+
+  xfree(name);
+  
+  if (! configname)
+    configname = make_filename (opt.homedir, "gpg" EXTSEP_S "conf", NULL);
+  if (! access (configname, R_OK))
+    {
+      /* Print a warning when both config files are present.  */
+      char *p = make_filename (opt.homedir, "options", NULL);
+      if (! access (p, R_OK))
+       log_info (_("NOTE: old default options file `%s' ignored\n"), p);
+      xfree (p);
+    }
+  else
+    {
+      /* Use the old default only if it exists.  */
+      char *p = make_filename (opt.homedir, "options", NULL);
+      if (!access (p, R_OK))
+       {
+         xfree (configname);
+         configname = p;
+       }
+      else
+       xfree (p);
+    }
+
+  return configname;
+}
+
+
 int
-main (int argc, char **argv )
+main (int argc, char **argv)
 {
     ARGPARSE_ARGS pargs;
     IOBUF a;
@@ -1751,11 +1847,12 @@ main (int argc, char **argv )
     int may_coredump;
     strlist_t sl, remusr= NULL, locusr=NULL;
     strlist_t nrings=NULL, sec_nrings=NULL;
-    armor_filter_context_t afx;
+    armor_filter_context_t *afx = NULL;
     int detached_sig = 0;
     FILE *configfp = NULL;
     char *configname = NULL;
     char *save_configname = NULL;
+    char *default_configname = NULL;
     unsigned configlineno;
     int parse_debug = 0;
     int default_config = 1;
@@ -1791,7 +1888,7 @@ main (int argc, char **argv )
     /* 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. */
-    reopen_std ();
+    gnupg_reopen_std ("gpg");
     trap_unaligned ();
     gnupg_rl_initialize ();
     set_strusage (my_strusage);
@@ -1801,6 +1898,9 @@ main (int argc, char **argv )
     gcry_control (GCRYCTL_DISABLE_INTERNAL_LOCKING);
     log_set_prefix ("gpg", 1);
 
+    /* Make sure that our subsystems are ready.  */
+    init_common_subsystems ();
+
     /* Check that the libraries are suitable.  Do it right here because the
        option parsing may need services of the library.  */
     if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
@@ -1839,8 +1939,8 @@ main (int argc, char **argv )
     opt.marginals_needed = 3;
     opt.max_cert_depth = 5;
     opt.pgp2_workarounds = 1;
-    opt.force_v3_sigs = 1;
     opt.escape_from = 1;
+    opt.flags.require_cross_cert = 1;
     opt.import_options=IMPORT_SK2PK;
     opt.export_options=EXPORT_ATTRIBUTES;
     opt.keyserver_options.import_options=IMPORT_REPAIR_PKS_SUBKEY_BUG;
@@ -1854,11 +1954,10 @@ main (int argc, char **argv )
     opt.min_cert_level=2;
     set_screen_dimensions();
     opt.keyid_format=KF_SHORT;
-    opt.rfc2440_text=1;
     opt.def_sig_expire="0";
     opt.def_cert_expire="0";
-    opt.flags.require_cross_cert = 1;
     set_homedir ( default_homedir () );
+    opt.passwd_repeat=1;
 
     /* Check whether we have a config file on the command line.  */
     orig_argc = argc;
@@ -1876,8 +1975,11 @@ main (int argc, char **argv )
            default_config = 0;
        }
        else if( pargs.r_opt == oNoOptions )
+          {
            default_config = 0; /* --no-options */
-       else if( pargs.r_opt == oHomedir )
+            opt.no_homedir_creation = 1;
+          }
+        else if( pargs.r_opt == oHomedir )
            set_homedir ( pargs.r.ret_str );
        else if( pargs.r_opt == oNoPermissionWarn )
            opt.no_perm_warn=1;
@@ -1914,8 +2016,8 @@ main (int argc, char **argv )
 #if defined(HAVE_GETUID) && defined(HAVE_GETEUID)
     /* There should be no way to get to this spot while still carrying
        setuid privs.  Just in case, bomb out if we are. */
-    if(getuid()!=geteuid())
-      BUG();
+    if ( getuid () != geteuid () )
+      BUG ();
 #endif
     maybe_setuid = 0;
 
@@ -1926,52 +2028,11 @@ main (int argc, char **argv )
     assuan_set_assuan_err_source (GPG_ERR_SOURCE_DEFAULT);
  
 
-    set_native_charset (NULL); /* Try to auto set the character set */
-
     /* Try for a version specific config file first */
-    if( default_config )
-      {
-       char *name=xstrdup("gpg" EXTSEP_S "conf-" SAFE_VERSION);
-       char *ver=&name[strlen("gpg" EXTSEP_S "conf-")];
-
-       do
-         {
-           if(configname)
-             {
-               char *tok;
-
-               xfree(configname);
-               configname=NULL;
-
-               if((tok=strrchr(ver,SAFE_VERSION_DASH)))
-                 *tok='\0';
-               else if((tok=strrchr(ver,SAFE_VERSION_DOT)))
-                 *tok='\0';
-               else
-                 break;
-             }
+    default_configname = get_default_configname ();
+    if (default_config)
+      configname = xstrdup (default_configname);
 
-           configname = make_filename(opt.homedir,name,NULL);
-         }
-       while(access(configname,R_OK));
-
-       xfree(name);
-
-       if(!configname)
-         configname=make_filename(opt.homedir, "gpg" EXTSEP_S "conf", NULL );
-        if (!access (configname, R_OK))
-          { /* Print a warning when both config files are present. */
-            char *p = make_filename(opt.homedir, "options", NULL );
-            if (!access (p, R_OK))
-              log_info (_("NOTE: old default options file `%s' ignored\n"), p);
-            xfree (p);
-          }
-        else
-          { /* Keep on using the old default one. */
-            xfree (configname);
-            configname = make_filename(opt.homedir, "options", NULL );
-          }
-      }
     argc = orig_argc;
     argv = orig_argv;
     pargs.argc = &argc;
@@ -2044,6 +2105,7 @@ main (int argc, char **argv )
           case aChangePIN:
 #endif /* ENABLE_CARD_SUPPORT*/
          case aListKeys: 
+         case aLocateKeys:
          case aListSigs: 
          case aExportSecret: 
          case aExportSecretSub: 
@@ -2092,6 +2154,10 @@ main (int argc, char **argv )
          case aVerifyFiles: multifile=1; /* fall through */
          case aVerify: set_cmd( &cmd, aVerify); break;
 
+          case aServer:
+            set_cmd (&cmd, pargs.r_opt);
+            opt.batch = 1;
+            break;
 
          case oArmor: opt.armor = 1; opt.no_armor=0; break;
          case oOutput: opt.outfile = pargs.r.ret_str; break;
@@ -2107,10 +2173,20 @@ main (int argc, char **argv )
            opt.list_options|=LIST_SHOW_UNUSABLE_SUBKEYS;
            break;
 
-         case oBatch: opt.batch = 1; nogreeting = 1; break;
+         case oBatch:
+            opt.batch = 1;
+            nogreeting = 1;
+            break;
+
           case oUseAgent: /* Dummy. */
-          case oNoUseAgent: /* Dummy. */ break;
-         case oGpgAgentInfo: opt.gpg_agent_info = pargs.r.ret_str; break;
+            break;
+          case oNoUseAgent:
+           obsolete_option (configname, configlineno, "--no-use-agent");
+            break;
+         case oGpgAgentInfo: 
+           obsolete_option (configname, configlineno, "--gpg-agent-info");
+            break;
+
          case oAnswerYes: opt.answer_yes = 1; break;
          case oAnswerNo: opt.answer_no = 1; break;
          case oKeyring: append_to_strlist( &nrings, pargs.r.ret_str); break;
@@ -2129,19 +2205,19 @@ main (int argc, char **argv )
           case oDebugLevel: debug_level = pargs.r.ret_str; break;
 
          case oStatusFD:
-            set_status_fd( iobuf_translate_file_handle (pargs.r.ret_int, 1) );
+            set_status_fd( translate_sys2libc_fd_int (pargs.r.ret_int, 1) );
             break;
          case oStatusFile:
             set_status_fd ( open_info_file (pargs.r.ret_str, 1) );
             break;
          case oAttributeFD:
-            set_attrib_fd(iobuf_translate_file_handle (pargs.r.ret_int, 1));
+            set_attrib_fd(translate_sys2libc_fd_int (pargs.r.ret_int, 1));
             break;
          case oAttributeFile:
             set_attrib_fd ( open_info_file (pargs.r.ret_str, 1) );
             break;
          case oLoggerFD:
-            log_set_fd (iobuf_translate_file_handle (pargs.r.ret_int, 1));
+            log_set_fd (translate_sys2libc_fd_int (pargs.r.ret_int, 1));
             break;
           case oLoggerFile:
             logfile = pargs.r.ret_str;
@@ -2195,9 +2271,13 @@ main (int argc, char **argv )
          case oNoOptions: opt.no_homedir_creation = 1; break; /* no-options */
          case oHomedir: break;
          case oNoBatch: opt.batch = 0; break;
-         case oWithKeyData: opt.with_key_data=1; /* fall thru */
+
+         case oWithKeyData: opt.with_key_data=1; /*FALLTHRU*/
          case oWithColons: opt.with_colons=':'; break;
 
+          case oWithSigCheck: opt.check_sigs = 1; /*FALLTHRU*/
+          case oWithSigList: opt.list_sigs = 1; break;  
+
          case oSkipVerify: opt.skip_verify=1; break;
          case oCompressKeys: opt.compress_keys = 1; break;
          case aListSecretKeys: set_cmd( &cmd, aListSecretKeys); break;
@@ -2219,18 +2299,8 @@ main (int argc, char **argv )
              }
            break;
          case oLoadExtension:
-#ifndef __riscos__
-#if defined(USE_DYNAMIC_LINKING) || defined(_WIN32)
-           if(check_permissions(pargs.r.ret_str,2))
-             log_info(_("cipher extension `%s' not loaded due to"
-                        " unsafe permissions\n"),pargs.r.ret_str);
-           else
-             register_cipher_extension(orig_argc? *orig_argv:NULL,
-                                       pargs.r.ret_str);
-#endif
-#else /* __riscos__ */
-            riscos_not_implemented("load-extension");
-#endif /* __riscos__ */
+            /* Dummy so that gpg 1.4 conf files can work. Should
+               eventually be removed.  */
            break;
          case oRFC1991:
            opt.compliance = CO_RFC1991;
@@ -2238,11 +2308,34 @@ main (int argc, char **argv )
            opt.escape_from = 1;
            break;
          case oOpenPGP:
+         case oRFC4880:
+           /* This is effectively the same as RFC2440, but with
+              "--enable-dsa2 --no-rfc2440-text --escape-from-lines
+              --require-cross-certification". */
+           opt.compliance = CO_RFC4880;
+           opt.flags.dsa2 = 1;
+           opt.flags.require_cross_cert = 1;
+           opt.rfc2440_text = 0;
+           opt.allow_non_selfsigned_uid = 1;
+           opt.allow_freeform_uid = 1;
+           opt.pgp2_workarounds = 0;
+           opt.escape_from = 1;
+           opt.force_v3_sigs = 0;
+           opt.compress_keys = 0;          /* not mandated, but we do it */
+           opt.compress_sigs = 0;          /* ditto. */
+           opt.not_dash_escaped = 0;
+           opt.def_cipher_algo = 0;
+           opt.def_digest_algo = 0;
+           opt.cert_digest_algo = 0;
+           opt.compress_algo = -1;
+            opt.s2k_mode = 3; /* iterated+salted */
+           opt.s2k_digest_algo = DIGEST_ALGO_SHA1;
+           opt.s2k_cipher_algo = CIPHER_ALGO_3DES;
+           break;
          case oRFC2440:
-           /* TODO: When 2440bis becomes a RFC, set new values for
-              oOpenPGP. */
-           opt.rfc2440_text=1;
            opt.compliance = CO_RFC2440;
+           opt.flags.dsa2 = 0;
+           opt.rfc2440_text = 1;
            opt.allow_non_selfsigned_uid = 1;
            opt.allow_freeform_uid = 1;
            opt.pgp2_workarounds = 0;
@@ -2415,13 +2508,14 @@ main (int argc, char **argv )
            set_passphrase_from_string(pargs.r.ret_str);
            break;
          case oPasswdFD:
-            pwfd = iobuf_translate_file_handle (pargs.r.ret_int, 0);
+            pwfd = translate_sys2libc_fd_int (pargs.r.ret_int, 0);
             break;
          case oPasswdFile:
             pwfd = open_info_file (pargs.r.ret_str, 0);
             break;
+         case oPasswdRepeat: opt.passwd_repeat=pargs.r.ret_int; break;
          case oCommandFD:
-            opt.command_fd = iobuf_translate_file_handle (pargs.r.ret_int, 0);
+            opt.command_fd = translate_sys2libc_fd_int (pargs.r.ret_int, 0);
             break;
          case oCommandFile:
             opt.command_fd = open_info_file (pargs.r.ret_str, 0);
@@ -2563,6 +2657,8 @@ main (int argc, char **argv )
                   N_("show user ID validity during signature verification")},
                  {"show-unusable-uids",VERIFY_SHOW_UNUSABLE_UIDS,NULL,
                   N_("show revoked and expired user IDs in signature verification")},
+                 {"show-primary-uid-only",VERIFY_SHOW_PRIMARY_UID_ONLY,NULL,
+                  N_("show only the primary user ID in signature verification")},
                  {"pka-lookups",VERIFY_PKA_LOOKUPS,NULL,
                   N_("validate signatures with PKA data")},
                  {"pka-trust-increase",VERIFY_PKA_TRUST_INCREASE,NULL,
@@ -2638,7 +2734,7 @@ main (int argc, char **argv )
                                   "--keyserver-options ","http-proxy");
                break;
          case oFastListMode: opt.fast_list_mode = 1; break;
-         case oFixedListMode: opt.fixed_list_mode = 1; break;
+         case oFixedListMode: /* Dummy */ break;
          case oListOnly: opt.list_only=1; break;
          case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break;
          case oIgnoreValidFrom: opt.ignore_valid_from = 1; break;
@@ -2708,6 +2804,7 @@ main (int argc, char **argv )
           case oTTYtype: opt.ttytype = pargs.r.ret_str; break;
           case oLCctype: opt.lc_ctype = pargs.r.ret_str; break;
           case oLCmessages: opt.lc_messages = pargs.r.ret_str; break;
+          case oXauthority: opt.xauthority = pargs.r.ret_str; break;
          case oGroup: add_group(pargs.r.ret_str); break;
          case oUnGroup: rm_group(pargs.r.ret_str); break;
          case oNoGroups:
@@ -2767,13 +2864,18 @@ main (int argc, char **argv )
            release_akl();
            break;
 
-          case oAllowMultisigVerification:
-            opt.allow_multisig_verification = 1;
-            break;
-
          case oEnableDSA2: opt.flags.dsa2=1; break;
          case oDisableDSA2: opt.flags.dsa2=0; break;
 
+          case oAllowMultisigVerification:
+         case oAllowMultipleMessages:
+           opt.flags.allow_multiple_messages=1;
+           break;
+
+         case oNoAllowMultipleMessages:
+           opt.flags.allow_multiple_messages=0;
+           break;
+
          case oNoop: break;
 
          default : pargs.err = configfp? 1:2; break;
@@ -2800,10 +2902,11 @@ main (int argc, char **argv )
        directly after the option parsing. */
     if (cmd == aGPGConfList)
       {
-        gpgconf_list (save_configname);
+        gpgconf_list (save_configname ? save_configname : default_configname);
         g10_exit (0);
       }
     xfree (save_configname);
+    xfree (default_configname);
 
     if( nogreeting )
        greeting = 0;
@@ -2837,6 +2940,24 @@ main (int argc, char **argv )
         log_set_prefix (NULL, 1|2|4);
       }
 
+#ifdef USE_CAMELLIA    
+    /* We better also print a runtime warning if people build it with
+       support for Camellia (which is not yet defined by OpenPGP). */
+    log_info ("WARNING: This version has been built with support for the "
+              "Camellia cipher.\n");
+    log_info ("         It is for testing only and is NOT for production "
+              "use!\n");
+#endif
+
+    /* Older Libgcrypts fail with an assertion during DSA key
+       generation.  Better disable DSA2 entirely. */
+    if (opt.flags.dsa2 && !gcry_check_version ("1.4.0") )
+      {
+        log_info ("WARNING: "
+                  "DSA2 is only available with Libgcrypt 1.4 and later\n");
+        opt.flags.dsa2 = 0;
+      }
+
     if (opt.verbose > 2)
         log_info ("using character set `%s'\n", get_native_charset ());
 
@@ -3102,7 +3223,7 @@ main (int argc, char **argv )
        if(opt.def_cipher_algo
           && !algo_available(PREFTYPE_SYM,opt.def_cipher_algo,NULL))
          {
-           badalg = gcry_cipher_algo_name (opt.def_cipher_algo);
+           badalg = openpgp_cipher_algo_name (opt.def_cipher_algo);
            badtype = PREFTYPE_SYM;
          }
        else if(opt.def_digest_algo
@@ -3164,15 +3285,6 @@ main (int argc, char **argv )
        set_cmd( &cmd, aListKeys);
     }
 
-    /* kludge to let -sat generate a clear text signature */
-    if( opt.textmode == 2 && !detached_sig && opt.armor && cmd == aSign )
-      {
-        log_info ("compatibility note:\n");
-        log_info ("\"-sat\" won't generate clear signed messages in "
-                  "future versions\n");
-        log_info ("Use \"--clearsign\" instead of \"-sat\"\n");
-       cmd = aClearsign;
-      }
 
     if( opt.verbose > 1 )
        set_packet_list_mode(1);
@@ -3190,7 +3302,7 @@ main (int argc, char **argv )
       {
         if (ALWAYS_ADD_KEYRINGS
             || (cmd != aCheckKeys && cmd != aListSigs && cmd != aListKeys
-                && cmd != aVerify && cmd != aSym))
+                && cmd != aVerify && cmd != aSym && cmd != aLocateKeys))
           {
             if (!sec_nrings || default_keyring) /* add default secret rings */
               keydb_add_resource ("secring" EXTSEP_S "gpg", 4, 1);
@@ -3251,6 +3363,16 @@ main (int argc, char **argv )
 
     switch( cmd )
       {
+      case aServer:
+        {
+          ctrl_t ctrl = xtrycalloc (1, sizeof *ctrl);
+          gpg_init_default_ctrl (ctrl);
+          gpg_server (ctrl);
+          gpg_deinit_default_ctrl (ctrl);
+          xfree (ctrl);
+        }
+        break;
+
       case aStore: /* only store the file */
        if( argc > 1 )
            wrong_args(_("--store [filename]"));
@@ -3463,7 +3585,7 @@ main (int argc, char **argv )
        sl = NULL;
        for( ; argc; argc--, argv++ )
            add_to_strlist2( &sl, *argv, utf8_strings );
-       public_key_list( sl );
+       public_key_list( sl, 0 );
        free_strlist(sl);
        break;
       case aListSecretKeys:
@@ -3473,6 +3595,13 @@ main (int argc, char **argv )
        secret_key_list( sl );
        free_strlist(sl);
        break;
+      case aLocateKeys:
+       sl = NULL;
+       for (; argc; argc--, argv++)
+          add_to_strlist2( &sl, *argv, utf8_strings );
+       public_key_list (sl, 1);
+       free_strlist (sl);
+       break;
 
       case aKeygen: /* generate a key */
        if( opt.batch ) {
@@ -3823,8 +3952,8 @@ main (int argc, char **argv )
 
            if( !opt.no_armor ) {
                if( use_armor_filter( a ) ) {
-                   memset( &afx, 0, sizeof afx);
-                   iobuf_push_filter( a, armor_filter, &afx );
+                   afx = new_armor_context ();
+                   push_armor_filter (afx, a);
                }
            }
            if( cmd == aListPackets ) {
@@ -3840,6 +3969,7 @@ main (int argc, char **argv )
       }
 
     /* cleanup */
+    release_armor_context (afx);
     FREE_STRLIST(remusr);
     FREE_STRLIST(locusr);
     g10_exit(0);
@@ -4016,8 +4146,8 @@ print_mds( const char *fname, int algo )
        gcry_md_enable (md, GCRY_MD_MD5);
        gcry_md_enable (md, GCRY_MD_SHA1);
        gcry_md_enable (md, GCRY_MD_RMD160);
-        if (!openpgp_md_test_algo (DIGEST_ALGO_SHA224))
-          gcry_md_enable (md, DIGEST_ALGO_SHA224);
+        if (!openpgp_md_test_algo (GCRY_MD_SHA224))
+          gcry_md_enable (md, GCRY_MD_SHA224);
         if (!openpgp_md_test_algo (GCRY_MD_SHA256))
           gcry_md_enable (md, GCRY_MD_SHA256);
         if (!openpgp_md_test_algo (GCRY_MD_SHA384))
@@ -4039,8 +4169,8 @@ print_mds( const char *fname, int algo )
                 print_hashline( md, GCRY_MD_MD5, fname );
                 print_hashline( md, GCRY_MD_SHA1, fname );
                 print_hashline( md, GCRY_MD_RMD160, fname );
-                if (!gcry_md_test_algo (DIGEST_ALGO_SHA224))
-                    print_hashline (md, DIGEST_ALGO_SHA224, fname);
+                if (!gcry_md_test_algo (GCRY_MD_SHA224))
+                    print_hashline (md, GCRY_MD_SHA224, fname);
                 if (!gcry_md_test_algo (GCRY_MD_SHA256))
                     print_hashline( md, GCRY_MD_SHA256, fname );
                 if (!gcry_md_test_algo (GCRY_MD_SHA384))
@@ -4056,8 +4186,8 @@ print_mds( const char *fname, int algo )
                 print_hex( md, GCRY_MD_MD5, fname );
                 print_hex( md, GCRY_MD_SHA1, fname );
                 print_hex( md, GCRY_MD_RMD160, fname );
-                if (!gcry_md_test_algo (DIGEST_ALGO_SHA224))
-                    print_hex (md, DIGEST_ALGO_SHA224, fname);
+                if (!gcry_md_test_algo (GCRY_MD_SHA224))
+                    print_hex (md, GCRY_MD_SHA224, fname);
                 if (!gcry_md_test_algo (GCRY_MD_SHA256))
                     print_hex( md, GCRY_MD_SHA256, fname );
                 if (!gcry_md_test_algo (GCRY_MD_SHA384))
@@ -4165,3 +4295,4 @@ add_keyserver_url( const char *string, int which )
   if(critical)
     sl->flags |= 1;    
 }
+