Generate the ChangeLog from commit logs.
[gnupg.git] / agent / gpg-agent.c
index a0e018e..0616875 100644 (file)
@@ -51,8 +51,9 @@
 #include "gc-opt-flags.h"
 #include "exechelp.h"
 #include "asshelp.h"
 #include "gc-opt-flags.h"
 #include "exechelp.h"
 #include "asshelp.h"
+#include "../include/cipher.h" /* for PUBKEY_ALGO_ECDSA, PUBKEY_ALGO_ECDH */
 
 
-enum cmd_and_opt_values 
+enum cmd_and_opt_values
 { aNull = 0,
   oCsh           = 'c',
   oQuiet         = 'q',
 { aNull = 0,
   oCsh           = 'c',
   oQuiet         = 'q',
@@ -104,6 +105,7 @@ enum cmd_and_opt_values
   oIgnoreCacheForSigning,
   oAllowMarkTrusted,
   oAllowPresetPassphrase,
   oIgnoreCacheForSigning,
   oAllowMarkTrusted,
   oAllowPresetPassphrase,
+  oAllowLoopbackPinentry,
   oKeepTTY,
   oKeepDISPLAY,
   oSSHSupport,
   oKeepTTY,
   oKeepDISPLAY,
   oSSHSupport,
@@ -117,8 +119,8 @@ static ARGPARSE_OPTS opts[] = {
 
   { aGPGConfList, "gpgconf-list", 256, "@" },
   { aGPGConfTest, "gpgconf-test", 256, "@" },
 
   { aGPGConfList, "gpgconf-list", 256, "@" },
   { aGPGConfTest, "gpgconf-test", 256, "@" },
-  { aUseStandardSocketP, "use-standard-socket-p", 256, "@" }, 
-  
+  { aUseStandardSocketP, "use-standard-socket-p", 256, "@" },
+
   { 301, NULL, 0, N_("@Options:\n ") },
 
   { oServer,   "server",     0, N_("run in server mode (foreground)") },
   { 301, NULL, 0, N_("@Options:\n ") },
 
   { oServer,   "server",     0, N_("run in server mode (foreground)") },
@@ -147,7 +149,7 @@ static ARGPARSE_OPTS opts[] = {
   { oFakedSystemTime, "faked-system-time", 2, "@" }, /* (epoch time) */
 
   { oBatch,      "batch",       0, "@" },
   { oFakedSystemTime, "faked-system-time", 2, "@" }, /* (epoch time) */
 
   { oBatch,      "batch",       0, "@" },
-  { oHomedir,    "homedir",     2, "@"},   
+  { oHomedir,    "homedir",     2, "@"},
 
   { oDisplay,    "display",     2, "@" },
   { oTTYname,    "ttyname",     2, "@" },
 
   { oDisplay,    "display",     2, "@" },
   { oTTYname,    "ttyname",     2, "@" },
@@ -178,6 +180,8 @@ static ARGPARSE_OPTS opts[] = {
                              N_("allow clients to mark keys as \"trusted\"")},
   { oAllowPresetPassphrase, "allow-preset-passphrase", 0,
                              N_("allow presetting passphrase")},
                              N_("allow clients to mark keys as \"trusted\"")},
   { oAllowPresetPassphrase, "allow-preset-passphrase", 0,
                              N_("allow presetting passphrase")},
+  { oAllowLoopbackPinentry, "allow-loopback-pinentry", 0,
+                             N_("allow presetting passphrase")},
   { oSSHSupport, "enable-ssh-support", 0, N_("enable ssh-agent emulation") },
   { oWriteEnvFile, "write-env-file", 2|8,
             N_("|FILE|write environment settings also to FILE")},
   { oSSHSupport, "enable-ssh-support", 0, N_("enable ssh-agent emulation") },
   { oWriteEnvFile, "write-env-file", 2|8,
             N_("|FILE|write environment settings also to FILE")},
@@ -189,17 +193,24 @@ static ARGPARSE_OPTS opts[] = {
 #define DEFAULT_CACHE_TTL_SSH (30*60)  /* 30 minutes */
 #define MAX_CACHE_TTL         (120*60) /* 2 hours */
 #define MAX_CACHE_TTL_SSH     (120*60) /* 2 hours */
 #define DEFAULT_CACHE_TTL_SSH (30*60)  /* 30 minutes */
 #define MAX_CACHE_TTL         (120*60) /* 2 hours */
 #define MAX_CACHE_TTL_SSH     (120*60) /* 2 hours */
-#define MIN_PASSPHRASE_LEN    (8)      
-#define MIN_PASSPHRASE_NONALPHA (1)      
+#define MIN_PASSPHRASE_LEN    (8)
+#define MIN_PASSPHRASE_NONALPHA (1)
 #define MAX_PASSPHRASE_DAYS   (0)
 
 /* The timer tick used for housekeeping stuff.  For Windows we use a
    longer period as the SetWaitableTimer seems to signal earlier than
 #define MAX_PASSPHRASE_DAYS   (0)
 
 /* The timer tick used for housekeeping stuff.  For Windows we use a
    longer period as the SetWaitableTimer seems to signal earlier than
-   the 2 seconds.  */
-#ifdef HAVE_W32_SYSTEM
-#define TIMERTICK_INTERVAL    (4)
+   the 2 seconds.  CHECK_OWN_SOCKET_INTERVAL defines how often we
+   check our own socket in standard socket mode.  If that value is 0
+   we don't check at all.   All values are in seconds. */
+#if defined(HAVE_W32CE_SYSTEM)
+# define TIMERTICK_INTERVAL         (60)
+# define CHECK_OWN_SOCKET_INTERVAL   (0)  /* Never */
+#elif defined(HAVE_W32_SYSTEM)
+# define TIMERTICK_INTERVAL          (4)
+# define CHECK_OWN_SOCKET_INTERVAL  (60)
 #else
 #else
-#define TIMERTICK_INTERVAL    (2)    /* Seconds.  */
+# define TIMERTICK_INTERVAL          (2)
+# define CHECK_OWN_SOCKET_INTERVAL  (60)
 #endif
 
 
 #endif
 
 
@@ -259,11 +270,11 @@ static pid_t parent_pid = (pid_t)(-1);
 
 \f
 /*
 
 \f
 /*
-   Local prototypes. 
+   Local prototypes.
  */
 
 static char *create_socket_name (char *standard_name, char *template);
  */
 
 static char *create_socket_name (char *standard_name, char *template);
-static gnupg_fd_t create_server_socket (char *name, int is_ssh, 
+static gnupg_fd_t create_server_socket (char *name, int is_ssh,
                                         assuan_sock_nonce_t *nonce);
 static void create_directories (void);
 
                                         assuan_sock_nonce_t *nonce);
 static void create_directories (void);
 
@@ -295,7 +306,7 @@ static unsigned long pth_thread_id (void)
 
 \f
 /*
 
 \f
 /*
-   Functions. 
+   Functions.
  */
 
 static char *
  */
 
 static char *
@@ -303,7 +314,7 @@ make_libversion (const char *libname, const char *(*getfnc)(const char*))
 {
   const char *s;
   char *result;
 {
   const char *s;
   char *result;
-  
+
   if (maybe_setuid)
     {
       gcry_control (GCRYCTL_INIT_SECMEM, 0, 0);  /* Drop setuid. */
   if (maybe_setuid)
     {
       gcry_control (GCRYCTL_INIT_SECMEM, 0, 0);  /* Drop setuid. */
@@ -345,7 +356,7 @@ my_strusage (int level)
     case 41: p =  _("Syntax: gpg-agent [options] [command [args]]\n"
                     "Secret key management for GnuPG\n");
     break;
     case 41: p =  _("Syntax: gpg-agent [options] [command [args]]\n"
                     "Secret key management for GnuPG\n");
     break;
-    
+
     default: p = NULL;
     }
   return p;
     default: p = NULL;
     }
   return p;
@@ -382,7 +393,7 @@ set_debug (void)
       /* Unless the "guru" string has been used we don't want to allow
          hashing debugging.  The rationale is that people tend to
          select the highest debug value and would then clutter their
       /* Unless the "guru" string has been used we don't want to allow
          hashing debugging.  The rationale is that people tend to
          select the highest debug value and would then clutter their
-         disk with debug files which may reveal confidential data.  */ 
+         disk with debug files which may reveal confidential data.  */
       if (numok)
         opt.debug &= ~(DBG_HASHING_VALUE);
     }
       if (numok)
         opt.debug &= ~(DBG_HASHING_VALUE);
     }
@@ -406,16 +417,16 @@ set_debug (void)
 
   if (opt.debug)
     log_info ("enabled debug flags:%s%s%s%s%s%s%s%s\n",
 
   if (opt.debug)
     log_info ("enabled debug flags:%s%s%s%s%s%s%s%s\n",
-              (opt.debug & DBG_COMMAND_VALUE)? " command":"",    
-              (opt.debug & DBG_MPI_VALUE    )? " mpi":"",    
-              (opt.debug & DBG_CRYPTO_VALUE )? " crypto":"",    
-              (opt.debug & DBG_MEMORY_VALUE )? " memory":"", 
-              (opt.debug & DBG_CACHE_VALUE  )? " cache":"", 
-              (opt.debug & DBG_MEMSTAT_VALUE)? " memstat":"", 
-              (opt.debug & DBG_HASHING_VALUE)? " hashing":"", 
+              (opt.debug & DBG_COMMAND_VALUE)? " command":"",
+              (opt.debug & DBG_MPI_VALUE    )? " mpi":"",
+              (opt.debug & DBG_CRYPTO_VALUE )? " crypto":"",
+              (opt.debug & DBG_MEMORY_VALUE )? " memory":"",
+              (opt.debug & DBG_CACHE_VALUE  )? " cache":"",
+              (opt.debug & DBG_MEMSTAT_VALUE)? " memstat":"",
+              (opt.debug & DBG_HASHING_VALUE)? " hashing":"",
               (opt.debug & DBG_ASSUAN_VALUE )? " assuan":"");
 }
               (opt.debug & DBG_ASSUAN_VALUE )? " assuan":"");
 }
+
 
 /* Helper for cleanup to remove one socket with NAME.  */
 static void
 
 /* Helper for cleanup to remove one socket with NAME.  */
 static void
@@ -435,7 +446,7 @@ remove_socket (char *name)
        }
       *name = 0;
     }
        }
       *name = 0;
     }
