common: Reduce buffer size.
[gnupg.git] / common / homedir.c
index 7939841..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
@@ -74,7 +75,7 @@ static int w32_portable_app;
 
 #ifdef HAVE_W32_SYSTEM
 /* This flag is true if this process' binary has been installed under
-   bin and not in the root directory. */
+   bin and not in the root directory as often used before GnuPG 2.1. */
 static int w32_bin_is_bin;
 #endif /*HAVE_W32_SYSTEM*/
 
@@ -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  */
@@ -288,21 +287,15 @@ w32_rootdir (void)
     {
       char *p;
       int rc;
+      wchar_t wdir [MAX_PATH+5];
 
-#ifdef HAVE_W32CE_SYSTEM
-      {
-        wchar_t wdir [MAX_PATH+5];
-        rc = GetModuleFileName (NULL, wdir, MAX_PATH);
-        if (rc && WideCharToMultiByte (CP_UTF8, 0, wdir, -1, dir, MAX_PATH-4,
-                                       NULL, NULL) < 0)
-          rc = 0;
-      }
-#else
-      rc = GetModuleFileName (NULL, dir, MAX_PATH);
-#endif
+      rc = GetModuleFileNameW (NULL, wdir, MAX_PATH);
+      if (rc && WideCharToMultiByte (CP_UTF8, 0, wdir, -1, dir, MAX_PATH-4,
+                                     NULL, NULL) < 0)
+        rc = 0;
       if (!rc)
         {
-          log_debug ("GetModuleFileName failed: %s\n", w32_strerror (0));
+          log_debug ("GetModuleFileName failed: %s\n", w32_strerror (-1));
           *dir = 0;
         }
       got_dir = 1;
@@ -613,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 *
@@ -636,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:
@@ -689,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);
+}