Add global flags disable-gpgconf, gpgconf-name, and gpg-name.
authorWerner Koch <wk@gnupg.org>
Mon, 6 Jan 2014 16:16:52 +0000 (17:16 +0100)
committerWerner Koch <wk@gnupg.org>
Mon, 6 Jan 2014 16:16:52 +0000 (17:16 +0100)
* src/gpgme.c (gpgme_set_global_flag): Add names "disable-gpgconf",
"gpgconf-name", and "gpg-name".
* src/dirinfo.c (_gpgme_dirinfo_disable_gpgconf): New.
(get_gpgconf_item): Minor debug info change.
* src/posix-util.c (default_gpg_name, default_gpgconf_name): Add vars.
(_gpgme_set_default_gpg_name): New.
(_gpgme_set_default_gpgconf_name): New.
(_gpgme_get_gpg_path, _gpgme_get_gpgconf_path): Use new vars.
(walk_path): Add debug output on failure.
* src/w32-util.c (default_gpg_name, default_gpgconf_name): Add vars.
(replace_slashes): New.
(get_basename): New.
(_gpgme_set_default_gpg_name): New.
(_gpgme_set_default_gpgconf_name): New.
(_gpgme_get_gpg_path, _gpgme_get_gpgconf_path): Use new vars.

* tests/t-engine-info.c (main): Add --verbose and --set-global-flag
options.
--

Note that the Windows part has not been tested.

doc/gpgme.texi
src/dirinfo.c
src/gpgme.c
src/posix-util.c
src/sys-util.h
src/util.h
src/w32-util.c
tests/t-engine-info.c