-}  
+}
 
 static void
 cleanup (void)
 
 static void
 cleanup (void)
@@ -444,7 +455,7 @@ cleanup (void)
 
   if (done)
     return;
 
   if (done)
     return;
-  done = 1;  
+  done = 1;
   deinitialize_module_cache ();
   remove_socket (socket_name);
   remove_socket (socket_name_ssh);
   deinitialize_module_cache ();
   remove_socket (socket_name);
   remove_socket (socket_name_ssh);
@@ -507,7 +518,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
       break;
 
     case oNoGrab: opt.no_grab = 1; break;
       break;
 
     case oNoGrab: opt.no_grab = 1; break;
-      
+
     case oPinentryProgram: opt.pinentry_program = pargs->r.ret_str; break;
     case oPinentryTouchFile: opt.pinentry_touch_file = pargs->r.ret_str; break;
     case oScdaemonProgram: opt.scdaemon_program = pargs->r.ret_str; break;
     case oPinentryProgram: opt.pinentry_program = pargs->r.ret_str; break;
     case oPinentryTouchFile: opt.pinentry_touch_file = pargs->r.ret_str; break;
     case oScdaemonProgram: opt.scdaemon_program = pargs->r.ret_str; break;
@@ -517,19 +528,19 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
     case oDefCacheTTLSSH: opt.def_cache_ttl_ssh = pargs->r.ret_ulong; break;
     case oMaxCacheTTL: opt.max_cache_ttl = pargs->r.ret_ulong; break;
     case oMaxCacheTTLSSH: opt.max_cache_ttl_ssh = pargs->r.ret_ulong; break;
     case oDefCacheTTLSSH: opt.def_cache_ttl_ssh = pargs->r.ret_ulong; break;
     case oMaxCacheTTL: opt.max_cache_ttl = pargs->r.ret_ulong; break;
     case oMaxCacheTTLSSH: opt.max_cache_ttl_ssh = pargs->r.ret_ulong; break;
-      
-    case oEnforcePassphraseConstraints: 
+
+    case oEnforcePassphraseConstraints:
       opt.enforce_passphrase_constraints=1;
       break;
     case oMinPassphraseLen: opt.min_passphrase_len = pargs->r.ret_ulong; break;
       opt.enforce_passphrase_constraints=1;
       break;
     case oMinPassphraseLen: opt.min_passphrase_len = pargs->r.ret_ulong; break;
-    case oMinPassphraseNonalpha: 
+    case oMinPassphraseNonalpha:
       opt.min_passphrase_nonalpha = pargs->r.ret_ulong;
       break;
     case oCheckPassphrasePattern:
       opt.check_passphrase_pattern = pargs->r.ret_str;
       break;
     case oMaxPassphraseDays:
       opt.min_passphrase_nonalpha = pargs->r.ret_ulong;
       break;
     case oCheckPassphrasePattern:
       opt.check_passphrase_pattern = pargs->r.ret_str;
       break;
     case oMaxPassphraseDays:
-      opt.max_passphrase_days = pargs->r.ret_ulong; 
+      opt.max_passphrase_days = pargs->r.ret_ulong;
       break;
     case oEnablePassphraseHistory:
       opt.enable_passhrase_history = 1;
       break;
     case oEnablePassphraseHistory:
       opt.enable_passhrase_history = 1;
