agent: Kludge to allow disabling of the extra sockets.
[gnupg.git] / agent / gpg-agent.c
index b60287d..d3f203b 100644 (file)
@@ -1,6 +1,6 @@
 /* gpg-agent.c  -  The GnuPG Agent
  * Copyright (C) 2000-2007, 2009-2010 Free Software Foundation, Inc.
- * Copyright (C) 2000-2014 Werner Koch
+ * Copyright (C) 2000-2016 Werner Koch
  *
  * This file is part of GnuPG.
  *
@@ -47,6 +47,9 @@
 #ifdef HAVE_SIGNAL_H
 # include <signal.h>
 #endif
+#ifdef HAVE_INOTIFY_INIT
+# include <sys/inotify.h>
+#endif /*HAVE_INOTIFY_INIT*/
 #include <npth.h>
 
 #define GNUPG_COMMON_NEED_AFLOCAL
@@ -58,7 +61,6 @@
 #include "gc-opt-flags.h"
 #include "exechelp.h"
 #include "asshelp.h"
-#include "openpgpdefs.h"  /* for PUBKEY_ALGO_ECDSA, PUBKEY_ALGO_ECDH */
 #include "../common/init.h"
 
 
@@ -93,6 +95,7 @@ enum cmd_and_opt_values
   oPinentryProgram,
   oPinentryTouchFile,
   oPinentryInvisibleChar,
+  oPinentryTimeout,
   oDisplay,
   oTTYname,
   oTTYtype,
@@ -121,6 +124,7 @@ enum cmd_and_opt_values
   oNoAllowMarkTrusted,
   oAllowPresetPassphrase,
   oAllowLoopbackPinentry,
+  oNoAllowLoopbackPinentry,
   oNoAllowExternalCache,
   oAllowEmacsPinentry,
   oKeepTTY,
@@ -168,6 +172,7 @@ static ARGPARSE_OPTS opts[] = {
                 /* */             N_("|PGM|use PGM as the PIN-Entry program")),
   ARGPARSE_s_s (oPinentryTouchFile, "pinentry-touch-file", "@"),
   ARGPARSE_s_s (oPinentryInvisibleChar, "pinentry-invisible-char", "@"),
+  ARGPARSE_s_u (oPinentryTimeout, "pinentry-timeout", "@"),
   ARGPARSE_s_s (oScdaemonProgram, "scdaemon-program",
                 /* */             N_("|PGM|use PGM as the SCdaemon program") ),
   ARGPARSE_s_n (oDisableScdaemon, "disable-scdaemon",
@@ -218,8 +223,9 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oAllowMarkTrusted,   "allow-mark-trusted", "@"),
   ARGPARSE_s_n (oAllowPresetPassphrase, "allow-preset-passphrase",
                 /* */                    N_("allow presetting passphrase")),
-  ARGPARSE_s_n (oAllowLoopbackPinentry, "allow-loopback-pinentry",
-                                   N_("allow caller to override the pinentry")),
+  ARGPARSE_s_n (oNoAllowLoopbackPinentry, "no-allow-loopback-pinentry",
+                                N_("disallow caller to override the pinentry")),
+  ARGPARSE_s_n (oAllowLoopbackPinentry, "allow-loopback-pinentry", "@"),
   ARGPARSE_s_n (oAllowEmacsPinentry,  "allow-emacs-pinentry",
                 /* */    N_("allow passphrase to be prompted through Emacs")),
 
@@ -370,6 +376,32 @@ static pid_t parent_pid = (pid_t)(-1);
 /* Number of active connections.  */
 static int active_connections;
 
