Page MenuHome GnuPG

No OneTemporary

This document is not UTF8. It was detected as ISO-8859-1 (Latin 1) and converted to UTF8 for display.
diff --git a/trunk/AUTHORS b/trunk/AUTHORS
index e69de29b..20ea6e00 100644
--- a/trunk/AUTHORS
+++ b/trunk/AUTHORS
@@ -0,0 +1,9 @@
+Program: gpgme
+Maintainer: Werner Koch <wk@gnupg.org>
+
+
+FSF <gnu@gnu.org>
+ * Code taken from GnuPG: gpgme/w32-util.c
+
+Werner Koch <wk@gnupg.org>
+ * Design and most stuff.
diff --git a/trunk/TODO b/trunk/TODO
index 59a6d8c8..a829ea0e 100644
--- a/trunk/TODO
+++ b/trunk/TODO
@@ -1,10 +1,10 @@
* Implement posix-sema.c
* Add gpgme_mime_xxx to make handling of MIME/PGP easier
* Allow to use GTK's main loop instead of the select stuff in
wait.c
-* Remove all that funny exit code handling - we donn't need it.
+* Remove all that funny exit code handling - we don't need it.
diff --git a/trunk/gpgme/ChangeLog b/trunk/gpgme/ChangeLog
index 03c72d3f..0f704a5a 100644
--- a/trunk/gpgme/ChangeLog
+++ b/trunk/gpgme/ChangeLog
@@ -1,34 +1,38 @@
2001-01-30 Werner Koch <wk@gnupg.org>
+ * posix-util.c, w32-util.c: New.
+ (_gpgme_get_gpg_path): New, suggested by Jan-Oliver.
+ * rungpg.c (_gpgme_gpg_spawn): Use new function to get GPG's path.
+
* signers.c (gpgme_signers_add): Ooops, one should test code and
not just write it; the newarr was not assigned. Thanks to José
for pointing this out. Hmmm, still not tested, why shoudl a coder
test his fix :-)
* w32-io.c: Does now use reader threads, so that we can use
WaitForMultipleObjects.
* sema.h, posix-sema.c, w32-sema.c: Support for Critcial sections.
Does currently only work for W32.
* debug.c, util.h : New. Changed all fprintfs to use this new
set of debugging functions.
2001-01-23 Werner Koch <wk@gnupg.org>
* data.c (_gpgme_data_release_and_return_string): Fixed string
termination.
2001-01-22 Werner Koch <wk@gnupg.org>
* delete.c: New.
* signers.c: New.
* key.c (gpgme_key_ref, gpgme_key_unref): New.
* sign.c (gpgme_op_sign_start): Allow the use of other keys.
* version.c (gpgme_get_engine_info,gpgme_check_engine): New.
* rungpg.c (_gpgme_gpg_set_simple_line_handler): New.
2001-01-05 Werner Koch <wk@gnupg.org>
* data.c (gpgme_data_rewind): Allow to rewind data_type_none.
diff --git a/trunk/gpgme/Makefile.am b/trunk/gpgme/Makefile.am
index 20944ac8..59faab48 100644
--- a/trunk/gpgme/Makefile.am
+++ b/trunk/gpgme/Makefile.am
@@ -1,48 +1,49 @@
# Process this file with automake to produce Makefile.in
EXTRA_DIST = gpgme-config.in gpgme.m4 mkerrors mkstatus
BUILT_SOURCES = errors.c status-table.h
bin_SCRIPTS = gpgme-config
m4datadir = $(datadir)/aclocal
m4data_DATA = gpgme.m4
include_HEADERS = gpgme.h
lib_LTLIBRARIES = libgpgme.la
libgpgme_la_LDFLAGS = -version-info \
@LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
libgpgme_la_INCLUDES = -I$(top_srcdir)/lib
libgpgme_la_SOURCES = \
- gpgme.h types.h util.h util.c debug.c \
+ gpgme.h types.h \
+ util.h util.c posix-util.c w32-util.c \
context.h ops.h \
data.c recipient.c signers.c \
wait.c wait.h \
encrypt.c \
decrypt.c \
verify.c \
sign.c \
key.c key.h \
keylist.c \
trustlist.c \
import.c \
export.c \
genkey.c \
delete.c \
rungpg.c rungpg.h status-table.h \
sema.h posix-sema.c w32-sema.c \
syshdr.h io.h posix-io.c w32-io.c \
- gpgme.c version.c errors.c
+ gpgme.c debug.c version.c errors.c
errors.c : gpgme.h
$(srcdir)/mkerrors < $(srcdir)/gpgme.h > errors.c
status-table.h : rungpg.h
$(srcdir)/mkstatus < $(srcdir)/rungpg.h > status-table.h
diff --git a/trunk/gpgme/debug.c b/trunk/gpgme/debug.c
index f41929b3..7cb5121d 100644
--- a/trunk/gpgme/debug.c
+++ b/trunk/gpgme/debug.c
@@ -1,156 +1,156 @@
/* debug.c
* Copyright (C) 2001 Werner Koch (dd9jn)
*
* This file is part of GPGME.
*
* GPGME is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GPGME is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <assert.h>
#include "util.h"
#include "sema.h"
DEFINE_STATIC_LOCK (debug_lock);
struct debug_control_s {
FILE *fp;
char fname[100];
};
static int debug_level = 0;
static void
debug_init (void)
{
static volatile int initialized = 0;
if (initialized)
return;
LOCK (debug_lock);
if (!initialized) {
const char *e = getenv ("GPGME_DEBUG");
debug_level = e? atoi (e): 0;
initialized = 1;
if (debug_level > 0)
fprintf (stderr,"gpgme_debug: level=%d\n", debug_level);
}
UNLOCK (debug_lock);
}
void
_gpgme_debug (int level, const char *format, ...)
{
va_list arg_ptr ;
debug_init ();
if ( debug_level < level )
return;
va_start ( arg_ptr, format ) ;
LOCK (debug_lock);
vfprintf (stderr, format, arg_ptr) ;
va_end ( arg_ptr ) ;
if( format && *format && format[strlen(format)-1] != '\n' )
putc ('\n', stderr);
UNLOCK (debug_lock);
fflush (stderr);
}
void
_gpgme_debug_begin ( void **helper, int level, const char *text)
{
struct debug_control_s *ctl;
debug_init ();
*helper = NULL;
if ( debug_level < level )
return;
ctl = xtrycalloc (1, sizeof *ctl );
if (!ctl) {
_gpgme_debug (255, __FILE__ ":" STR2(__LINE__)": out of core");
return;
}
- /* Oh what a pitty sthat we don't have a asprintf or snprintf under
+ /* Oh what a pitty that we don't have a asprintf or snprintf under
* Windoze. We definitely should write our own clib for W32! */
sprintf ( ctl->fname, "/tmp/gpgme_debug.%d.%p", getpid (), ctl );
ctl->fp = fopen (ctl->fname, "w+");
if (!ctl->fp) {
_gpgme_debug (255,__FILE__ ":" STR2(__LINE__)": failed to create `%s'",
ctl->fname );
xfree (ctl);
return;
}
*helper = ctl;
_gpgme_debug_add (helper, "%s", text );
}
int
_gpgme_debug_enabled (void **helper)
{
return helper && *helper;
}
void
_gpgme_debug_add (void **helper, const char *format, ...)
{
struct debug_control_s *ctl = *helper;
va_list arg_ptr ;
if ( !*helper )
return;
va_start ( arg_ptr, format ) ;
vfprintf (ctl->fp, format, arg_ptr) ;
va_end ( arg_ptr ) ;
}
void
_gpgme_debug_end (void **helper, const char *text)
{
struct debug_control_s *ctl = *helper;
int c, last_c=EOF;
if ( !*helper )
return;
_gpgme_debug_add (helper, "%s", text );
rewind (ctl->fp);
LOCK (debug_lock);
while ( (c=getc (ctl->fp)) != EOF ) {
putc (c, stderr);
last_c = c;
}
if (last_c != '\n')
putc ('\n', stderr);
UNLOCK (debug_lock);
remove (ctl->fname);
xfree (ctl);
*helper = NULL;
}
diff --git a/trunk/gpgme/posix-util.c b/trunk/gpgme/posix-util.c
new file mode 100644
index 00000000..3c0c692a
--- /dev/null
+++ b/trunk/gpgme/posix-util.c
@@ -0,0 +1,45 @@
+/* posix-util.c - Utility functions for Posix
+ * Copyright (C) 2001 Werner Koch (dd9jn)
+ *
+ * This file is part of GPGME.
+ *
+ * GPGME is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GPGME is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#include <config.h>
+#ifndef HAVE_DOSISH_SYSTEM
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "util.h"
+
+
+const char *
+_gpgme_get_gpg_path (void)
+{
+ return GPG_PATH;
+}
+
+
+#endif /*!HAVE_DOSISH_SYSTEM*/
+
+
+
+
+
diff --git a/trunk/gpgme/rungpg.c b/trunk/gpgme/rungpg.c
index 101d9a9f..8c9d2b77 100644
--- a/trunk/gpgme/rungpg.c
+++ b/trunk/gpgme/rungpg.c
@@ -1,1276 +1,1277 @@
/* rungpg.c
* Copyright (C) 2000 Werner Koch (dd9jn)
*
* This file is part of GPGME.
*
* GPGME is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GPGME is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/types.h>
#include <signal.h>
#include <fcntl.h>
#include "unistd.h"
#include "gpgme.h"
#include "util.h"
#include "ops.h"
#include "wait.h"
#include "rungpg.h"
#include "context.h" /*temp hack until we have GpmeData methods to do I/O */
#include "io.h"
#include "status-table.h"
/* This type is used to build a list of gpg arguments and
* data sources/sinks */
struct arg_and_data_s {
struct arg_and_data_s *next;
GpgmeData data; /* If this is not NULL .. */
int dup_to;
int print_fd; /* print the fd number and not the special form of it */
char arg[1]; /* .. this is used */
};
struct fd_data_map_s {
GpgmeData data;
int inbound; /* true if this is used for reading from gpg */
int dup_to;
int fd; /* the fd to use */
int peer_fd; /* the outher side of the pipe */
};
struct gpg_object_s {
struct arg_and_data_s *arglist;
struct arg_and_data_s **argtail;
int arg_error;
struct {
int fd[2];
size_t bufsize;
char *buffer;
size_t readpos;
int eof;
GpgStatusHandler fnc;
void *fnc_value;
} status;
/* This is a kludge - see the comment at gpg_colon_line_handler */
struct {
int fd[2];
size_t bufsize;
char *buffer;
size_t readpos;
int eof;
GpgColonLineHandler fnc; /* this indicate use of this structrue */
void *fnc_value;
int simple;
} colon;
char **argv;
struct fd_data_map_s *fd_data_map;
int pid; /* we can't use pid_t because we don't use it in Windoze */
int running;
int exit_status;
int exit_signal;
/* stuff needed for pipemode */
struct {
int used;
int active;
GpgmeData sig;
GpgmeData text;
int stream_started;
} pm;
/* stuff needed for interactive (command) mode */
struct {
int used;
int fd;
GpgmeData cb_data; /* hack to get init the above fd later */
GpgStatusCode code; /* last code */
char *keyword; /* what has been requested (malloced) */
GpgCommandHandler fnc;
void *fnc_value;
} cmd;
};
static void kill_gpg ( GpgObject gpg );
static void free_argv ( char **argv );
static void free_fd_data_map ( struct fd_data_map_s *fd_data_map );
static int gpg_inbound_handler ( void *opaque, int pid, int fd );
static int gpg_outbound_handler ( void *opaque, int pid, int fd );
static int gpg_status_handler ( void *opaque, int pid, int fd );
static GpgmeError read_status ( GpgObject gpg );
static int gpg_colon_line_handler ( void *opaque, int pid, int fd );
static GpgmeError read_colon_line ( GpgObject gpg );
static int pipemode_cb ( void *opaque,
char *buffer, size_t length, size_t *nread );
static int command_cb ( void *opaque,
char *buffer, size_t length, size_t *nread );
GpgmeError
_gpgme_gpg_new ( GpgObject *r_gpg )
{
GpgObject gpg;
int rc = 0;
gpg = xtrycalloc ( 1, sizeof *gpg );
if ( !gpg ) {
rc = mk_error (Out_Of_Core);
goto leave;
}
gpg->argtail = &gpg->arglist;
gpg->status.fd[0] = -1;
gpg->status.fd[1] = -1;
gpg->colon.fd[0] = -1;
gpg->colon.fd[1] = -1;
gpg->cmd.fd = -1;
/* allocate the read buffer for the status pipe */
gpg->status.bufsize = 1024;
gpg->status.readpos = 0;
gpg->status.buffer = xtrymalloc (gpg->status.bufsize);
if (!gpg->status.buffer) {
rc = mk_error (Out_Of_Core);
goto leave;
}
/* In any case we need a status pipe - create it right here and
* don't handle it with our generic GpgmeData mechanism */
if (_gpgme_io_pipe (gpg->status.fd, 1) == -1) {
rc = mk_error (Pipe_Error);
goto leave;
}
gpg->status.eof = 0;
_gpgme_gpg_add_arg ( gpg, "--status-fd" );
{
char buf[25];
sprintf ( buf, "%d", gpg->status.fd[1]);
_gpgme_gpg_add_arg ( gpg, buf );
}
_gpgme_gpg_add_arg ( gpg, "--no-tty" );
leave:
if (rc) {
_gpgme_gpg_release (gpg);
*r_gpg = NULL;
}
else
*r_gpg = gpg;
return rc;
}
void
_gpgme_gpg_release ( GpgObject gpg )
{
if ( !gpg )
return;
xfree (gpg->status.buffer);
xfree (gpg->colon.buffer);
if ( gpg->argv )
free_argv (gpg->argv);
xfree (gpg->cmd.keyword);
#if 0
/* fixme: We need a way to communicate back closed fds, so that we
* don't do it a second time. One way to do it is by using a global
* table of open fds associated with gpg objects - but this requires
* additional locking. */
if (gpg->status.fd[0] != -1 )
_gpgme_io_close (gpg->status.fd[0]);
if (gpg->status.fd[1] != -1 )
_gpgme_io_close (gpg->status.fd[1]);
if (gpg->colon.fd[0] != -1 )
_gpgme_io_close (gpg->colon.fd[0]);
if (gpg->colon.fd[1] != -1 )
_gpgme_io_close (gpg->colon.fd[1]);
#endif
free_fd_data_map (gpg->fd_data_map);
kill_gpg (gpg); /* fixme: should be done asyncronously */
xfree (gpg);
}
static void
kill_gpg ( GpgObject gpg )
{
#if 0
if ( gpg->running ) {
/* still running? Must send a killer */
kill ( gpg->pid, SIGTERM);
sleep (2);
if ( !waitpid (gpg->pid, NULL, WNOHANG) ) {
/* pay the murderer better and then forget about it */
kill (gpg->pid, SIGKILL);
}
gpg->running = 0;
}
#endif
}
void
_gpgme_gpg_enable_pipemode ( GpgObject gpg )
{
gpg->pm.used = 1;
assert ( !gpg->pm.sig );
assert ( !gpg->pm.text );
}
GpgmeError
_gpgme_gpg_add_arg ( GpgObject gpg, const char *arg )
{
struct arg_and_data_s *a;
assert (gpg);
assert (arg);
if (gpg->pm.active)
return 0;
a = xtrymalloc ( sizeof *a + strlen (arg) );
if ( !a ) {
gpg->arg_error = 1;
return mk_error(Out_Of_Core);
}
a->next = NULL;
a->data = NULL;
a->dup_to = -1;
strcpy ( a->arg, arg );
*gpg->argtail = a;
gpg->argtail = &a->next;
return 0;
}
GpgmeError
_gpgme_gpg_add_data ( GpgObject gpg, GpgmeData data, int dup_to )
{
struct arg_and_data_s *a;
assert (gpg);
assert (data);
if (gpg->pm.active)
return 0;
a = xtrymalloc ( sizeof *a - 1 );
if ( !a ) {
gpg->arg_error = 1;
return mk_error(Out_Of_Core);
}
a->next = NULL;
a->data = data;
if ( dup_to == -2 ) {
a->print_fd = 1;
a->dup_to = -1;
}
else {
a->print_fd = 0;
a->dup_to = dup_to;
}
*gpg->argtail = a;
gpg->argtail = &a->next;
return 0;
}
GpgmeError
_gpgme_gpg_add_pm_data ( GpgObject gpg, GpgmeData data, int what )
{
GpgmeError rc=0;
assert ( gpg->pm.used );
if ( !what ) {
/* the signature */
assert ( !gpg->pm.sig );
gpg->pm.sig = data;
}
else if (what == 1) {
/* the signed data */
assert ( !gpg->pm.text );
gpg->pm.text = data;
}
else {
assert (0);
}
if ( gpg->pm.sig && gpg->pm.text ) {
if ( !gpg->pm.active ) {
/* create the callback handler and connect it to stdin */
GpgmeData tmp;
rc = gpgme_data_new_with_read_cb ( &tmp, pipemode_cb, gpg );
if (!rc )
rc = _gpgme_gpg_add_data (gpg, tmp, 0);
}
if ( !rc ) {
/* here we can reset the handler stuff */
gpg->pm.stream_started = 0;
}
}
return rc;
}
/*
* Note, that the status_handler is allowed to modifiy the args value
*/
void
_gpgme_gpg_set_status_handler ( GpgObject gpg,
GpgStatusHandler fnc, void *fnc_value )
{
assert (gpg);
if (gpg->pm.active)
return;
gpg->status.fnc = fnc;
gpg->status.fnc_value = fnc_value;
}
/* Kludge to process --with-colon output */
GpgmeError
_gpgme_gpg_set_colon_line_handler ( GpgObject gpg,
GpgColonLineHandler fnc, void *fnc_value )
{
assert (gpg);
if (gpg->pm.active)
return 0;
gpg->colon.bufsize = 1024;
gpg->colon.readpos = 0;
gpg->colon.buffer = xtrymalloc (gpg->colon.bufsize);
if (!gpg->colon.buffer) {
return mk_error (Out_Of_Core);
}
if (_gpgme_io_pipe (gpg->colon.fd, 1) == -1) {
xfree (gpg->colon.buffer); gpg->colon.buffer = NULL;
return mk_error (Pipe_Error);
}
gpg->colon.eof = 0;
gpg->colon.fnc = fnc;
gpg->colon.fnc_value = fnc_value;
gpg->colon.simple = 0;
return 0;
}
GpgmeError
_gpgme_gpg_set_simple_line_handler ( GpgObject gpg,
GpgColonLineHandler fnc,
void *fnc_value )
{
GpgmeError err;
err = _gpgme_gpg_set_colon_line_handler (gpg, fnc, fnc_value);
if (!err)
gpg->colon.simple = 1;
return err;
}
/*
* The Fnc will be called to get a value for one of the commands with
* a key KEY. If the Code pssed to FNC is 0, the function may release
* resources associated with the returned value from another call. To
* match such a second call to a first call, the returned value from
* the first call is passed as keyword.
*/
GpgmeError
_gpgme_gpg_set_command_handler ( GpgObject gpg,
GpgCommandHandler fnc, void *fnc_value )
{
GpgmeData tmp;
GpgmeError err;
assert (gpg);
if (gpg->pm.active)
return 0;
err = gpgme_data_new_with_read_cb ( &tmp, command_cb, gpg );
if (err)
return err;
_gpgme_gpg_add_arg ( gpg, "--command-fd" );
_gpgme_gpg_add_data (gpg, tmp, -2);
gpg->cmd.cb_data = tmp;
gpg->cmd.fnc = fnc;
gpg->cmd.fnc_value = fnc_value;
gpg->cmd.used = 1;
return 0;
}
static void
free_argv ( char **argv )
{
int i;
for (i=0; argv[i]; i++ )
xfree (argv[i]);
xfree (argv);
}
static void
free_fd_data_map ( struct fd_data_map_s *fd_data_map )
{
int i;
if ( !fd_data_map )
return;
for (i=0; fd_data_map[i].data; i++ ) {
#if 0 /* fixme -> see gpg_release */
if ( fd_data_map[i].fd != -1 )
_gpgme_io_close (fd_data_map[i].fd);
if ( fd_data_map[i].peer_fd != -1 )
_gpgme_io_close (fd_data_map[i].peer_fd);
#endif
/* don't release data because this is only a reference */
}
xfree (fd_data_map);
}
static GpgmeError
build_argv ( GpgObject gpg )
{
struct arg_and_data_s *a;
struct fd_data_map_s *fd_data_map;
size_t datac=0, argc=0;
char **argv;
int need_special = 0;
int use_agent = !!getenv ("GPG_AGENT_INFO");
if ( gpg->argv ) {
free_argv ( gpg->argv );
gpg->argv = NULL;
}
if (gpg->fd_data_map) {
free_fd_data_map (gpg->fd_data_map);
gpg->fd_data_map = NULL;
}
argc++; /* for argv[0] */
for ( a=gpg->arglist; a; a = a->next ) {
argc++;
if (a->data) {
/*fprintf (stderr, "build_argv: data\n" );*/
datac++;
if ( a->dup_to == -1 && !a->print_fd )
need_special = 1;
}
else {
/* fprintf (stderr, "build_argv: arg=`%s'\n", a->arg );*/
}
}
if ( need_special )
argc++;
if (use_agent)
argc++;
if (!gpg->cmd.used)
argc++;
argv = xtrycalloc ( argc+1, sizeof *argv );
if (!argv)
return mk_error (Out_Of_Core);
fd_data_map = xtrycalloc ( datac+1, sizeof *fd_data_map );
if (!fd_data_map) {
free_argv (argv);
return mk_error (Out_Of_Core);
}
argc = datac = 0;
argv[argc] = xtrystrdup ( "gpg" ); /* argv[0] */
if (!argv[argc]) {
xfree (fd_data_map);
free_argv (argv);
return mk_error (Out_Of_Core);
}
argc++;
if ( need_special ) {
argv[argc] = xtrystrdup ( "--enable-special-filenames" );
if (!argv[argc]) {
xfree (fd_data_map);
free_argv (argv);
return mk_error (Out_Of_Core);
}
argc++;
}
if ( use_agent ) {
argv[argc] = xtrystrdup ( "--use-agent" );
if (!argv[argc]) {
xfree (fd_data_map);
free_argv (argv);
return mk_error (Out_Of_Core);
}
argc++;
}
if ( !gpg->cmd.used ) {
argv[argc] = xtrystrdup ( "--batch" );
if (!argv[argc]) {
xfree (fd_data_map);
free_argv (argv);
return mk_error (Out_Of_Core);
}
argc++;
}
for ( a=gpg->arglist; a; a = a->next ) {
if ( a->data ) {
switch ( _gpgme_data_get_mode (a->data) ) {
case GPGME_DATA_MODE_NONE:
case GPGME_DATA_MODE_INOUT:
xfree (fd_data_map);
free_argv (argv);
return mk_error (Invalid_Mode);
case GPGME_DATA_MODE_IN:
/* create a pipe to read from gpg */
fd_data_map[datac].inbound = 1;
break;
case GPGME_DATA_MODE_OUT:
/* create a pipe to pass it down to gpg */
fd_data_map[datac].inbound = 0;
break;
}
switch ( gpgme_data_get_type (a->data) ) {
case GPGME_DATA_TYPE_NONE:
if ( fd_data_map[datac].inbound )
break; /* allowed */
xfree (fd_data_map);
free_argv (argv);
return mk_error (Invalid_Type);
case GPGME_DATA_TYPE_MEM:
case GPGME_DATA_TYPE_CB:
break;
case GPGME_DATA_TYPE_FD:
case GPGME_DATA_TYPE_FILE:
xfree (fd_data_map);
free_argv (argv);
return mk_error (Not_Implemented);
}
/* create a pipe */
{
int fds[2];
if (_gpgme_io_pipe (fds, fd_data_map[datac].inbound?1:0 )
== -1) {
xfree (fd_data_map);
free_argv (argv);
return mk_error (Pipe_Error);
}
/* if the data_type is FD, we have to do a dup2 here */
if (fd_data_map[datac].inbound) {
fd_data_map[datac].fd = fds[0];
fd_data_map[datac].peer_fd = fds[1];
}
else {
fd_data_map[datac].fd = fds[1];
fd_data_map[datac].peer_fd = fds[0];
}
}
/* Hack to get hands on the fd later */
if ( gpg->cmd.used && gpg->cmd.cb_data == a->data ) {
assert (gpg->cmd.fd == -1);
gpg->cmd.fd = fd_data_map[datac].fd;
}
fd_data_map[datac].data = a->data;
fd_data_map[datac].dup_to = a->dup_to;
if ( a->dup_to == -1 ) {
argv[argc] = xtrymalloc ( 25 );
if (!argv[argc]) {
xfree (fd_data_map);
free_argv (argv);
return mk_error (Out_Of_Core);
}
sprintf ( argv[argc],
a->print_fd? "%d" : "-&%d",
fd_data_map[datac].peer_fd );
argc++;
}
datac++;
}
else {
argv[argc] = xtrystrdup ( a->arg );
if (!argv[argc]) {
xfree (fd_data_map);
free_argv (argv);
return mk_error (Out_Of_Core);
}
argc++;
}
}
gpg->argv = argv;
gpg->fd_data_map = fd_data_map;
return 0;
}
GpgmeError
_gpgme_gpg_spawn( GpgObject gpg, void *opaque )
{
int rc;
int i, n;
int pid;
struct spawn_fd_item_s *fd_child_list, *fd_parent_list;
if ( !gpg )
return mk_error (Invalid_Value);
/* Kludge, so that we don't need to check the return code of
* all the gpgme_gpg_add_arg(). we bail out here instead */
if ( gpg->arg_error )
return mk_error (Out_Of_Core);
if (gpg->pm.active)
return 0;
rc = build_argv ( gpg );
if ( rc )
return rc;
n = 4; /* status fd, 2*colon_fd and end of list */
for (i=0; gpg->fd_data_map[i].data; i++ )
n += 2;
fd_child_list = xtrycalloc ( n+n, sizeof *fd_child_list );
if (!fd_child_list)
return mk_error (Out_Of_Core);
fd_parent_list = fd_child_list + n;
/* build the fd list for the child */
n=0;
fd_child_list[n].fd = gpg->status.fd[0];
fd_child_list[n].dup_to = -1;
n++;
if ( gpg->colon.fnc ) {
fd_child_list[n].fd = gpg->colon.fd[0];
fd_child_list[n].dup_to = -1;
n++;
fd_child_list[n].fd = gpg->colon.fd[1];
fd_child_list[n].dup_to = 1; /* dup to stdout */
n++;
}
for (i=0; gpg->fd_data_map[i].data; i++ ) {
fd_child_list[n].fd = gpg->fd_data_map[i].fd;
fd_child_list[n].dup_to = -1;
n++;
if (gpg->fd_data_map[i].dup_to != -1) {
fd_child_list[n].fd = gpg->fd_data_map[i].peer_fd;
fd_child_list[n].dup_to = gpg->fd_data_map[i].dup_to;
n++;
}
}
fd_child_list[n].fd = -1;
fd_child_list[n].dup_to = -1;
/* build the fd list for the parent */
n=0;
if ( gpg->status.fd[1] != -1 ) {
fd_parent_list[n].fd = gpg->status.fd[1];
fd_parent_list[n].dup_to = -1;
n++;
gpg->status.fd[1] = -1;
}
if ( gpg->colon.fd[1] != -1 ) {
fd_parent_list[n].fd = gpg->colon.fd[1];
fd_parent_list[n].dup_to = -1;
n++;
gpg->colon.fd[1] = -1;
}
for (i=0; gpg->fd_data_map[i].data; i++ ) {
fd_parent_list[n].fd = gpg->fd_data_map[i].peer_fd;
fd_parent_list[n].dup_to = -1;
n++;
gpg->fd_data_map[i].peer_fd = -1;
}
fd_parent_list[n].fd = -1;
fd_parent_list[n].dup_to = -1;
- pid = _gpgme_io_spawn (GPG_PATH, gpg->argv, fd_child_list, fd_parent_list);
+ pid = _gpgme_io_spawn (_gpgme_get_gpg_path (),
+ gpg->argv, fd_child_list, fd_parent_list);
xfree (fd_child_list);
if (pid == -1) {
return mk_error (Exec_Error);
}
gpg->pid = pid;
if (gpg->pm.used)
gpg->pm.active = 1;
/*_gpgme_register_term_handler ( closure, closure_value, pid );*/
if ( _gpgme_register_pipe_handler ( opaque, gpg_status_handler,
gpg, pid, gpg->status.fd[0], 1 ) ) {
/* FIXME: kill the child */
return mk_error (General_Error);
}
if ( gpg->colon.fnc ) {
assert ( gpg->colon.fd[0] != -1 );
if ( _gpgme_register_pipe_handler ( opaque, gpg_colon_line_handler,
gpg, pid, gpg->colon.fd[0], 1 ) ) {
/* FIXME: kill the child */
return mk_error (General_Error);
}
}
for (i=0; gpg->fd_data_map[i].data; i++ ) {
/* Due to problems with select and write we set outbound pipes
* to non-blocking */
if (!gpg->fd_data_map[i].inbound) {
_gpgme_io_set_nonblocking (gpg->fd_data_map[i].fd);
}
if ( _gpgme_register_pipe_handler (
opaque,
gpg->fd_data_map[i].inbound?
gpg_inbound_handler:gpg_outbound_handler,
gpg->fd_data_map[i].data,
pid, gpg->fd_data_map[i].fd,
gpg->fd_data_map[i].inbound )
) {
/* FIXME: kill the child */
return mk_error (General_Error);
}
}
if ( gpg->cmd.used )
_gpgme_freeze_fd ( gpg->cmd.fd );
/* fixme: check what data we can release here */
gpg->running = 1;
return 0;
}
static int
gpg_inbound_handler ( void *opaque, int pid, int fd )
{
GpgmeData dh = opaque;
GpgmeError err;
int nread;
char buf[200];
assert ( _gpgme_data_get_mode (dh) == GPGME_DATA_MODE_IN );
nread = _gpgme_io_read (fd, buf, 200 );
if ( nread < 0 ) {
DEBUG3 ("read_mem_data: read failed on fd %d (n=%d): %s",
fd, nread, strerror (errno) );
return 1;
}
else if (!nread)
return 1; /* eof */
/* We could improve this with a GpgmeData function which takes
* the read function or provides a memory area for writing to it.
*/
err = _gpgme_data_append ( dh, buf, nread );
if ( err ) {
DEBUG1 ("_gpgme_append_data failed: %s\n",
gpgme_strerror(err));
/* Fixme: we should close the pipe or read it to /dev/null in
* this case. Returnin EOF is not sufficient */
return 1;
}
return 0;
}
static int
write_mem_data ( GpgmeData dh, int fd )
{
size_t nbytes;
int nwritten;
nbytes = dh->len - dh->readpos;
if ( !nbytes ) {
_gpgme_io_close (fd);
return 1;
}
/* FIXME: Arggg, the pipe blocks on large write request, although
* select told us that it is okay to write - need to figure out
* why this happens? Stevens says nothing about this problem (or
* is it my Linux kernel 2.4.0test1)
* To avoid that we have set the pipe to nonblocking.
*/
nwritten = _gpgme_io_write ( fd, dh->data+dh->readpos, nbytes );
if (nwritten == -1 && errno == EAGAIN )
return 0;
if ( nwritten < 1 ) {
DEBUG3 ("write_mem_data(%d): write failed (n=%d): %s",
fd, nwritten, strerror (errno) );
_gpgme_io_close (fd);
return 1;
}
dh->readpos += nwritten;
return 0;
}
static int
write_cb_data ( GpgmeData dh, int fd )
{
size_t nbytes;
int err, nwritten;
char buffer[512];
err = gpgme_data_read ( dh, buffer, DIM(buffer), &nbytes );
if (err == GPGME_EOF) {
_gpgme_io_close (fd);
return 1;
}
nwritten = _gpgme_io_write ( fd, buffer, nbytes );
if (nwritten == -1 && errno == EAGAIN )
return 0;
if ( nwritten < 1 ) {
DEBUG3 ("write_cb_data(%d): write failed (n=%d): %s",
fd, nwritten, strerror (errno) );
_gpgme_io_close (fd);
return 1;
}
if ( nwritten < nbytes ) {
/* ugly, ugly: It does currently only for for MEM type data */
if ( _gpgme_data_unread (dh, buffer + nwritten, nbytes - nwritten ) )
DEBUG1 ("wite_cb_data: unread of %d bytes failed\n",
nbytes - nwritten );
_gpgme_io_close (fd);
return 1;
}
return 0;
}
static int
gpg_outbound_handler ( void *opaque, int pid, int fd )
{
GpgmeData dh = opaque;
assert ( _gpgme_data_get_mode (dh) == GPGME_DATA_MODE_OUT );
switch ( gpgme_data_get_type (dh) ) {
case GPGME_DATA_TYPE_MEM:
if ( write_mem_data ( dh, fd ) )
return 1; /* ready */
break;
case GPGME_DATA_TYPE_CB:
if (write_cb_data (dh, fd))
return 1; /* ready */
break;
default:
assert (0);
}
return 0;
}
static int
gpg_status_handler ( void *opaque, int pid, int fd )
{
GpgObject gpg = opaque;
int rc = 0;
assert ( fd == gpg->status.fd[0] );
rc = read_status ( gpg );
if ( rc ) {
DEBUG1 ("gpg_handler: read_status problem %d\n - stop", rc);
return 1;
}
return gpg->status.eof;
}
static int
status_cmp (const void *ap, const void *bp)
{
const struct status_table_s *a = ap;
const struct status_table_s *b = bp;
return strcmp (a->name, b->name);
}
/*
* Handle the status output of GnuPG. This function does read entire
* lines and passes them as C strings to the callback function (we can
* use C Strings because the status output is always UTF-8 encoded).
* Of course we have to buffer the lines to cope with long lines
* e.g. with a large user ID. Note: We can optimize this to only cope
* with status line code we know about and skip all other stuff
* without buffering (i.e. without extending the buffer). */
static GpgmeError
read_status ( GpgObject gpg )
{
char *p;
int nread;
size_t bufsize = gpg->status.bufsize;
char *buffer = gpg->status.buffer;
size_t readpos = gpg->status.readpos;
assert (buffer);
if (bufsize - readpos < 256) {
/* need more room for the read */
bufsize += 1024;
buffer = xtryrealloc (buffer, bufsize);
if ( !buffer )
return mk_error (Out_Of_Core);
}
nread = _gpgme_io_read ( gpg->status.fd[0],
buffer+readpos, bufsize-readpos );
if (nread == -1)
return mk_error(Read_Error);
if (!nread) {
gpg->status.eof = 1;
if (gpg->status.fnc)
gpg->status.fnc ( gpg->status.fnc_value, STATUS_EOF, "" );
return 0;
}
while (nread > 0) {
for (p = buffer + readpos; nread; nread--, p++) {
if ( *p == '\n' ) {
/* (we require that the last line is terminated by a LF) */
*p = 0;
/*fprintf (stderr, "read_status: `%s'\n", buffer);*/
if (!strncmp (buffer, "[GNUPG:] ", 9 )
&& buffer[9] >= 'A' && buffer[9] <= 'Z' ) {
struct status_table_s t, *r;
char *rest;
rest = strchr (buffer+9, ' ');
if ( !rest )
rest = p; /* set to an empty string */
else
*rest++ = 0;
t.name = buffer+9;
/* (the status table as one extra element) */
r = bsearch ( &t, status_table, DIM(status_table)-1,
sizeof t, status_cmp );
if ( r ) {
if ( gpg->cmd.used
&& ( r->code == STATUS_GET_BOOL
|| r->code == STATUS_GET_LINE
|| r->code == STATUS_GET_HIDDEN )) {
gpg->cmd.code = r->code;
xfree (gpg->cmd.keyword);
gpg->cmd.keyword = xtrystrdup (rest);
if ( !gpg->cmd.keyword )
return mk_error (Out_Of_Core);
/* this should be the last thing we have received
* and the next thing will be that the command
* handler does its action */
if ( nread > 1 )
DEBUG0 ("ERROR, unexpected data in read_status");
_gpgme_thaw_fd (gpg->cmd.fd);
}
else if ( gpg->status.fnc ) {
gpg->status.fnc ( gpg->status.fnc_value,
r->code, rest);
}
}
if ( r->code == STATUS_END_STREAM ) {
/* _gpgme_freeze_fd ( ? );*/
}
}
/* To reuse the buffer for the next line we have to
* shift the remaining data to the buffer start and
* restart the loop Hmmm: We can optimize this
* function by looking forward in the buffer to see
* whether a second complete line is available and in
* this case avoid the memmove for this line. */
nread--; p++;
if (nread)
memmove (buffer, p, nread);
readpos = 0;
break; /* the for loop */
}
else
readpos++;
}
}
/* Update the gpg object. */
gpg->status.bufsize = bufsize;
gpg->status.buffer = buffer;
gpg->status.readpos = readpos;
return 0;
}
/*
* This colonline handler thing is not the clean way to do it.
* It might be better to enhance the GpgmeData object to act as
* a wrapper for a callback. Same goes for the status thing.
* For now we use this thing here becuase it is easier to implement.
*/
static int
gpg_colon_line_handler ( void *opaque, int pid, int fd )
{
GpgObject gpg = opaque;
GpgmeError rc = 0;
assert ( fd == gpg->colon.fd[0] );
rc = read_colon_line ( gpg );
if ( rc ) {
DEBUG1 ("gpg_colon_line_handler: "
"read problem %d\n - stop", rc);
return 1;
}
return gpg->status.eof;
}
static GpgmeError
read_colon_line ( GpgObject gpg )
{
char *p;
int nread;
size_t bufsize = gpg->colon.bufsize;
char *buffer = gpg->colon.buffer;
size_t readpos = gpg->colon.readpos;
assert (buffer);
if (bufsize - readpos < 256) {
/* need more room for the read */
bufsize += 1024;
buffer = xtryrealloc (buffer, bufsize);
if ( !buffer )
return mk_error (Out_Of_Core);
}
nread = _gpgme_io_read ( gpg->colon.fd[0],
buffer+readpos, bufsize-readpos );
if (nread == -1)
return mk_error(Read_Error);
if (!nread) {
gpg->colon.eof = 1;
assert (gpg->colon.fnc);
gpg->colon.fnc ( gpg->colon.fnc_value, NULL );
return 0;
}
while (nread > 0) {
for (p = buffer + readpos; nread; nread--, p++) {
if ( *p == '\n' ) {
/* (we require that the last line is terminated by a
* LF) and we skip empty lines. Note: we use UTF8
* encoding and escaping of special characters
* We require at least one colon to cope with
* some other printed information.
*/
*p = 0;
if ( gpg->colon.simple
|| (*buffer && strchr (buffer, ':')) ) {
assert (gpg->colon.fnc);
gpg->colon.fnc ( gpg->colon.fnc_value, buffer );
}
/* To reuse the buffer for the next line we have to
* shift the remaining data to the buffer start and
* restart the loop Hmmm: We can optimize this
* function by looking forward in the buffer to see
* whether a second complete line is available and in
* this case avoid the memmove for this line. */
nread--; p++;
if (nread)
memmove (buffer, p, nread);
readpos = 0;
break; /* the for loop */
}
else
readpos++;
}
}
/* Update the gpg object. */
gpg->colon.bufsize = bufsize;
gpg->colon.buffer = buffer;
gpg->colon.readpos = readpos;
return 0;
}
static GpgmeError
pipemode_copy (char *buffer, size_t length, size_t *nread, GpgmeData data )
{
GpgmeError err;
int nbytes;
char tmp[1000], *s, *d;
/* we can optimize this whole thing but for now we just
* return after each escape character */
if (length > 990)
length = 990;
err = gpgme_data_read ( data, tmp, length, &nbytes );
if (err)
return err;
for (s=tmp, d=buffer; nbytes; s++, nbytes--) {
*d++ = *s;
if (*s == '@' ) {
*d++ = '@';
break;
}
}
*nread = d - buffer;
return 0;
}
static int
pipemode_cb ( void *opaque, char *buffer, size_t length, size_t *nread )
{
GpgObject gpg = opaque;
GpgmeError err;
if ( !buffer || !length || !nread )
return 0; /* those values are reserved for extensions */
*nread =0;
if ( !gpg->pm.stream_started ) {
assert (length > 4 );
strcpy (buffer, "@<@B" );
*nread = 4;
gpg->pm.stream_started = 1;
}
else if ( gpg->pm.sig ) {
err = pipemode_copy ( buffer, length, nread, gpg->pm.sig );
if ( err == GPGME_EOF ) {
gpg->pm.sig = NULL;
assert (length > 4 );
strcpy (buffer, "@t" );
*nread = 2;
}
else if (err) {
DEBUG1 ("pipemode_cb: copy sig failed: %s\n",
gpgme_strerror (err) );
return -1;
}
}
else if ( gpg->pm.text ) {
err = pipemode_copy ( buffer, length, nread, gpg->pm.text );
if ( err == GPGME_EOF ) {
gpg->pm.text = NULL;
assert (length > 4 );
strcpy (buffer, "@.@>" );
*nread = 4;
}
else if (err) {
DEBUG1 ("pipemode_cb: copy data failed: %s\n",
gpgme_strerror (err) );
return -1;
}
}
else {
return 0; /* eof */
}
return 0;
}
/*
* Here we handle --command-fd. This works closely together with
* the status handler.
*/
static int
command_cb ( void *opaque, char *buffer, size_t length, size_t *nread )
{
GpgObject gpg = opaque;
const char *value;
int value_len;
DEBUG0 ("command_cb: enter\n");
assert (gpg->cmd.used);
if ( !buffer || !length || !nread )
return 0; /* those values are reserved for extensions */
*nread =0;
if ( !gpg->cmd.code ) {
DEBUG0 ("command_cb: no code\n");
return -1;
}
if ( !gpg->cmd.fnc ) {
DEBUG0 ("command_cb: no user cb\n");
return -1;
}
value = gpg->cmd.fnc ( gpg->cmd.fnc_value,
gpg->cmd.code, gpg->cmd.keyword );
if ( !value ) {
DEBUG0 ("command_cb: no data from user cb\n");
gpg->cmd.fnc ( gpg->cmd.fnc_value, 0, value);
return -1;
}
value_len = strlen (value);
if ( value_len+1 > length ) {
DEBUG0 ("command_cb: too much data from user cb\n");
gpg->cmd.fnc ( gpg->cmd.fnc_value, 0, value);
return -1;
}
memcpy ( buffer, value, value_len );
if ( !value_len || (value_len && value[value_len-1] != '\n') )
buffer[value_len++] = '\n';
*nread = value_len;
gpg->cmd.fnc ( gpg->cmd.fnc_value, 0, value);
gpg->cmd.code = 0;
/* and sleep again until read_status will wake us up again */
_gpgme_freeze_fd ( gpg->cmd.fd );
return 0;
}
diff --git a/trunk/gpgme/util.h b/trunk/gpgme/util.h
index 65bfa2b4..0d901e65 100644
--- a/trunk/gpgme/util.h
+++ b/trunk/gpgme/util.h
@@ -1,126 +1,131 @@
/* util.h
* Copyright (C) 2000 Werner Koch (dd9jn)
*
* This file is part of GPGME.
*
* GPGME is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GPGME is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifndef UTIL_H
#define UTIL_H
#include "types.h"
void *_gpgme_malloc (size_t n );
void *_gpgme_calloc (size_t n, size_t m );
void *_gpgme_realloc (void *p, size_t n);
char *_gpgme_strdup (const char *p);
void _gpgme_free ( void *a );
#define xtrymalloc(a) _gpgme_malloc((a))
#define xtrycalloc(a,b) _gpgme_calloc((a),(b))
#define xtryrealloc(a,b) _gpgme_realloc((a),(b))
#define xtrystrdup(a) _gpgme_strdup((a))
#define xfree(a) _gpgme_free((a))
#define mk_error(a) ( GPGME_##a )
#define DIM(v) (sizeof(v)/sizeof((v)[0]))
#define DIMof(type,member) DIM(((type *)0)->member)
#ifndef STR
#define STR(v) #v
#endif
#define STR2(v) STR(v)
void _gpgme_debug (int level, const char *format, ...);
void _gpgme_debug_begin ( void **helper, int level, const char *text);
int _gpgme_debug_enabled ( void **helper );
void _gpgme_debug_add (void **helper, const char *format, ...);
void _gpgme_debug_end (void **helper, const char *text);
#define DEBUG0(x) _gpgme_debug (1, __FILE__ ":" \
STR2 (__LINE__) ": " x )
#define DEBUG1(x,a) _gpgme_debug (1, __FILE__ ":" \
STR2 (__LINE__)": " x, (a) )
#define DEBUG2(x,a,b) _gpgme_debug (1, __FILE__ ":" \
STR2 (__LINE__) ": " x, (a), (b) )
#define DEBUG3(x,a,b,c) _gpgme_debug (1, __FILE__ ":" \
STR2 (__LINE__) ": " x, (a), (b), (c) )
#define DEBUG4(x,a,b,c,d) _gpgme_debug (1, __FILE__ ":" \
STR2 (__LINE__) ": " x, (a), (b), (c), (d) )
#define DEBUG5(x,a,b,c,d,e) _gpgme_debug (1, __FILE__ ":" \
STR2 (__LINE__) ": " x, (a), (b), (c), (d), (e) )
#define DEBUG6(x,a,b,c,d,e,f) _gpgme_debug (1, __FILE__ ":" \
STR2 (__LINE__) ": " x, (a), (b), (c), (d), (e), (f) )
#define DEBUG7(x,a,b,c,d,e,f,g) _gpgme_debug (1, __FILE__ ":" \
STR2 (__LINE__) ": " x, (a), (b), (c), (d), (e), (f), (g) )
#define DEBUG8(x,a,b,c,d,e,f,g,h) _gpgme_debug (1, __FILE__ ":" \
STR2 (__LINE__) ": " x, (a), (b), (c), (d), (e), (f), (g), (h) )
#define DEBUG9(x,a,b,c,d,e,f,g,h,i) _gpgme_debug (1, __FILE__ ":" \
STR2 (__LINE__) ": " x, (a), (b), (c), (d), (e), (f), (g), (h), (i) )
#define DEBUG10(x,a,b,c,d,e,f,g,h,i,j) _gpgme_debug (1, __FILE__ ":" \
STR2 (__LINE__) ": " x, (a), (b), (c), (d), (e), (f), (g), (h), (i), (j) )
#define DEBUG_BEGIN(y,x) _gpgme_debug_begin (&(y), 1, __FILE__ ":" \
STR2 (__LINE__) ": " x )
#define DEBUG_ENABLED(y) _gpgme_debug_enabled(&(y))
#define DEBUG_ADD0(y,x) _gpgme_debug_add (&(y), (x), \
)
#define DEBUG_ADD1(y,x,a) _gpgme_debug_add (&(y), (x), \
(a) )
#define DEBUG_ADD2(y,x,a,b) _gpgme_debug_add (&(y), (x), \
(a), (b) )
#define DEBUG_ADD3(y,x,a,b,c) _gpgme_debug_add (&(y), (x), \
(a), (b), (c) )
#define DEBUG_ADD4(y,x,a,b,c,d) _gpgme_debug_add (&(y), (x), \
(a), (b), (c), (d) )
#define DEBUG_ADD5(y,x,a,b,c,d,e) _gpgme_debug_add (&(y), (x), \
(a), (b), (c), (d), (e) )
#define DEBUG_END(y,x) _gpgme_debug_end (&(y), (x) )
#ifndef HAVE_STPCPY
char *stpcpy (char *a, const char *b);
#endif
#define return_if_fail(expr) do { \
if (!(expr)) { \
fprintf (stderr, "%s:%d: assertion `%s' failed", \
__FILE__, __LINE__, #expr ); \
return; \
} } while (0)
#define return_null_if_fail(expr) do { \
if (!(expr)) { \
fprintf (stderr, "%s:%d: assertion `%s' failed", \
__FILE__, __LINE__, #expr ); \
return NULL; \
} } while (0)
#define return_val_if_fail(expr,val) do { \
if (!(expr)) { \
fprintf (stderr, "%s:%d: assertion `%s' failed", \
__FILE__, __LINE__, #expr ); \
return (val); \
} } while (0)
+/*-- {posix,w32}-util.c --*/
+const char *_gpgme_get_gpg_path (void);
+
+
+
#endif /* UTIL_H */
diff --git a/trunk/gpgme/w32-util.c b/trunk/gpgme/w32-util.c
new file mode 100644
index 00000000..f1001a68
--- /dev/null
+++ b/trunk/gpgme/w32-util.c
@@ -0,0 +1,114 @@
+/* w32-util.c - Utility functions for the W32 API
+ * Copyright (C) 2001 Werner Koch (dd9jn)
+ * Copyright (C) 1999 Free Software Foundation, Inc
+ *
+ * This file is part of GPGME.
+ *
+ * GPGME is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GPGME is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#include <config.h>
+#ifdef HAVE_DOSISH_SYSTEM
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <windows.h>
+#include "syshdr.h"
+
+#include "util.h"
+
+/****************
+ * Return a string from the Win32 Registry or NULL in case of
+ * error. Caller must release the return value. A NULL for root
+ * is an alias fro HKEY_CURRENT_USER
+ */
+static char *
+read_w32_registry_string ( const char *root,
+ const char *dir, const char *name )
+{
+ HKEY root_key, key_handle;
+ DWORD n1, nbytes;
+ char *result = NULL;
+
+ if( !root )
+ root_key = HKEY_CURRENT_USER;
+ else if( !strcmp( root, "HKEY_CLASSES_ROOT" ) )
+ root_key = HKEY_CLASSES_ROOT;
+ else if( !strcmp( root, "HKEY_CURRENT_USER" ) )
+ root_key = HKEY_CURRENT_USER;
+ else if( !strcmp( root, "HKEY_LOCAL_MACHINE" ) )
+ root_key = HKEY_LOCAL_MACHINE;
+ else if( !strcmp( root, "HKEY_USERS" ) )
+ root_key = HKEY_USERS;
+ else if( !strcmp( root, "HKEY_PERFORMANCE_DATA" ) )
+ root_key = HKEY_PERFORMANCE_DATA;
+ else if( !strcmp( root, "HKEY_CURRENT_CONFIG" ) )
+ root_key = HKEY_CURRENT_CONFIG;
+ else
+ return NULL;
+
+ if( RegOpenKeyEx( root_key, dir, 0, KEY_READ, &key_handle ) )
+ return NULL; /* no need for a RegClose, so return direct */
+
+ nbytes = 1;
+ if( RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes ) )
+ goto leave;
+ result = xtrymalloc( (n1=nbytes+1) );
+ if( !result )
+ goto leave;
+ if( RegQueryValueEx( key_handle, name, 0, NULL, result, &n1 ) ) {
+ xfree(result); result = NULL;
+ goto leave;
+ }
+ result[nbytes] = 0; /* make sure it is really a string */
+
+ leave:
+ RegCloseKey( key_handle );
+ return result;
+}
+
+
+const char *
+_gpgme_get_gpg_path (void)
+{
+ static char *gpg_program = NULL;
+
+ if (!gpg_program) {
+ gpg_program = read_w32_registry_string ( NULL,
+ "Software\\GNU\\GnuPG", "gpgProgram" );
+ if (!gpg_program)
+ gpg_program = GPG_PATH;
+ }
+
+ return gpg_program;
+}
+
+
+
+
+#endif /*HAVE_DOSISH_SYSTEM*/
+
+
+
+
+

File Metadata

Mime Type
text/x-diff
Expires
Tue, Dec 16, 4:43 AM (1 d, 16 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
98/0d/7e4ce4a574830bc0a53620f9f8b4

Event Timeline