@@ -541,6 +552,8 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
 
     case oAllowPresetPassphrase: opt.allow_preset_passphrase = 1; break;
 
 
     case oAllowPresetPassphrase: opt.allow_preset_passphrase = 1; break;
 
+    case oAllowLoopbackPinentry: opt.allow_loopback_pinentry = 1; break;
+
     default:
       return 0; /* not handled */
     }
     default:
       return 0; /* not handled */
     }
@@ -555,7 +568,6 @@ main (int argc, char **argv )
 {
   ARGPARSE_ARGS pargs;
   int orig_argc;
 {
   ARGPARSE_ARGS pargs;
   int orig_argc;
-  int may_coredump;
   char **orig_argv;
   FILE *configfp = NULL;
   char *configname = NULL;
   char **orig_argv;
   FILE *configfp = NULL;
   char *configname = NULL;
@@ -591,7 +603,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 INIT_SECMEM()
      somewhere after the option parsing */
   /* Please note that we may running SUID(ROOT), so be very CAREFUL
      when adding any stuff between here and the call to INIT_SECMEM()
      somewhere after the option parsing */
-  log_set_prefix ("gpg-agent", JNLIB_LOG_WITH_PREFIX|JNLIB_LOG_WITH_PID); 
+  log_set_prefix ("gpg-agent", JNLIB_LOG_WITH_PREFIX|JNLIB_LOG_WITH_PID);
 
   /* Make sure that our subsystems are ready.  */
   i18n_init ();
 
   /* Make sure that our subsystems are ready.  */
   i18n_init ();
@@ -629,14 +641,14 @@ main (int argc, char **argv )
   setup_libgcrypt_logging ();
   gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
 
   setup_libgcrypt_logging ();
   gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
 
-  may_coredump = disable_core_dumps ();
+  disable_core_dumps ();
 
   /* Set default options.  */
   parse_rereadable_options (NULL, 0); /* Reset them to default values. */
 #ifdef USE_STANDARD_SOCKET
   opt.use_standard_socket = 1;
 #endif
 
   /* Set default options.  */
   parse_rereadable_options (NULL, 0); /* Reset them to default values. */
 #ifdef USE_STANDARD_SOCKET
   opt.use_standard_socket = 1;
 #endif
-  
+
   shell = getenv ("SHELL");
   if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") )
     csh_style = 1;
   shell = getenv ("SHELL");
   if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") )
     csh_style = 1;
@@ -647,7 +659,7 @@ main (int argc, char **argv )
   {
     const char *s;
     int idx;
   {
     const char *s;
     int idx;
-    static const char *names[] = 
+    static const char *names[] =
       { "DISPLAY", "TERM", "XAUTHORITY", "PINENTRY_USER_DATA", NULL };
 
     err = 0;
       { "DISPLAY", "TERM", "XAUTHORITY", "PINENTRY_USER_DATA", NULL };
 
     err = 0;
@@ -669,10 +681,10 @@ main (int argc, char **argv )
     if (err)
       log_fatal ("error recording startup environment: %s\n",
                  gpg_strerror (err));
     if (err)
       log_fatal ("error recording startup environment: %s\n",
                  gpg_strerror (err));
-    
+
     /* Fixme: Better use the locale function here.  */
     opt.startup_lc_ctype = getenv ("LC_CTYPE");
     /* Fixme: Better use the locale function here.  */
     opt.startup_lc_ctype = getenv ("LC_CTYPE");
-    if (opt.startup_lc_ctype) 
+    if (opt.startup_lc_ctype)
       opt.startup_lc_ctype = xstrdup (opt.startup_lc_ctype);
     opt.startup_lc_messages = getenv ("LC_MESSAGES");
     if (opt.startup_lc_messages)
       opt.startup_lc_ctype = xstrdup (opt.startup_lc_ctype);
     opt.startup_lc_messages = getenv ("LC_MESSAGES");
     if (opt.startup_lc_messages)
@@ -705,13 +717,13 @@ main (int argc, char **argv )
   gcry_control (GCRYCTL_INIT_SECMEM, 32768, 0);
   maybe_setuid = 0;
 
   gcry_control (GCRYCTL_INIT_SECMEM, 32768, 0);
   maybe_setuid = 0;
 
-  /* 
-     Now we are now working under our real uid 
+  /*
+     Now we are now working under our real uid
   */
 
   if (default_config)
     configname = make_filename (opt.homedir, "gpg-agent.conf", NULL );
   */
 
   if (default_config)
     configname = make_filename (opt.homedir, "gpg-agent.conf", NULL );
-  
+
   argc = orig_argc;
   argv = orig_argv;
   pargs.argc = &argc;
   argc = orig_argc;
   argv = orig_argv;
   pargs.argc = &argc;
@@ -742,7 +754,7 @@ main (int argc, char **argv )
                          configname, strerror(errno) );
               exit(2);
            }
                          configname, strerror(errno) );
               exit(2);
            }
-          xfree (configname); 
+          xfree (configname);
           configname = NULL;
        }
       if (parse_debug && configname )
           configname = NULL;
        }
       if (parse_debug && configname )
@@ -796,7 +808,7 @@ main (int argc, char **argv )
 
         case oFakedSystemTime:
           {
 
         case oFakedSystemTime:
           {
-            time_t faked_time = isotime2epoch (pargs.r.ret_str); 
+            time_t faked_time = isotime2epoch (pargs.r.ret_str);
             if (faked_time == (time_t)(-1))
               faked_time = (time_t)strtoul (pargs.r.ret_str, NULL, 10);
             gnupg_set_time (faked_time, 0);
             if (faked_time == (time_t)(-1))
               faked_time = (time_t)strtoul (pargs.r.ret_str, NULL, 10);
             gnupg_set_time (faked_time, 0);
@@ -830,7 +842,7 @@ main (int argc, char **argv )
       configname = NULL;
       goto next_pass;
     }
       configname = NULL;
       goto next_pass;
     }
-    
+
   xfree (configname);
   configname = NULL;
   if (log_get_errorcount(0))
   xfree (configname);
   configname = NULL;
   if (log_get_errorcount(0))
@@ -850,8 +862,31 @@ main (int argc, char **argv )
   /*log_info ("NOTE: this is a development version!\n");*/
 #endif
 
   /*log_info ("NOTE: this is a development version!\n");*/
 #endif
 
+#ifdef ENABLE_NLS
+  /* gpg-agent usually does not output any messages because it runs in
+     the background.  For log files it is acceptable to have messages
+     always encoded in utf-8.  We switch here to utf-8, so that
+     commands like --help still give native messages.  It is far
+     easier to switch only once instead of for every message and it
+     actually helps when more then one thread is active (avoids an
+     extra copy step). */
+    bind_textdomain_codeset (PACKAGE_GT, "UTF-8");
+#endif
+
+  if (!pipe_server && !is_daemon && !gpgconf_list)
+    {
+     /* We have been called without any options and thus we merely
+        check whether an agent is already running.  We do this right
+        here so that we don't clobber a logfile with this check but
+        print the status directly to stderr. */
+      opt.debug = 0;
+      set_debug ();
+      check_for_running_agent (0, 0);
+      agent_exit (0);
+    }
+
   set_debug ();
   set_debug ();