+/* This object is used to dispatch progress messages from Libgcrypt to
+ * the right thread.  Given that we won't have at max a few dozen
+ * connections at the same time using a linked list is the easiest way
+ * to handle this. */
+struct progress_dispatch_s
+{
+  struct progress_dispatch_s *next;
+  /* The control object of the connection.  If this is NULL no
+   * connection is associated with this item and it is free for reuse
+   * by new connections.  */
+  ctrl_t ctrl;
+
+  /* The thread id of (npth_self) of the connection.  */
+  npth_t tid;
+
+  /* The callback set by the connection.  This is similar to the
+   * Libgcrypt callback but with the control object passed as the
+   * first argument.  */
+  void (*cb)(ctrl_t ctrl,
+             const char *what, int printchar,
+             int current, int total);
+};
+struct progress_dispatch_s *progress_dispatch_list;
+
+
+
 \f
 /*
    Local prototypes.
@@ -381,6 +413,9 @@ static gnupg_fd_t create_server_socket (char *name, int primary, int cygwin,
                                         assuan_sock_nonce_t *nonce);
 static void create_directories (void);
 
+static void agent_libgcrypt_progress_cb (void *data, const char *what,
+                                         int printchar,
+                                         int current, int total);
 static void agent_init_default_ctrl (ctrl_t ctrl);
 static void agent_deinit_default_ctrl (ctrl_t ctrl);
 
@@ -522,19 +557,10 @@ remove_socket (char *name, char *redir_name)
 {
   if (name && *name)
     {
-      char *p;
-
       if (redir_name)
         name = redir_name;
 
       gnupg_remove (name);
-      p = strrchr (name, '/');
-      if (p)
-       {
-         *p = 0;
-         rmdir (name);
-         *p = '/';
-       }
       *name = 0;
     }
 }
@@ -580,6 +606,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
       opt.pinentry_touch_file = NULL;
       xfree (opt.pinentry_invisible_char);
       opt.pinentry_invisible_char = NULL;
+      opt.pinentry_timeout = 0;
       opt.scdaemon_program = NULL;
       opt.def_cache_ttl = DEFAULT_CACHE_TTL;
       opt.def_cache_ttl_ssh = DEFAULT_CACHE_TTL_SSH;
@@ -594,6 +621,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
       opt.ignore_cache_for_signing = 0;
       opt.allow_mark_trusted = 1;
       opt.allow_external_cache = 1;
+      opt.allow_loopback_pinentry = 1;
       opt.allow_emacs_pinentry = 0;
       opt.disable_scdaemon = 0;
       disable_check_own_socket = 0;
@@ -632,6 +660,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
       xfree (opt.pinentry_invisible_char);
       opt.pinentry_invisible_char = xtrystrdup (pargs->r.ret_str); break;
       break;
+    case oPinentryTimeout: opt.pinentry_timeout = pargs->r.ret_ulong; break;
     case oScdaemonProgram: opt.scdaemon_program = pargs->r.ret_str; break;
     case oDisableScdaemon: opt.disable_scdaemon = 1; break;
     case oDisableCheckOwnSocket: disable_check_own_socket = 1; break;
@@ -666,6 +695,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
     case oAllowPresetPassphrase: opt.allow_preset_passphrase = 1; break;
 
     case oAllowLoopbackPinentry: opt.allow_loopback_pinentry = 1; break;
+    case oNoAllowLoopbackPinentry: opt.allow_loopback_pinentry = 0; break;
 
     case oNoAllowExternalCache: opt.allow_external_cache = 0;
       break;
@@ -737,14 +767,6 @@ main (int argc, char **argv )
 
   npth_init ();
 
-  /* Check that the libraries are suitable.  Do it here because
-     the option parsing may need services of the library. */
-  if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
-    {
-      log_fatal( _("%s is too old (need %s, have %s)\n"), "libgcrypt",
-                 NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
-    }
-
   malloc_hooks.malloc = gcry_malloc;
   malloc_hooks.realloc = gcry_realloc;
   malloc_hooks.free = gcry_free;
@@ -752,10 +774,11 @@ main (int argc, char **argv )
   assuan_set_gpg_err_source (GPG_ERR_SOURCE_DEFAULT);
   assuan_set_system_hooks (ASSUAN_SYSTEM_NPTH);
   assuan_sock_init ();
-  setup_libassuan_logging (&opt.debug);
+  setup_libassuan_logging (&opt.debug, NULL);
 
   setup_libgcrypt_logging ();
   gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
+  gcry_set_progress_handler (agent_libgcrypt_progress_cb, NULL);
 
   disable_core_dumps ();
 
@@ -766,8 +789,6 @@ main (int argc, char **argv )
   if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") )
     csh_style = 1;
 
-  opt.homedir = default_homedir ();
-
   /* Record some of the original environment strings. */
   {
     const char *s;
@@ -823,7 +844,7 @@ main (int argc, char **argv )
        else if (pargs.r_opt == oNoOptions)
           default_config = 0; /* --no-options */
        else if (pargs.r_opt == oHomedir)
-          opt.homedir = pargs.r.ret_str;
+          gnupg_set_homedir (pargs.r.ret_str);
        else if (pargs.r_opt == oDebugQuickRandom)
           {
             gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
@@ -840,8 +861,8 @@ main (int argc, char **argv )
   */
 
   if (default_config)
-    configname = make_filename (opt.homedir, GPG_AGENT_NAME EXTSEP_S "conf",
-                                NULL );
+    configname = make_filename (gnupg_homedir (),
+                                GPG_AGENT_NAME EXTSEP_S "conf", NULL);
 
   argc = orig_argc;
   argv = orig_argv;
@@ -906,7 +927,7 @@ main (int argc, char **argv )
         case oNoGreeting: /* Dummy option.  */ break;
         case oNoVerbose: opt.verbose = 0; break;
         case oNoOptions: break; /* no-options */
-        case oHomedir: opt.homedir = pargs.r.ret_str; break;
+        case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break;
         case oNoDetach: nodetach = 1; break;
         case oLogFile: logfile = pargs.r.ret_str; break;
         case oCsh: csh_style = 1; break;
@@ -991,9 +1012,6 @@ main (int argc, char **argv )
 
   finalize_rereadable_options ();
 
-  /* Turn the homedir into an absolute one. */
-  opt.homedir = make_absfilename (opt.homedir, NULL);
-
   /* Print a warning if an argument looks like an option.  */
   if (!opt.quiet && !(pargs.flags & ARGPARSE_FLAG_STOP_SEEN))
     {
@@ -1027,6 +1045,34 @@ main (int argc, char **argv )
       agent_exit (0);
     }
 
+  if (! opt.extra_socket)
+    {
+      opt.extra_socket = 1;  /* (1 = points into r/o section)  */
+      socket_name_extra = GPG_AGENT_EXTRA_SOCK_NAME;
+    }
+  else if (socket_name_extra
+           && (!strcmp (socket_name_extra, "none")
+               || !strcmp (socket_name_extra, "/dev/null")))
+    {
+      /* User requested not to create this socket.  */
+      opt.extra_socket = 0;
+      socket_name_extra = NULL;
+    }
+
+  if (! opt.browser_socket)
+    {
+      opt.browser_socket = 1;  /* (1 = points into r/o section)  */
+      socket_name_browser = GPG_AGENT_BROWSER_SOCK_NAME;
+    }
+  else if (socket_name_browser
+           && (!strcmp (socket_name_browser, "none")
+               || !strcmp (socket_name_browser, "/dev/null")))
+    {
+      /* User requested not to create this socket.  */
+      opt.browser_socket = 0;
+      socket_name_browser = NULL;
+    }
+
   set_debug ();
 
   if (atexit (cleanup))
@@ -1066,8 +1112,8 @@ main (int argc, char **argv )
       char *filename_esc;
 
       /* List options and default values in the GPG Conf format.  */
-      filename = make_filename (opt.homedir, GPG_AGENT_NAME EXTSEP_S "conf",
-                                NULL );
+      filename = make_filename (gnupg_homedir (),
+                                GPG_AGENT_NAME EXTSEP_S "conf", NULL);
       filename_esc = percent_escape (filename, NULL);
 
       es_printf ("%s-%s.conf:%lu:\"%s\n",
@@ -1120,10 +1166,12 @@ main (int argc, char **argv )
 #ifdef HAVE_W32_SYSTEM
       es_printf ("enable-putty-support:%lu:\n", GC_OPT_FLAG_NONE);
 #endif
-      es_printf ("allow-loopback-pinentry:%lu:\n",
-                 GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
+      es_printf ("no-allow-loopback-pinentry:%lu:\n",
+              GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
       es_printf ("allow-emacs-pinentry:%lu:\n",
                  GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
+      es_printf ("pinentry-timeout:%lu:0:\n",
+                 GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME);
 
       agent_exit (0);
     }
@@ -1221,13 +1269,10 @@ main (int argc, char **argv )
                                              &socket_nonce_browser);
         }
 
-      if (ssh_support)
-        {
-          socket_name_ssh = create_socket_name (GPG_AGENT_SSH_SOCK_NAME, 1);
-          fd_ssh = create_server_socket (socket_name_ssh, 0, 1,
-                                         &redir_socket_name_ssh,
-                                         &socket_nonce_ssh);
-        }
+      socket_name_ssh = create_socket_name (GPG_AGENT_SSH_SOCK_NAME, 1);
+      fd_ssh = create_server_socket (socket_name_ssh, 0, 1,
+                                     &redir_socket_name_ssh,
+                                     &socket_nonce_ssh);
 
       /* If we are going to exec a program in the parent, we record
          the PID, so that the child may check whether the program is
@@ -1293,8 +1338,7 @@ main (int argc, char **argv )
            *socket_name_extra = 0;
          if (opt.browser_socket)
            *socket_name_browser = 0;
-         if (ssh_support)
-           *socket_name_ssh = 0;
+          *socket_name_ssh = 0;
 
           if (argc)
             { /* Run the program given on the commandline.  */
@@ -1439,6 +1483,88 @@ agent_exit (int rc)
 }
 
 
+/* This is our callback function for gcrypt progress messages.  It is
+   set once at startup and dispatches progress messages to the
+   corresponding threads of the agent.  */
+static void
+agent_libgcrypt_progress_cb (void *data, const char *what, int printchar,
+                             int current, int total)
+{
+  struct progress_dispatch_s *dispatch;
+  npth_t mytid = npth_self ();
+
+  (void)data;
+
+  for (dispatch = progress_dispatch_list; dispatch; dispatch = dispatch->next)
+    if (dispatch->ctrl && dispatch->tid == mytid)
+      break;
+  if (dispatch && dispatch->cb)
+    dispatch->cb (dispatch->ctrl, what, printchar, current, total);
+}
+
+
+/* If a progress dispatcher callback has been associated with the
+ * current connection unregister it.  */
+static void
+unregister_progress_cb (void)
+{
+  struct progress_dispatch_s *dispatch;
+  npth_t mytid = npth_self ();
+
+  for (dispatch = progress_dispatch_list; dispatch; dispatch = dispatch->next)
+    if (dispatch->ctrl && dispatch->tid == mytid)
+      break;
+  if (dispatch)
+    {
+      dispatch->ctrl = NULL;
+      dispatch->cb = NULL;
+    }
+}
+
+
+/* Setup a progress callback CB for the current connection.  Using a
+ * CB of NULL disables the callback.  */
+void
+agent_set_progress_cb (void (*cb)(ctrl_t ctrl, const char *what,
+                                  int printchar, int current, int total),
+                       ctrl_t ctrl)
+{
+  struct progress_dispatch_s *dispatch, *firstfree;
+  npth_t mytid = npth_self ();
+
+  firstfree = NULL;
+  for (dispatch = progress_dispatch_list; dispatch; dispatch = dispatch->next)
+    {
+      if (dispatch->ctrl && dispatch->tid == mytid)
+        break;
+      if (!dispatch->ctrl && !firstfree)
+        firstfree = dispatch;
+    }
+  if (!dispatch) /* None allocated: Reuse or allocate a new one.  */
+    {
+      if (firstfree)
+        {
+          dispatch = firstfree;
+        }
+      else if ((dispatch = xtrycalloc (1, sizeof *dispatch)))
+        {
+          dispatch->next = progress_dispatch_list;
+          progress_dispatch_list = dispatch;
+        }
+      else
+        {
+          log_error ("error allocating new progress dispatcher slot: %s\n",
+                     gpg_strerror (gpg_error_from_syserror ()));
+          return;
+        }
+      dispatch->ctrl = ctrl;
+      dispatch->tid = mytid;
+    }
+
+  dispatch->cb = cb;
+}
+
+
 /* Each thread has its own local variables conveyed by a control
    structure usually identified by an argument named CTRL.  This
    function is called immediately after allocating the control
@@ -1475,6 +1601,7 @@ agent_init_default_ctrl (ctrl_t ctrl)
 static void
 agent_deinit_default_ctrl (ctrl_t ctrl)
 {
+  unregister_progress_cb ();
   session_env_release (ctrl->session_env);
 
   if (ctrl->lc_ctype)
@@ -1585,6 +1712,14 @@ get_agent_ssh_socket_name (void)
 }
 
 
+/* Return the number of active connections. */
+int
+get_agent_active_connection_count (void)
+{
+  return active_connections;
+}
+
+
 /* Under W32, this function returns the handle of the scdaemon
    notification event.  Calling it the first time creates that
    event.  */
@@ -1641,7 +1776,7 @@ create_socket_name (char *standard_name, int with_homedir)
   char *name;
 
   if (with_homedir)
-    name = make_filename (opt.homedir, standard_name, NULL);
+    name = make_filename (gnupg_socketdir (), standard_name, NULL);
   else
     name = make_filename (standard_name, NULL);
   if (strchr (name, PATHSEP_C))
@@ -1756,6 +1891,10 @@ create_server_socket (char *name, int primary, int cygwin,
       agent_exit (2);
     }
 
+  if (gnupg_chmod (unaddr->sun_path, "-rwx"))
+    log_error (_("can't set permissions of '%s': %s\n"),
+               unaddr->sun_path, strerror (errno));
+
   if (listen (FD2INT(fd), 5 ) == -1)
     {
       log_error (_("listen() failed: %s\n"), strerror (errno));
@@ -1789,9 +1928,13 @@ create_private_keys_directory (const char *home)
       else if (!opt.quiet)
         log_info (_("directory '%s' created\n"), fname);
     }
+  if (gnupg_chmod (fname, "-rwx"))
+    log_error (_("can't set permissions of '%s': %s\n"),
+               fname, strerror (errno));
   xfree (fname);
 }
 
+
 /* Create the directory only if the supplied directory name is the
    same as the default one.  This way we avoid to create arbitrary
    directories when a non-default home directory is used.  To cope
@@ -1805,7 +1948,7 @@ create_directories (void)
   const char *defhome = standard_homedir ();
   char *home;
 
-  home = make_filename (opt.homedir, NULL);
+  home = make_filename (gnupg_homedir (), NULL);
   if ( stat (home, &statbuf) )
     {
       if (errno == ENOENT)
@@ -2185,18 +2328,20 @@ putty_message_thread (void *arg)
 static void *
 do_start_connection_thread (ctrl_t ctrl)
 {
+  active_connections++;
   agent_init_default_ctrl (ctrl);
-  if (opt.verbose)
+  if (opt.verbose && !DBG_IPC)
     log_info (_("handler 0x%lx for fd %d started\n"),
               (unsigned long) npth_self(), FD2INT(ctrl->thread_startup.fd));
 
   start_command_handler (ctrl, GNUPG_INVALID_FD, ctrl->thread_startup.fd);
-  if (opt.verbose)
+  if (opt.verbose && !DBG_IPC)
     log_info (_("handler 0x%lx for fd %d terminated\n"),
               (unsigned long) npth_self(), FD2INT(ctrl->thread_startup.fd));
 
   agent_deinit_default_ctrl (ctrl);
   xfree (ctrl);
+  active_connections--;
   return NULL;
 }
 
@@ -2263,6 +2408,7 @@ start_connection_thread_ssh (void *arg)
   if (check_nonce (ctrl, &socket_nonce_ssh))
     return NULL;
 
+  active_connections++;
   agent_init_default_ctrl (ctrl);
   if (opt.verbose)
     log_info (_("ssh handler 0x%lx for fd %d started\n"),
@@ -2275,10 +2421,36 @@ start_connection_thread_ssh (void *arg)
 
   agent_deinit_default_ctrl (ctrl);
   xfree (ctrl);
+  active_connections--;
   return NULL;
 }
 
 
+#ifdef HAVE_INOTIFY_INIT
+/* Read an inotify event and return true if it matches NAME.  */
+static int
+my_inotify_is_name (int fd, const char *name)
+{
+  union {
+    struct inotify_event ev;
+    char _buf[sizeof (struct inotify_event) + 100 + 1];
+  } buf;
+  int n;
+
+  n = npth_read (fd, &buf, sizeof buf);
+  if (n < sizeof (struct inotify_event))
+    return 0;
+  if (buf.ev.len < strlen (name)+1)
+    return 0;
+  if (strcmp (buf.ev.name, name))
+    return 0; /* Not the desired file.  */
+
+  return 1; /* Found.  */
+}
+#endif /*HAVE_INOTIFY_INIT*/
+
+
+
 /* Connection handler loop.  Wait for connection requests and spawn a
    thread after accepting a connection.  */
 static void
@@ -2302,6 +2474,9 @@ handle_connections (gnupg_fd_t listen_fd,
   HANDLE events[2];
   unsigned int events_set;
 #endif
+#ifdef HAVE_INOTIFY_INIT
+  int my_inotify_fd;
+#endif /*HAVE_INOTIFY_INIT*/
   struct {
     const char *name;
     void *(*func) (void *arg);
@@ -2339,6 +2514,28 @@ handle_connections (gnupg_fd_t listen_fd,
 # endif
 #endif
 
+#ifdef HAVE_INOTIFY_INIT
+  if (disable_check_own_socket)
+    my_inotify_fd = -1;
+  else if ((my_inotify_fd = inotify_init ()) == -1)
+    log_info ("error enabling fast daemon termination: %s\n",
+              strerror (errno));
+  else
+    {
+      /* We need to watch the directory for the file because there
+       * won't be an IN_DELETE_SELF for a socket file.  */
+      char *slash = strrchr (socket_name, '/');
+      log_assert (slash && slash[1]);
+      *slash = 0;
+      if (inotify_add_watch (my_inotify_fd, socket_name, IN_DELETE) == -1)
+        {
+          close (my_inotify_fd);
+          my_inotify_fd = -1;
+        }
+      *slash = '/';
+    }
+#endif /*HAVE_INOTIFY_INIT*/
+
   /* On Windows we need to fire up a separate thread to listen for
      requests from Putty (an SSH client), so we can replace Putty's
      Pageant (its ssh-agent implementation). */
@@ -2380,6 +2577,14 @@ handle_connections (gnupg_fd_t listen_fd,
       if (FD2INT (listen_fd_ssh) > nfd)
         nfd = FD2INT (listen_fd_ssh);
     }
+#ifdef HAVE_INOTIFY_INIT
+  if (my_inotify_fd != -1)
+    {
+      FD_SET (my_inotify_fd, &fdset);
+      if (my_inotify_fd > nfd)
+        nfd = my_inotify_fd;
+    }
+#endif /*HAVE_INOTIFY_INIT*/
 
   listentbl[0].l_fd = listen_fd;
   listentbl[1].l_fd = listen_fd_extra;
@@ -2454,6 +2659,15 @@ handle_connections (gnupg_fd_t listen_fd,
           ctrl_t ctrl;
           npth_t thread;
 
+#ifdef HAVE_INOTIFY_INIT
+          if (my_inotify_fd != -1 && FD_ISSET (my_inotify_fd, &read_fdset)
+              && my_inotify_is_name (my_inotify_fd, GPG_AGENT_SOCK_NAME))
+            {
+              shutdown_pending = 1;
+              log_info ("socket file has been removed - shutting down\n");
+            }
+#endif /*HAVE_INOTIFY_INIT*/
+
           for (idx=0; idx < DIM(listentbl); idx++)
             {
               if (listentbl[idx].l_fd == GNUPG_INVALID_FD)
@@ -2500,6 +2714,10 @@ handle_connections (gnupg_fd_t listen_fd,
         }
     }
 
+#ifdef HAVE_INOTIFY_INIT
+  if (my_inotify_fd != -1)
+    close (my_inotify_fd);
+#endif /*HAVE_INOTIFY_INIT*/
   cleanup ();
   log_info (_("%s %s stopped\n"), strusage(11), strusage(13));
   npth_attr_destroy (&tattr);
@@ -2537,6 +2755,7 @@ check_own_socket_thread (void *arg)
       log_error ("can't allocate assuan context: %s\n", gpg_strerror (rc));
       goto leave;
     }
+  assuan_set_flag (ctx, ASSUAN_NO_LOGGING, 1);
 
   rc = assuan_socket_connect (ctx, sockname, (pid_t)(-1), 0);
   if (rc)
@@ -2604,7 +2823,7 @@ check_own_socket (void)
   if (check_own_socket_running || shutdown_pending)
     return;  /* Still running or already shutting down.  */
 
-  sockname = make_filename (opt.homedir, GPG_AGENT_SOCK_NAME, NULL);
+  sockname = make_filename_try (gnupg_socketdir (), GPG_AGENT_SOCK_NAME, NULL);
   if (!sockname)
     return; /* Out of memory.  */
 
@@ -2630,7 +2849,9 @@ check_for_running_agent (int silent)
   char *sockname;
   assuan_context_t ctx = NULL;
 
-  sockname = make_filename (opt.homedir, GPG_AGENT_SOCK_NAME, NULL);
+  sockname = make_filename_try (gnupg_socketdir (), GPG_AGENT_SOCK_NAME, NULL);
+  if (!sockname)
+    return gpg_error_from_syserror ();
 
   err = assuan_new (&ctx);
   if (!err)