Add global flags disable-gpgconf, gpgconf-name, and gpg-name.

* 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.
This commit is contained in:
Werner Koch 2014-01-06 17:16:52 +01:00
parent 02ba35c1b6
commit 6564e5e78e
8 changed files with 268 additions and 30 deletions

View 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}.
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}.
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}.
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

View 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;
/* 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)

View File

@ -37,6 +37,7 @@
#include "wait.h"
#include "debug.h"
#include "priv-io.h"
#include "sys-util.h"
/* 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;
}

View File

@ -29,6 +29,46 @@
#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 */

View 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);

View 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);

View 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;
}

View File

@ -28,6 +28,12 @@
#include <gpgme.h>
#define PGM "t-engine-info"
static int verbose;
#define fail_if_err(err) \
do \
@ -42,13 +48,66 @@
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);