common: Reduce buffer size.
[gnupg.git] / common / homedir.c
index 27141eb..e0a88fa 100644 (file)
@@ -32,6 +32,7 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <unistd.h>
 
 #ifdef HAVE_W32_SYSTEM
 #include <winsock2.h>   /* Due to the stupid mingw64 requirement to
@@ -255,9 +256,7 @@ check_portable_app (const char *dir)
   char *fname;
 
   fname = xstrconcat (dir, DIRSEP_S "gpgconf.exe", NULL);
-  if (access (fname, F_OK))
-    log_error ("required binary '%s' is not installed\n", fname);
-  else
+  if (!access (fname, F_OK))
     {
       strcpy (fname + strlen (fname) - 3, "ctl");
       if (!access (fname, F_OK))
@@ -267,7 +266,7 @@ check_portable_app (const char *dir)
           {
             unsigned int flags;
             log_get_prefix (&flags);
-            log_set_prefix (NULL, (flags | JNLIB_LOG_NO_REGISTRY));
+            log_set_prefix (NULL, (flags | GPGRT_LOG_NO_REGISTRY));
           }
           /* FIXME: We should read the file to detect special flags
              and print a warning if we don't understand them  */
@@ -607,6 +606,66 @@ dirmngr_user_socket_name (void)
 }
 
 
+/* Return the default pinentry name.  If RESET is true the internal
+   cache is first flushed.  */
+static const char *
+get_default_pinentry_name (int reset)
+{
+  static struct {
+    const char *(*rfnc)(void);
+    const char *name;
+  } names[] = {
+    /* The first entry is what we return in case we found no
+       other pinentry.  */
+    { gnupg_bindir, DIRSEP_S "pinentry" EXEEXT_S },
+#ifdef HAVE_W32_SYSTEM
+    /* Try Gpg4win directory (with bin and without.) */
+    { w32_rootdir, "\\..\\Gpg4win\\bin\\pinentry.exe" },
+    { w32_rootdir, "\\..\\Gpg4win\\pinentry.exe" },
+    /* Try old Gpgwin directory.  */
+    { w32_rootdir, "\\..\\GNU\\GnuPG\\pinentry.exe" },
+    /* Try a Pinentry from the common GNU dir.  */
+    { w32_rootdir, "\\..\\GNU\\bin\\pinentry.exe" },
+#endif
+    /* Last chance is a pinentry-basic (which comes with the
+       GnuPG 2.1 Windows installer).  */
+    { gnupg_bindir, DIRSEP_S "pinentry-basic" EXEEXT_S }
+  };
+  static char *name;
+
+  if (reset)
+    {
+      xfree (name);
+      name = NULL;
+    }
+
+  if (!name)
+    {
+      int i;
+
+      for (i=0; i < DIM(names); i++)
+        {
+          char *name2;
+
+          name2 = xstrconcat (names[i].rfnc (), names[i].name, NULL);
+          if (!access (name2, F_OK))
+            {
+              /* Use that pinentry.  */
+              xfree (name);
+              name = name2;
+              break;
+            }
+          if (!i) /* Store the first as fallback return.  */
+            name = name2;
+          else
+            xfree (name2);
+        }
+    }
+
+  return name;
+}
+
+
 /* Return the file name of a helper tool.  WHICH is one of the
    GNUPG_MODULE_NAME_foo constants.  */
 const char *
@@ -630,9 +689,9 @@ gnupg_module_name (int which)
 
     case GNUPG_MODULE_NAME_PINENTRY:
 #ifdef GNUPG_DEFAULT_PINENTRY
-      return GNUPG_DEFAULT_PINENTRY;
+      return GNUPG_DEFAULT_PINENTRY;  /* (Set by a configure option) */
 #else
-      X(bindir, "pinentry");
+      return get_default_pinentry_name (0);
 #endif
 
     case GNUPG_MODULE_NAME_SCDAEMON:
@@ -683,3 +742,12 @@ gnupg_module_name (int which)
     }
 #undef X
 }
+
+
+/* Flush some of the cached module names.  This is for example used by
+   gpg-agent to allow configuring a different pinentry.  */
+void
+gnupg_module_name_flush_some (void)
+{
+  (void)get_default_pinentry_name (1);
+}