common/iobuf.c: Improve iobuf_peek.
[gnupg.git] / common / homedir.c
index faf9787..3918693 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*/
 
@@ -221,7 +222,8 @@ default_homedir (void)
             {
               char *tmp;
 
-              tmp = read_w32_registry_string (NULL, "Software\\GNU\\GnuPG",
+              tmp = read_w32_registry_string (NULL,
+                                              GNUPG_REGISTRY_DIR,
                                               "HomeDir");
               if (tmp && !*tmp)
                 {
@@ -266,7 +268,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  */
@@ -287,21 +289,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;
@@ -554,9 +550,9 @@ gnupg_cachedir (void)
 }
 
 
-/* Return the default socket name used by DirMngr. */
+/* Return the system socket name used by DirMngr.  */
 const char *
-dirmngr_socket_name (void)
+dirmngr_sys_socket_name (void)
 {
 #ifdef HAVE_W32_SYSTEM
   static char *name;
@@ -585,7 +581,7 @@ dirmngr_socket_name (void)
           s1 = s1buf;
         }
 # endif
-      s2 = DIRSEP_S "S.dirmngr";
+      s2 = DIRSEP_S DIRMNGR_SOCK_NAME;
       name = xmalloc (strlen (s1) + strlen (s2) + 1);
       strcpy (stpcpy (name, s1), s2);
       for (p=name; *p; p++)
@@ -594,11 +590,83 @@ dirmngr_socket_name (void)
     }
   return name;
 #else /*!HAVE_W32_SYSTEM*/
-  return GNUPG_LOCALSTATEDIR "/run/" PACKAGE_NAME "/S.dirmngr";
+  return GNUPG_LOCALSTATEDIR "/run/" PACKAGE_NAME "/"DIRMNGR_SOCK_NAME;
 #endif /*!HAVE_W32_SYSTEM*/
 }
 
 
+/* Return the user socket name used by DirMngr.  If a user specific
+   dirmngr installation is not supported, NULL is returned.  */
+const char *
+dirmngr_user_socket_name (void)
+{
+  static char *name;
+
+  if (!name)
+    name = make_absfilename (default_homedir (), DIRMNGR_SOCK_NAME, NULL);
+  return name;
+}
+
+
+/* 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.  */
@@ -623,9 +691,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:
@@ -639,7 +707,7 @@ gnupg_module_name (int which)
 #ifdef GNUPG_DEFAULT_DIRMNGR
       return GNUPG_DEFAULT_DIRMNGR;
 #else
-      X(bindir, "dirmngr");
+      X(bindir, DIRMNGR_NAME);
 #endif
 
     case GNUPG_MODULE_NAME_PROTECT_TOOL:
@@ -676,3 +744,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);
+}