-  
+
   if (atexit (cleanup))
     {
       log_error ("atexit failed\n");
   if (atexit (cleanup))
     {
       log_error ("atexit failed\n");
@@ -863,7 +898,7 @@ main (int argc, char **argv )
   initialize_module_call_pinentry ();
   initialize_module_call_scd ();
   initialize_module_trustlist ();
   initialize_module_call_pinentry ();
   initialize_module_call_scd ();
   initialize_module_trustlist ();
-  
+
   /* Try to create missing directories. */
   create_directories ();
 
   /* Try to create missing directories. */
   create_directories ();
 
@@ -874,7 +909,7 @@ main (int argc, char **argv )
       gnupg_sleep (debug_wait);
       log_debug ("... okay\n");
     }
       gnupg_sleep (debug_wait);
       log_debug ("... okay\n");
     }
-  
+
   if (gpgconf_list == 3)
     {
       if (opt.use_standard_socket && !opt.quiet)
   if (gpgconf_list == 3)
     {
       if (opt.use_standard_socket && !opt.quiet)
@@ -913,21 +948,21 @@ main (int argc, char **argv )
               GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME, MAX_CACHE_TTL );
       es_printf ("max-cache-ttl-ssh:%lu:%d:\n",
               GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME, MAX_CACHE_TTL_SSH );
               GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME, MAX_CACHE_TTL );
       es_printf ("max-cache-ttl-ssh:%lu:%d:\n",
               GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME, MAX_CACHE_TTL_SSH );
