2003-01-30  Marcus Brinkmann  <marcus@g10code.de>

	* gpgme.texi (Engine Information): Rename member part to
	file_name.

gpgme/
2003-01-30  Marcus Brinkmann  <marcus@g10code.de>

	* engine-backend.h (struct engine_ops): Rename get_path to
	get_file_name.
	* gpgme.h (struct _gpgme_engine_info): Rename member path to
	file_name.
	* version.c: Do not include <stdio.h>, <stdlib.h>, context.h and
	util.h.  Other clean ups.
	(parse_version_number): Protect more seriously against
	overflow.
	(gpgme_get_engine_info): Move to ...
	* engine.c (gpgme_get_engine_info): ... here.
	(_gpgme_engine_get_info): Function removed.
	(_gpgme_engine_get_path): Make static and rename to ...
	(engine_get_file_name): .. this.
	(_gpgme_engine_get_version): Make static and rename to ...
	(engine_get_version): ... this.
	(_gpgme_engine_get_req_version): Make static and rename to ...
	(engine_get_req_version): ... this.
	* engine.h (_gpgme_engine_get_path, _gpgme_engine_get_version,
	_gpgme_engine_req_version, _gpgme_engine_get_info.): Remove
	prototypes.

tests/
2003-01-30  Marcus Brinkmann  <marcus@g10code.de>

	* t-engine-info.c: Use file_name instead path throughout.
This commit is contained in:
Marcus Brinkmann 2003-01-30 13:11:25 +00:00
parent feb78b25ec
commit d102681aef
10 changed files with 165 additions and 169 deletions

View File

@ -1,5 +1,8 @@
2003-01-30 Marcus Brinkmann <marcus@g10code.de> 2003-01-30 Marcus Brinkmann <marcus@g10code.de>
* gpgme.texi (Engine Information): Rename member part to
file_name.
* gpgme.texi (Protocols and Engines): Document * gpgme.texi (Protocols and Engines): Document
gpgme_get_protocol_name. gpgme_get_protocol_name.

View File

@ -632,8 +632,8 @@ This is the protocol for which the crypo engine is used. You can
convert this to a string with @code{gpgme_get_protocol_name} for convert this to a string with @code{gpgme_get_protocol_name} for
printing. printing.
@item const char *path @item const char *file_name
This is a string holding the path to the executable of the crypto This is a string holding the file name of the executable of the crypto
engine. Currently, it is never @code{NULL}, but using @code{NULL} is engine. Currently, it is never @code{NULL}, but using @code{NULL} is
reserved for future use, so always check before you use it. reserved for future use, so always check before you use it.

View File

@ -1,5 +1,26 @@
2003-01-30 Marcus Brinkmann <marcus@g10code.de> 2003-01-30 Marcus Brinkmann <marcus@g10code.de>
* engine-backend.h (struct engine_ops): Rename get_path to
get_file_name.
* gpgme.h (struct _gpgme_engine_info): Rename member path to
file_name.
* version.c: Do not include <stdio.h>, <stdlib.h>, context.h and
util.h. Other clean ups.
(parse_version_number): Protect more seriously against
overflow.
(gpgme_get_engine_info): Move to ...
* engine.c (gpgme_get_engine_info): ... here.
(_gpgme_engine_get_info): Function removed.
(_gpgme_engine_get_path): Make static and rename to ...
(engine_get_file_name): .. this.
(_gpgme_engine_get_version): Make static and rename to ...
(engine_get_version): ... this.
(_gpgme_engine_get_req_version): Make static and rename to ...
(engine_get_req_version): ... this.
* engine.h (_gpgme_engine_get_path, _gpgme_engine_get_version,
_gpgme_engine_req_version, _gpgme_engine_get_info.): Remove
prototypes.
* gpgme.h (enum GpgmeProtocol): Remove GPGME_PROTOCOL_AUTO. * gpgme.h (enum GpgmeProtocol): Remove GPGME_PROTOCOL_AUTO.
* gpgme.c (gpgme_set_protocol): Don't handle GPGME_PROTOCOL_AUTO. * gpgme.c (gpgme_set_protocol): Don't handle GPGME_PROTOCOL_AUTO.
(gpgme_get_protocol_name): New function. (gpgme_get_protocol_name): New function.

View File

