From d102681aef8e58fe2503d2a58142558bc6034d80 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Thu, 30 Jan 2003 13:11:25 +0000 Subject: [PATCH] doc/ 2003-01-30 Marcus Brinkmann * gpgme.texi (Engine Information): Rename member part to file_name. gpgme/ 2003-01-30 Marcus Brinkmann * 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 , , 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 * t-engine-info.c: Use file_name instead path throughout. --- doc/ChangeLog | 3 + doc/gpgme.texi | 4 +- gpgme/ChangeLog | 21 +++++ gpgme/engine-backend.h | 2 +- gpgme/engine.c | 97 ++++++++++++---------- gpgme/engine.h | 12 --- gpgme/gpgme.h | 4 +- gpgme/version.c | 181 +++++++++++++++++------------------------ tests/ChangeLog | 2 + tests/t-engine-info.c | 8 +- 10 files changed, 165 insertions(+), 169 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index 8487dc12..4b695d71 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,5 +1,8 @@ 2003-01-30 Marcus Brinkmann + * gpgme.texi (Engine Information): Rename member part to + file_name. + * gpgme.texi (Protocols and Engines): Document gpgme_get_protocol_name. diff --git a/doc/gpgme.texi b/doc/gpgme.texi index 96f9184f..88472cc3 100644 --- a/doc/gpgme.texi +++ b/doc/gpgme.texi @@ -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 printing. -@item const char *path -This is a string holding the path to the executable of the crypto +@item const char *file_name +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 reserved for future use, so always check before you use it. diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog index b143582e..cdeec938 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -1,5 +1,26 @@ 2003-01-30 Marcus Brinkmann + * 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 , , 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.c (gpgme_set_protocol): Don't handle GPGME_PROTOCOL_AUTO. (gpgme_get_protocol_name): New function. diff --git a/gpgme/engine-backend.h b/gpgme/engine-backend.h index b291f05a..c97297d7 100644 --- a/gpgme/engine-backend.h +++ b/gpgme/engine-backend.h @@ -32,7 +32,7 @@ struct engine_ops { /* Static functions. */ - const char *(*get_path) (void); + const char *(*get_file_name) (void); const char *(*get_version) (void); const char *(*get_req_version) (void); GpgmeError (*new) (void **r_engine); diff --git a/gpgme/engine.c b/gpgme/engine.c index 131a0de8..fdadef7c 100644 --- a/gpgme/engine.c +++ b/gpgme/engine.c @@ -50,24 +50,24 @@ static struct engine_ops *engine_ops[] = #endif }; - -/* Get the path of the engine for PROTOCOL. */ -const char * -_gpgme_engine_get_path (GpgmeProtocol proto) + +/* Get the file name of the engine for PROTOCOL. */ +static const char * +engine_get_file_name (GpgmeProtocol proto) { if (proto > DIM (engine_ops)) return NULL; - if (engine_ops[proto] && engine_ops[proto]->get_path) - return (*engine_ops[proto]->get_path) (); + if (engine_ops[proto] && engine_ops[proto]->get_file_name) + return (*engine_ops[proto]->get_file_name) (); else return NULL; } /* Get the version number of the engine for PROTOCOL. */ -const char * -_gpgme_engine_get_version (GpgmeProtocol proto) +static const char * +engine_get_version (GpgmeProtocol proto) { if (proto > DIM (engine_ops)) return NULL; @@ -80,8 +80,8 @@ _gpgme_engine_get_version (GpgmeProtocol proto) /* Get the required version number of the engine for PROTOCOL. */ -const char * -_gpgme_engine_get_req_version (GpgmeProtocol proto) +static const char * +engine_get_req_version (GpgmeProtocol proto) { if (proto > DIM (engine_ops)) return NULL; @@ -97,57 +97,68 @@ _gpgme_engine_get_req_version (GpgmeProtocol proto) GpgmeError gpgme_engine_check_version (GpgmeProtocol proto) { - return _gpgme_compare_versions (_gpgme_engine_get_version (proto), - _gpgme_engine_get_req_version (proto)) + return _gpgme_compare_versions (engine_get_version (proto), + engine_get_req_version (proto)) ? 0 : GPGME_Invalid_Engine; } -const char * -_gpgme_engine_get_info (GpgmeProtocol proto) +/* 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 const char fmt[] = " \n" - " %s\n" - " %s\n" - " %s\n" - " \n"; - static const char *const strproto[3] = { "OpenPGP", "CMS", NULL }; - static const char *engine_info[3]; /* FIXME: MAX_PROTO + 1*/ + static GpgmeEngineInfo engine_info; DEFINE_STATIC_LOCK (engine_info_lock); - if (proto > 2 /* FIXME MAX_PROTO */ || !strproto[proto]) - return NULL; - LOCK (engine_info_lock); - if (!engine_info[proto]) + if (!engine_info) { - const char *path = _gpgme_engine_get_path (proto); - const char *version = _gpgme_engine_get_version (proto); + GpgmeEngineInfo *lastp = &engine_info; + 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]) - + strlen (path) + strlen (version) + 1); - if (!info) - info = " \n" - " Out of core\n" - " "; - else - sprintf (info, fmt, strproto[proto], version, path); - engine_info[proto] = info; + const char *file_name = engine_get_file_name (proto_list[proto]); + + if (!file_name) + 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)->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); - return engine_info[proto]; + *info = engine_info; + return 0; } - + GpgmeError _gpgme_engine_new (GpgmeProtocol proto, EngineObject *r_engine) { EngineObject engine; - const char *path; + const char *file_name; const char *version; if (proto > DIM (engine_ops)) @@ -156,9 +167,9 @@ _gpgme_engine_new (GpgmeProtocol proto, EngineObject *r_engine) if (!engine_ops[proto]) return GPGME_Invalid_Engine; - path = _gpgme_engine_get_path (proto); - version = _gpgme_engine_get_version (proto); - if (!path || !version) + file_name = engine_get_file_name (proto); + version = engine_get_version (proto); + if (!file_name || !version) return GPGME_Invalid_Engine; engine = calloc (1, sizeof *engine); diff --git a/gpgme/engine.h b/gpgme/engine.h index 746de6f1..de782dad 100644 --- a/gpgme/engine.h +++ b/gpgme/engine.h @@ -23,18 +23,6 @@ #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); void _gpgme_engine_release (EngineObject engine); void _gpgme_engine_set_status_handler (EngineObject engine, diff --git a/gpgme/gpgme.h b/gpgme/gpgme.h index 341a32dd..dcc1eb04 100644 --- a/gpgme/gpgme.h +++ b/gpgme/gpgme.h @@ -319,8 +319,8 @@ struct _gpgme_engine_info /* The protocol ID. */ GpgmeProtocol protocol; - /* The path to the engine binary. */ - const char *path; + /* The file name of the engine binary. */ + const char *file_name; /* The version string of the installed engine. */ const char *version; diff --git a/gpgme/version.c b/gpgme/version.c index 1af91cf6..68f085e0 100644 --- a/gpgme/version.c +++ b/gpgme/version.c @@ -21,19 +21,25 @@ #if HAVE_CONFIG_H #include #endif -#include -#include #include +#include #include #include "gpgme.h" -#include "context.h" -#include "sema.h" -#include "util.h" -#include "key.h" /* for key_cache_init */ #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 do_subsystem_inits (void) { @@ -41,92 +47,106 @@ do_subsystem_inits (void) if (done) return; + _gpgme_sema_subsystem_init (); _gpgme_key_cache_init (); 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; - if (*s == '0' && isdigit(s[1])) - return NULL; /* Leading zeros are not allowed. */ - for (; isdigit(*s); s++) + /* Leading zeros are not allowed. */ + if (*str == '0' && isdigit(str[1])) + return NULL; + + while (isdigit (*str) && val <= MAXVAL) { val *= 10; - val += *s - '0'; + val += *(str++) - '0'; } *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 * -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); - if (!s || *s != '.') + str = parse_version_number (str, major); + if (!str || *str != '.') return NULL; - s++; - s = parse_version_number (s, minor); - if (!s || *s != '.') + str++; + + str = parse_version_number (str, minor); + if (!str || *str != '.') return NULL; - s++; - s = parse_version_number (s, micro); - if (!s) + str++; + + str = parse_version_number (str, micro); + if (!str) return NULL; - return s; /* Patchlevel. */ + + /* A patchlevel might follow. */ + return str; } + const char * _gpgme_compare_versions (const char *my_version, - const char *req_version) + const char *rq_version) { int my_major, my_minor, my_micro; int rq_major, rq_minor, rq_micro; const char *my_plvl, *rq_plvl; - if (!req_version) + if (!rq_version) return my_version; if (!my_version) return NULL; my_plvl = parse_version_string (my_version, &my_major, &my_minor, &my_micro); if (!my_plvl) - return NULL; /* Very strange: our own version is bogus. */ - rq_plvl = parse_version_string(req_version, - &rq_major, &rq_minor, &rq_micro); + return NULL; + + rq_plvl = parse_version_string (rq_version, &rq_major, &rq_minor, &rq_micro); if (!rq_plvl) - return NULL; /* Requested version string is invalid. */ + return NULL; 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_micro > rq_micro) || (my_major == rq_major && my_minor == rq_minor - && my_micro == rq_micro - && strcmp( my_plvl, rq_plvl ) >= 0)) - { - return my_version; - } + && my_micro == rq_micro && strcmp (my_plvl, rq_plvl) >= 0)) + return my_version; + return NULL; } -/** - * gpgme_check_version: - * @req_version: A string with a version - * - * Check that the the version of the library is at minimum the 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 is done and - * the version string is simply returned. It is a pretty good idea to - * run this function as soon as possible, because it also intializes - * some subsystems. In a multithreaded environment if should be called - * before the first thread is created. - * - * Return value: The version string or NULL - **/ + +/* Check that the the version of the library is at minimum the + 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 is done and the version string is simply returned. + + This function must be run once at startup, as it also initializes + some subsystems. Its invocation must be synchronized against + calling any of the other functions in a multi-threaded + environments. */ const char * 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); } - -/* 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 +/* Retrieve the version number from the --version output of the + program FILE_NAME. */ char * -_gpgme_get_program_version (const char *const path) +_gpgme_get_program_version (const char *const file_name) { char line[LINELENGTH] = ""; int linelen = 0; char *mark = NULL; int rp[2]; 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 cfd[] = { {-1, 1 /* STDOUT_FILENO */}, {-1, -1} }; int status; - if (!path) + if (!file_name) return NULL; - argv[0] = (char *) path; + argv[0] = (char *) file_name; if (_gpgme_io_pipe (rp, 1) < 0) return NULL; @@ -211,7 +182,7 @@ _gpgme_get_program_version (const char *const path) pfd[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) { _gpgme_io_close (rp[0]); diff --git a/tests/ChangeLog b/tests/ChangeLog index 425884b9..2ff2aff5 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,5 +1,7 @@ 2003-01-30 Marcus Brinkmann + * t-engine-info.c: Use file_name instead path throughout. + * Makefile.am (TESTS): Add t-engine-info. * t-engine-info.c: New file. * gpg/t-encrypt.c (main): Don't print engine info. diff --git a/tests/t-engine-info.c b/tests/t-engine-info.c index e4d0eda9..ef69b1f5 100644 --- a/tests/t-engine-info.c +++ b/tests/t-engine-info.c @@ -43,7 +43,7 @@ void 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) { @@ -51,10 +51,10 @@ check_engine_info (GpgmeEngineInfo info, GpgmeProtocol protocol, info->protocol, protocol); exit (1); } - if (strcmp (info->path, path)) + if (strcmp (info->file_name, file_name)) { - fprintf (stderr, "Unexpected path to executable %s (expected %s instead)", - info->path, path); + fprintf (stderr, "Unexpected file name to executable %s (expected %s instead)", + info->file_name, file_name); exit (1); } if (strcmp (info->req_version, req_version))