-      es_printf ("enforce-passphrase-constraints:%lu:\n", 
+      es_printf ("enforce-passphrase-constraints:%lu:\n",
               GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
       es_printf ("min-passphrase-len:%lu:%d:\n",
               GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME, MIN_PASSPHRASE_LEN );
       es_printf ("min-passphrase-nonalpha:%lu:%d:\n",
               GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
       es_printf ("min-passphrase-len:%lu:%d:\n",
               GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME, MIN_PASSPHRASE_LEN );
       es_printf ("min-passphrase-nonalpha:%lu:%d:\n",
-              GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME, 
+              GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME,
               MIN_PASSPHRASE_NONALPHA);
       es_printf ("check-passphrase-pattern:%lu:\n",
               GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME);
       es_printf ("max-passphrase-days:%lu:%d:\n",
               MIN_PASSPHRASE_NONALPHA);
       es_printf ("check-passphrase-pattern:%lu:\n",
               GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME);
       es_printf ("max-passphrase-days:%lu:%d:\n",
-              GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME, 
+              GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME,
               MAX_PASSPHRASE_DAYS);
               MAX_PASSPHRASE_DAYS);
-      es_printf ("enable-passphrase-history:%lu:\n", 
+      es_printf ("enable-passphrase-history:%lu:\n",
               GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
               GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
-      es_printf ("no-grab:%lu:\n", 
+      es_printf ("no-grab:%lu:\n",
               GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
       es_printf ("ignore-cache-for-signing:%lu:\n",
               GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
               GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
       es_printf ("ignore-cache-for-signing:%lu:\n",
               GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
@@ -939,27 +974,6 @@ main (int argc, char **argv )
       agent_exit (0);
     }
 
       agent_exit (0);
     }
 
-  /* If this has been called without any options, we merely check
-     whether an agent is already running.  We do this here so that we
-     don't clobber a logfile but print it directly to stderr. */
-  if (!pipe_server && !is_daemon)
-    {
-      log_set_prefix (NULL, JNLIB_LOG_WITH_PREFIX); 
-      check_for_running_agent (0, 0);
-      agent_exit (0);
-    }
-  
-#ifdef ENABLE_NLS
-  /* gpg-agent usually does not output any messages because it runs in
-     the background.  For log files it is acceptable to have messages
-     always encoded in utf-8.  We switch here to utf-8, so that
-     commands like --help still give native messages.  It is far
-     easier to switch only once instead of for every message and it
-     actually helps when more then one thread is active (avoids an
-     extra copy step). */
-    bind_textdomain_codeset (PACKAGE_GT, "UTF-8");
-#endif
-
   /* Now start with logging to a file if this is desired. */
   if (logfile)
     {
   /* Now start with logging to a file if this is desired. */
   if (logfile)
     {
@@ -978,7 +992,7 @@ main (int argc, char **argv )
 
 
   if (pipe_server)
 
 
   if (pipe_server)
-    { 
+    {
       /* This is the simple pipe based server */
       ctrl_t ctrl;
 
       /* This is the simple pipe based server */
       ctrl_t ctrl;
 
@@ -1023,11 +1037,11 @@ main (int argc, char **argv )
 
 
       /* Create the sockets.  */
 
 
       /* Create the sockets.  */
-      socket_name = create_socket_name 
-        ("S.gpg-agent", "/tmp/gpg-XXXXXX/S.gpg-agent");
+      socket_name = create_socket_name
+        ("S.gpg-agent", "gpg-XXXXXX/S.gpg-agent");
       if (opt.ssh_support)
       if (opt.ssh_support)
-       socket_name_ssh = create_socket_name 
-          ("S.gpg-agent.ssh", "/tmp/gpg-XXXXXX/S.gpg-agent.ssh");
+       socket_name_ssh = create_socket_name
+          ("S.gpg-agent.ssh", "gpg-XXXXXX/S.gpg-agent.ssh");
 
       fd = create_server_socket (socket_name, 0, &socket_nonce);
       if (opt.ssh_support)
 
       fd = create_server_socket (socket_name, 0, &socket_nonce);
       if (opt.ssh_support)
@@ -1047,14 +1061,14 @@ main (int argc, char **argv )
       es_printf ("set GPG_AGENT_INFO=%s;%lu;1\n", socket_name, (ulong)pid);
 #else /*!HAVE_W32_SYSTEM*/
       pid = fork ();
       es_printf ("set GPG_AGENT_INFO=%s;%lu;1\n", socket_name, (ulong)pid);
 #else /*!HAVE_W32_SYSTEM*/
       pid = fork ();
-      if (pid == (pid_t)-1) 
+      if (pid == (pid_t)-1)
         {
           log_fatal ("fork failed: %s\n", strerror (errno) );
           exit (1);
         }
         {
           log_fatal ("fork failed: %s\n", strerror (errno) );
           exit (1);
         }
-      else if (pid) 
+      else if (pid)
         { /* We are the parent */
         { /* We are the parent */
-          char *infostr, *infostr_ssh_sock, *infostr_ssh_pid;
+          char *infostr, *infostr_ssh_sock;
 
           /* Close the socket FD. */
           close (fd);
 
           /* Close the socket FD. */
           close (fd);
@@ -1069,9 +1083,10 @@ main (int argc, char **argv )
              right now and thus we restore it.  That is not strictly
              necessary but some programs falsely assume a cleared
              signal mask.  */
              right now and thus we restore it.  That is not strictly
              necessary but some programs falsely assume a cleared
              signal mask.  */
+#warning need to do something about pth_kill - see bug#1320
           if ( !pth_kill () )
             log_error ("pth_kill failed in forked process\n");
           if ( !pth_kill () )
             log_error ("pth_kill failed in forked process\n");
-            
+
 #ifdef HAVE_SIGPROCMASK
           if (startup_signal_mask_valid)
             {
 #ifdef HAVE_SIGPROCMASK
           if (startup_signal_mask_valid)
             {
@@ -1081,7 +1096,7 @@ main (int argc, char **argv )
             }
           else
             log_info ("no saved signal mask\n");
             }
           else
             log_info ("no saved signal mask\n");
-#endif /*HAVE_SIGPROCMASK*/          
+#endif /*HAVE_SIGPROCMASK*/
 
           /* Create the info string: <name>:<pid>:<protocol_version> */
           if (asprintf (&infostr, "GPG_AGENT_INFO=%s:%lu:1",
 
           /* Create the info string: <name>:<pid>:<protocol_version> */
           if (asprintf (&infostr, "GPG_AGENT_INFO=%s:%lu:1",
@@ -1100,13 +1115,6 @@ main (int argc, char **argv )
                  kill (pid, SIGTERM);
                  exit (1);
                }
                  kill (pid, SIGTERM);
                  exit (1);
                }
-             if (asprintf (&infostr_ssh_pid, "SSH_AGENT_PID=%u",
-                           pid) < 0)
-               {
-                 log_error ("out of core\n");
-                 kill (pid, SIGTERM);
-                 exit (1);
-               }
            }
 
           *socket_name = 0; /* Don't let cleanup() remove the socket -
            }
 
           *socket_name = 0; /* Don't let cleanup() remove the socket -
@@ -1117,7 +1125,7 @@ main (int argc, char **argv )
           if (env_file_name)
             {
               estream_t fp;
           if (env_file_name)
             {
               estream_t fp;
-              
+
               fp = es_fopen (env_file_name, "w,mode=-rw");
               if (!fp)
                 log_error (_("error creating `%s': %s\n"),
               fp = es_fopen (env_file_name, "w,mode=-rw");
               if (!fp)
                 log_error (_("error creating `%s': %s\n"),
@@ -1130,15 +1138,13 @@ main (int argc, char **argv )
                     {
                       es_fputs (infostr_ssh_sock, fp);
                       es_putc ('\n', fp);
                     {
                       es_fputs (infostr_ssh_sock, fp);
                       es_putc ('\n', fp);
-                      es_fputs (infostr_ssh_pid, fp);
-                      es_putc ('\n', fp);
                     }
                   es_fclose (fp);
                 }
             }
 
 
                     }
                   es_fclose (fp);
                 }
             }
 
 
-          if (argc) 
+          if (argc)
             { /* Run the program given on the commandline.  */
               if (putenv (infostr))
                 {
             { /* Run the program given on the commandline.  */
               if (putenv (infostr))
                 {
@@ -1154,13 +1160,6 @@ main (int argc, char **argv )
                   kill (pid, SIGTERM );
                   exit (1);
                 }
                   kill (pid, SIGTERM );
                   exit (1);
                 }
-              if (opt.ssh_support && putenv (infostr_ssh_pid))
-                {
-                  log_error ("failed to set environment: %s\n",
-                             strerror (errno) );
-                  kill (pid, SIGTERM );
-                  exit (1);
-                }
 
               /* Close all the file descriptors except the standard
                  ones and those open at startup.  We explicitly don't
 
               /* Close all the file descriptors except the standard
                  ones and those open at startup.  We explicitly don't
@@ -1186,8 +1185,6 @@ main (int argc, char **argv )
                    {
                      *strchr (infostr_ssh_sock, '=') = ' ';
                      es_printf ("setenv %s\n", infostr_ssh_sock);
                    {
                      *strchr (infostr_ssh_sock, '=') = ' ';
                      es_printf ("setenv %s\n", infostr_ssh_sock);
-                     *strchr (infostr_ssh_pid, '=') = ' ';
-                     es_printf ("setenv %s\n", infostr_ssh_pid);
                    }
                 }
               else
                    }
                 }
               else
@@ -1197,33 +1194,30 @@ main (int argc, char **argv )
                    {
                      es_printf ("%s; export SSH_AUTH_SOCK;\n",
                                  infostr_ssh_sock);
                    {
                      es_printf ("%s; export SSH_AUTH_SOCK;\n",
                                  infostr_ssh_sock);
-                     es_printf ("%s; export SSH_AGENT_PID;\n",
-                                 infostr_ssh_pid);
                    }
                 }
                    }
                 }
-              xfree (infostr); 
+              xfree (infostr);
              if (opt.ssh_support)
                {
                  xfree (infostr_ssh_sock);
              if (opt.ssh_support)
                {
                  xfree (infostr_ssh_sock);
-                 xfree (infostr_ssh_pid);
                }
                }
-              exit (0); 
+              exit (0);
             }
           /*NOTREACHED*/
         } /* End parent */
 
             }
           /*NOTREACHED*/
         } /* End parent */
 
-      /* 
+      /*
          This is the child
        */
 
       /* Detach from tty and put process into a new session */
       if (!nodetach )
          This is the child
        */
 
       /* Detach from tty and put process into a new session */
       if (!nodetach )
-        { 
+        {
           int i;
           unsigned int oldflags;
 
           /* Close stdin, stdout and stderr unless it is the log stream */
           int i;
           unsigned int oldflags;
 
           /* Close stdin, stdout and stderr unless it is the log stream */
-          for (i=0; i <= 2; i++) 
+          for (i=0; i <= 2; i++)
             {
               if (!log_test_fd (i) && i != fd )
                 {
             {
               if (!log_test_fd (i) && i != fd )
                 {
@@ -1257,7 +1251,7 @@ main (int argc, char **argv )
 
       {
         struct sigaction sa;
 
       {
         struct sigaction sa;
-        
+
         sa.sa_handler = SIG_IGN;
         sigemptyset (&sa.sa_mask);
         sa.sa_flags = 0;
         sa.sa_handler = SIG_IGN;
         sigemptyset (&sa.sa_mask);
         sa.sa_flags = 0;
@@ -1269,7 +1263,7 @@ main (int argc, char **argv )
       handle_connections (fd, opt.ssh_support ? fd_ssh : GNUPG_INVALID_FD);
       assuan_sock_close (fd);
     }
       handle_connections (fd, opt.ssh_support ? fd_ssh : GNUPG_INVALID_FD);
       assuan_sock_close (fd);
     }
-  
+
   return 0;
 }
 
   return 0;
 }
 
@@ -1311,16 +1305,17 @@ agent_init_default_ctrl (ctrl_t ctrl)
   session_env_setenv (ctrl->session_env, "TERM", default_ttytype);
   session_env_setenv (ctrl->session_env, "XAUTHORITY", default_xauthority);
   session_env_setenv (ctrl->session_env, "PINENTRY_USER_DATA", NULL);
   session_env_setenv (ctrl->session_env, "TERM", default_ttytype);
   session_env_setenv (ctrl->session_env, "XAUTHORITY", default_xauthority);
   session_env_setenv (ctrl->session_env, "PINENTRY_USER_DATA", NULL);
-  
+
   if (ctrl->lc_ctype)
     xfree (ctrl->lc_ctype);
   ctrl->lc_ctype = default_lc_ctype? xtrystrdup (default_lc_ctype) : NULL;
   if (ctrl->lc_ctype)
     xfree (ctrl->lc_ctype);
   ctrl->lc_ctype = default_lc_ctype? xtrystrdup (default_lc_ctype) : NULL;
-  
+
   if (ctrl->lc_messages)
     xfree (ctrl->lc_messages);
   ctrl->lc_messages = default_lc_messages? xtrystrdup (default_lc_messages)
                                     /**/ : NULL;
 
   if (ctrl->lc_messages)
     xfree (ctrl->lc_messages);
   ctrl->lc_messages = default_lc_messages? xtrystrdup (default_lc_messages)
                                     /**/ : NULL;
 
+  ctrl->cache_ttl_opt_preset = CACHE_TTL_OPT_PRESET;
 }
 
 
 }
 
 
@@ -1338,7 +1333,7 @@ agent_deinit_default_ctrl (ctrl_t ctrl)
 
 /* Reread parts of the configuration.  Note, that this function is
    obviously not thread-safe and should only be called from the PTH
 
 /* Reread parts of the configuration.  Note, that this function is
    obviously not thread-safe and should only be called from the PTH
-   signal handler. 
+   signal handler.
 
    Fixme: Due to the way the argument parsing works, we create a
    memory leak here for all string type arguments.  There is currently
 
    Fixme: Due to the way the argument parsing works, we create a
    memory leak here for all string type arguments.  There is currently
@@ -1428,7 +1423,7 @@ get_agent_scd_notify_event (void)
         log_error ("can't create scd notify event: %s\n", w32_strerror (-1) );
       else if (!DuplicateHandle (GetCurrentProcess(), h,
                                  GetCurrentProcess(), &h2,
         log_error ("can't create scd notify event: %s\n", w32_strerror (-1) );
       else if (!DuplicateHandle (GetCurrentProcess(), h,
                                  GetCurrentProcess(), &h2,
-                                 EVENT_MODIFY_STATE|SYNCHRONIZE, TRUE, 0)) 
+                                 EVENT_MODIFY_STATE|SYNCHRONIZE, TRUE, 0))
         {
           log_error ("setting syncronize for scd notify event failed: %s\n",
                      w32_strerror (-1) );
         {
           log_error ("setting syncronize for scd notify event failed: %s\n",
                      w32_strerror (-1) );
@@ -1441,7 +1436,6 @@ get_agent_scd_notify_event (void)
         }
     }
 
         }
     }
 
-  log_debug  ("returning notify handle %p\n", the_event);
   return the_event;
 }
 #endif /*HAVE_W32_SYSTEM && !HAVE_W32CE_SYSTEM*/
   return the_event;
 }
 #endif /*HAVE_W32_SYSTEM && !HAVE_W32CE_SYSTEM*/
@@ -1465,7 +1459,15 @@ create_socket_name (char *standard_name, char *template)
     name = make_filename (opt.homedir, standard_name, NULL);
   else
     {
     name = make_filename (opt.homedir, standard_name, NULL);
   else
     {
-      name = xstrdup (template);
+      /* Prepend the tmp directory to the template.  */
+      p = getenv ("TMPDIR");
+      if (!p || !*p)
+        p = "/tmp";
+      if (p[strlen (p) - 1] == '/')
+        name = xstrconcat (p, template, NULL);
+      else
+        name = xstrconcat (p, "/", template, NULL);
+
       p = strrchr (name, '/');
       if (!p)
        BUG ();
       p = strrchr (name, '/');
       if (!p)
        BUG ();
@@ -1513,7 +1515,7 @@ create_server_socket (char *name, int is_ssh, assuan_sock_nonce_t *nonce)
       agent_exit (2);
     }
 
       agent_exit (2);
     }
 
-  serv_addr = xmalloc (sizeof (*serv_addr)); 
+  serv_addr = xmalloc (sizeof (*serv_addr));
   memset (serv_addr, 0, sizeof *serv_addr);
   serv_addr->sun_family = AF_UNIX;
   if (strlen (name) + 1 >= sizeof (serv_addr->sun_path))
   memset (serv_addr, 0, sizeof *serv_addr);
   serv_addr->sun_family = AF_UNIX;
   if (strlen (name) + 1 >= sizeof (serv_addr->sun_path))
@@ -1527,7 +1529,7 @@ create_server_socket (char *name, int is_ssh, assuan_sock_nonce_t *nonce)
 
   /* Our error code mapping on W32CE returns EEXIST thus we also test
      for this. */
 
   /* Our error code mapping on W32CE returns EEXIST thus we also test
      for this. */
-  if (opt.use_standard_socket && rc == -1 
+  if (opt.use_standard_socket && rc == -1
       && (errno == EADDRINUSE
 #ifdef HAVE_W32_SYSTEM
           || errno == EEXIST
       && (errno == EADDRINUSE
 #ifdef HAVE_W32_SYSTEM
           || errno == EEXIST
@@ -1544,6 +1546,8 @@ create_server_socket (char *name, int is_ssh, assuan_sock_nonce_t *nonce)
          a hang.  */
       if (!is_ssh && !check_for_running_agent (1, 1))
         {
          a hang.  */
       if (!is_ssh && !check_for_running_agent (1, 1))
         {
+          log_set_prefix (NULL, JNLIB_LOG_WITH_PREFIX);
+          log_set_file (NULL);
           log_error (_("a gpg-agent is already running - "
                        "not starting a new one\n"));
           *name = 0; /* Inhibit removal of the socket by cleanup(). */
           log_error (_("a gpg-agent is already running - "
                        "not starting a new one\n"));
           *name = 0; /* Inhibit removal of the socket by cleanup(). */
@@ -1553,7 +1557,7 @@ create_server_socket (char *name, int is_ssh, assuan_sock_nonce_t *nonce)
       gnupg_remove (name);
       rc = assuan_sock_bind (fd, (struct sockaddr*) serv_addr, len);
     }
       gnupg_remove (name);
       rc = assuan_sock_bind (fd, (struct sockaddr*) serv_addr, len);
     }
-  if (rc != -1 
+  if (rc != -1
       && (rc=assuan_sock_get_nonce ((struct sockaddr*)serv_addr, len, nonce)))
     log_error (_("error getting nonce for the socket\n"));
   if (rc == -1)
       && (rc=assuan_sock_get_nonce ((struct sockaddr*)serv_addr, len, nonce)))
     log_error (_("error getting nonce for the socket\n"));
   if (rc == -1)
@@ -1561,9 +1565,9 @@ create_server_socket (char *name, int is_ssh, assuan_sock_nonce_t *nonce)
       /* We use gpg_strerror here because it allows us to get strings
          for some W32 socket error codes.  */
       log_error (_("error binding socket to `%s': %s\n"),
       /* We use gpg_strerror here because it allows us to get strings
          for some W32 socket error codes.  */
       log_error (_("error binding socket to `%s': %s\n"),
-                serv_addr->sun_path, 
+                serv_addr->sun_path,
                  gpg_strerror (gpg_error_from_errno (errno)));
                  gpg_strerror (gpg_error_from_errno (errno)));
-      
+
       assuan_sock_close (fd);
       if (opt.use_standard_socket)
         *name = 0; /* Inhibit removal of the socket by cleanup(). */
       assuan_sock_close (fd);
       if (opt.use_standard_socket)
         *name = 0; /* Inhibit removal of the socket by cleanup(). */
@@ -1576,7 +1580,7 @@ create_server_socket (char *name, int is_ssh, assuan_sock_nonce_t *nonce)
       assuan_sock_close (fd);
       agent_exit (2);
     }
       assuan_sock_close (fd);
       agent_exit (2);
     }
-          
+
   if (opt.verbose)
     log_info (_("listening on socket `%s'\n"), serv_addr->sun_path);
 
   if (opt.verbose)
     log_info (_("listening on socket `%s'\n"), serv_addr->sun_path);
 
@@ -1638,7 +1642,7 @@ create_directories (void)
               if (gnupg_mkdir (home, "-rwx"))
                 log_error (_("can't create directory `%s': %s\n"),
                            home, strerror (errno) );
               if (gnupg_mkdir (home, "-rwx"))
                 log_error (_("can't create directory `%s': %s\n"),
                            home, strerror (errno) );
-              else 
+              else
                 {
                   if (!opt.quiet)
                     log_info (_("directory `%s' created\n"), home);
                 {
                   if (!opt.quiet)
                     log_info (_("directory `%s' created\n"), home);
@@ -1690,13 +1694,15 @@ handle_tick (void)
         }
     }
 #endif /*HAVE_W32_SYSTEM*/
         }
     }
 #endif /*HAVE_W32_SYSTEM*/
-  
-  /* Code to be run every minute.  */
-  if (last_minute + 60 <= time (NULL))
+
+  /* Code to be run from time to time.  */
+#if CHECK_OWN_SOCKET_INTERVAL > 0
+  if (last_minute + CHECK_OWN_SOCKET_INTERVAL <= time (NULL))
     {
       check_own_socket ();
       last_minute = time (NULL);
     }
     {
       check_own_socket ();
       last_minute = time (NULL);
     }
+#endif
 
 }
 
 
 }
 
@@ -1733,7 +1739,7 @@ handle_signal (int signo)
     case SIGHUP:
       agent_sighup_action ();
       break;
     case SIGHUP:
       agent_sighup_action ();
       break;
-      
+
     case SIGUSR1:
       log_info ("SIGUSR1 received - printing internal information:\n");
       /* Fixme: We need to see how to integrate pth dumping into our
     case SIGUSR1:
       log_info ("SIGUSR1 received - printing internal information:\n");
       /* Fixme: We need to see how to integrate pth dumping into our
@@ -1742,7 +1748,7 @@ handle_signal (int signo)
       agent_query_dump_state ();
       agent_scd_dump_state ();
       break;
       agent_query_dump_state ();
       agent_scd_dump_state ();
       break;
-      
+
     case SIGUSR2:
       agent_sigusr2_action ();
       break;
     case SIGUSR2:
       agent_sigusr2_action ();
       break;
@@ -1762,7 +1768,7 @@ handle_signal (int signo)
           agent_exit (0);
        }
       break;
           agent_exit (0);
        }
       break;
-        
+
     case SIGINT:
       log_info ("SIGINT received - immediate shutdown\n");
       log_info( "%s %s stopped\n", strusage(11), strusage(13));
     case SIGINT:
       log_info ("SIGINT received - immediate shutdown\n");
       log_info( "%s %s stopped\n", strusage(11), strusage(13));
@@ -1778,12 +1784,12 @@ handle_signal (int signo)
 
 /* Check the nonce on a new connection.  This is a NOP unless we we
    are using our Unix domain socket emulation under Windows.  */
 
 /* Check the nonce on a new connection.  This is a NOP unless we we
    are using our Unix domain socket emulation under Windows.  */
-static int 
+static int
 check_nonce (ctrl_t ctrl, assuan_sock_nonce_t *nonce)
 {
   if (assuan_sock_check_nonce (ctrl->thread_startup.fd, nonce))
     {
 check_nonce (ctrl_t ctrl, assuan_sock_nonce_t *nonce)
 {
   if (assuan_sock_check_nonce (ctrl->thread_startup.fd, nonce))
     {
-      log_info (_("error reading nonce on fd %d: %s\n"), 
+      log_info (_("error reading nonce on fd %d: %s\n"),
                 FD2INT(ctrl->thread_startup.fd), strerror (errno));
       assuan_sock_close (ctrl->thread_startup.fd);
       xfree (ctrl);
                 FD2INT(ctrl->thread_startup.fd), strerror (errno));
       assuan_sock_close (ctrl->thread_startup.fd);
       xfree (ctrl);
@@ -1801,18 +1807,21 @@ start_connection_thread (void *arg)
   ctrl_t ctrl = arg;
 
   if (check_nonce (ctrl, &socket_nonce))
   ctrl_t ctrl = arg;
 
   if (check_nonce (ctrl, &socket_nonce))
-    return NULL;
+    {
+      log_error ("handler 0x%lx nonce check FAILED\n", pth_thread_id ());
+      return NULL;
+    }
 
   agent_init_default_ctrl (ctrl);
   if (opt.verbose)
 
   agent_init_default_ctrl (ctrl);
   if (opt.verbose)
-    log_info (_("handler 0x%lx for fd %d started\n"), 
+    log_info (_("handler 0x%lx for fd %d started\n"),
               pth_thread_id (), FD2INT(ctrl->thread_startup.fd));
 
   start_command_handler (ctrl, GNUPG_INVALID_FD, ctrl->thread_startup.fd);
   if (opt.verbose)
               pth_thread_id (), FD2INT(ctrl->thread_startup.fd));
 
   start_command_handler (ctrl, GNUPG_INVALID_FD, ctrl->thread_startup.fd);
   if (opt.verbose)
-    log_info (_("handler 0x%lx for fd %d terminated\n"), 
+    log_info (_("handler 0x%lx for fd %d terminated\n"),
               pth_thread_id (), FD2INT(ctrl->thread_startup.fd));
               pth_thread_id (), FD2INT(ctrl->thread_startup.fd));
-  
+
   agent_deinit_default_ctrl (ctrl);
   xfree (ctrl);
   return NULL;
   agent_deinit_default_ctrl (ctrl);
   xfree (ctrl);
   return NULL;
@@ -1837,7 +1846,7 @@ start_connection_thread_ssh (void *arg)
   if (opt.verbose)
     log_info (_("ssh handler 0x%lx for fd %d terminated\n"),
               pth_thread_id (), FD2INT(ctrl->thread_startup.fd));
   if (opt.verbose)
     log_info (_("ssh handler 0x%lx for fd %d terminated\n"),
               pth_thread_id (), FD2INT(ctrl->thread_startup.fd));
-  
+
   agent_deinit_default_ctrl (ctrl);
   xfree (ctrl);
   return NULL;
   agent_deinit_default_ctrl (ctrl);
   xfree (ctrl);
   return NULL;
@@ -1883,7 +1892,7 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
         sa.sa_handler = SIG_IGN;
         sa.sa_flags = 0;
         sigaction (mysigs[i], &sa, NULL);
         sa.sa_handler = SIG_IGN;
         sa.sa_flags = 0;
         sigaction (mysigs[i], &sa, NULL);
-        
+
         sigaddset (&sigs, mysigs[i]);
       }
   }
         sigaddset (&sigs, mysigs[i]);
       }
   }
@@ -1903,6 +1912,10 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
 #endif
   time_ev = NULL;
 
 #endif
   time_ev = NULL;
 
+  /* Set a flag to tell call-scd.c that it may enable event
+     notifications.  */
+  opt.sigusr2_enabled = 1;
+
   FD_ZERO (&fdset);
   FD_SET (FD2INT (listen_fd), &fdset);
   nfd = FD2INT (listen_fd);
   FD_ZERO (&fdset);
   FD_SET (FD2INT (listen_fd), &fdset);
   nfd = FD2INT (listen_fd);
@@ -1950,6 +1963,7 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
 
       if (time_ev)
         pth_event_concat (ev, time_ev, NULL);
 
       if (time_ev)
         pth_event_concat (ev, time_ev, NULL);
+
       ret = pth_select_ev (nfd+1, &read_fdset, NULL, NULL, NULL, ev);
       if (time_ev)
         pth_event_isolate (time_ev);
       ret = pth_select_ev (nfd+1, &read_fdset, NULL, NULL, NULL, ev);
       if (time_ev)
         pth_event_isolate (time_ev);
@@ -2027,7 +2041,7 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
               xfree (ctrl);
               assuan_sock_close (fd);
             }
               xfree (ctrl);
               assuan_sock_close (fd);
             }
-          else 
+          else
             {
               char threadname[50];
 
             {
               char threadname[50];
 
@@ -2047,7 +2061,7 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
           fd = GNUPG_INVALID_FD;
        }
 
           fd = GNUPG_INVALID_FD;
        }
 
-      if (!shutdown_pending && listen_fd_ssh != GNUPG_INVALID_FD 
+      if (!shutdown_pending && listen_fd_ssh != GNUPG_INVALID_FD
           && FD_ISSET ( FD2INT (listen_fd_ssh), &read_fdset))
        {
           ctrl_t ctrl;
           && FD_ISSET ( FD2INT (listen_fd_ssh), &read_fdset))
        {
           ctrl_t ctrl;
@@ -2140,7 +2154,7 @@ check_own_socket_thread (void *arg)
       log_error ("can't connect my own socket: %s\n", gpg_strerror (rc));
       goto leave;
     }
       log_error ("can't connect my own socket: %s\n", gpg_strerror (rc));
       goto leave;
     }
+
   init_membuf (&mb, 100);
   rc = assuan_transact (ctx, "GETINFO pid", check_own_socket_pid_cb, &mb,
                         NULL, NULL, NULL, NULL);
   init_membuf (&mb, 100);
   rc = assuan_transact (ctx, "GETINFO pid", check_own_socket_pid_cb, &mb,
                         NULL, NULL, NULL, NULL);
@@ -2148,7 +2162,7 @@ check_own_socket_thread (void *arg)
   buffer = get_membuf (&mb, NULL);
   if (rc || !buffer)
     {
   buffer = get_membuf (&mb, NULL);
   if (rc || !buffer)
     {
-      log_error ("sending command \"%s\" to my own socket failed: %s\n", 
+      log_error ("sending command \"%s\" to my own socket failed: %s\n",
                  "GETINFO pid", gpg_strerror (rc));
       rc = 1;
     }
                  "GETINFO pid", gpg_strerror (rc));
       rc = 1;
     }
@@ -2159,7 +2173,7 @@ check_own_socket_thread (void *arg)
     }
   else if (opt.verbose > 1)
     log_error ("socket is still served by this server\n");
     }
   else if (opt.verbose > 1)
     log_error ("socket is still served by this server\n");
-    
+
   xfree (buffer);
 
  leave:
   xfree (buffer);
 
  leave:
@@ -2184,7 +2198,7 @@ check_own_socket_thread (void *arg)
 
 /* Check whether we are still listening on our own socket.  In case
    another gpg-agent process started after us has taken ownership of
 
 /* Check whether we are still listening on our own socket.  In case
    another gpg-agent process started after us has taken ownership of
-   our socket, we woulf linger around without any real task.  Thus we
+   our socket, we would linger around without any real task.  Thus we
    better check once in a while whether we are really needed.  */
 static void
 check_own_socket (void)
    better check once in a while whether we are really needed.  */
 static void
 check_own_socket (void)
@@ -2294,3 +2308,12 @@ check_for_running_agent (int silent, int mode)
   assuan_release (ctx);
   return 0;
 }
   assuan_release (ctx);
   return 0;
 }
+
+/* TODO: it is also in misc, which is not linked with the agent */
+/* FIXME: The agent should not know about openpgp internals - weel
+   except for some stuff in cvt-openpgp.  */
+int
+map_pk_openpgp_to_gcry (int algo)
+{
+  return (algo==PUBKEY_ALGO_ECDSA ? GCRY_PK_ECDSA : (algo==PUBKEY_ALGO_ECDH ? GCRY_PK_ECDH : algo));
+}