index 18b3c94..3f31492 100644 (file)
@@ -1,5 +1,5 @@
-\input texinfo                   @c -*- mode: texinfo; coding: latin-1; -*-
-@documentencoding ISO-8859-1
+\input texinfo                   @c -*- mode: texinfo; coding: utf-8; -*-
+@documentencoding UTF-8
 @setfilename gpgme.info
 @settitle The `GnuPG Made Easy' Reference Manual
 
@@ -14,7 +14,7 @@
 
 @copying
 Copyright @copyright{} 2002, 2003, 2004, 2005, 2006, 2007,
-2008, 2010, 2012, 2013 g10 Code GmbH.
+2008, 2010, 2012, 2013, 2014 g10 Code GmbH.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
@@ -72,7 +72,7 @@ This is Edition @value{EDITION}, last updated @value{UPDATED}, of
 @center for version @value{VERSION}
 @page
 @vskip 0pt plus 1filll
-Published by g10 Code GmbH@* Hüttenstr. 61@* 40699 Erkrath, Germany
+Published by g10 Code GmbH@* Hüttenstr. 61@* 40699 Erkrath, Germany
 
 @insertcopying
 @end titlepage
@@ -648,14 +648,39 @@ does not return a detailed error code).
 On some systems it is not easy to set environment variables and thus
 hard to use @acronym{GPGME}'s internal trace facility for debugging.
 This function has been introduced as an alternative way to enable
-debugging.  It is important to assure that only one thread accesses
-@acronym{GPGME} functions between a call to this function and after
-the return from the call to @code{gpgme_check_version}.
-
-To enable debugging, you need to call this function as early as
-possible --- even before @code{gpgme_check_version} --- with the
-string ``debug'' for @var{name} and @var{value} identical to the value
-used with the environment variable @code{GPGME_DEBUG}.
+debugging and for a couple of other rarely used tweaks.  It is
+important to assure that only one thread accesses @acronym{GPGME}
+functions between a call to this function and after the return from
+the call to @code{gpgme_check_version}.
+
+All currently supported features require that this function is called
+as early as possible --- even before @code{gpgme_check_version}.  The
+features are identified by the following values for @var{name}:
+
+@table @code
+@item "debug"
+To enable debugging use the string ``debug'' for @var{name} and
+@var{value} identical to the value used with the environment variable
+@code{GPGME_DEBUG}.
+
+@item "disable-gpgconf"
+Using this feature with any @var{value} disables the detection of the
+gpgconf program and thus forces GPGME to fallback into the simple
+OpenPGP only mode.  It may be used to force the use of GnuPG-1 on
+systems which have both GPG versions installed.  Note that in general
+the use of @code{gpgme_set_engine_info} is a better way to select a
+specific engine version.
+
+@item "gpgconf-name"
+@itemx "gpg-name"
+Set the name of the gpgconf respective gpg binary.  The defaults are
+@code{GNU/GnuPG/gpgconf} and @code{GNU/GnuPG/gpg}.  Under Unix the
+leading directory part is ignored.  Under Windows the leading
+directory part is used as the default installation directory; the
+@code{.exe} suffix is added by GPGME.  Use forward slashed even under
+Windows.
+
+@end table
 
 This function returns @code{0} on success.  In contrast to other
 functions the non-zero return value on failure does not convey any
index 2e387fa..eb29c6b 100644 (file)
@@ -48,6 +48,7 @@ enum
 /* Values retrieved via gpgconf and cached here.  */
 static struct {
   int  valid;         /* Cached information is valid.  */
+  int  disable_gpgconf;
   char *homedir;
   char *agent_socket;
   char *gpgconf_name;
@@ -58,6 +59,15 @@ static struct {
 } dirinfo;
 
 
+\f
+/* Helper function to be used only by gpgme_set_global_flag.  */
+void
+_gpgme_dirinfo_disable_gpgconf (void)
+{
+  dirinfo.disable_gpgconf = 1;
+}
+
+
 /* Parse the output of "gpgconf --list-dirs".  This function expects
    that DIRINFO_LOCK is held by the caller.  If COMPONENTS is set, the
    output of --list-components is expected. */
@@ -198,16 +208,16 @@ get_gpgconf_item (int what)
     {
       char *pgmname;
 
-      pgmname = _gpgme_get_gpgconf_path ();
+      pgmname = dirinfo.disable_gpgconf? NULL : _gpgme_get_gpgconf_path ();
       if (pgmname && access (pgmname, F_OK))
         {
           _gpgme_debug (DEBUG_INIT,
-                        "gpgme_dinfo: gpgconf='%s' [not installed]\n", pgmname);
+                        "gpgme-dinfo: gpgconf='%s' [not installed]\n", pgmname);
           free (pgmname);
           pgmname = NULL; /* Not available.  */
         }
       else
-        _gpgme_debug (DEBUG_INIT, "gpgme_dinfo: gpgconf='%s'\n",
+        _gpgme_debug (DEBUG_INIT, "gpgme-dinfo: gpgconf='%s'\n",
                       pgmname? pgmname : "[null]");
       if (!pgmname)
         {
@@ -231,22 +241,22 @@ get_gpgconf_item (int what)
          allocated.  */
       dirinfo.valid = 1;
       if (dirinfo.gpg_name)
-        _gpgme_debug (DEBUG_INIT, "gpgme_dinfo:     gpg='%s'\n",
+        _gpgme_debug (DEBUG_INIT, "gpgme-dinfo:     gpg='%s'\n",
                       dirinfo.gpg_name);
       if (dirinfo.g13_name)
-        _gpgme_debug (DEBUG_INIT, "gpgme_dinfo:     g13='%s'\n",
+        _gpgme_debug (DEBUG_INIT, "gpgme-dinfo:     g13='%s'\n",
                       dirinfo.g13_name);
       if (dirinfo.gpgsm_name)
-        _gpgme_debug (DEBUG_INIT, "gpgme_dinfo:   gpgsm='%s'\n",
+        _gpgme_debug (DEBUG_INIT, "gpgme-dinfo:   gpgsm='%s'\n",
                       dirinfo.gpgsm_name);
       if (dirinfo.homedir)
-        _gpgme_debug (DEBUG_INIT, "gpgme_dinfo: homedir='%s'\n",
+        _gpgme_debug (DEBUG_INIT, "gpgme-dinfo: homedir='%s'\n",
                       dirinfo.homedir);
       if (dirinfo.agent_socket)
-        _gpgme_debug (DEBUG_INIT, "gpgme_dinfo:   agent='%s'\n",
+        _gpgme_debug (DEBUG_INIT, "gpgme-dinfo:   agent='%s'\n",
                       dirinfo.agent_socket);
       if (dirinfo.uisrv_socket)
-        _gpgme_debug (DEBUG_INIT, "gpgme_dinfo:   uisrv='%s'\n",
+        _gpgme_debug (DEBUG_INIT, "gpgme-dinfo:   uisrv='%s'\n",
                       dirinfo.uisrv_socket);
     }
   switch (what)
index a8de64b..4a8afa9 100644 (file)
@@ -37,6 +37,7 @@
 #include "wait.h"
 #include "debug.h"
 #include "priv-io.h"
+#include "sys-util.h"
 
 \f
 /* The default locale.  */
@@ -65,6 +66,15 @@ gpgme_set_global_flag (const char *name, const char *value)
     return -1;
   else if (!strcmp (name, "debug"))
     return _gpgme_debug_set_debug_envvar (value);
+  else if (!strcmp (name, "disable-gpgconf"))
+    {
+      _gpgme_dirinfo_disable_gpgconf ();
+      return 0;
+    }
+  else if (!strcmp (name, "gpgconf-name"))
+    return _gpgme_set_default_gpgconf_name (value);
+  else if (!strcmp (name, "gpg-name"))
+    return _gpgme_set_default_gpg_name (value);
   else
     return -1;
 }
index d4e4e3f..5bfc486 100644 (file)
 
 #include "util.h"
 #include "sys-util.h"
+#include "debug.h"
+
+/* These variables store the malloced name of alternative default
+   binaries.  The are set only once by gpgme_set_global_flag.  */
+static char *default_gpg_name;
+static char *default_gpgconf_name;
+
+/* Set the default name for the gpg binary.  This function may only be
+   called by gpgme_set_global_flag.  Returns 0 on success.  Leading
+   directories are removed from NAME.  */
+int
+_gpgme_set_default_gpg_name (const char *name)
+{
+  const char *s;
+
+  s = strrchr (name, '/');
+  if (s)
+    name = s + 1;
+
+  if (!default_gpg_name)
+    default_gpg_name = strdup (name);
+  return !default_gpg_name;
+}
+
+/* Set the default name for the gpgconf binary.  This function may
+   only be called by gpgme_set_global_flag.  Returns 0 on success.
+   Leading directories are removed from NAME.  */
+int
+_gpgme_set_default_gpgconf_name (const char *name)
+{
+  const char *s;
+
+  s = strrchr (name, '/');
+  if (s)
+    name = s + 1;
+
+  if (!default_gpgconf_name)
+    default_gpgconf_name = strdup (name);
+  return !default_gpgconf_name;
+}
 
 
 /* Find an executable program PGM along the envvar PATH.  */
@@ -60,6 +100,9 @@ walk_path (const char *pgm)
       path = s + 1;
     }
 
+  _gpgme_debug (DEBUG_ENGINE, "gpgme-walk_path: '%s' not found in '%s'",
+                pgm, path);
+
   free (fname);
   return NULL;
 }
@@ -72,7 +115,7 @@ walk_path (const char *pgm)
 char *
 _gpgme_get_gpg_path (void)
 {
-  return walk_path ("gpg");
+  return walk_path (default_gpg_name? default_gpg_name : "gpg");
 }
 
 
@@ -81,7 +124,7 @@ _gpgme_get_gpg_path (void)
 char *
 _gpgme_get_gpgconf_path (void)
 {
-  return walk_path ("gpgconf");
+  return walk_path (default_gpgconf_name? default_gpgconf_name : "gpgconf");
 }
 
 /* See w32-util.c */
index 3686f89..7180fca 100644 (file)
@@ -21,6 +21,9 @@
 #define SYS_UTIL_H
 
 /*-- {posix,w32}-util.c --*/
+int _gpgme_set_default_gpg_name (const char *name);
+int _gpgme_set_default_gpgconf_name (const char *name);
+
 char *_gpgme_get_gpg_path (void);
 char *_gpgme_get_gpgconf_path (void);
 
index 57c8b13..c0934e1 100644 (file)
@@ -51,6 +51,8 @@ int _gpgme_get_conf_int (const char *key, int *value);
 void _gpgme_allow_set_foreground_window (pid_t pid);
 
 /*-- dirinfo.c --*/
+void _gpgme_dirinfo_disable_gpgconf (void);
+
 const char *_gpgme_get_default_homedir (void);
 const char *_gpgme_get_default_agent_socket (void);
 const char *_gpgme_get_default_gpg_name (void);
index 31a58bb..3884b40 100644 (file)
@@ -81,6 +81,11 @@ DEFINE_STATIC_LOCK (get_path_lock);
    file name of the DLL or executable which contains the gpgme code.  */
 static HMODULE my_hmodule;
 
+/* These variables store the malloced name of alternative default
+   binaries.  The are set only once by gpgme_set_global_flag.  */
+static char *default_gpg_name;
+static char *default_gpgconf_name;
+
 
 #ifdef HAVE_ALLOW_SET_FOREGROUND_WINDOW
 
@@ -151,6 +156,32 @@ wchar_to_utf8 (const wchar_t *string)
 }
 
 
+/* Replace all forward slashes by backslashes.  */
+static void
+replace_slashes (char *string)
+{
+  for (; *string; string++)
+    if (*string == '/')
+      *string = '\\';
+}
+
+
+/* Get the base name of NAME.  Returns a pointer into NAME right after
+   the last slash or backslash or to NAME if no slash or backslash
+   exists.  */
+static const char *
+get_basename (const char *name)
+{
+  const char *mark, *s;
+
+  for (mark=NULL, s=name; *s; s++)
+    if (*s == '/' || *s == '\\')
+      mark = s;
+
+  return mark? mark+1 : name;
+}
+
+
 void
 _gpgme_allow_set_foreground_window (pid_t pid)
 {
@@ -373,7 +404,7 @@ find_program_in_inst_dir (const char *inst_dir, const char *name)
   char *dir;
 
   /* If an installation directory has been passed, this overrides a
-     location given bu the registry.  The idea here is that we prefer
+     location given by the registry.  The idea here is that we prefer
      a program installed alongside with gpgme.  We don't want the
      registry to override this to have a better isolation of an gpgme
      aware applications for other effects.  Note that the "Install
@@ -424,6 +455,41 @@ find_program_at_standard_place (const char *name)
 }
 
 
+/* Set the default name for the gpg binary.  This function may only be
+   called by gpgme_set_global_flag.  Returns 0 on success.  */
+int
+_gpgme_set_default_gpg_name (const char *name)
+{
+  if (!default_gpg_name)
+    {
+      default_gpg_name = malloc (strlen (name) + 5);
+      if (default_gpg_name)
+        {
+          strcpy (stpcpy (default_gpg_name, name), ".exe");
+          replace_slashes (default_gpg_name);
+        }
+    }
+  return !default_gpg_name;
+}
+
+/* Set the default name for the gpgconf binary.  This function may only be
+   called by gpgme_set_global_flag.  Returns 0 on success.  */
+int
+_gpgme_set_default_gpgconf_name (const char *name)
+{
+  if (!default_gpgconf_name)
+    {
+      default_gpgconf_name = malloc (strlen (name) + 5);
+      if (default_gpgconf_name)
+        {
+          strcpy (stpcpy (default_gpgconf_name, name), ".exe");
+          replace_slashes (default_gpgconf_name);
+        }
+    }
+  return !default_gpgconf_name;
+}
+
+
 /* Return the full file name of the GPG binary.  This function is used
    if gpgconf was not found and thus it can be assumed that gpg2 is
    not installed.  This function is only called by get_gpgconf_item
@@ -432,27 +498,47 @@ char *
 _gpgme_get_gpg_path (void)
 {
   char *gpg;
-  const char *inst_dir;
+  const char *inst_dir, *name;
 
   inst_dir = _gpgme_get_inst_dir ();
-  gpg = find_program_in_inst_dir (inst_dir, "gpg.exe");
+  gpg = find_program_in_inst_dir
+    (inst_dir,
+     default_gpg_name? get_basename (default_gpg_name) : "gpg.exe");
   if (!gpg)
-    gpg = find_program_at_standard_place ("GNU\\GnuPG\\gpg.exe");
+    {
+      name = (default_gpg_name? default_gpg_name
+              /* */           : "GNU\\GnuPG\\gpg.exe");
+      gpg = find_program_at_standard_place (name);
+      if (!gpg)
+        _gpgme_debug (DEBUG_ENGINE, "_gpgme_get_gpg_path: '%s' not found",
+                      name);
+    }
+
   return gpg;
 }
 
+
 /* This function is only called by get_gpgconf_item and may not be
    called concurrently.  */
 char *
 _gpgme_get_gpgconf_path (void)
 {
   char *gpgconf;
-  const char *inst_dir;
+  const char *inst_dir, *name;
 
   inst_dir = _gpgme_get_inst_dir ();
-  gpgconf = find_program_in_inst_dir (inst_dir, "gpgconf.exe");
+  gpgconf = find_program_in_inst_dir
+    (inst_dir,
+     default_gpgconf_name? get_basename (default_gpgconf_name) : "gpgconf.exe");
   if (!gpgconf)
-    gpgconf = find_program_at_standard_place ("GNU\\GnuPG\\gpgconf.exe");
+    {
+      name = (default_gpgconf_name? default_gpgconf_name
+              /* */               : "GNU\\GnuPG\\gpgconf.exe");
+      gpgconf = find_program_at_standard_place (name);
+      if (!gpgconf)
+        _gpgme_debug (DEBUG_ENGINE, "_gpgme_get_gpgconf_path: '%s' not found",
+                      name);
+    }
   return gpgconf;
 }
 
index 43acd3d..11fe4a4 100644 (file)
 
 #include <gpgme.h>
 
+#define PGM "t-engine-info"
+
+static int verbose;
+
+
+
 \f
 #define fail_if_err(err)                                       \
   do                                                           \
   while (0)
 
 
-
 int
 main (int argc, char **argv )
 {
+  int last_argc = -1;
   gpgme_engine_info_t info;
   gpgme_error_t err;
 
+  if (argc)
+    { argc--; argv++; }
+
+  while (argc && last_argc != argc )
+    {
+      last_argc = argc;
+      if (!strcmp (*argv, "--"))
+        {
+          argc--; argv++;
+          break;
+        }
+      else if (!strcmp (*argv, "--help"))
+        {
+          fputs ("usage: " PGM " [options]\n"
+                 "Options:\n"
+                 "  --set-global-flag KEY VALUE\n",
+                 stdout);
+          exit (0);
+        }
+      else if (!strcmp (*argv, "--verbose"))
+        {
+          verbose++;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--set-global-flag"))
+        {
+          argc--; argv++;
+          if (argc < 2)
+            {
+              fprintf (stderr, PGM ": not enough arguments for option\n");
+              exit (1);
+            }
+          if (gpgme_set_global_flag (argv[0], argv[1]))
+            {
+              fprintf (stderr, PGM ": gpgme_set_global_flag failed\n");
+              exit (1);
+            }
+          argc--; argv++;
+          argc--; argv++;
+        }
+      else if (!strncmp (*argv, "--", 2))
+        {
+          fprintf (stderr, PGM ": unknown option '%s'\n", *argv);
+          exit (1);
+        }
+    }
+
+  if (argc)
+    {
+      fprintf (stderr, PGM ": unexpected arguments\n");
+      exit (1);
+    }
+
   gpgme_check_version (NULL);
   err = gpgme_get_engine_info (&info);
   fail_if_err (err);