@ -32,7 +32,7 @@
struct engine_ops struct engine_ops
{ {
/* Static functions. */ /* Static functions. */
const char *(*get_path) (void); const char *(*get_file_name) (void);
const char *(*get_version) (void); const char *(*get_version) (void);
const char *(*get_req_version) (void); const char *(*get_req_version) (void);
GpgmeError (*new) (void **r_engine); GpgmeError (*new) (void **r_engine);

View File

@ -50,24 +50,24 @@ static struct engine_ops *engine_ops[] =
#endif #endif
}; };
/* Get the path of the engine for PROTOCOL. */ /* Get the file name of the engine for PROTOCOL. */
const char * static const char *
_gpgme_engine_get_path (GpgmeProtocol proto) engine_get_file_name (GpgmeProtocol proto)
{ {
if (proto > DIM (engine_ops)) if (proto > DIM (engine_ops))
return NULL; return NULL;
if (engine_ops[proto] && engine_ops[proto]->get_path) if (engine_ops[proto] && engine_ops[proto]->get_file_name)
return (*engine_ops[proto]->get_path) (); return (*engine_ops[proto]->get_file_name) ();
else else
return NULL; return NULL;
} }
/* Get the version number of the engine for PROTOCOL. */ /* Get the version number of the engine for PROTOCOL. */
const char * static const char *
_gpgme_engine_get_version (GpgmeProtocol proto) engine_get_version (GpgmeProtocol proto)
{ {
if (proto > DIM (engine_ops)) if (proto > DIM (engine_ops))
return NULL; return NULL;
@ -80,8 +80,8 @@ _gpgme_engine_get_version (GpgmeProtocol proto)
/* Get the required version number of the engine for PROTOCOL. */ /* Get the required version number of the engine for PROTOCOL. */
const char * static const char *
_gpgme_engine_get_req_version (GpgmeProtocol proto) engine_get_req_version (GpgmeProtocol proto)
{ {
if (proto > DIM (engine_ops)) if (proto > DIM (engine_ops))
return NULL; return NULL;
@ -97,57 +97,68 @@ _gpgme_engine_get_req_version (GpgmeProtocol proto)
GpgmeError GpgmeError
gpgme_engine_check_version (GpgmeProtocol proto) gpgme_engine_check_version (GpgmeProtocol proto)
{ {
return _gpgme_compare_versions (_gpgme_engine_get_version (proto), return _gpgme_compare_versions (engine_get_version (proto),
_gpgme_engine_get_req_version (proto)) engine_get_req_version (proto))
? 0 : GPGME_Invalid_Engine; ? 0 : GPGME_Invalid_Engine;
} }
const char * /* Get the information about the configured and installed engines. A
_gpgme_engine_get_info (GpgmeProtocol proto) pointer to the first engine in the statically allocated linked list
is returned in *INFO. If an error occurs, it is returned. */
GpgmeError
gpgme_get_engine_info (GpgmeEngineInfo *info)
{ {
static const char fmt[] = " <engine>\n" static GpgmeEngineInfo engine_info;
" <protocol>%s</protocol>\n"
" <version>%s</version>\n"
" <path>%s</path>\n"
" </engine>\n";
static const char *const strproto[3] = { "OpenPGP", "CMS", NULL };
static const char *engine_info[3]; /* FIXME: MAX_PROTO + 1*/
DEFINE_STATIC_LOCK (engine_info_lock); DEFINE_STATIC_LOCK (engine_info_lock);
if (proto > 2 /* FIXME MAX_PROTO */ || !strproto[proto])
return NULL;
LOCK (engine_info_lock); LOCK (engine_info_lock);
if (!engine_info[proto]) if (!engine_info)
{ {
const char *path = _gpgme_engine_get_path (proto); GpgmeEngineInfo *lastp = &engine_info;
const char *version = _gpgme_engine_get_version (proto); GpgmeProtocol proto_list[] = { GPGME_PROTOCOL_OpenPGP,
GPGME_PROTOCOL_CMS };
int proto;
if (path && version) for (proto = 0; proto < DIM (proto_list); proto++)
{ {
char *info = malloc (strlen (fmt) + strlen (strproto[proto]) const char *file_name = engine_get_file_name (proto_list[proto]);
+ strlen (path) + strlen (version) + 1);
if (!info) if (!file_name)
info = " <engine>\n" continue;
" <error>Out of core</error>\n"
" </engine>"; *lastp = malloc (sizeof (*engine_info));
else if (!*lastp)
sprintf (info, fmt, strproto[proto], version, path); {
engine_info[proto] = info; while (engine_info)
{
GpgmeEngineInfo next_info = engine_info->next;
free (engine_info);
engine_info = next_info;
}
UNLOCK (engine_info_lock);
return GPGME_Out_Of_Core;
}
(*lastp)->protocol = proto_list[proto];
(*lastp)->file_name = file_name;
(*lastp)->version = engine_get_version (proto_list[proto]);
(*lastp)->req_version = engine_get_req_version (proto_list[proto]);
lastp = &(*lastp)->next;
} }
} }
UNLOCK (engine_info_lock); UNLOCK (engine_info_lock);
return engine_info[proto]; *info = engine_info;
return 0;
} }
GpgmeError GpgmeError
_gpgme_engine_new (GpgmeProtocol proto, EngineObject *r_engine) _gpgme_engine_new (GpgmeProtocol proto, EngineObject *r_engine)
{ {
EngineObject engine; EngineObject engine;
const char *path; const char *file_name;
const char *version; const char *version;
if (proto > DIM (engine_ops)) if (proto > DIM (engine_ops))
@ -156,9 +167,9 @@ _gpgme_engine_new (GpgmeProtocol proto, EngineObject *r_engine)
if (!engine_ops[proto]) if (!engine_ops[proto])
return GPGME_Invalid_Engine; return GPGME_Invalid_Engine;
path = _gpgme_engine_get_path (proto); file_name = engine_get_file_name (proto);
version = _gpgme_engine_get_version (proto); version = engine_get_version (proto);
if (!path || !version) if (!file_name || !version)
return GPGME_Invalid_Engine; return GPGME_Invalid_Engine;
engine = calloc (1, sizeof *engine); engine = calloc (1, sizeof *engine);

View File

@ -23,18 +23,6 @@
#include "types.h" #include "types.h"
/* Get the path of the engine for PROTOCOL. */
const char *_gpgme_engine_get_path (GpgmeProtocol proto);
/* Get the version number of the engine for PROTOCOL. */
const char *_gpgme_engine_get_version (GpgmeProtocol proto);
/* Get the version number of the engine for PROTOCOL. */
const char *_gpgme_engine_req_version (GpgmeProtocol proto);
/* Verify the version requirement for the engine for PROTOCOL. */
const char *_gpgme_engine_get_info (GpgmeProtocol proto);
GpgmeError _gpgme_engine_new (GpgmeProtocol proto, EngineObject *r_engine); GpgmeError _gpgme_engine_new (GpgmeProtocol proto, EngineObject *r_engine);
void _gpgme_engine_release (EngineObject engine); void _gpgme_engine_release (EngineObject engine);
void _gpgme_engine_set_status_handler (EngineObject engine, void _gpgme_engine_set_status_handler (EngineObject engine,

View File

@ -319,8 +319,8 @@ struct _gpgme_engine_info
/* The protocol ID. */ /* The protocol ID. */
GpgmeProtocol protocol; GpgmeProtocol protocol;
/* The path to the engine binary. */ /* The file name of the engine binary. */
const char *path; const char *file_name;
/* The version string of the installed engine. */ /* The version string of the installed engine. */
const char *version; const char *version;

View File

@ -21,19 +21,25 @@
#if HAVE_CONFIG_H #if HAVE_CONFIG_H
#include <config.h> #include <config.h>
#endif #endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <limits.h>
#include <ctype.h> #include <ctype.h>
#include "gpgme.h" #include "gpgme.h"
#include "context.h"
#include "sema.h"
#include "util.h"
#include "key.h" /* for key_cache_init */
#include "io.h" #include "io.h"
/* For _gpgme_sema_subsystem_init (). */
#include "sema.h"
/* For _gpgme_key_cache_init (). */
#include "key.h"
/* Bootstrap the subsystems needed for concurrent operation. This
must be done once at startup. We can not guarantee this using a
lock, though, because the semaphore subsystem needs to be
initialized itself before it can be used. So we expect that the
user performs the necessary syncrhonization. */
static void static void
do_subsystem_inits (void) do_subsystem_inits (void)
{ {
@ -41,92 +47,106 @@ do_subsystem_inits (void)
if (done) if (done)
return; return;
_gpgme_sema_subsystem_init (); _gpgme_sema_subsystem_init ();
_gpgme_key_cache_init (); _gpgme_key_cache_init ();
done = 1; done = 1;
} }
static const char*
parse_version_number (const char *s, int *number) /* Read the next number in the version string STR and return it in
*NUMBER. Return a pointer to the tail of STR after parsing, or
*NULL if the version string was invalid. */
static const char *
parse_version_number (const char *str, int *number)
{ {
#define MAXVAL ((INT_MAX - 10) / 10)
int val = 0; int val = 0;
if (*s == '0' && isdigit(s[1])) /* Leading zeros are not allowed. */
return NULL; /* Leading zeros are not allowed. */ if (*str == '0' && isdigit(str[1]))
for (; isdigit(*s); s++) return NULL;
while (isdigit (*str) && val <= MAXVAL)
{ {
val *= 10; val *= 10;
val += *s - '0'; val += *(str++) - '0';
} }
*number = val; *number = val;
return val < 0 ? NULL : s; return val > MAXVAL ? NULL : str;
} }
/* Parse the version string STR in the format MAJOR.MINOR.MICRO (for
example, 9.3.2) and return the components in MAJOR, MINOR and MICRO
as integers. The function returns the tail of the string that
follows the version number. This might be te empty string if there
is nothing following the version number, or a patchlevel. The
function returns NULL if the version string is not valid. */
static const char * static const char *
parse_version_string (const char *s, int *major, int *minor, int *micro) parse_version_string (const char *str, int *major, int *minor, int *micro)
{ {
s = parse_version_number (s, major); str = parse_version_number (str, major);
if (!s || *s != '.') if (!str || *str != '.')
return NULL; return NULL;
s++; str++;
s = parse_version_number (s, minor);
if (!s || *s != '.') str = parse_version_number (str, minor);
if (!str || *str != '.')
return NULL; return NULL;
s++; str++;
s = parse_version_number (s, micro);
if (!s) str = parse_version_number (str, micro);
if (!str)
return NULL; return NULL;
return s; /* Patchlevel. */
/* A patchlevel might follow. */
return str;
} }
const char * const char *
_gpgme_compare_versions (const char *my_version, _gpgme_compare_versions (const char *my_version,
const char *req_version) const char *rq_version)
{ {
int my_major, my_minor, my_micro; int my_major, my_minor, my_micro;
int rq_major, rq_minor, rq_micro; int rq_major, rq_minor, rq_micro;
const char *my_plvl, *rq_plvl; const char *my_plvl, *rq_plvl;
if (!req_version) if (!rq_version)
return my_version; return my_version;
if (!my_version) if (!my_version)
return NULL; return NULL;
my_plvl = parse_version_string (my_version, &my_major, &my_minor, &my_micro); my_plvl = parse_version_string (my_version, &my_major, &my_minor, &my_micro);
if (!my_plvl) if (!my_plvl)
return NULL; /* Very strange: our own version is bogus. */ return NULL;
rq_plvl = parse_version_string(req_version,
&rq_major, &rq_minor, &rq_micro); rq_plvl = parse_version_string (rq_version, &rq_major, &rq_minor, &rq_micro);
if (!rq_plvl) if (!rq_plvl)
return NULL; /* Requested version string is invalid. */ return NULL;
if (my_major > rq_major if (my_major > rq_major
|| (my_major == rq_major && my_minor > rq_minor) || (my_major == rq_major && my_minor > rq_minor)
|| (my_major == rq_major && my_minor == rq_minor || (my_major == rq_major && my_minor == rq_minor
&& my_micro > rq_micro) && my_micro > rq_micro)
|| (my_major == rq_major && my_minor == rq_minor || (my_major == rq_major && my_minor == rq_minor
&& my_micro == rq_micro && my_micro == rq_micro && strcmp (my_plvl, rq_plvl) >= 0))
&& strcmp( my_plvl, rq_plvl ) >= 0)) return my_version;
{
return my_version;
}
return NULL; return NULL;
} }
/**
* gpgme_check_version: /* Check that the the version of the library is at minimum the
* @req_version: A string with a version requested one and return the version string; return NULL if the
* condition is not met. If a NULL is passed to this function, no
* Check that the the version of the library is at minimum the requested one check is done and the version string is simply returned.
* and return the version string; return NULL if the condition is not
* met. If a NULL is passed to this function, no check is done and This function must be run once at startup, as it also initializes
* the version string is simply returned. It is a pretty good idea to some subsystems. Its invocation must be synchronized against
* run this function as soon as possible, because it also intializes calling any of the other functions in a multi-threaded
* some subsystems. In a multithreaded environment if should be called environments. */
* before the first thread is created.
*
* Return value: The version string or NULL
**/
const char * const char *
gpgme_check_version (const char *req_version) gpgme_check_version (const char *req_version)
{ {
@ -134,76 +154,27 @@ gpgme_check_version (const char *req_version)
return _gpgme_compare_versions (VERSION, req_version); return _gpgme_compare_versions (VERSION, req_version);
} }
/* Get the information about the configured and installed engines. A
pointer to the first engine in the statically allocated linked list
is returned in *INFO. If an error occurs, it is returned. */
GpgmeError
gpgme_get_engine_info (GpgmeEngineInfo *info)
{
static GpgmeEngineInfo engine_info;
DEFINE_STATIC_LOCK (engine_info_lock);
LOCK (engine_info_lock);
if (!engine_info)
{
GpgmeEngineInfo *lastp = &engine_info;
GpgmeProtocol proto_list[] = { GPGME_PROTOCOL_OpenPGP,
GPGME_PROTOCOL_CMS };
int proto;
for (proto = 0; proto < DIM (proto_list); proto++)
{
const char *path = _gpgme_engine_get_path (proto_list[proto]);
if (!path)
continue;
*lastp = malloc (sizeof (*engine_info));
if (!*lastp)
{
while (engine_info)
{
GpgmeEngineInfo next_info = engine_info->next;
free (engine_info);
engine_info = next_info;
}
UNLOCK (engine_info_lock);
return GPGME_Out_Of_Core;
}
(*lastp)->protocol = proto_list[proto];
(*lastp)->path = path;
(*lastp)->version = _gpgme_engine_get_version (proto_list[proto]);
(*lastp)->req_version
= _gpgme_engine_get_req_version (proto_list[proto]);
lastp = &(*lastp)->next;
}
}
UNLOCK (engine_info_lock);
*info = engine_info;
return 0;
}
#define LINELENGTH 80 #define LINELENGTH 80
/* Retrieve the version number from the --version output of the
program FILE_NAME. */
char * char *
_gpgme_get_program_version (const char *const path) _gpgme_get_program_version (const char *const file_name)
{ {
char line[LINELENGTH] = ""; char line[LINELENGTH] = "";
int linelen = 0; int linelen = 0;
char *mark = NULL; char *mark = NULL;
int rp[2]; int rp[2];
int nread; int nread;
char *argv[] = {NULL /* path */, "--version", 0}; char *argv[] = {NULL /* file_name */, "--version", 0};
struct spawn_fd_item_s pfd[] = { {0, -1}, {-1, -1} }; struct spawn_fd_item_s pfd[] = { {0, -1}, {-1, -1} };
struct spawn_fd_item_s cfd[] = { {-1, 1 /* STDOUT_FILENO */}, {-1, -1} }; struct spawn_fd_item_s cfd[] = { {-1, 1 /* STDOUT_FILENO */}, {-1, -1} };
int status; int status;
if (!path) if (!file_name)
return NULL; return NULL;
argv[0] = (char *) path; argv[0] = (char *) file_name;
if (_gpgme_io_pipe (rp, 1) < 0) if (_gpgme_io_pipe (rp, 1) < 0)
return NULL; return NULL;
@ -211,7 +182,7 @@ _gpgme_get_program_version (const char *const path)
pfd[0].fd = rp[1]; pfd[0].fd = rp[1];
cfd[0].fd = rp[1]; cfd[0].fd = rp[1];
status = _gpgme_io_spawn (path, argv, cfd, pfd); status = _gpgme_io_spawn (file_name, argv, cfd, pfd);
if (status < 0) if (status < 0)
{ {
_gpgme_io_close (rp[0]); _gpgme_io_close (rp[0]);

View File

@ -1,5 +1,7 @@
2003-01-30 Marcus Brinkmann <marcus@g10code.de> 2003-01-30 Marcus Brinkmann <marcus@g10code.de>
* t-engine-info.c: Use file_name instead path throughout.
* Makefile.am (TESTS): Add t-engine-info. * Makefile.am (TESTS): Add t-engine-info.
* t-engine-info.c: New file. * t-engine-info.c: New file.
* gpg/t-encrypt.c (main): Don't print engine info. * gpg/t-encrypt.c (main): Don't print engine info.

View File

@ -43,7 +43,7 @@
void void
check_engine_info (GpgmeEngineInfo info, GpgmeProtocol protocol, check_engine_info (GpgmeEngineInfo info, GpgmeProtocol protocol,
const char *path, const char *req_version) const char *file_name, const char *req_version)
{ {
if (info->protocol != protocol) if (info->protocol != protocol)
{ {
@ -51,10 +51,10 @@ check_engine_info (GpgmeEngineInfo info, GpgmeProtocol protocol,
info->protocol, protocol); info->protocol, protocol);
exit (1); exit (1);
} }
if (strcmp (info->path, path)) if (strcmp (info->file_name, file_name))
{ {
fprintf (stderr, "Unexpected path to executable %s (expected %s instead)", fprintf (stderr, "Unexpected file name to executable %s (expected %s instead)",
info->path, path); info->file_name, file_name);
exit (1); exit (1);
} }
if (strcmp (info->req_version, req_version)) if (strcmp (info->req_version, req_version))