This commit was manufactured by cvs2svn to create tag 'GPGME-0-1-3'.

This commit is contained in:
Repo Admin 2000-12-19 10:09:11 +00:00
parent 8e92991dda
commit 9541ca1f79
93 changed files with 14327 additions and 0 deletions

0
tags/GPGME-0-1-3/AUTHORS Normal file
View File

View File

182
tags/GPGME-0-1-3/INSTALL Normal file
View File

@ -0,0 +1,182 @@
Basic Installation
==================
These are generic installation instructions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, a file
`config.cache' that saves the results of its tests to speed up
reconfiguring, and a file `config.log' containing compiler output
(useful mainly for debugging `configure').
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If at some point `config.cache'
contains results you don't want to keep, you may remove or edit it.
The file `configure.in' is used to create `configure' by a program
called `autoconf'. You only need `configure.in' if you want to change
it or regenerate `configure' using a newer version of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. You can give `configure'
initial values for variables by setting them in the environment. Using
a Bourne-compatible shell, you can do that on the command line like
this:
CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
Or on systems that have the `env' program, you can do it like this:
env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not supports the `VPATH'
variable, you have to compile the package for one architecture at a time
in the source code directory. After you have installed the package for
one architecture, use `make distclean' before reconfiguring for another
architecture.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PATH', the package will use
PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=PATH' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' can not figure out
automatically, but needs to determine by the type of host the package
will run on. Usually `configure' can figure that out, but if it prints
a message saying it can not guess the host type, give it the
`--host=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name with three fields:
CPU-COMPANY-SYSTEM
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the host type.
If you are building compiler tools for cross-compiling, you can also
use the `--target=TYPE' option to select the type of system they will
produce code for and the `--build=TYPE' option to select the type of
system on which you are compiling the package.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Operation Controls
==================
`configure' recognizes the following options to control how it
operates.
`--cache-file=FILE'
Use and save the results of the tests in FILE instead of
`./config.cache'. Set FILE to `/dev/null' to disable caching, for
debugging `configure'.
`--help'
Print a summary of the options to `configure', and exit.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`--version'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`configure' also accepts some other, not widely useful, options.

View File

@ -0,0 +1,18 @@
EXTRA_DIST = README-alpha build-w32
if BUILD_BONOBO
bonobo = bonobo
else
bonobo =
endif
if BUILD_COMPLUS
complus = complus
else
complus =
endif
SUBDIRS = jnlib gpgme tests ${bonobo} ${complus}

0
tags/GPGME-0-1-3/NEWS Normal file
View File

25
tags/GPGME-0-1-3/README Normal file
View File

@ -0,0 +1,25 @@
GPGME - GnuPG Made Easy
---------------------------
!!!! THIS IS WORK IN PROGRESS !!!
If you want to hack on it, start with one of the tests/t-foo programs.
You need the latest CVS version of GnuPG 1.0, see
http://www.gnupg.org/cvs-access.html . If you use passphrases for
your keys, you should get the gpg-agent which comes with the GnuPG
unstable version (either CVS HEAD or
ftp.gnupg.org/pub/gcrypt/alpha/gnupg/gnupg-1.1.2.tar.gz) and install
the agent from the agent subdirectory or use the new
gpgme_set_passphrase_cb()
Please subscribe to the gnupg-devel@gnupg.org mailing list if you want
to do serious work.

View File

@ -0,0 +1 @@
THIS IS WORK IN PROGRESS !!!!

View File

@ -0,0 +1,58 @@
/* acconfig.h - used by autoheader to make config.h.in
* 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 GPGME_CONFIG_H
#define GPGME_CONFIG_H
/* need this, because some autoconf tests rely on this (e.g. stpcpy)
* and it should be used for new programs */
#define _GNU_SOURCE 1
/* To allow the use of gpgme in multithreaded programs we have to use
* special features from the library.
* IMPORTANT: gpgme is not yet fully reentrant and you should use it
* only from one thread. */
#define _REENTRANT 1
@TOP@
/* defined if we run on some of the PCDOS like systems (DOS, Windoze. OS/2)
* with special properties like no file modes */
#undef HAVE_DOSISH_SYSTEM
/* defined if the filesystem uses driver letters */
#undef HAVE_DRIVE_LETTERS
/* Some systems have a mkdir that takes a single argument. */
#undef MKDIR_TAKES_ONE_ARG
/* path to the gpg binary */
#undef GPG_PATH
/* stuff needed by lnlib/ */
#undef HAVE_BYTE_TYPEDEF
#undef HAVE_USHORT_TYPEDEF
#undef HAVE_ULONG_TYPEDEF
#undef HAVE_U16_TYPEDEF
#undef HAVE_U32_TYPEDEF
@BOTTOM@
/* not yet needed #include "gpgme-defs.h"*/
#endif /*GPGME_CONFIG_H*/

View File

@ -0,0 +1,44 @@
dnl Macros to configure gpgme
dnl GNUPG_FIX_HDR_VERSION(FILE, NAME)
dnl (wk 2000-11-17)
AC_DEFUN(GNUPG_FIX_HDR_VERSION,
[ sed "s/^#define $2 \".*/#define $2 \"$VERSION\"/" $srcdir/$1 > $srcdir/$1.tmp
if cmp -s $srcdir/$1 $srcdir/$1.tmp 2>/dev/null; then
rm -f $srcdir/$1.tmp
else
rm -f $srcdir/$1
if mv $srcdir/$1.tmp $srcdir/$1 ; then
:
else
AC_MSG_ERROR([[
*** Failed to fix the version string macro $2 in $1.
*** The old file has been saved as $1.tmp
]])
fi
AC_MSG_WARN([fixed the $2 macro in $1])
fi
])
dnl GNUPG_CHECK_TYPEDEF(TYPE, HAVE_NAME)
dnl Check whether a typedef exists and create a #define $2 if it exists
dnl
AC_DEFUN(GNUPG_CHECK_TYPEDEF,
[ AC_MSG_CHECKING(for $1 typedef)
AC_CACHE_VAL(gnupg_cv_typedef_$1,
[AC_TRY_COMPILE([#include <stdlib.h>
#include <sys/types.h>], [
#undef $1
int a = sizeof($1);
], gnupg_cv_typedef_$1=yes, gnupg_cv_typedef_$1=no )])
AC_MSG_RESULT($gnupg_cv_typedef_$1)
if test "$gnupg_cv_typedef_$1" = yes; then
AC_DEFINE($2)
fi
])

View File

@ -0,0 +1,11 @@
## Process this file with automake to produce Makefile.in
bin_PROGRAMS = gpgme
INCLUDES = -I$(top_srcdir)/jnlib
LDADD = -L ../jnlib -ljnlib
gpgme_SOURCES = main.c main.h

View File

@ -0,0 +1,20 @@
/* gpgme - Bonbobo component to access GnuPG
* 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
*/

View File

@ -0,0 +1,20 @@
/* main.c - Bonbobo component to access GnuPG
* 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
*/

View File

@ -0,0 +1,42 @@
/* main.h - GPGME Bonobo component
* 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 MAIN_H
#define MAIN_H
struct {
int verbose;
int quiet;
unsigned int debug;
char *homedir;
} opt;
#endif /* MAIN_H */

11
tags/GPGME-0-1-3/build-w32 Executable file
View File

@ -0,0 +1,11 @@
#!/bin/sh
target=i386--mingw32
host=`./config.guess`
CC="${target}-gcc"
CPP="${target}-gcc -E"
RANLIB="${target}-ranlib"
export CC CPP RANLIB
./configure --host=${host} --target=${target} $*

View File

@ -0,0 +1,17 @@
## Process this file with automake to produce Makefile.in
EXTRA_DIST = WINE-LICENSE WINE-AUTHORS
# No need to install this becuase we are cross-compiling anyway.
noinst_PROGRAMS = gpgcom
INCLUDES = -I$(top_srcdir)/jnlib
LDADD = -L ../jnlib -ljnlib
comheaders = obj_base.h basetsd.h guiddef.h wtypes.h
gpgcom_SOURCES = main.c main.h \
$(comheaders) \
ignupg.c ignupg.h

View File

@ -0,0 +1,331 @@
@c This file is processed by GNU's TeXinfo
@c If you modify it or move it to another location, make sure that
@c TeXinfo works (type `make' in directory documentation).
@c This is a list of the Wine authors and copyright holders.
Wine is available thanks to the work of:
James Abbatiello,
Michael Abd-El-Malek,
Howard Abrams,
Mark G. Adams,
Bruno Afonso,
Samir Al-Battran,
Guy Albertelli,
Gustavo Junior Alves,
Bob Amstadt,
Dag Asheim,
Jim Aston,
Martin Ayotte,
Viktor Babrian,
Karl Backström,
Bradley Baetz,
Peter Bajusz,
Andre Malafaya Baptista,
Aaron Barnes,
Jean-Claude Batista,
Marcel Baur,
Francis Beaudet,
Tom Bech,
Matthew Becker,
Georg Beyerle,
Ross Biro,
Dennis Björklund,
Zygo Blaxell,
Martin Boehme,
Francois Boisvert,
Pim Bollen,
Uwe Bonnes,
Peter Bortas,
Noel Borthwick,
Erik Bos,
Fons Botman,
Sylvain Bouchard,
Frederic Boulanger,
Justin Bradford,
John Brezak,
Andrew Bulhak,
John Burton,
Jonathan Buzzard,
Jose Marcos López Caravaca,
Eddie Carpenter,
Niels de Carpentier,
Mike Castle,
Ron Cemer,
Gordon Chaffee,
Gael de Chalendar,
Jimen Ching,
Geoff Clare,
Robert 'Admiral' Coeyman,
Richard Cohen,
Jean-Claude Cote,
Stephen Crowley,
Pascal Cuoq,
David A. Cuthbert,
Brian Joseph Czapiga,
Ulrich Czekalla,
Huw D. M. Davies,
Moses DeJong,
Petar Djukic,
Roman Dolejsi,
Frans van Dorsselaer,
Rikhardur Egilsson,
Morten Eriksen,
Chris Faherty,
Carsten Fallesen,
Paul Falstad,
David Faure,
Wesley Filardo,
Claus Fischer,
Olaf Flebbe,
Chad Fraleigh,
Matthew Francis,
Philippe Froidevaux,
Peter Galbavy,
Peter Ganten,
Ramon Garcia,
Jeff Garzik,
Julio Cesar Gazquez,
Klaas van Gend,
Abey George,
Brian Gerst,
Matthew Ghio,
Jody Goldberg,
David Golding,
François Gouget,
Hans de Graaff,
David Grant,
Albert den Haan,
Jess Haas,
Robert W Hall,
Noomen Hamza,
Charles M. Hannum,
Adrian Harvey,
John Harvey,
James Hatheway,
Kalevi J Hautaniemi,
Bill Hawes,
Lars Heete,
Cameron Heide,
Bernd Herd,
Theodore S. Hetke,
Haithem Hmida,
Jochen Hoenicke,
Henning Hoffmann,
Kevin Holbrook,
Nick Holloway,
Onno Hovers,
Jeffrey Hsu,
Peter Hunnisett,
Miguel de Icaza,
Jukka Iivonen,
Kostya Ivanov,
Serge Ivanov,
Lee Jaekil,
Gautam Jain,
Niels Kristian Bech Jensen,
Rajeev Jhangiani,
Bill Jin,
Jeff Johann,
Alexandre Julliard,
Bang Jun-Young,
James Juran,
Achim Kaiser,
Alexander Kanavin,
Jukka Kangas,
Pavel Kankovsky,
Michael Karcher,
Niclas Karlsson,
Jochen Karrer,
Don Kelly,
Andreas Kirschbaum,
Rein Klazes,
Albrecht Kleine,
Dietmar Kling,
Eric Kohl,
Jon Konrath,
Alex Korobka,
Zoltan Kovacs,
Greg Kreider,
Anand Kumria,
Ove Kåven,
Scott A. Laird,
David Lee Lambert,
Stephen Langasek,
Sean Langley,
Dan Langlois,
Alexander Larsson,
David Lassonde,
Stefan Leichter,
Karl Lessard,
Pascal Lessard,
Andrew Lewycky,
John Li,
Weisheng Li,
Xiang Li,
Per Lindström,
Brian Litzinger,
Juergen Lock,
Martin von Loewis,
Michiel van Loon,
Richard A Lough,
Alexander V. Lukyanov,
Jiuming Luo,
Stephane Lussier,
David Luyer,
José Marcos López,
Kenneth MacDonald,
Peter MacDonald,
Pierre Mageau,
William Magro,
Juergen Marquardt,
Ricardo Massaro,
Keith Matthews,
Joerg Mayer,
Michael McCormack,
Jason McMullan,
Caolan McNamara,
Marcus Meissner,
Graham Menhennitt,
David Metcalfe,
Toufic Milan,
Paul Millar,
Bruce Milner,
Steffen Moeller,
Andreas Mohr,
Slava Monich,
James Moody,
Chris Morgan,
Kai Morich,
Richard Mortimer,
Vasudev Mulchandani,
Rick Mutzke,
Philippe De Muyter,
Itai Nahshon,
Jonathan Naylor,
Tim Newsome,
Thuy Nguyen,
Kristian Nielsen,
Damien O'Neill,
Henrik Olsen,
Gerard Patel,
Michael Patra,
Murali Pattathe,
Dimitrie O. Paun,
Bernd Paysan,
Brad Pepers,
Jim Peterson,
Gerald Pfeifer,
Dave Pickles,
Ian Pilcher,
Brian Pirie,
Michael Poole,
Eric Pouech,
Robert Pouliot,
Vahid Pourlotfali,
Chad Powell,
Joseph Pranevich,
Alex Priem,
Paul Quinn,
Pete Ratzlaff,
Ron Record,
Petter Reinholdtsen,
Keith Reynolds,
Slaven Rezic,
John Richardson,
Rick Richardson,
Douglas Ridgway,
Robert Riggs,
Bernhard Rosenkraenzer,
Matthew Robertson,
Pavel Roskin,
Herbert Rosmanith,
Lilia Roumiantseva,
Johannes Ruscheinski,
Adam Sacarny,
Ivan de Saedeleer,
Thomas Sandford,
Constantine Sapuntzakis,
Pablo Saratxaga,
Carl van Schaik,
Daniel Schepler,
Christian Schlaile,
Peter Schlaile,
Ulrich Schmid,
Bernd Schmidt,
Ian Schmidt,
Juergen Schmied,
Ingo Schneider,
Victor Schneider,
John Sheets,
Yngvi Sigurjonsson,
Stephen Simmons,
Jesper Skov,
Rick Sladkey,
William Smith,
Jaroslaw Piotr Sobieszek,
Patrick Spinler,
Sylvain St-Germain,
Gavriel State,
Sheri Steeves,
Norman Stevens,
Dominik Strasser,
Patrik Stridvall,
Vadim Strizhevsky,
Bertho Stultiens,
Abraham Sudhakar,
Charles Suprin,
James Sutherland,
Erik Svendsen,
Tristan Tarrant,
Andrew Taylor,
Joshua Thielen,
Dirk Thierbach,
Jean-Louis Thirot,
Duncan C Thomson,
Adrian Thurston,
Goran Thyni,
Steve Tibbett,
Dmitry Timoshkov,
Jimmy Tirtawangsa,
Jon Tombs,
Linus Torvalds,
Luc Tourangeau,
Jeff Tranter,
Gregory Trubetskoy,
Petri Tuomola,
Sergey Turchanov,
Lionel Ulmer,
Moshe Vainer,
Michael Veksler,
Sven Verdoolaege,
Todd Vierling,
Erez Volk,
Jerome Vouillon,
Duc Vuong,
Ronan Waide,
Martin Walker,
Owen Wang,
Eric Warnke,
Leigh Wedding,
Randy Weems,
Manfred Weichel,
Ulrich Weigand,
Morten Welinder,
Jeremy White,
Len White,
Lawson Whitney,
Jan Willamowius,
Carl Williams,
Eric Williams,
Cliff Wright,
Karl Guenter Wuensch,
Eric Youngdale,
James Youngman,
Nikita V. Youshchenko,
Mikolaj Zalewski,
John Zero,
Yuxi Zhang,
Nathan Zorich,
Luiz Otavio L. Zorzella,
and Per Ångström.

View File

@ -0,0 +1,26 @@
This is the license file as it appeared in the CVS version of
Wine at cvs@rhlx01.fht-esslingen.de:/home/wine as of 2000-12-04
where only AUTHORS has been renamed to WINE-AUTHORS. It applies
to the header files establishing the COM+ framework
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Copyright (c) 1993-2000 the Wine project authors (see the file WINE-AUTHORS
for a complete list)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

View File

@ -0,0 +1,160 @@
/* basetsd.h - Compilers that uses ILP32, LP64 or P64 type models
for both Win32 and Win64 are supported by this file.
Copyright (c) 1993-2000 the Wine project authors (see the file WINE-AUTHORS
for a complete list)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __WINE_BASETSD_H
#define __WINE_BASETSD_H
#ifdef __cplusplus
extern "C" {
#endif /* defined(__cplusplus) */
/*
* Win32 was easy to implement under Unix since most (all?) 32-bit
* Unices uses the same type model (ILP32) as Win32, where int, long
* and pointer are 32-bit.
*
* Win64, however, will cause some problems when implemented under Unix.
* Linux/{Alpha, Sparc64} and most (all?) other 64-bit Unices uses
* the LP64 type model where int is 32-bit and long and pointer are
* 64-bit. Win64 on the other hand uses the P64 (sometimes called LLP64)
* type model where int and long are 32 bit and pointer is 64-bit.
*/
/* Type model indepent typedefs */
typedef char __int8;
typedef unsigned char __uint8;
typedef short __int16;
typedef unsigned short __uint16;
typedef int __int32;
typedef unsigned int __uint32;
typedef long long __int64;
typedef unsigned long long __uint64;
#if defined(_WIN64)
typedef __uint32 __ptr32;
typedef void *__ptr64;
#else /* FIXME: defined(_WIN32) */
typedef void *__ptr32;
typedef __uint64 __ptr64;
#endif
/* Always signed and 32 bit wide */
typedef __int32 LONG32;
typedef __int32 INT32;
typedef LONG32 *PLONG32;
typedef INT32 *PINT32;
/* Always unsigned and 32 bit wide */
typedef __uint32 ULONG32;
typedef __uint32 DWORD32;
typedef __uint32 UINT32;
typedef ULONG32 *PULONG32;
typedef DWORD32 *PDWORD32;
typedef UINT32 *PUINT32;
/* Always signed and 64 bit wide */
typedef __int64 LONG64;
typedef __int64 INT64;
typedef LONG64 *PLONG64;
typedef INT64 *PINT64;
/* Always unsigned and 64 bit wide */
typedef __uint64 ULONG64;
typedef __uint64 DWORD64;
typedef __uint64 UINT64;
typedef ULONG64 *PULONG64;
typedef DWORD64 *PDWORD64;
typedef UINT64 *PUINT64;
/* Win32 or Win64 dependent typedef/defines. */
#ifdef _WIN64
typedef __int64 INT_PTR, *PINT_PTR;
typedef __uint64 UINT_PTR, *PUINT_PTR;
#define MAXINT_PTR 0x7fffffffffffffff
#define MININT_PTR 0x8000000000000000
#define MAXUINT_PTR 0xffffffffffffffff
typedef __int32 HALF_PTR, *PHALF_PTR;
typedef __int32 UHALF_PTR, *PUHALF_PTR;
#define MAXHALF_PTR 0x7fffffff
#define MINHALF_PTR 0x80000000
#define MAXUHALF_PTR 0xffffffff
typedef __int64 LONG_PTR, *PLONG_PTR;
typedef __uint64 ULONG_PTR, *PULONG_PTR;
typedef __uint64 DWORD_PTR, *PDWORD_PTR;
#else /* FIXME: defined(_WIN32) */
typedef __int32 INT_PTR, *PINT_PTR;
typedef __uint32 UINT_PTR, *PUINT_PTR;
#define MAXINT_PTR 0x7fffffff
#define MININT_PTR 0x80000000
#define MAXUINT_PTR 0xffffffff
typedef __int16 HALF_PTR, *PHALF_PTR;
typedef __uint16 UHALF_PTR, *PUHALF_PTR;
#define MAXUHALF_PTR 0xffff
#define MAXHALF_PTR 0x7fff
#define MINHALF_PTR 0x8000
typedef __int32 LONG_PTR, *PLONG_PTR;
typedef __uint32 ULONG_PTR, *PULONG_PTR;
typedef __uint32 DWORD_PTR, *PDWORD_PTR;
#endif /* defined(_WIN64) || defined(_WIN32) */
typedef INT_PTR SSIZE_T, *PSSIZE_T;
typedef UINT_PTR SIZE_T, *PSIZE_T;
#ifdef __cplusplus
} /* extern "C" */
#endif /* defined(__cplusplus) */
#endif /* !defined(__WINE_BASETSD_H) */

View File

@ -0,0 +1,598 @@
/*
* Copyright 1999 Marcus Meissner
*/
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "winbase.h"
#include "winnls.h"
#include "mmsystem.h"
#include "winerror.h"
#include "debugtools.h"
#include "initguid.h"
#include "vfw.h"
DEFAULT_DEBUG_CHANNEL(avifile);
static HRESULT WINAPI IAVIFile_fnQueryInterface(IAVIFile* iface,REFIID refiid,LPVOID *obj);
static ULONG WINAPI IAVIFile_fnAddRef(IAVIFile* iface);
static ULONG WINAPI IAVIFile_fnRelease(IAVIFile* iface);
static HRESULT WINAPI IAVIFile_fnInfo(IAVIFile*iface,AVIFILEINFOW*afi,LONG size);
static HRESULT WINAPI IAVIFile_fnGetStream(IAVIFile*iface,PAVISTREAM*avis,DWORD fccType,LONG lParam);
static HRESULT WINAPI IAVIFile_fnCreateStream(IAVIFile*iface,PAVISTREAM*avis,AVISTREAMINFOW*asi);
static HRESULT WINAPI IAVIFile_fnWriteData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG size);
static HRESULT WINAPI IAVIFile_fnReadData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG *size);
static HRESULT WINAPI IAVIFile_fnEndRecord(IAVIFile*iface);
static HRESULT WINAPI IAVIFile_fnDeleteStream(IAVIFile*iface,DWORD fccType,LONG lParam);
struct ICOM_VTABLE(IAVIFile) iavift = {
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
IAVIFile_fnQueryInterface,
IAVIFile_fnAddRef,
IAVIFile_fnRelease,
IAVIFile_fnInfo,
IAVIFile_fnGetStream,
IAVIFile_fnCreateStream,
IAVIFile_fnWriteData,
IAVIFile_fnReadData,
IAVIFile_fnEndRecord,
IAVIFile_fnDeleteStream
};
static HRESULT WINAPI IAVIStream_fnQueryInterface(IAVIStream*iface,REFIID refiid,LPVOID *obj);
static ULONG WINAPI IAVIStream_fnAddRef(IAVIStream*iface);
static ULONG WINAPI IAVIStream_fnRelease(IAVIStream* iface);
static HRESULT WINAPI IAVIStream_fnCreate(IAVIStream*iface,LPARAM lParam1,LPARAM lParam2);
static HRESULT WINAPI IAVIStream_fnInfo(IAVIStream*iface,AVISTREAMINFOW *psi,LONG size);
static LONG WINAPI IAVIStream_fnFindSample(IAVIStream*iface,LONG pos,LONG flags);
static HRESULT WINAPI IAVIStream_fnReadFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG *formatsize);
static HRESULT WINAPI IAVIStream_fnSetFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG formatsize);
static HRESULT WINAPI IAVIStream_fnRead(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,LONG *bytesread,LONG *samplesread);
static HRESULT WINAPI IAVIStream_fnWrite(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,DWORD flags,LONG *sampwritten,LONG *byteswritten);
static HRESULT WINAPI IAVIStream_fnDelete(IAVIStream*iface,LONG start,LONG samples);
static HRESULT WINAPI IAVIStream_fnReadData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG *lpread);
static HRESULT WINAPI IAVIStream_fnWriteData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG size);
static HRESULT WINAPI IAVIStream_fnSetInfo(IAVIStream*iface,AVISTREAMINFOW*info,LONG infolen);
struct ICOM_VTABLE(IAVIStream) iavist = {
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
IAVIStream_fnQueryInterface,
IAVIStream_fnAddRef,
IAVIStream_fnRelease,
IAVIStream_fnCreate,
IAVIStream_fnInfo,
IAVIStream_fnFindSample,
IAVIStream_fnReadFormat,
IAVIStream_fnSetFormat,
IAVIStream_fnRead,
IAVIStream_fnWrite,
IAVIStream_fnDelete,
IAVIStream_fnReadData,
IAVIStream_fnWriteData,
IAVIStream_fnSetInfo
};
typedef struct IAVIStreamImpl {
/* IUnknown stuff */
ICOM_VFIELD(IAVIStream);
DWORD ref;
/* IAVIStream stuff */
LPVOID lpInputFormat;
DWORD inputformatsize;
BOOL iscompressing;
DWORD curframe;
/* Compressor stuff */
HIC hic;
LPVOID lpCompressFormat;
ICINFO icinfo;
DWORD compbufsize;
LPVOID compbuffer;
DWORD decompbufsize;
LPVOID decompbuffer;
LPVOID decompformat;
AVICOMPRESSOPTIONS aco;
LPVOID lpPrev; /* pointer to decompressed frame later */
LPVOID lpPrevFormat; /* pointer to decompressed info later */
} IAVIStreamImpl;
/***********************************************************************
* AVIFileInit
*/
void WINAPI
AVIFileInit(void) {
FIXME("(),stub!\n");
}
typedef struct IAVIFileImpl {
/* IUnknown stuff */
ICOM_VFIELD(IAVIFile);
DWORD ref;
/* IAVIFile stuff... */
} IAVIFileImpl;
static HRESULT WINAPI IAVIFile_fnQueryInterface(IAVIFile* iface,REFIID refiid,LPVOID *obj) {
ICOM_THIS(IAVIFileImpl,iface);
TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(refiid),obj);
if ( !memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown)) ||
!memcmp(&IID_IAVIFile,refiid,sizeof(IID_IAVIFile))
) {
*obj = iface;
return S_OK;
}
return OLE_E_ENUM_NOMORE;
}
static ULONG WINAPI IAVIFile_fnAddRef(IAVIFile* iface) {
ICOM_THIS(IAVIFileImpl,iface);
FIXME("(%p)->AddRef()\n",iface);
return ++(This->ref);
}
static ULONG WINAPI IAVIFile_fnRelease(IAVIFile* iface) {
ICOM_THIS(IAVIFileImpl,iface);
FIXME("(%p)->Release()\n",iface);
if (!--(This->ref)) {
HeapFree(GetProcessHeap(),0,iface);
return 0;
}
return This->ref;
}
static HRESULT WINAPI IAVIFile_fnInfo(IAVIFile*iface,AVIFILEINFOW*afi,LONG size) {
FIXME("(%p)->Info(%p,%ld)\n",iface,afi,size);
/* FIXME: fill out struct? */
return E_FAIL;
}
static HRESULT WINAPI IAVIFile_fnGetStream(IAVIFile*iface,PAVISTREAM*avis,DWORD fccType,LONG lParam) {
FIXME("(%p)->GetStream(%p,0x%08lx,%ld)\n",iface,avis,fccType,lParam);
/* FIXME: create interface etc. */
return E_FAIL;
}
static HRESULT WINAPI IAVIFile_fnCreateStream(IAVIFile*iface,PAVISTREAM*avis,AVISTREAMINFOW*asi) {
ICOM_THIS(IAVIStreamImpl,iface);
char fcc[5];
IAVIStreamImpl *istream;
FIXME("(%p,%p,%p)\n",This,avis,asi);
istream = (IAVIStreamImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IAVIStreamImpl));
istream->ref = 1;
ICOM_VTBL(istream) = &iavist;
fcc[4]='\0';
memcpy(fcc,(char*)&(asi->fccType),4);
FIXME("\tfccType '%s'\n",fcc);
memcpy(fcc,(char*)&(asi->fccHandler),4);
FIXME("\tfccHandler '%s'\n",fcc);
FIXME("\tdwFlags 0x%08lx\n",asi->dwFlags);
FIXME("\tdwCaps 0x%08lx\n",asi->dwCaps);
FIXME("\tname '%s'\n",debugstr_w(asi->szName));
istream->curframe = 0;
*avis = (PAVISTREAM)istream;
return S_OK;
}
static HRESULT WINAPI IAVIFile_fnWriteData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG size) {
FIXME("(%p)->WriteData(0x%08lx,%p,%ld)\n",iface,ckid,lpData,size);
/* FIXME: write data to file */
return E_FAIL;
}
static HRESULT WINAPI IAVIFile_fnReadData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG *size) {
FIXME("(%p)->ReadData(0x%08lx,%p,%p)\n",iface,ckid,lpData,size);
/* FIXME: read at most size bytes from file */
return E_FAIL;
}
static HRESULT WINAPI IAVIFile_fnEndRecord(IAVIFile*iface) {
FIXME("(%p)->EndRecord()\n",iface);
/* FIXME: end record? */
return E_FAIL;
}
static HRESULT WINAPI IAVIFile_fnDeleteStream(IAVIFile*iface,DWORD fccType,LONG lParam) {
FIXME("(%p)->DeleteStream(0x%08lx,%ld)\n",iface,fccType,lParam);
/* FIXME: delete stream? */
return E_FAIL;
}
/***********************************************************************
* AVIFileOpenA
*/
HRESULT WINAPI AVIFileOpenA(
PAVIFILE * ppfile,LPCSTR szFile,UINT uMode,LPCLSID lpHandler
) {
IAVIFileImpl *iavi;
FIXME("(%p,%s,0x%08lx,%s),stub!\n",ppfile,szFile,(DWORD)uMode,debugstr_guid(lpHandler));
iavi = (IAVIFileImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IAVIFileImpl));
iavi->ref = 1;
ICOM_VTBL(iavi) = &iavift;
*ppfile = (LPVOID)iavi;
return S_OK;
}
static HRESULT WINAPI IAVIStream_fnQueryInterface(IAVIStream*iface,REFIID refiid,LPVOID *obj) {
ICOM_THIS(IAVIStreamImpl,iface);
TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(refiid),obj);
if ( !memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown)) ||
!memcmp(&IID_IAVIStream,refiid,sizeof(IID_IAVIStream))
) {
*obj = This;
return S_OK;
}
/* can return IGetFrame interface too */
return OLE_E_ENUM_NOMORE;
}
static ULONG WINAPI IAVIStream_fnAddRef(IAVIStream*iface) {
ICOM_THIS(IAVIStreamImpl,iface);
FIXME("(%p)->AddRef()\n",iface);
return ++(This->ref);
}
static ULONG WINAPI IAVIStream_fnRelease(IAVIStream* iface) {
ICOM_THIS(IAVIStreamImpl,iface);
FIXME("(%p)->Release()\n",iface);
if (!--(This->ref)) {
HeapFree(GetProcessHeap(),0,This);
return 0;
}
return This->ref;
}
static HRESULT WINAPI IAVIStream_fnCreate(IAVIStream*iface,LPARAM lParam1,LPARAM lParam2) {
FIXME("(%p)->Create(0x%08lx,0x%08lx)\n",iface,lParam1,lParam2);
return E_FAIL;
}
static HRESULT WINAPI IAVIStream_fnInfo(IAVIStream*iface,AVISTREAMINFOW *psi,LONG size) {
FIXME("(%p)->Info(%p,%ld)\n",iface,psi,size);
return E_FAIL;
}
static LONG WINAPI IAVIStream_fnFindSample(IAVIStream*iface,LONG pos,LONG flags) {
FIXME("(%p)->FindSample(%ld,0x%08lx)\n",iface,pos,flags);
return E_FAIL;
}
static HRESULT WINAPI IAVIStream_fnReadFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG *formatsize) {
FIXME("(%p)->ReadFormat(%ld,%p,%p)\n",iface,pos,format,formatsize);
return E_FAIL;
}
/***********************************************************************
* IAVIStream::SetFormat
*/
static HRESULT WINAPI IAVIStream_fnSetFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG formatsize) {
IAVIStreamImpl *as = (IAVIStreamImpl*)iface;
FIXME("(%p)->SetFormat(%ld,%p,%ld)\n",iface,pos,format,formatsize);
if (as->lpInputFormat) HeapFree(GetProcessHeap(),0,as->lpInputFormat);
as->inputformatsize = formatsize;
as->lpInputFormat = HeapAlloc(GetProcessHeap(),0,formatsize);
memcpy(as->lpInputFormat,format,formatsize);
if (as->iscompressing) {
int xsize;
/* Set up the Compressor part */
xsize = ICCompressGetFormatSize(as->hic,as->lpInputFormat);
as->lpCompressFormat = HeapAlloc(GetProcessHeap(),0,xsize);
ICCompressGetFormat(as->hic,as->lpInputFormat,as->lpCompressFormat);
ICCompressBegin(as->hic,as->lpInputFormat,as->lpCompressFormat);
as->compbufsize = ICCompressGetSize(as->hic,as->lpInputFormat,as->lpCompressFormat);
as->compbuffer = HeapAlloc(GetProcessHeap(),0,as->compbufsize);
/* Set up the Decompressor part (for prev frames?) */
xsize=ICDecompressGetFormatSize(as->hic,as->lpCompressFormat);
as->decompformat = HeapAlloc(GetProcessHeap(),0,xsize);
ICDecompressGetFormat(as->hic,as->lpCompressFormat,as->decompformat);
as->decompbufsize=((LPBITMAPINFOHEADER)as->decompbuffer)->biSizeImage;
as->decompbuffer = HeapReAlloc(GetProcessHeap(),0,as->decompbuffer,as->decompbufsize);
memset(as->decompbuffer,0xff,as->decompbufsize);
assert(HeapValidate(GetProcessHeap(),0,NULL));
ICDecompressGetFormat(as->hic,as->lpCompressFormat,as->decompformat);
ICDecompressBegin(as->hic,as->lpCompressFormat,as->decompformat);
as->lpPrev = as->lpPrevFormat = NULL;
}
return S_OK;
}
static HRESULT WINAPI IAVIStream_fnRead(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,LONG *bytesread,LONG *samplesread) {
FIXME("(%p)->Read(%ld,%ld,%p,%ld,%p,%p)\n",iface,start,samples,buffer,buffersize,bytesread,samplesread);
return E_FAIL;
}
static HRESULT WINAPI IAVIStream_fnWrite(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,DWORD flags,LONG *sampwritten,LONG *byteswritten) {
IAVIStreamImpl *as = (IAVIStreamImpl*)iface;
DWORD ckid,xflags;
FIXME("(%p)->Write(%ld,%ld,%p,%ld,0x%08lx,%p,%p)\n",iface,start,samples,buffer,buffersize,flags,sampwritten,byteswritten);
ICCompress(
as->hic,flags,
as->lpCompressFormat,
as->compbuffer,
as->lpInputFormat,buffer,
&ckid,&xflags,
as->curframe,0xffffff/*framesize*/,as->aco.dwQuality,
as->lpPrevFormat,as->lpPrev
);
ICDecompress(
as->hic,
flags, /* FIXME: check */
as->lpCompressFormat,
as->compbuffer,
as->decompformat,
as->decompbuffer
);
/* We now have a prev format for the next compress ... */
as->lpPrevFormat = as->decompformat;
as->lpPrev = as->decompbuffer;
return S_OK;
}
static HRESULT WINAPI IAVIStream_fnDelete(IAVIStream*iface,LONG start,LONG samples) {
FIXME("(%p)->Delete(%ld,%ld)\n",iface,start,samples);
return E_FAIL;
}
static HRESULT WINAPI IAVIStream_fnReadData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG *lpread) {
FIXME("(%p)->ReadData(0x%08lx,%p,%p)\n",iface,fcc,lp,lpread);
return E_FAIL;
}
static HRESULT WINAPI IAVIStream_fnWriteData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG size) {
FIXME("(%p)->WriteData(0x%08lx,%p,%ld)\n",iface,fcc,lp,size);
return E_FAIL;
}
static HRESULT WINAPI IAVIStream_fnSetInfo(IAVIStream*iface,AVISTREAMINFOW*info,LONG infolen) {
FIXME("(%p)->SetInfo(%p,%ld)\n",iface,info,infolen);
return E_FAIL;
}
/***********************************************************************
* AVIFileCreateStreamA
*/
HRESULT WINAPI AVIFileCreateStreamA(PAVIFILE iface,PAVISTREAM *ppavi,AVISTREAMINFOA * psi) {
AVISTREAMINFOW psiw;
/* Only the szName at the end is different */
memcpy(&psiw,psi,sizeof(*psi)-sizeof(psi->szName));
MultiByteToWideChar( CP_ACP, 0, psi->szName, -1,
psiw.szName, sizeof(psiw.szName) / sizeof(WCHAR) );
return IAVIFile_CreateStream(iface,ppavi,&psiw);
}
/***********************************************************************
* AVIFileCreateStreamW
*/
HRESULT WINAPI AVIFileCreateStreamW(IAVIFile*iface,PAVISTREAM*avis,AVISTREAMINFOW*asi) {
return IAVIFile_CreateStream(iface,avis,asi);
}
/***********************************************************************
* AVIFileGetStream
*/
HRESULT WINAPI AVIFileGetStream(IAVIFile*iface,PAVISTREAM*avis,DWORD fccType,LONG lParam) {
return IAVIFile_GetStream(iface,avis,fccType,lParam);
}
/***********************************************************************
* AVIFileInfoA
*/
HRESULT WINAPI AVIFileInfoA(PAVIFILE iface,LPAVIFILEINFOA afi,LONG size) {
AVIFILEINFOW afiw;
HRESULT hres;
if (size < sizeof(AVIFILEINFOA))
return AVIERR_BADSIZE;
hres = IAVIFile_Info(iface,&afiw,sizeof(afiw));
memcpy(afi,&afiw,sizeof(*afi)-sizeof(afi->szFileType));
WideCharToMultiByte( CP_ACP, 0, afiw.szFileType, -1,
afi->szFileType, sizeof(afi->szFileType), NULL, NULL );
afi->szFileType[sizeof(afi->szFileType)-1] = 0;
return hres;
}
/***********************************************************************
* AVIStreamInfoW
*/
HRESULT WINAPI AVIStreamInfoW(PAVISTREAM iface,AVISTREAMINFOW *asi,LONG
size) {
return IAVIFile_Info(iface,asi,size);
}
/***********************************************************************
* AVIStreamInfoA
*/
HRESULT WINAPI AVIStreamInfoA(PAVISTREAM iface,AVISTREAMINFOA *asi,LONG
size) {
AVISTREAMINFOW asiw;
HRESULT hres;
if (size<sizeof(AVISTREAMINFOA))
return AVIERR_BADSIZE;
hres = IAVIFile_Info(iface,&asiw,sizeof(asiw));
memcpy(asi,&asiw,sizeof(asiw)-sizeof(asiw.szName));
WideCharToMultiByte( CP_ACP, 0, asiw.szName, -1,
asi->szName, sizeof(asi->szName), NULL, NULL );
asi->szName[sizeof(asi->szName)-1] = 0;
return hres;
}
/***********************************************************************
* AVIFileInfoW
*/
HRESULT WINAPI AVIFileInfoW(PAVIFILE iface,LPAVIFILEINFOW afi,LONG size) {
return IAVIFile_Info(iface,afi,size);
}
/***********************************************************************
* AVIMakeCompressedStream
*/
HRESULT WINAPI AVIMakeCompressedStream(PAVISTREAM *ppsCompressed,PAVISTREAM ppsSource,AVICOMPRESSOPTIONS *aco,CLSID *pclsidHandler) {
char fcc[5];
IAVIStreamImpl *as;
FIXME("(%p,%p,%p,%p)\n",ppsCompressed,ppsSource,aco,pclsidHandler);
fcc[4]='\0';
memcpy(fcc,&(aco->fccType),4);
FIXME("\tfccType: '%s'\n",fcc);
memcpy(fcc,&(aco->fccHandler),4);
FIXME("\tfccHandler: '%s'\n",fcc);
FIXME("\tdwFlags: 0x%08lx\n",aco->dwFlags);
/* we just create a duplicate for now */
IAVIStream_AddRef(ppsSource);
*ppsCompressed = ppsSource;
as = (IAVIStreamImpl*)ppsSource;
/* this is where the fun begins. Open a compressor and prepare it. */
as->hic = ICOpen(aco->fccType,aco->fccHandler,ICMODE_COMPRESS);
/* May happen. for instance if the codec is not able to compress */
if (!as->hic)
return AVIERR_UNSUPPORTED;
ICGetInfo(as->hic,&(as->icinfo),sizeof(ICINFO));
FIXME("Opened compressor: '%s' '%s'\n",debugstr_w(as->icinfo.szName),debugstr_w(as->icinfo.szDescription));
as->iscompressing = TRUE;
memcpy(&(as->aco),aco,sizeof(*aco));
if (as->icinfo.dwFlags & VIDCF_COMPRESSFRAMES) {
ICCOMPRESSFRAMES icf;
/* now what to fill in there ... Hmm */
memset(&icf,0,sizeof(icf));
icf.lDataRate = aco->dwBytesPerSecond;
icf.lQuality = aco->dwQuality;
icf.lKeyRate = aco->dwKeyFrameEvery;
icf.GetData = (void *)0xdead4242;
icf.PutData = (void *)0xdead4243;
ICSendMessage(as->hic,ICM_COMPRESS_FRAMES_INFO,(LPARAM)&icf,sizeof(icf));
}
return S_OK;
}
/***********************************************************************
* AVIStreamSetFormat
*/
HRESULT WINAPI AVIStreamSetFormat(PAVISTREAM iface,LONG pos,LPVOID format,LONG formatsize) {
return IAVIStream_SetFormat(iface,pos,format,formatsize);
}
/***********************************************************************
* AVIStreamReadFormat
*/
HRESULT WINAPI AVIStreamReadFormat(PAVISTREAM iface,LONG pos,LPVOID format,LONG *formatsize) {
return IAVIStream_ReadFormat(iface,pos,format,formatsize);
}
/***********************************************************************
* AVIStreamWrite(
*/
HRESULT WINAPI AVIStreamWrite(PAVISTREAM iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,DWORD flags,LONG *sampwritten,LONG *byteswritten) {
return IAVIStream_Write(iface,start,samples,buffer,buffersize,flags,sampwritten,byteswritten);
}
/***********************************************************************
* AVIStreamRead
*/
HRESULT WINAPI AVIStreamRead(PAVISTREAM iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,LONG *bytesread,LONG *samplesread) {
return IAVIStream_Read(iface,start,samples,buffer,buffersize,bytesread,samplesread);
}
/***********************************************************************
* AVIStreamWriteData
*/
HRESULT WINAPI AVIStreamWriteData(PAVISTREAM iface,DWORD fcc,LPVOID lp,LONG size) {
return IAVIStream_WriteData(iface,fcc,lp,size);
}
/***********************************************************************
* AVIStreamReadData
*/
HRESULT WINAPI AVIStreamReadData(PAVISTREAM iface,DWORD fcc,LPVOID lp,LONG *lpread) {
return IAVIStream_ReadData(iface,fcc,lp,lpread);
}
/***********************************************************************
* AVIStreamStart
*/
LONG WINAPI AVIStreamStart(PAVISTREAM iface) {
AVISTREAMINFOW si;
IAVIStream_Info(iface,&si,sizeof(si));
return si.dwStart;
}
/***********************************************************************
* AVIStreamLength
*/
LONG WINAPI AVIStreamLength(PAVISTREAM iface) {
AVISTREAMINFOW si;
HRESULT ret;
ret = IAVIStream_Info(iface,&si,sizeof(si));
if (ret) /* error */
return 1;
return si.dwLength;
}
/***********************************************************************
* AVIStreamRelease
*/
ULONG WINAPI AVIStreamRelease(PAVISTREAM iface) {
return IAVIStream_Release(iface);
}
/***********************************************************************
* AVIStreamGetFrameOpen
*/
PGETFRAME WINAPI AVIStreamGetFrameOpen(PAVISTREAM iface,LPBITMAPINFOHEADER bmi) {
FIXME("(%p)->(%p),stub!\n",iface,bmi);
return NULL;
}
/***********************************************************************
* AVIStreamGetFrame
*/
LPVOID WINAPI AVIStreamGetFrame(PGETFRAME pg,LONG pos) {
return IGetFrame_GetFrame(pg,pos);
}
/***********************************************************************
* AVIStreamGetFrameClose
*/
HRESULT WINAPI AVIStreamGetFrameClose(PGETFRAME pg) {
if (pg) IGetFrame_Release(pg);
return 0;
}
/***********************************************************************
* AVIFileRelease
*/
ULONG WINAPI AVIFileRelease(PAVIFILE iface) {
return IAVIFile_Release(iface);
}
/***********************************************************************
* AVIFileExit
*/
void WINAPI AVIFileExit(void) {
FIXME("(), stub.\n");
}

View File

@ -0,0 +1,95 @@
/* guiddef.h
Copyright (c) 1993-2000 the Wine project authors (see the file WINE-AUTHORS
for a complete list)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/* already defined bu Mingw32/cpd
#ifndef GUID_DEFINED
#define GUID_DEFINED
typedef struct _GUID
{
unsigned long Data1;
unsigned short Data2;
unsigned short Data3;
unsigned char Data4[ 8 ];
} GUID;
#endif
*/
#undef DEFINE_GUID
#ifdef INITGUID
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
const GUID name = \
{ l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
#else
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
extern const GUID name
#endif
#define DEFINE_OLEGUID(name, l, w1, w2) \
DEFINE_GUID(name, l, w1, w2, 0xC0,0,0,0,0,0,0,0x46)
#ifndef _GUIDDEF_H_
#define _GUIDDEF_H_
/* typedef GUID *LPGUID;
typedef GUID CLSID,*LPCLSID; */
typedef GUID IID,*LPIID;
typedef GUID FMTID,*LPFMTID;
#if defined(__cplusplus) && !defined(CINTERFACE)
#define REFGUID const GUID &
#define REFCLSID const CLSID &
#define REFIID const IID &
#define REFFMTID const FMTID &
#else /* !defined(__cplusplus) && !defined(CINTERFACE) */
#define REFGUID const GUID* const
#define REFCLSID const CLSID* const
#define REFIID const IID* const
#define REFFMTID const FMTID* const
#endif /* !defined(__cplusplus) && !defined(CINTERFACE) */
#if defined(__cplusplus) && !defined(CINTERFACE)
#define IsEqualGUID(rguid1, rguid2) (!memcmp(&(rguid1), &(rguid2), sizeof(GUID)))
#else /* defined(__cplusplus) && !defined(CINTERFACE) */
#define IsEqualGUID(rguid1, rguid2) (!memcmp(rguid1, rguid2, sizeof(GUID)))
#endif /* defined(__cplusplus) && !defined(CINTERFACE) */
#define IsEqualIID(riid1, riid2) IsEqualGUID(riid1, riid2)
#define IsEqualCLSID(rclsid1, rclsid2) IsEqualGUID(rclsid1, rclsid2)
#if defined(__cplusplus) && !defined(CINTERFACE)
inline bool operator==(const GUID& guidOne, const GUID& guidOther)
{
return !memcmp(&guidOne,&guidOther,sizeof(GUID));
}
inline bool operator!=(const GUID& guidOne, const GUID& guidOther)
{
return !(guidOne == guidOther);
}
#endif
extern const IID GUID_NULL;
#define IID_NULL GUID_NULL
#define CLSID_NULL GUID_NULL
#define FMTID_NULL GUID_NULL
#endif /* _GUIDDEF_H_ */

View File

@ -0,0 +1,202 @@
/* ignupg.c - COM+ class IGnuPG
* 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 <errno.h>
#include <assert.h>
#include <time.h>
#include <windows.h>
#define INITGUID
#include "ignupg.h"
/*
* Declare the interface implementation structures
*/
typedef struct IGnuPGImpl IGnuPGImpl;
typedef struct IClassFactoryImpl IClassFactoryImpl;
struct IGnuPGImpl {
/* IUnknown required stuff */
ICOM_VFIELD (IGnuPG);
DWORD ref;
/* Our stuff */
int foo;
};
struct IClassFactoryImpl {
/* IUnknown fields */
ICOM_VFIELD(IClassFactory);
DWORD ref;
};
/**********************************************************
************** IGnuPG Implementation *******************
**********************************************************/
static HRESULT WINAPI
IGnuPGImpl_QueryInterface (IGnuPG *iface, REFIID refiid, LPVOID *obj)
{
ICOM_THIS (IGnuPGImpl,iface);
fprintf (stderr,"(%p)->QueryInterface(%s,%p)\n",
This, "debugstr_guid(refiid)", obj);
if ( IsEqualGUID (&IID_IUnknown, refiid)
|| !IsEqualGUID (&IID_IGnuPG, refiid) ) {
*obj = iface;
return 0;
}
*obj = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI
IGnuPGImpl_AddRef (IGnuPG *iface)
{
ICOM_THIS (IGnuPGImpl,iface);
return ++This->ref;
}
static ULONG WINAPI
IGnuPGImpl_Release (IGnuPG *iface)
{
ICOM_THIS (IGnuPGImpl,iface);
if (--This->ref)
return This->ref;
HeapFree(GetProcessHeap(),0,iface);
return 0;
}
static ICOM_VTABLE(IGnuPG) gnupg_vtbl =
{
/* IUnknow methods */
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
IGnuPGImpl_QueryInterface,
IGnuPGImpl_AddRef,
IGnuPGImpl_Release,
/* Our methods */
};
/***************************************************************
****************** GnuPG Factory ****************************
***************************************************************/
static HRESULT WINAPI
GnuPGFactory_QueryInterface (IClassFactory *iface, REFIID refiid, LPVOID *obj)
{
/*ICOM_THIS(IClassFactoryImpl,iface);*/
return E_NOINTERFACE;
}
static ULONG WINAPI
GnuPGFactory_AddRef (IClassFactory *iface)
{
ICOM_THIS(IClassFactoryImpl,iface);
return ++(This->ref);
}
static ULONG WINAPI
GnuPGFactory_Release (IClassFactory *iface)
{
ICOM_THIS(IClassFactoryImpl,iface);
return --(This->ref);
}
static HRESULT WINAPI
GnuPGFactory_CreateInstance (IClassFactory *iface, IUnknown *outer,
REFIID refiid, LPVOID *r_obj )
{
/*ICOM_THIS(IClassFactoryImpl,iface);*/
if ( IsEqualGUID (&IID_IGnuPG, refiid) ) {
IGnuPGImpl *obj;
obj = HeapAlloc (GetProcessHeap(), 0, sizeof *obj );
if ( !obj)
return E_OUTOFMEMORY;
ICOM_VTBL(obj) = &gnupg_vtbl;
obj->ref = 1;
*r_obj = obj;
return 0;
}
*r_obj = NULL;
return E_NOINTERFACE;
}
static HRESULT WINAPI
GnuPGFactory_LockServer (IClassFactory *iface, BOOL dolock )
{
/*ICOM_THIS(IClassFactoryImpl,iface);*/
return 0;
}
static ICOM_VTABLE(IClassFactory) gnupg_factory_vtbl = {
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
GnuPGFactory_QueryInterface,
GnuPGFactory_AddRef,
GnuPGFactory_Release,
GnuPGFactory_CreateInstance,
GnuPGFactory_LockServer
};
static IClassFactoryImpl GnuPG_CF = {&gnupg_factory_vtbl, 1 };
IClassFactory *
gnupg_factory_new ( CLSID *r_clsid )
{
*r_clsid = CLSID_GnuPG;
IClassFactory_AddRef((IClassFactory*)&GnuPG_CF);
return (IClassFactory*)&GnuPG_CF;
}
void
gnupg_factory_release ( IClassFactory *factory )
{
/* it's static - nothing to do */
}

View File

@ -0,0 +1,68 @@
/* ignupg.h - COM+ class IGnuPG
* 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 IGNUPG_H
#define IGNUPG_H 1
#include "obj_base.h"
DEFINE_GUID(CLSID_GnuPG, 0x42424242, 0x62e8, 0x11cf,
0x93, 0xbc, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0);
DEFINE_GUID(IID_IGnuPG, 0x24242424, 0x4981, 0x11CE,
0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60);
typedef struct IGnuPG IGnuPG;
#define ICOM_INTERFACE IGnuPG
#define IGnuPG_METHODS \
ICOM_METHOD1(HRESULT,Initialize, REFIID,) \
ICOM_METHOD1(HRESULT,EnumDevices, LPVOID,)
#define IGnuPG_IMETHODS \
IUnknown_IMETHODS \
IGnuPG_METHODS
ICOM_DEFINE(IGnuPG,IUnknown)
#undef ICOM_INTERFACE
/*** IUnknown methods ***/
#define IGnuPG_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b)
#define IGnuPG_AddRef(p) ICOM_CALL (AddRef,p)
#define IGnuPG_Release(p) ICOM_CALL (Release,p)
/*** IGnuPG methods ***/
#define IGnuPG_Initialize(p,a) ICOM_CALL1(Initialize,p,a)
#define IGnuPG_EnumDevices(p,a,b) ICOM_CALL2(EnumDevice,p,a,b)
#endif /*IGNUPG_H*/

View File

@ -0,0 +1,285 @@
/* main.c - COM+ component to access GnuPG
* 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 <errno.h>
#include <assert.h>
#include <time.h>
#include <windows.h>
#include "obj_base.h"
#include "argparse.h"
#include "main.h"
static void register_server (void);
static void unregister_server (void);
static void enter_complus (void);
enum cmd_and_opt_values { aNull = 0,
oQuiet = 'q',
oVerbose = 'v',
oNoVerbose = 500,
oOptions,
oDebug,
oDebugAll,
oNoGreeting,
oNoOptions,
oHomedir,
oGPGBinary,
oRegServer,
oUnregServer,
oEmbedding,
aTest };
static ARGPARSE_OPTS opts[] = {
{ 301, NULL, 0, N_("@Options:\n ") },
{ oVerbose, "verbose", 0, N_("verbose") },
{ oQuiet, "quiet", 0, N_("be somewhat more quiet") },
{ oOptions, "options" , 2, N_("read options from file")},
{ oDebug, "debug" ,4|16, N_("set debugging flags")},
{ oDebugAll, "debug-all" ,0, N_("enable full debugging")},
{ oGPGBinary, "gpg-program", 2 , "@" },
{ oRegServer, "RegServer" , 0, "@" },
{ oUnregServer, "UnregServer" , 0, "@" },
{ oEmbedding, "Embedding" , 0, "@" },
{0} };
static const char *
my_strusage( int level )
{
const char *p;
switch( level ) {
case 11: p = "gpgme";
break;
case 13: p = VERSION; break;
/*case 17: p = PRINTABLE_OS_NAME; break;*/
case 19: p =
_("Please report bugs to <gpgme-bugs@gnupg.org>.\n");
break;
case 1:
case 40: p =
_("Usage: gpgme [options] (-h for help)");
break;
case 41: p =
_("Syntax: gpgme [options]\n"
"GnuPG COM+ component\n");
break;
default: p = NULL;
}
return p;
}
int
main (int argc, char **argv )
{
ARGPARSE_ARGS pargs;
int orig_argc;
char **orig_argv;
FILE *configfp = NULL;
char *configname = NULL;
unsigned configlineno;
int parse_debug = 0;
int default_config =1;
int greeting = 0;
int nogreeting = 0;
int action = 0;
set_strusage( my_strusage );
/*log_set_name ("gpa"); not yet implemented in logging.c */
opt.homedir = getenv("GNUPGHOME");
if( !opt.homedir || !*opt.homedir ) {
#ifdef HAVE_DRIVE_LETTERS
opt.homedir = "c:/gnupg";
#else
opt.homedir = "~/.gnupg";
#endif
}
/* check whether we have a config file on the commandline */
orig_argc = argc;
orig_argv = argv;
pargs.argc = &argc;
pargs.argv = &argv;
pargs.flags= 1|(1<<6); /* do not remove the args, ignore version */
while( arg_parse( &pargs, opts) ) {
if( pargs.r_opt == oDebug || pargs.r_opt == oDebugAll )
parse_debug++;
else if( pargs.r_opt == oOptions ) {
/* yes there is one, so we do not try the default one, but
* read the option file when it is encountered at the commandline
*/
default_config = 0;
}
else if( pargs.r_opt == oNoOptions )
default_config = 0; /* --no-options */
else if( pargs.r_opt == oHomedir )
opt.homedir = pargs.r.ret_str;
}
if( default_config )
configname = make_filename(opt.homedir, "gpgme.conf", NULL );
argc = orig_argc;
argv = orig_argv;
pargs.argc = &argc;
pargs.argv = &argv;
pargs.flags= 1 | (1<<5); /* do not remove the args, allow one dash */
next_pass:
if( configname ) {
configlineno = 0;
configfp = fopen( configname, "r" );
if( !configfp ) {
if( default_config ) {
if( parse_debug )
log_info(_("NOTE: no default option file `%s'\n"),
configname );
}
else {
log_error(_("option file `%s': %s\n"),
configname, strerror(errno) );
exit(2);
}
free(configname); configname = NULL;
}
if( parse_debug && configname )
log_info(_("reading options from `%s'\n"), configname );
default_config = 0;
}
while( optfile_parse( configfp, configname, &configlineno,
&pargs, opts) ) {
switch( pargs.r_opt ) {
case oQuiet: opt.quiet = 1; break;
case oVerbose: opt.verbose++; break;
case oDebug: opt.debug |= pargs.r.ret_ulong; break;
case oDebugAll: opt.debug = ~0; break;
case oOptions:
/* config files may not be nested (silently ignore them) */
if( !configfp ) {
free(configname);
configname = xstrdup(pargs.r.ret_str);
goto next_pass;
}
break;
case oNoGreeting: nogreeting = 1; break;
case oNoVerbose: opt.verbose = 0; break;
case oNoOptions: break; /* no-options */
case oHomedir: opt.homedir = pargs.r.ret_str; break;
case oGPGBinary: break;
case oRegServer: action = 1; break;
case oUnregServer: action = 2; break;
case oEmbedding: action = 3; break;
default : pargs.err = configfp? 1:2; break;
}
}
if( configfp ) {
fclose( configfp );
configfp = NULL;
free(configname); configname = NULL;
goto next_pass;
}
free( configname ); configname = NULL;
if( log_get_errorcount(0) )
exit(2);
if( nogreeting )
greeting = 0;
if( greeting ) {
fprintf(stderr, "%s %s; %s\n",
strusage(11), strusage(13), strusage(14) );
fprintf(stderr, "%s\n", strusage(15) );
}
#ifdef IS_DEVELOPMENT_VERSION
log_info("NOTE: this is a development version!\n");
#endif
if ( action == 1 )
register_server ();
else if (action == 2 )
unregister_server ();
else if (action == 3 )
enter_complus ();
else {
fprintf (stderr, "This is a COM+ component with no user interface.\n"
"gpgme --help will give you a list of options\n" );
exit (1);
}
return 0;
}
static void
register_server ()
{
}
static void
unregister_server ()
{
}
static void
enter_complus ()
{
HANDLE running;
int reg;
IClassFactory *factory;
CLSID clsid;
CoInitializeEx (NULL, COINIT_MULTITHREADED);
running = CreateEvent (NULL, FALSE, FALSE, NULL );
factory = gnupg_factory_new ( &clsid );
CoRegisterClassObject (&clsid, (IUnknown*)factory,
CLSCTX_LOCAL_SERVER,
REGCLS_SUSPENDED|REGCLS_MULTIPLEUSE, &reg );
CoResumeClassObjects ();
WaitForSingleObject ( running, INFINITE );
CloseHandle (running);
CoRevokeClassObject ( reg );
gnupg_factory_release (factory);
CoUninitialize ();
}

View File

@ -0,0 +1,54 @@
/* main.h - GPGME COM+ component
* 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 COMPLUS_MAIN_H
#define COMPLUS_MAIN_H
#include "xmalloc.h"
#include "stringhelp.h"
#include "logging.h"
#define _(a) (a)
#define N_(a) (a)
struct {
int verbose;
int quiet;
unsigned int debug;
char *homedir;
} opt;
/*-- ignupg.c --*/
IClassFactory *gnupg_factory_new ( CLSID *r_clsid );
void gnupg_factory_release ( IClassFactory *factory );
#endif /* COMPLUS_MAIN_H */

View File

@ -0,0 +1,800 @@
/* obj_base.h - This file defines the macros and types necessary to
define COM interfaces, and the three most basic COM interfaces:
IUnknown, IMalloc and IClassFactory.
Copyright (c) 1993-2000 the Wine project authors (see the file WINE-AUTHORS
for a complete list)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __WINE_WINE_OBJ_BASE_H
#define __WINE_WINE_OBJ_BASE_H
/* check these values! */
#define E_NOINTERFACE 0x80040002
#define E_OUTOFMEMORY 0x8007000E
/*****************************************************************************
* define ICOM_MSVTABLE_COMPAT
* to implement the microsoft com vtable compatibility workaround for g++.
*
* NOTE: Turning this option on will produce a winelib that is incompatible
* with the binary emulator.
*
* If the compiler supports the com_interface attribute, leave this off, and
* define the ICOM_USE_COM_INTERFACE_ATTRIBUTE macro below. This may also
* require the addition of the -vtable-thunks option for g++.
*
* If you aren't interested in Winelib C++ compatibility at all, leave both
* options off.
*
* The preferable method for using ICOM_USE_COM_INTERFACE_ATTRIBUTE macro
* would be to define it only for your Winelib application. This allows you
* to have both binary and Winelib compatibility for C and C++ at the same
* time :)
*/
/* #define ICOM_MSVTABLE_COMPAT 1 */
/* #define ICOM_USE_COM_INTERFACE_ATTRIBUTE 1 */
/*****************************************************************************
* Defines the basic types
*/
#include "wtypes.h"
#include "guiddef.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef NONAMELESSSTRUCT
#define LISet32(li, v) ((li).HighPart = (v) < 0 ? -1 : 0, (li).LowPart = (v))
#define ULISet32(li, v) ((li).HighPart = 0, (li).LowPart = (v))
#else
#define LISet32(li, v) ((li).s.HighPart = (v) < 0 ? -1 : 0, (li).s.LowPart = (v))
#define ULISet32(li, v) ((li).s.HighPart = 0, (li).s.LowPart = (v))
#endif
/*****************************************************************************
* GUID API
*/
HRESULT WINAPI StringFromCLSID16(REFCLSID id, LPOLESTR16*);
HRESULT WINAPI StringFromCLSID(REFCLSID id, LPOLESTR*);
HRESULT WINAPI CLSIDFromString16(LPCOLESTR16, CLSID *);
HRESULT WINAPI CLSIDFromString(LPCOLESTR, CLSID *);
HRESULT WINAPI CLSIDFromProgID16(LPCOLESTR16 progid, LPCLSID riid);
HRESULT WINAPI CLSIDFromProgID(LPCOLESTR progid, LPCLSID riid);
HRESULT WINAPI ProgIDFromCLSID(REFCLSID clsid, LPOLESTR *lplpszProgID);
INT WINAPI StringFromGUID2(REFGUID id, LPOLESTR str, INT cmax);
/*****************************************************************************
* Macros to define a COM interface
*/
/*
* The goal of the following set of definitions is to provide a way to use the same
* header file definitions to provide both a C interface and a C++ object oriented
* interface to COM interfaces. The type of interface is selected automatically
* depending on the language but it is always possible to get the C interface in C++
* by defining CINTERFACE.
*
* It is based on the following assumptions:
* - all COM interfaces derive from IUnknown, this should not be a problem.
* - the header file only defines the interface, the actual fields are defined
* separately in the C file implementing the interface.
*
* The natural approach to this problem would be to make sure we get a C++ class and
* virtual methods in C++ and a structure with a table of pointer to functions in C.
* Unfortunately the layout of the virtual table is compiler specific, the layout of
* g++ virtual tables is not the same as that of an egcs virtual table which is not the
* same as that generated by Visual C+. There are workarounds to make the virtual tables
* compatible via padding but unfortunately the one which is imposed to the WINE emulator
* by the Windows binaries, i.e. the Visual C++ one, is the most compact of all.
*
* So the solution I finally adopted does not use virtual tables. Instead I use inline
* non virtual methods that dereference the method pointer themselves and perform the call.
*
* Let's take Direct3D as an example:
*
* #define ICOM_INTERFACE IDirect3D
* #define IDirect3D_METHODS \
* ICOM_METHOD1(HRESULT,Initialize, REFIID,) \
* ICOM_METHOD2(HRESULT,EnumDevices, LPD3DENUMDEVICESCALLBACK,, LPVOID,) \
* ICOM_METHOD2(HRESULT,CreateLight, LPDIRECT3DLIGHT*,, IUnknown*,) \
* ICOM_METHOD2(HRESULT,CreateMaterial,LPDIRECT3DMATERIAL*,, IUnknown*,) \
* ICOM_METHOD2(HRESULT,CreateViewport,LPDIRECT3DVIEWPORT*,, IUnknown*,) \
* ICOM_METHOD2(HRESULT,FindDevice, LPD3DFINDDEVICESEARCH,, LPD3DFINDDEVICERESULT,)
* #define IDirect3D_IMETHODS \
* IUnknown_IMETHODS \
* IDirect3D_METHODS
* ICOM_DEFINE(IDirect3D,IUnknown)
* #undef ICOM_INTERFACE
*
* #ifdef ICOM_CINTERFACE
* // *** IUnknown methods *** //
* #define IDirect3D_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b)
* #define IDirect3D_AddRef(p) ICOM_CALL (AddRef,p)
* #define IDirect3D_Release(p) ICOM_CALL (Release,p)
* // *** IDirect3D methods *** //
* #define IDirect3D_Initialize(p,a) ICOM_CALL1(Initialize,p,a)
* #define IDirect3D_EnumDevices(p,a,b) ICOM_CALL2(EnumDevice,p,a,b)
* #define IDirect3D_CreateLight(p,a,b) ICOM_CALL2(CreateLight,p,a,b)
* #define IDirect3D_CreateMaterial(p,a,b) ICOM_CALL2(CreateMaterial,p,a,b)
* #define IDirect3D_CreateViewport(p,a,b) ICOM_CALL2(CreateViewport,p,a,b)
* #define IDirect3D_FindDevice(p,a,b) ICOM_CALL2(FindDevice,p,a,b)
* #endif
*
* Comments:
* - The ICOM_INTERFACE macro is used in the ICOM_METHOD macros to define the type of the 'this'
* pointer. Defining this macro here saves us the trouble of having to repeat the interface
* name everywhere. Note however that because of the way macros work, a macro like ICOM_METHOD1
* cannot use 'ICOM_INTERFACE##_VTABLE' because this would give 'ICOM_INTERFACE_VTABLE' and not
* 'IDirect3D_VTABLE'.
* - ICOM_METHODS defines the methods specific to this interface. It is then aggregated with the
* inherited methods to form ICOM_IMETHODS.
* - ICOM_IMETHODS defines the list of methods that are inheritable from this interface. It must
* be written manually (rather than using a macro to generate the equivalent code) to avoid
* macro recursion (which compilers don't like).
* - The ICOM_DEFINE finally declares all the structures necessary for the interface. We have to
* explicitly use the interface name for macro expansion reasons again.
* Inherited methods are inherited in C by using the IDirect3D_METHODS macro and the parent's
* Xxx_IMETHODS macro. In C++ we need only use the IDirect3D_METHODS since method inheritance
* is taken care of by the language.
* - In C++ the ICOM_METHOD macros generate a function prototype and a call to a function pointer
* method. This means using once 't1 p1, t2 p2, ...' and once 'p1, p2' without the types. The
* only way I found to handle this is to have one ICOM_METHOD macro per number of parameters and
* to have it take only the type information (with const if necessary) as parameters.
* The 'undef ICOM_INTERFACE' is here to remind you that using ICOM_INTERFACE in the following
* macros will not work. This time it's because the ICOM_CALL macro expansion is done only once
* the 'IDirect3D_Xxx' macro is expanded. And by that time ICOM_INTERFACE will be long gone
* anyway.
* - You may have noticed the double commas after each parameter type. This allows you to put the
* name of that parameter which I think is good for documentation. It is not required and since
* I did not know what to put there for this example (I could only find doc about IDirect3D2),
* I left them blank.
* - Finally the set of 'IDirect3D_Xxx' macros is a standard set of macros defined to ease access
* to the interface methods in C. Unfortunately I don't see any way to avoid having to duplicate
* the inherited method definitions there. This time I could have used a trick to use only one
* macro whatever the number of parameters but I prefered to have it work the same way as above.
* - You probably have noticed that we don't define the fields we need to actually implement this
* interface: reference count, pointer to other resources and miscellaneous fields. That's
* because these interfaces are just that: interfaces. They may be implemented more than once, in
* different contexts and sometimes not even in Wine. Thus it would not make sense to impose
* that the interface contains some specific fields.
*
*
* In C this gives:
* typedef struct IDirect3DVtbl IDirect3DVtbl;
* struct IDirect3D {
* IDirect3DVtbl* lpVtbl;
* };
* struct IDirect3DVtbl {
* HRESULT (*fnQueryInterface)(IDirect3D* me, REFIID riid, LPVOID* ppvObj);
* ULONG (*fnQueryInterface)(IDirect3D* me);
* ULONG (*fnQueryInterface)(IDirect3D* me);
* HRESULT (*fnInitialize)(IDirect3D* me, REFIID a);
* HRESULT (*fnEnumDevices)(IDirect3D* me, LPD3DENUMDEVICESCALLBACK a, LPVOID b);
* HRESULT (*fnCreateLight)(IDirect3D* me, LPDIRECT3DLIGHT* a, IUnknown* b);
* HRESULT (*fnCreateMaterial)(IDirect3D* me, LPDIRECT3DMATERIAL* a, IUnknown* b);
* HRESULT (*fnCreateViewport)(IDirect3D* me, LPDIRECT3DVIEWPORT* a, IUnknown* b);
* HRESULT (*fnFindDevice)(IDirect3D* me, LPD3DFINDDEVICESEARCH a, LPD3DFINDDEVICERESULT b);
* };
*
* #ifdef ICOM_CINTERFACE
* // *** IUnknown methods *** //
* #define IDirect3D_QueryInterface(p,a,b) (p)->lpVtbl->fnQueryInterface(p,a,b)
* #define IDirect3D_AddRef(p) (p)->lpVtbl->fnAddRef(p)
* #define IDirect3D_Release(p) (p)->lpVtbl->fnRelease(p)
* // *** IDirect3D methods *** //
* #define IDirect3D_Initialize(p,a) (p)->lpVtbl->fnInitialize(p,a)
* #define IDirect3D_EnumDevices(p,a,b) (p)->lpVtbl->fnEnumDevice(p,a,b)
* #define IDirect3D_CreateLight(p,a,b) (p)->lpVtbl->fnCreateLight(p,a,b)
* #define IDirect3D_CreateMaterial(p,a,b) (p)->lpVtbl->fnCreateMaterial(p,a,b)
* #define IDirect3D_CreateViewport(p,a,b) (p)->lpVtbl->fnCreateViewport(p,a,b)
* #define IDirect3D_FindDevice(p,a,b) (p)->lpVtbl->fnFindDevice(p,a,b)
* #endif
*
* Comments:
* - IDirect3D only contains a pointer to the IDirect3D virtual/jump table. This is the only thing
* the user needs to know to use the interface. Of course the structure we will define to
* implement this interface will have more fields but the first one will match this pointer.
* - The code generated by ICOM_DEFINE defines both the structure representing the interface and
* the structure for the jump table. ICOM_DEFINE uses the parent's Xxx_IMETHODS macro to
* automatically repeat the prototypes of all the inherited methods and then uses IDirect3D_METHODS
* to define the IDirect3D methods.
* - Each method is declared as a pointer to function field in the jump table. The implementation
* will fill this jump table with appropriate values, probably using a static variable, and
* initialize the lpVtbl field to point to this variable.
* - The IDirect3D_Xxx macros then just derefence the lpVtbl pointer and use the function pointer
* corresponding to the macro name. This emulates the behavior of a virtual table and should be
* just as fast.
* - This C code should be quite compatible with the Windows headers both for code that uses COM
* interfaces and for code implementing a COM interface.
*
*
* And in C++ (with gcc's g++):
*
* typedef struct IDirect3D: public IUnknown {
* private: HRESULT (*fnInitialize)(IDirect3D* me, REFIID a);
* public: inline HRESULT Initialize(REFIID a) { return ((IDirect3D*)t.lpVtbl)->fnInitialize(this,a); };
* private: HRESULT (*fnEnumDevices)(IDirect3D* me, LPD3DENUMDEVICESCALLBACK a, LPVOID b);
* public: inline HRESULT EnumDevices(LPD3DENUMDEVICESCALLBACK a, LPVOID b)
* { return ((IDirect3D*)t.lpVtbl)->fnEnumDevices(this,a,b); };
* private: HRESULT (*fnCreateLight)(IDirect3D* me, LPDIRECT3DLIGHT* a, IUnknown* b);
* public: inline HRESULT CreateLight(LPDIRECT3DLIGHT* a, IUnknown* b)
* { return ((IDirect3D*)t.lpVtbl)->fnCreateLight(this,a,b); };
* private: HRESULT (*fnCreateMaterial)(IDirect3D* me, LPDIRECT3DMATERIAL* a, IUnknown* b);
* public: inline HRESULT CreateMaterial(LPDIRECT3DMATERIAL* a, IUnknown* b)
* { return ((IDirect3D*)t.lpVtbl)->fnCreateMaterial(this,a,b); };
* private: HRESULT (*fnCreateViewport)(IDirect3D* me, LPDIRECT3DVIEWPORT* a, IUnknown* b);
* public: inline HRESULT CreateViewport(LPDIRECT3DVIEWPORT* a, IUnknown* b)
* { return ((IDirect3D*)t.lpVtbl)->fnCreateViewport(this,a,b); };
* private: HRESULT (*fnFindDevice)(IDirect3D* me, LPD3DFINDDEVICESEARCH a, LPD3DFINDDEVICERESULT b);
* public: inline HRESULT FindDevice(LPD3DFINDDEVICESEARCH a, LPD3DFINDDEVICERESULT b)
* { return ((IDirect3D*)t.lpVtbl)->fnFindDevice(this,a,b); };
* };
*
* Comments:
* - In C++ IDirect3D does double duty as both the virtual/jump table and as the interface
* definition. The reason for this is to avoid having to duplicate the mehod definitions: once
* to have the function pointers in the jump table and once to have the methods in the interface
* class. Here one macro can generate both. This means though that the first pointer, t.lpVtbl
* defined in IUnknown, must be interpreted as the jump table pointer if we interpret the
* structure as the the interface class, and as the function pointer to the QueryInterface
* method, t.fnQueryInterface, if we interpret the structure as the jump table. Fortunately this
* gymnastic is entirely taken care of in the header of IUnknown.
* - Of course in C++ we use inheritance so that we don't have to duplicate the method definitions.
* - Since IDirect3D does double duty, each ICOM_METHOD macro defines both a function pointer and
* a non-vritual inline method which dereferences it and calls it. This way this method behaves
* just like a virtual method but does not create a true C++ virtual table which would break the
* structure layout. If you look at the implementation of these methods you'll notice that they
* would not work for void functions. We have to return something and fortunately this seems to
* be what all the COM methods do (otherwise we would need another set of macros).
* - Note how the ICOM_METHOD generates both function prototypes mixing types and formal parameter
* names and the method invocation using only the formal parameter name. This is the reason why
* we need different macros to handle different numbers of parameters.
* - Finally there is no IDirect3D_Xxx macro. These are not needed in C++ unless the CINTERFACE
* macro is defined in which case we would not be here.
* - This C++ code works well for code that just uses COM interfaces. But it will not work with
* C++ code implement a COM interface. That's because such code assumes the interface methods
* are declared as virtual C++ methods which is not the case here.
*
*
* Implementing a COM interface.
*
* This continues the above example. This example assumes that the implementation is in C.
*
* typedef struct _IDirect3D {
* void* lpVtbl;
* // ...
*
* } _IDirect3D;
*
* static ICOM_VTABLE(IDirect3D) d3dvt;
*
* // implement the IDirect3D methods here
*
* int IDirect3D_fnQueryInterface(IDirect3D* me)
* {
* ICOM_THIS(IDirect3D,me);
* // ...
* }
*
* // ...
*
* static ICOM_VTABLE(IDirect3D) d3dvt = {
* ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
* IDirect3D_fnQueryInterface,
* IDirect3D_fnAdd,
* IDirect3D_fnAdd2,
* IDirect3D_fnInitialize,
* IDirect3D_fnSetWidth
* };
*
* Comments:
* - We first define what the interface really contains. This is th e_IDirect3D structure. The
* first field must of course be the virtual table pointer. Everything else is free.
* - Then we predeclare our static virtual table variable, we will need its address in some
* methods to initialize the virtual table pointer of the returned interface objects.
* - Then we implement the interface methods. To match what has been declared in the header file
* they must take a pointer to a IDirect3D structure and we must cast it to an _IDirect3D so that
* we can manipulate the fields. This is performed by the ICOM_THIS macro.
* - Finally we initialize the virtual table.
*/
#define ICOM_VTABLE(iface) iface##Vtbl
#define ICOM_VFIELD(iface) ICOM_VTABLE(iface)* lpVtbl
#define ICOM_VTBL(iface) (iface)->lpVtbl
#if !defined(__cplusplus) || defined(CINTERFACE)
#define ICOM_CINTERFACE 1
#endif
#ifndef ICOM_CINTERFACE
/* C++ interface */
#define ICOM_METHOD(ret,xfn) \
public: virtual ret CALLBACK (xfn)(void) = 0;
#define ICOM_METHOD1(ret,xfn,ta,na) \
public: virtual ret CALLBACK (xfn)(ta a) = 0;
#define ICOM_METHOD2(ret,xfn,ta,na,tb,nb) \
public: virtual ret CALLBACK (xfn)(ta a,tb b) = 0;
#define ICOM_METHOD3(ret,xfn,ta,na,tb,nb,tc,nc) \
public: virtual ret CALLBACK (xfn)(ta a,tb b,tc c) = 0;
#define ICOM_METHOD4(ret,xfn,ta,na,tb,nb,tc,nc,td,nd) \
public: virtual ret CALLBACK (xfn)(ta a,tb b,tc c,td d) = 0;
#define ICOM_METHOD5(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne) \
public: virtual ret CALLBACK (xfn)(ta a,tb b,tc c,td d,te e) = 0;
#define ICOM_METHOD6(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf) \
public: virtual ret CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f) = 0;
#define ICOM_METHOD7(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng) \
public: virtual ret CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g) = 0;
#define ICOM_METHOD8(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh) \
public: virtual ret CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g,th h) = 0;
#define ICOM_METHOD9(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni) \
public: virtual ret CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i) = 0;
#define ICOM_METHOD10(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj) \
public: virtual ret CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j) = 0;
#define ICOM_METHOD11(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj,tk,nk) \
public: virtual ret CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j,tk k) = 0;
#define ICOM_VMETHOD(xfn) \
public: virtual void CALLBACK (xfn)(void) = 0;
#define ICOM_VMETHOD1(xfn,ta,na) \
public: virtual void CALLBACK (xfn)(ta a) = 0;
#define ICOM_VMETHOD2(xfn,ta,na,tb,nb) \
public: virtual void CALLBACK (xfn)(ta a,tb b) = 0;
#define ICOM_VMETHOD3(xfn,ta,na,tb,nb,tc,nc) \
public: virtual void CALLBACK (xfn)(ta a,tb b,tc c) = 0;
#define ICOM_VMETHOD4(xfn,ta,na,tb,nb,tc,nc,td,nd) \
public: virtual void CALLBACK (xfn)(ta a,tb b,tc c,td d) = 0;
#define ICOM_VMETHOD5(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne) \
public: virtual void CALLBACK (xfn)(ta a,tb b,tc c,td d,te e) = 0;
#define ICOM_VMETHOD6(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf) \
public: virtual void CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f) = 0;
#define ICOM_VMETHOD7(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng) \
public: virtual void CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g) = 0;
#define ICOM_VMETHOD8(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh) \
public: virtual void CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g,th h) = 0;
#define ICOM_VMETHOD9(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni) \
public: virtual void CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i) = 0;
#define ICOM_VMETHOD10(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj) \
public: virtual void CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i, tj j) = 0;
#define ICOM_VMETHOD11(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj,tk,nk) \
public: virtual void CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i, tj j, tk k) = 0;
#ifdef ICOM_USE_COM_INTERFACE_ATTRIBUTE
#define ICOM_DEFINE(iface,ibase) \
typedef struct iface: public ibase { \
iface##_METHODS \
} __attribute__ ((com_interface));
#else
#define ICOM_DEFINE(iface,ibase) \
typedef struct iface: public ibase { \
iface##_METHODS \
};
#endif /* ICOM_USE_COM_INTERFACE_ATTRIBUTE */
#define ICOM_CALL(xfn, p) (p)->xfn()
#define ICOM_CALL1(xfn, p,a) (p)->xfn(a)
#define ICOM_CALL2(xfn, p,a,b) (p)->xfn(a,b)
#define ICOM_CALL3(xfn, p,a,b,c) (p)->xfn(a,b,c)
#define ICOM_CALL4(xfn, p,a,b,c,d) (p)->xfn(a,b,c,d)
#define ICOM_CALL5(xfn, p,a,b,c,d,e) (p)->xfn(a,b,c,d,e)
#define ICOM_CALL6(xfn, p,a,b,c,d,e,f) (p)->xfn(a,b,c,d,e,f)
#define ICOM_CALL7(xfn, p,a,b,c,d,e,f,g) (p)->xfn(a,b,c,d,e,f,g)
#define ICOM_CALL8(xfn, p,a,b,c,d,e,f,g,h) (p)->xfn(a,b,c,d,e,f,g,h)
#define ICOM_CALL9(xfn, p,a,b,c,d,e,f,g,h,i) (p)->xfn(a,b,c,d,e,f,g,h,i)
#define ICOM_CALL10(xfn, p,a,b,c,d,e,f,g,h,i,j) (p)->xfn(a,b,c,d,e,f,g,h,i,j)
#define ICOM_CALL11(xfn, p,a,b,c,d,e,f,g,h,i,j,k) (p)->xfn(a,b,c,d,e,f,g,h,i,j,k)
#else
/* C interface */
#ifdef __WINE__
#define ICOM_METHOD(ret,xfn) \
ret CALLBACK (*fn##xfn)(ICOM_INTERFACE* me);
#define ICOM_METHOD1(ret,xfn,ta,na) \
ret CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a);
#define ICOM_METHOD2(ret,xfn,ta,na,tb,nb) \
ret CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b);
#define ICOM_METHOD3(ret,xfn,ta,na,tb,nb,tc,nc) \
ret CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c);
#define ICOM_METHOD4(ret,xfn,ta,na,tb,nb,tc,nc,td,nd) \
ret CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d);
#define ICOM_METHOD5(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne) \
ret CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e);
#define ICOM_METHOD6(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf) \
ret CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f);
#define ICOM_METHOD7(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng) \
ret CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g);
#define ICOM_METHOD8(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh) \
ret CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h);
#define ICOM_METHOD9(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni) \
ret CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i);
#define ICOM_METHOD10(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj) \
ret CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j);
#define ICOM_METHOD11(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj,tk,nk) \
ret CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j,tk k);
#define ICOM_VMETHOD(xfn) \
void CALLBACK (*fn##xfn)(ICOM_INTERFACE* me);
#define ICOM_VMETHOD1(xfn,ta,na) \
void CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a);
#define ICOM_VMETHOD2(xfn,ta,na,tb,nb) \
void CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b);
#define ICOM_VMETHOD3(xfn,ta,na,tb,nb,tc,nc) \
void CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c);
#define ICOM_VMETHOD4(xfn,ta,na,tb,nb,tc,nc,td,nd) \
void CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d);
#define ICOM_VMETHOD5(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne) \
void CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e);
#define ICOM_VMETHOD6(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf) \
void CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f);
#define ICOM_VMETHOD7(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng) \
void CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g);
#define ICOM_VMETHOD8(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,nh) \
void CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h);
#define ICOM_VMETHOD9(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ni) \
void CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i);
#define ICOM_VMETHOD10(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,nj) \
void CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j);
#define ICOM_VMETHOD11(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj,nk) \
void CALLBACK (*fn##xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j,tk k);
#define ICOM_CALL(xfn, p) ICOM_VTBL(p)->fn##xfn(p)
#define ICOM_CALL1(xfn, p,a) ICOM_VTBL(p)->fn##xfn(p,a)
#define ICOM_CALL2(xfn, p,a,b) ICOM_VTBL(p)->fn##xfn(p,a,b)
#define ICOM_CALL3(xfn, p,a,b,c) ICOM_VTBL(p)->fn##xfn(p,a,b,c)
#define ICOM_CALL4(xfn, p,a,b,c,d) ICOM_VTBL(p)->fn##xfn(p,a,b,c,d)
#define ICOM_CALL5(xfn, p,a,b,c,d,e) ICOM_VTBL(p)->fn##xfn(p,a,b,c,d,e)
#define ICOM_CALL6(xfn, p,a,b,c,d,e,f) ICOM_VTBL(p)->fn##xfn(p,a,b,c,d,e,f)
#define ICOM_CALL7(xfn, p,a,b,c,d,e,f,g) ICOM_VTBL(p)->fn##xfn(p,a,b,c,d,e,f,g)
#define ICOM_CALL8(xfn, p,a,b,c,d,e,f,g,h) ICOM_VTBL(p)->fn##xfn(p,a,b,c,d,e,f,g,h)
#define ICOM_CALL9(xfn, p,a,b,c,d,e,f,g,h,i) ICOM_VTBL(p)->fn##xfn(p,a,b,c,d,e,f,g,h,i)
#define ICOM_CALL10(xfn, p,a,b,c,d,e,f,g,h,i,j) ICOM_VTBL(p)->fn##xfn(p,a,b,c,d,e,f,g,h,i,j)
#define ICOM_CALL11(xfn, p,a,b,c,d,e,f,g,h,i,j,k) ICOM_VTBL(p)->fn##xfn(p,a,b,c,d,e,f,g,h,i,j,k)
#else
/* WINELIB case */
#define ICOM_METHOD(ret,xfn) \
ret CALLBACK (*xfn)(ICOM_INTERFACE* me);
#define ICOM_METHOD1(ret,xfn,ta,na) \
ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a);
#define ICOM_METHOD2(ret,xfn,ta,na,tb,nb) \
ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b);
#define ICOM_METHOD3(ret,xfn,ta,na,tb,nb,tc,nc) \
ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c);
#define ICOM_METHOD4(ret,xfn,ta,na,tb,nb,tc,nc,td,nd) \
ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d);
#define ICOM_METHOD5(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne) \
ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e);
#define ICOM_METHOD6(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf) \
ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f);
#define ICOM_METHOD7(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng) \
ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g);
#define ICOM_METHOD8(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh) \
ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h);
#define ICOM_METHOD9(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni) \
ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i);
#define ICOM_METHOD10(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj) \
ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j);
#define ICOM_METHOD11(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj,tk,nk) \
ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j,tk k);
#define ICOM_VMETHOD(xfn) \
void CALLBACK (*xfn)(ICOM_INTERFACE* me);
#define ICOM_VMETHOD1(xfn,ta,na) \
void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a);
#define ICOM_VMETHOD2(xfn,ta,na,tb,nb) \
void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b);
#define ICOM_VMETHOD3(xfn,ta,na,tb,nb,tc,nc) \
void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c);
#define ICOM_VMETHOD4(xfn,ta,na,tb,nb,tc,nc,td,nd) \
void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d);
#define ICOM_VMETHOD5(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne) \
void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e);
#define ICOM_VMETHOD6(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf) \
void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f);
#define ICOM_VMETHOD7(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng) \
void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g);
#define ICOM_VMETHOD8(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,nh) \
void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h);
#define ICOM_VMETHOD9(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ni) \
void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i);
#define ICOM_VMETHOD10(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,nj) \
void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j);
#define ICOM_VMETHOD11(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj,nk) \
void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j,tk k);
#define ICOM_CVMETHOD(xfn) \
void CALLBACK (*xfn)(const ICOM_INTERFACE* me);
#define ICOM_CVMETHOD1(xfn,ta,na) \
void CALLBACK (*xfn)(const ICOM_INTERFACE* me,ta a);
#define ICOM_CVMETHOD2(xfn,ta,na,tb,nb) \
void CALLBACK (*xfn)(const ICOM_INTERFACE* me,ta a,tb b);
#define ICOM_CVMETHOD3(xfn,ta,na,tb,nb,tc,nc) \
void CALLBACK (*xfn)(const ICOM_INTERFACE* me,ta a,tb b,tc c);
#define ICOM_CVMETHOD4(xfn,ta,na,tb,nb,tc,nc,td,nd) \
void CALLBACK (*xfn)(const ICOM_INTERFACE* me,ta a,tb b,tc c,td d);
#define ICOM_CVMETHOD5(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne) \
void CALLBACK (*xfn)(const ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e);
#define ICOM_CVMETHOD6(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf) \
void CALLBACK (*xfn)(const ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f);
#define ICOM_CVMETHOD7(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng) \
void CALLBACK (*xfn)(const ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g);
#define ICOM_CVMETHOD8(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh) \
void CALLBACK (*xfn)(const ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h);
#define ICOM_CVMETHOD9(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni) \
void CALLBACK (*xfn)(const ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i);
#define ICOM_CVMETHOD10(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj) \
void CALLBACK (*xfn)(const ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j);
#define ICOM_CVMETHOD11(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj,tk,nk) \
void CALLBACK (*xfn)(const ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j,tk k);
#define ICOM_CALL(xfn, p) ICOM_VTBL(p)->xfn(p)
#define ICOM_CALL1(xfn, p,a) ICOM_VTBL(p)->xfn(p,a)
#define ICOM_CALL2(xfn, p,a,b) ICOM_VTBL(p)->xfn(p,a,b)
#define ICOM_CALL3(xfn, p,a,b,c) ICOM_VTBL(p)->xfn(p,a,b,c)
#define ICOM_CALL4(xfn, p,a,b,c,d) ICOM_VTBL(p)->xfn(p,a,b,c,d)
#define ICOM_CALL5(xfn, p,a,b,c,d,e) ICOM_VTBL(p)->xfn(p,a,b,c,d,e)
#define ICOM_CALL6(xfn, p,a,b,c,d,e,f) ICOM_VTBL(p)->xfn(p,a,b,c,d,e,f)
#define ICOM_CALL7(xfn, p,a,b,c,d,e,f,g) ICOM_VTBL(p)->xfn(p,a,b,c,d,e,f,g)
#define ICOM_CALL8(xfn, p,a,b,c,d,e,f,g,h) ICOM_VTBL(p)->xfn(p,a,b,c,d,e,f,g,h)
#define ICOM_CALL9(xfn, p,a,b,c,d,e,f,g,h,i) ICOM_VTBL(p)->xfn(p,a,b,c,d,e,f,g,h,i)
#define ICOM_CALL10(xfn, p,a,b,c,d,e,f,g,h,i,j) ICOM_VTBL(p)->xfn(p,a,b,c,d,e,f,g,h,i,j)
#define ICOM_CALL11(xfn, p,a,b,c,d,e,f,g,h,i,j,k) ICOM_VTBL(p)->xfn(p,a,b,c,d,e,f,g,h,i,j,k)
#endif /* __WINE__ */
#ifdef ICOM_MSVTABLE_COMPAT
#define ICOM_DEFINE(iface,ibase) \
typedef struct ICOM_VTABLE(iface) ICOM_VTABLE(iface); \
struct iface { \
const ICOM_VFIELD(iface); \
}; \
struct ICOM_VTABLE(iface) { \
long dummyRTTI1; \
long dummyRTTI2; \
ibase##_IMETHODS \
iface##_METHODS \
};
#define ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE 0,0,
#else
#define ICOM_DEFINE(iface,ibase) \
typedef struct ICOM_VTABLE(iface) ICOM_VTABLE(iface); \
struct iface { \
const ICOM_VFIELD(iface); \
}; \
struct ICOM_VTABLE(iface) { \
ibase##_IMETHODS \
iface##_METHODS \
};
#define ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
#endif /* ICOM_MSVTABLE_COMPAT */
#define ICOM_THIS(impl,iface) impl* const This=(impl*)iface
#define ICOM_CTHIS(impl,iface) const impl* const This=(const impl*)iface
#endif
/*****************************************************************************
* Predeclare the interfaces
*/
DEFINE_OLEGUID(IID_IClassFactory, 0x00000001L, 0, 0);
typedef struct IClassFactory IClassFactory, *LPCLASSFACTORY;
DEFINE_OLEGUID(IID_IMalloc, 0x00000002L, 0, 0);
typedef struct IMalloc IMalloc,*LPMALLOC;
DEFINE_OLEGUID(IID_IUnknown, 0x00000000L, 0, 0);
typedef struct IUnknown IUnknown, *LPUNKNOWN;
/*****************************************************************************
* IUnknown interface
*/
#define ICOM_INTERFACE IUnknown
#define IUnknown_IMETHODS \
ICOM_METHOD2(HRESULT,QueryInterface,REFIID,riid, LPVOID*,ppvObj) \
ICOM_METHOD (ULONG,AddRef) \
ICOM_METHOD (ULONG,Release)
#ifdef ICOM_CINTERFACE
typedef struct ICOM_VTABLE(IUnknown) ICOM_VTABLE(IUnknown);
struct IUnknown {
ICOM_VFIELD(IUnknown);
#if defined(ICOM_USE_COM_INTERFACE_ATTRIBUTE)
} __attribute__ ((com_interface));
#else
};
#endif /* ICOM_US_COM_INTERFACE_ATTRIBUTE */
struct ICOM_VTABLE(IUnknown) {
#ifdef ICOM_MSVTABLE_COMPAT
long dummyRTTI1;
long dummyRTTI2;
#endif /* ICOM_MSVTABLE_COMPAT */
#else /* ICOM_CINTERFACE */
struct IUnknown {
#endif /* ICOM_CINTERFACE */
ICOM_METHOD2(HRESULT,QueryInterface,REFIID,riid, LPVOID*,ppvObj)
ICOM_METHOD (ULONG,AddRef)
ICOM_METHOD (ULONG,Release)
#if defined(ICOM_USE_COM_INTERFACE_ATTRIBUTE)
} __attribute__ ((com_interface));
#else
};
#endif /* ICOM_US_COM_INTERFACE_ATTRIBUTE */
#undef ICOM_INTERFACE
/*** IUnknown methods ***/
#define IUnknown_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b)
#define IUnknown_AddRef(p) ICOM_CALL (AddRef,p)
#define IUnknown_Release(p) ICOM_CALL (Release,p)
/*****************************************************************************
* IClassFactory interface
*/
#define ICOM_INTERFACE IClassFactory
#define IClassFactory_METHODS \
ICOM_METHOD3(HRESULT,CreateInstance, LPUNKNOWN,pUnkOuter, REFIID,riid, LPVOID*,ppvObject) \
ICOM_METHOD1(HRESULT,LockServer, BOOL,fLock)
#define IClassFactory_IMETHODS \
IUnknown_IMETHODS \
IClassFactory_METHODS
ICOM_DEFINE(IClassFactory,IUnknown)
#undef ICOM_INTERFACE
/*** IUnknown methods ***/
#define IClassFactory_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b)
#define IClassFactory_AddRef(p) ICOM_CALL (AddRef,p)
#define IClassFactory_Release(p) ICOM_CALL (Release,p)
/*** IClassFactory methods ***/
#define IClassFactory_CreateInstance(p,a,b,c) ICOM_CALL3(CreateInstance,p,a,b,c)
#define IClassFactory_LockServer(p,a) ICOM_CALL1(LockServer,p,a)
/*****************************************************************************
* IMalloc interface
*/
#define ICOM_INTERFACE IMalloc
#define IMalloc_METHODS \
ICOM_METHOD1 (LPVOID,Alloc, DWORD,cb) \
ICOM_METHOD2 (LPVOID,Realloc, LPVOID,pv, DWORD,cb) \
ICOM_VMETHOD1( Free, LPVOID,pv) \
ICOM_METHOD1(DWORD, GetSize, LPVOID,pv) \
ICOM_METHOD1(INT, DidAlloc, LPVOID,pv) \
ICOM_METHOD (VOID, HeapMinimize)
#define IMalloc_IMETHODS \
IUnknown_IMETHODS \
IMalloc_METHODS
ICOM_DEFINE(IMalloc,IUnknown)
#undef ICOM_INTERFACE
/*** IUnknown methods ***/
#define IMalloc_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b)
#define IMalloc_AddRef(p) ICOM_CALL (AddRef,p)
#define IMalloc_Release(p) ICOM_CALL (Release,p)
/*** IMalloc32 methods ***/
#define IMalloc_Alloc(p,a) ICOM_CALL1(Alloc,p,a)
#define IMalloc_Realloc(p,a,b) ICOM_CALL2(Realloc,p,a,b)
#define IMalloc_Free(p,a) ICOM_CALL1(Free,p,a)
#define IMalloc_GetSize(p,a) ICOM_CALL1(GetSize,p,a)
#define IMalloc_DidAlloc(p,a) ICOM_CALL1(DidAlloc,p,a)
#define IMalloc_HeapMinimize(p) ICOM_CALL (HeapMinimize,p)
HRESULT WINAPI CoGetMalloc(DWORD dwMemContext,LPMALLOC* lpMalloc);
LPVOID WINAPI CoTaskMemAlloc(ULONG size);
void WINAPI CoTaskMemFree(LPVOID ptr);
/* FIXME: unimplemented */
LPVOID WINAPI CoTaskMemRealloc(LPVOID ptr, ULONG size);
/*****************************************************************************
* Additional API
*/
HRESULT WINAPI CoCreateGuid(GUID* pguid);
HINSTANCE WINAPI CoLoadLibrary(LPOLESTR lpszLibName, BOOL bAutoFree);
void WINAPI CoFreeAllLibraries(void);
void WINAPI CoFreeLibrary(HINSTANCE hLibrary);
void WINAPI CoFreeUnusedLibraries(void);
HRESULT WINAPI CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv);
HRESULT WINAPI CoGetClassObject(REFCLSID rclsid, DWORD dwClsContext, LPVOID pvReserved, REFIID iid, LPVOID *ppv);
HRESULT WINAPI CoInitialize(LPVOID lpReserved);
HRESULT WINAPI CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit);
void WINAPI CoUninitialize(void);
typedef enum tagCOINIT
{
COINIT_APARTMENTTHREADED = 0x2, /* Apartment model */
COINIT_MULTITHREADED = 0x0, /* OLE calls objects on any thread */
COINIT_DISABLE_OLE1DDE = 0x4, /* Don't use DDE for Ole1 support */
COINIT_SPEED_OVER_MEMORY = 0x8 /* Trade memory for speed */
} COINIT;
/* FIXME: not implemented */
BOOL WINAPI CoIsOle1Class(REFCLSID rclsid);
HRESULT WINAPI CoLockObjectExternal(LPUNKNOWN pUnk, BOOL fLock, BOOL fLastUnlockReleases);
/* class registration flags; passed to CoRegisterClassObject */
typedef enum tagREGCLS
{
REGCLS_SINGLEUSE = 0,
REGCLS_MULTIPLEUSE = 1,
REGCLS_MULTI_SEPARATE = 2,
REGCLS_SUSPENDED = 4
} REGCLS;
HRESULT WINAPI CoResumeClassObjects (void);
HRESULT WINAPI CoRegisterClassObject(REFCLSID rclsid,LPUNKNOWN pUnk,DWORD dwClsContext,DWORD flags,LPDWORD lpdwRegister);
HRESULT WINAPI CoRevokeClassObject(DWORD dwRegister);
/*****************************************************************************
* COM Server dll - exports
*/
HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID * ppv);
HRESULT WINAPI DllCanUnloadNow(void);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* __WINE_WINE_OBJ_BASE_H */

View File

@ -0,0 +1,272 @@
/* wtypes.h - Defines the basic types used by COM interfaces.
Copyright (c) 1993-2000 the Wine project authors (see the file WINE-AUTHORS
for a complete list)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __WINE_WTYPES_H
#define __WINE_WTYPES_H
#include "basetsd.h"
#include "guiddef.h"
/*#include "rpc.h"*/
/*#include "rpcndr.h"*/
typedef WORD CLIPFORMAT, *LPCLIPFORMAT;
/* FIXME: does not belong here */
typedef CHAR OLECHAR16;
typedef LPSTR LPOLESTR16;
typedef LPCSTR LPCOLESTR16;
typedef OLECHAR16 *BSTR16;
typedef BSTR16 *LPBSTR16;
#define OLESTR16(x) x
typedef WCHAR OLECHAR;
typedef LPWSTR LPOLESTR;
typedef LPCWSTR LPCOLESTR;
typedef OLECHAR *BSTR;
typedef BSTR *LPBSTR;
/*
#ifndef _DWORDLONG_
#define _DWORDLONG_
typedef __uint64 DWORDLONG, *PDWORDLONG;
#endif
#ifndef _ULONGLONG_
#define _ULONGLONG_
typedef __int64 LONGLONG, *PLONGLONG;
typedef __uint64 ULONGLONG, *PULONGLONG;
#endif
*/
#define OLESTR(x) L##x
typedef enum tagDVASPECT
{
DVASPECT_CONTENT = 1,
DVASPECT_THUMBNAIL = 2,
DVASPECT_ICON = 4,
DVASPECT_DOCPRINT = 8
} DVASPECT;
typedef enum tagSTGC
{
STGC_DEFAULT = 0,
STGC_OVERWRITE = 1,
STGC_ONLYIFCURRENT = 2,
STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE = 4,
STGC_CONSOLIDATE = 8
} STGC;
typedef enum tagSTGMOVE
{
STGMOVE_MOVE = 0,
STGMOVE_COPY = 1,
STGMOVE_SHALLOWCOPY = 2
} STGMOVE;
typedef struct _COAUTHIDENTITY
{
USHORT* User;
ULONG UserLength;
USHORT* Domain;
ULONG DomainLength;
USHORT* Password;
ULONG PasswordLength;
ULONG Flags;
} COAUTHIDENTITY;
typedef struct _COAUTHINFO
{
DWORD dwAuthnSvc;
DWORD dwAuthzSvc;
LPWSTR pwszServerPrincName;
DWORD dwAuthnLevel;
DWORD dwImpersonationLevel;
COAUTHIDENTITY* pAuthIdentityData;
DWORD dwCapabilities;
} COAUTHINFO;
typedef struct _COSERVERINFO
{
DWORD dwReserved1;
LPWSTR pwszName;
COAUTHINFO* pAuthInfo;
DWORD dwReserved2;
} COSERVERINFO;
typedef enum tagCLSCTX
{
CLSCTX_INPROC_SERVER = 0x1,
CLSCTX_INPROC_HANDLER = 0x2,
CLSCTX_LOCAL_SERVER = 0x4,
CLSCTX_INPROC_SERVER16 = 0x8,
CLSCTX_REMOTE_SERVER = 0x10,
CLSCTX_INPROC_HANDLER16 = 0x20,
CLSCTX_INPROC_SERVERX86 = 0x40,
CLSCTX_INPROC_HANDLERX86 = 0x80,
CLSCTX_ESERVER_HANDLER = 0x100
} CLSCTX;
#define CLSCTX_INPROC (CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER)
#define CLSCTX_ALL (CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER)
#define CLSCTX_SERVER (CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER)
typedef enum tagMSHLFLAGS
{
MSHLFLAGS_NORMAL = 0,
MSHLFLAGS_TABLESTRONG = 1,
MSHLFLAGS_TABLEWEAK = 2,
MSHLFLAGS_NOPING = 4
} MSHLFLAGS;
typedef enum tagMSHCTX
{
MSHCTX_LOCAL = 0,
MSHCTX_NOSHAREDMEM = 1,
MSHCTX_DIFFERENTMACHINE = 2,
MSHCTX_INPROC = 3
} MSHCTX;
typedef unsigned short VARTYPE;
typedef ULONG PROPID;
/*
#ifndef _tagBLOB_DEFINED
#define _tagBLOB_DEFINED
#define _BLOB_DEFINED
#define _LPBLOB_DEFINED
typedef struct tagBLOB
{
ULONG cbSize;
BYTE *pBlobData;
} BLOB, *LPBLOB;
#endif
*/
#ifndef _tagCY_DEFINED
#define _tagCY_DEFINED
typedef union tagCY {
struct {
#ifdef BIG_ENDIAN
LONG Hi;
LONG Lo;
#else /* defined(BIG_ENDIAN) */
ULONG Lo;
LONG Hi;
#endif /* defined(BIG_ENDIAN) */
} DUMMYSTRUCTNAME;
LONGLONG int64;
} CY;
#endif /* _tagCY_DEFINED */
/*
* 0 == FALSE and -1 == TRUE
*/
#define VARIANT_TRUE ((VARIANT_BOOL)0xFFFF)
#define VARIANT_FALSE ((VARIANT_BOOL)0x0000)
typedef short VARIANT_BOOL,_VARIANT_BOOL;
typedef struct tagCLIPDATA
{
ULONG cbSize;
long ulClipFmt;
BYTE *pClipData;
} CLIPDATA;
/* Macro to calculate the size of the above pClipData */
#define CBPCLIPDATA(clipdata) ( (clipdata).cbSize - sizeof((clipdata).ulClipFmt) )
typedef LONG SCODE;
/*
#ifndef _FILETIME_
#define _FILETIME_
*/
/* 64 bit number of 100 nanoseconds intervals since January 1, 1601 */
/*
typedef struct
{
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME, *LPFILETIME;
#endif
*/
#ifndef _SECURITY_DEFINED
#define _SECURITY_DEFINED
/*
typedef struct {
BYTE Value[6];
} SID_IDENTIFIER_AUTHORITY,*PSID_IDENTIFIER_AUTHORITY;
typedef struct _SID {
BYTE Revision;
BYTE SubAuthorityCount;
SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
DWORD SubAuthority[1];
} SID,*PSID;
*/
/*
* ACL
*/
/*
typedef struct _ACL {
BYTE AclRevision;
BYTE Sbz1;
WORD AclSize;
WORD AceCount;
WORD Sbz2;
} ACL, *PACL;
typedef DWORD SECURITY_INFORMATION;
typedef WORD SECURITY_DESCRIPTOR_CONTROL, *PSECURITY_DESCRIPTOR_CONTROL;
typedef DWORD ACCESS_MASK, *PACCESS_MASK;
typedef PVOID PGENERIC_MAPPING;
*/
/* The security descriptor structure */
/*
typedef struct {
BYTE Revision;
BYTE Sbz1;
SECURITY_DESCRIPTOR_CONTROL Control;
PSID Owner;
PSID Group;
PACL Sacl;
PACL Dacl;
} SECURITY_DESCRIPTOR, *PSECURITY_DESCRIPTOR;
*/
#endif /* _SECURITY_DEFINED */
#ifndef _ROTFLAGS_DEFINED
#define _ROTFLAGS_DEFINED
#define ROTFLAGS_REGISTRATIONKEEPSALIVE 0x1
#define ROTFLAGS_ALLOWANYCLIENT 0x2
#endif /* !defined(_ROTFLAGS_DEFINED) */
#endif /* __WINE_WTYPES_H */

View File

@ -0,0 +1,170 @@
# configure.in for GPGME
#
dnl (Process this file with autoconf to produce a configure script.)
AC_REVISION($Revision$)dnl
AC_INIT(gpgme/gpgme.h)
AM_CONFIG_HEADER(config.h)
AM_MAINTAINER_MODE
#############################################
# Version numbers (Remember to change them just before a release)
# 1. No interfaces changed, only implementations (good): Increment REVISION.
# 2. Interfaces added, none removed (good): Increment CURRENT, increment
# AGE, set REVISION to 0.
# 3. Interfaces removed (BAD, breaks upward compatibility): Increment
# CURRENT, set AGE and REVISION to 0.
AM_INIT_AUTOMAKE(gpgme,0.1.3)
LIBGPGME_LT_CURRENT=1
LIBGPGME_LT_AGE=1
LIBGPGME_LT_REVISION=0
##############################################
AC_SUBST(LIBGPGME_LT_CURRENT)
AC_SUBST(LIBGPGME_LT_AGE)
AC_SUBST(LIBGPGME_LT_REVISION)
AM_MAINTAINER_MODE
dnl
dnl Checks for programs
dnl
AC_ARG_PROGRAM
dnl Don't default to build static libs
AM_DISABLE_STATIC
AM_PROG_LIBTOOL
if test "$GCC" = yes; then
CFLAGS="$CFLAGS -Wall -Wcast-align -Wshadow -Wstrict-prototypes"
fi
GPG=
component_system=None
case "${target}" in
*-*-mingw32* | i?86-emx-os2 | i?86-*-os2*emx | i?86-*-msdosdjgpp* )
# special stuff for Windoze NT
# OS/2 with the EMX environment
# DOS with the DJGPP environment
AC_DEFINE(HAVE_DRIVE_LETTERS)
AC_DEFINE(HAVE_DOSISH_SYSTEM)
GPG='c:\\gnupg\\gpg.exe'
#component_system='COM+'
;;
*)
;;
esac
dnl
dnl Checks for libraries
dnl
dnl
dnl Checks for header files
dnl
dnl
dnl Checks for typedefs and structures
dnl
GNUPG_CHECK_TYPEDEF(byte, HAVE_BYTE_TYPEDEF)
GNUPG_CHECK_TYPEDEF(ushort, HAVE_USHORT_TYPEDEF)
GNUPG_CHECK_TYPEDEF(ulong, HAVE_ULONG_TYPEDEF)
GNUPG_CHECK_TYPEDEF(u16, HAVE_U16_TYPEDEF)
GNUPG_CHECK_TYPEDEF(u32, HAVE_U32_TYPEDEF)
# We should not use them in this software;
# However jnlib/types.h needs them - so we take the easy way.
AC_CHECK_SIZEOF(unsigned short, 2)
AC_CHECK_SIZEOF(unsigned int, 4)
AC_CHECK_SIZEOF(unsigned long, 4)
if test "$ac_cv_sizeof_unsigned_short" = "0" \
|| test "$ac_cv_sizeof_unsigned_int" = "0" \
|| test "$ac_cv_sizeof_unsigned_long" = "0"; then
AC_MSG_WARN([Hmmm, something is wrong with the sizes - using defaults]);
fi
dnl
dnl Checks for compiler features
dnl
dnl
dnl Checks for library functions
dnl
dnl These are needed by libjnlib
AC_CHECK_FUNCS(memicmp stpcpy strlwr strtoul memmove stricmp)
dnl
dnl Checks for system services
dnl
if test -z "$GPG"; then
AC_PATH_PROG(GPG, gpg)
if test -z "$GPG"; then
AC_MSG_ERROR([[
***
*** GnuPG not found. Please install GnuPG first.
*** See http://www.gnupg.org/download.html
***
]])
fi
fi
AC_DEFINE_UNQUOTED(GPG_PATH, "$GPG")
dnl
dnl FIXME: check whether Bonobo is installed
dnl
dnl
dnl Create config files
dnl
dnl
AM_CONDITIONAL(BUILD_COMPLUS, test "$component_system" = "COM+")
AM_CONDITIONAL(BUILD_BONOBO, test "$component_system" = "Bonobo")
dnl Make the version number in gpgme/gpgme.h the same as the one here.
dnl (this is easier than to have a *.in file just for one substitution)
GNUPG_FIX_HDR_VERSION(gpgme/gpgme.h, GPGME_VERSION)
dnl Substitution used for gpgme-config
GPGME_LIBS="-L${libdir} -lgpgme"
GPGME_CFLAGS=""
AC_SUBST(GPGME_LIBS)
AC_SUBST(GPGME_CFLAGS)
AC_OUTPUT_COMMANDS([
chmod +x gpgme/gpgme-config
])
AC_OUTPUT([
Makefile
jnlib/Makefile
gpgme/Makefile
gpgme/gpgme-config
tests/Makefile
bonobo/Makefile
complus/Makefile
])
echo "
GPGME v${VERSION} has been configured as follows:
GPG path: $GPG
Component: $component_system
"

View File

View File

@ -0,0 +1,45 @@
# 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 \
context.h ops.h \
data.c recipient.c \
wait.c wait.h \
encrypt.c \
decrypt.c \
verify.c \
sign.c \
key.c key.h \
keylist.c \
import.c \
export.c \
genkey.c \
rungpg.c rungpg.h status-table.h \
syshdr.h io.h posix-io.c w32-io.c \
gpgme.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

View File

@ -0,0 +1,129 @@
/* context.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 CONTEXT_H
#define CONTEXT_H
#include "gpgme.h"
#include "types.h"
#include "rungpg.h" /* for GpgObject */
typedef enum {
RESULT_TYPE_NONE = 0,
RESULT_TYPE_VERIFY,
RESULT_TYPE_DECRYPT,
RESULT_TYPE_SIGN,
} ResultType;
struct key_queue_item_s {
struct key_queue_item_s *next;
GpgmeKey key;
};
/* Currently we need it at several places, so we put the definition
* into this header file */
struct gpgme_context_s {
int initialized;
int pending; /* a gpg request is still pending */
/* at some points we need to allocate memory but we are not
* able to handle a malloc problem at that point, so we set this
* flag to indicate this condition */
int out_of_core;
GpgObject gpg; /* the running gpg process */
int verbosity; /* level of verbosity to use */
int use_armor;
int use_textmode;
ResultType result_type;
union {
VerifyResult verify;
DecryptResult decrypt;
SignResult sign;
} result;
GpgmeData notation; /* last signature notation */
GpgmeKey tmp_key; /* used by keylist.c */
volatile int key_cond; /* something new is available */
struct key_queue_item_s *key_queue;
GpgmePassphraseCb passphrase_cb;
void *passphrase_cb_value;
GpgmeProgressCb progress_cb;
void *progress_cb_value;
GpgmeData help_data_1;
};
struct gpgme_data_s {
size_t len;
const char *data;
GpgmeDataType type;
GpgmeDataMode mode;
int (*read_cb)( void *, char *, size_t, size_t *);
void *read_cb_value;
int read_cb_eof;
size_t readpos;
size_t writepos;
size_t private_len;
char *private_buffer;
};
struct user_id_s {
struct user_id_s *next;
int validity; /* 0 = undefined, 1 = not, 2 = marginal,
3 = full, 4 = ultimate */
char name[1];
};
struct gpgme_recipients_s {
struct user_id_s *list;
int checked; /* wether the recipients are all valid */
};
#define fail_on_pending_request(c) \
do { \
if (!(c)) return GPGME_Invalid_Value; \
if ((c)->pending) return GPGME_Busy; \
} while (0)
#define wait_on_request_or_fail(c) \
do { \
if (!(c)) return GPGME_Invalid_Value;\
if (!(c)->pending) return GPGME_No_Request; \
gpgme_wait ((c), 1); \
} while (0)
#endif /* CONTEXT_H */

View File

@ -0,0 +1,636 @@
/* data.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 <assert.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "syshdr.h"
#include "util.h"
#include "context.h"
#include "ops.h"
#define ALLOC_CHUNK 1024
#define my_isdigit(a) ( (a) >='0' && (a) <= '9' )
#define my_isxdigit(a) ( my_isdigit((a)) \
|| ((a) >= 'A' && (a) <= 'F') \
|| ((a) >= 'f' && (a) <= 'f') )
/**
* gpgme_data_new:
* @r_dh: returns the new data object
*
* Create a new data object without any content.
*
* Return value: An error value or 0 on success
**/
GpgmeError
gpgme_data_new ( GpgmeData *r_dh )
{
GpgmeData dh;
if (!r_dh)
return mk_error (Invalid_Value);
*r_dh = NULL;
dh = xtrycalloc ( 1, sizeof *dh );
if (!dh)
return mk_error (Out_Of_Core);
dh->mode = GPGME_DATA_MODE_INOUT;
*r_dh = dh;
return 0;
}
/**
* gpgme_data_new_from_mem:
* @r_dh: Returns a new data object.
* @buffer: Initialize with this.
* @size: Size of the buffer
* @copy: Flag wether a copy of the buffer should be used.
*
* Create a new data object and initialize with data
* from the memory. A @copy with value %TRUE creates a copy of the
* memory, a value of %FALSE uses the original memory of @buffer and the
* caller has to make sure that this buffer is valid until gpgme_release_data()
* is called.
*
* Return value:
**/
GpgmeError
gpgme_data_new_from_mem ( GpgmeData *r_dh,
const char *buffer, size_t size, int copy )
{
GpgmeData dh;
GpgmeError err;
if (!r_dh || !buffer)
return mk_error (Invalid_Value);
*r_dh = NULL;
err = gpgme_data_new ( &dh );
if (err)
return err;
dh->len = size;
if (copy) {
dh->private_buffer = xtrymalloc ( size );
if ( !dh->private_buffer ) {
gpgme_data_release (dh);
return mk_error (Out_Of_Core);
}
dh->private_len = size;
memcpy (dh->private_buffer, buffer, size );
dh->data = dh->private_buffer;
dh->writepos = size;
}
else {
dh->data = buffer;
}
dh->type = GPGME_DATA_TYPE_MEM;
*r_dh = dh;
return 0;
}
GpgmeError
gpgme_data_new_with_read_cb ( GpgmeData *r_dh,
int (*read_cb)(void*,char *,size_t,size_t*),
void *read_cb_value )
{
GpgmeData dh;
GpgmeError err;
if (!r_dh || !read_cb)
return mk_error (Invalid_Value);
*r_dh = NULL;
err = gpgme_data_new ( &dh );
if (err)
return err;
dh->type = GPGME_DATA_TYPE_CB;
dh->mode = GPGME_DATA_MODE_OUT;
dh->read_cb = read_cb;
dh->read_cb_value = read_cb_value;
*r_dh = dh;
return 0;
}
/**
* gpgme_data_new_from_file:
* @r_dh: returns the new data object
* @fname: filename
* @copy: Flag, whether the file should be copied.
*
* Create a new data object and initialize it with the content of
* the file @file. If @copy is %True the file is immediately read in
* adn closed. @copy of %False is not yet supportted.
*
* Return value: An error code or 0 on success. If the error code is
* %GPGME_File_Error, the OS error code is held in %errno.
**/
GpgmeError
gpgme_data_new_from_file ( GpgmeData *r_dh, const char *fname, int copy )
{
GpgmeData dh;
GpgmeError err;
struct stat st;
FILE *fp;
if (!r_dh)
return mk_error (Invalid_Value);
*r_dh = NULL;
/* We only support copy for now - in future we might want to honor the
* copy flag and just store a file pointer */
if (!copy)
return mk_error (Not_Implemented);
if (!fname)
return mk_error (Invalid_Value);
err = gpgme_data_new ( &dh );
if (err)
return err;
fp = fopen (fname, "rb");
if (!fp) {
int save_errno = errno;
gpgme_data_release (dh);
errno = save_errno;
return mk_error (File_Error);
}
if( fstat(fileno(fp), &st) ) {
int save_errno = errno;
fclose (fp);
gpgme_data_release (dh);
errno = save_errno;
return mk_error (File_Error);
}
/* We should check the length of the file and don't allow for to
* large files */
dh->private_buffer = xtrymalloc ( st.st_size );
if ( !dh->private_buffer ) {
fclose (fp);
gpgme_data_release (dh);
return mk_error (Out_Of_Core);
}
dh->private_len = st.st_size;
if ( fread ( dh->private_buffer, dh->private_len, 1, fp ) != 1 ) {
int save_errno = errno;
fclose (fp);
gpgme_data_release (dh);
errno = save_errno;
return mk_error (File_Error);
}
fclose (fp);
dh->len = dh->private_len;
dh->data = dh->private_buffer;
dh->writepos = dh->len;
dh->type = GPGME_DATA_TYPE_MEM;
*r_dh = dh;
return 0;
}
/**
* gpgme_data_release:
* @dh: Data object
*
* Release the data object @dh. @dh may be NULL in which case nothing
* happens.
**/
void
gpgme_data_release ( GpgmeData dh )
{
if (dh) {
xfree (dh->private_buffer);
xfree (dh);
}
}
char *
_gpgme_data_release_and_return_string ( GpgmeData dh )
{
char *val = NULL;
if (dh) {
if ( _gpgme_data_append ( dh, "", 0 ) ) /* append EOS */
xfree (dh->private_buffer );
else {
val = dh->private_buffer;
if ( !val && dh->data ) {
val = xtrymalloc ( dh->len );
if ( val )
memcpy ( val, dh->data, dh->len );
}
}
xfree (dh);
}
return val;
}
/**
* gpgme_data_release_and_get_mem:
* @dh: the data object
* @r_len: returns the length of the memory
*
* Release the data object @dh and return its content and the length of
* that content. The caller has to free this data. @dh maybe NULL in
* which case NULL is returned. I there is not enough memory for allocating
* the return value, NULL is returned and the object is released.
*
* Return value: a pointer to an allocated buffer of length @r_len.
**/
char *
gpgme_data_release_and_get_mem ( GpgmeData dh, size_t *r_len )
{
char *val = NULL;
if (r_len)
*r_len = 0;
if (dh) {
size_t len = dh->len;
val = dh->private_buffer;
if ( !val && dh->data ) {
val = xtrymalloc ( len );
if ( val )
memcpy ( val, dh->data, len );
}
xfree (dh);
if (val && r_len )
*r_len = len;
}
return val;
}
/**
* gpgme_data_get_type:
* @dh: the data object
*
* Get the type of the data object.
* Data types are prefixed with %GPGME_DATA_TYPE_
*
* Return value: the data type
**/
GpgmeDataType
gpgme_data_get_type ( GpgmeData dh )
{
if ( !dh || (!dh->data && !dh->read_cb))
return GPGME_DATA_TYPE_NONE;
return dh->type;
}
void
_gpgme_data_set_mode ( GpgmeData dh, GpgmeDataMode mode )
{
assert (dh);
dh->mode = mode;
}
GpgmeDataMode
_gpgme_data_get_mode ( GpgmeData dh )
{
assert (dh);
return dh->mode;
}
/**
* gpgme_data_rewind:
* @dh: the data object
*
* Prepare the data object in a way, that a gpgme_data_read() does start
* at the beginning of the data. This has to be done for all types
* of data objects.
*
* Return value: An error code or 0 on success
**/
GpgmeError
gpgme_data_rewind ( GpgmeData dh )
{
if ( !dh )
return mk_error (Invalid_Value);
if (dh->type == GPGME_DATA_TYPE_MEM ) {
dh->readpos = 0;
}
else if (dh->type == GPGME_DATA_TYPE_CB) {
dh->len = dh->readpos = 0;
dh->read_cb_eof = 0;
/* FIXME: do a special call to the read function to trigger a rewind
there */
}
else
return mk_error (General_Error);
return 0;
}
/**
* gpgme_data_read:
* @dh: the data object
* @buffer: A buffer
* @length: The length of that bufer
* @nread: Returns the number of bytes actually read.
*
* Copy data from the current read position (which may be set by
* gpgme_data_rewind()) to the supplied @buffer, max. @length bytes
* are copied and the actual number of bytes are returned in @nread.
* If there are no more bytes available %GPGME_EOF is returned and @nread
* is set to 0.
*
* Return value: An errorcode or 0 on success, EOF is indcated by the
* error code GPGME_EOF.
**/
GpgmeError
gpgme_data_read ( GpgmeData dh, char *buffer, size_t length, size_t *nread )
{
size_t nbytes;
if ( !dh )
return mk_error (Invalid_Value);
if (dh->type == GPGME_DATA_TYPE_MEM ) {
nbytes = dh->len - dh->readpos;
if ( !nbytes ) {
*nread = 0;
return mk_error(EOF);
}
if (nbytes > length)
nbytes = length;
memcpy ( buffer, dh->data + dh->readpos, nbytes );
*nread = nbytes;
dh->readpos += nbytes;
}
else if (dh->type == GPGME_DATA_TYPE_CB) {
nbytes = dh->len - dh->readpos;
if ( nbytes ) {
/* we have unread data - return this */
if (nbytes > length)
nbytes = length;
memcpy ( buffer, dh->data + dh->readpos, nbytes );
*nread = nbytes;
dh->readpos += nbytes;
}
else { /* get the data from the callback */
if (!dh->read_cb || dh->read_cb_eof) {
*nread = 0;
return mk_error (EOF);
}
if (dh->read_cb (dh->read_cb_value, buffer, length, nread )) {
*nread = 0;
dh->read_cb_eof = 1;
return mk_error (EOF);
}
}
}
else
return mk_error (General_Error);
return 0;
}
GpgmeError
_gpgme_data_unread (GpgmeData dh, const char *buffer, size_t length )
{
if ( !dh )
return mk_error (Invalid_Value);
if (dh->type == GPGME_DATA_TYPE_MEM ) {
/* check that we don't unread more than we have yet read */
if ( dh->readpos < length )
return mk_error (Invalid_Value);
/* No need to use the buffer for this data type */
dh->readpos -= length;
}
else {
return mk_error (General_Error);
}
return 0;
}
/*
* This function does make sense when we know that it contains no nil chars.
*/
char *
_gpgme_data_get_as_string ( GpgmeData dh )
{
char *val = NULL;
if (dh) {
val = xtrymalloc ( dh->len+1 );
if ( val ) {
memcpy ( val, dh->data, dh->len );
val[dh->len] = 0;
}
}
return val;
}
GpgmeError
_gpgme_data_append ( GpgmeData dh, const char *buffer, size_t length )
{
assert (dh);
if ( dh->type == GPGME_DATA_TYPE_NONE ) {
/* convert it to a mem data type */
assert (!dh->private_buffer);
dh->type = GPGME_DATA_TYPE_MEM;
dh->private_len = length < ALLOC_CHUNK? ALLOC_CHUNK : length;
dh->private_buffer = xtrymalloc ( dh->private_len );
if (!dh->private_buffer) {
dh->private_len = 0;
return mk_error (Out_Of_Core);
}
dh->writepos = 0;
dh->data = dh->private_buffer;
}
else if ( dh->type != GPGME_DATA_TYPE_MEM )
return mk_error (Invalid_Type);
if ( dh->mode != GPGME_DATA_MODE_INOUT
&& dh->mode != GPGME_DATA_MODE_IN )
return mk_error (Invalid_Mode);
if ( !dh->private_buffer ) {
/* we have to copy it now */
assert (dh->data);
dh->private_len = dh->len+length;
if (dh->private_len < ALLOC_CHUNK)
dh->private_len = ALLOC_CHUNK;
dh->private_buffer = xtrymalloc ( dh->private_len );
if (!dh->private_buffer) {
dh->private_len = 0;
return mk_error (Out_Of_Core);
}
memcpy ( dh->private_buffer, dh->data, dh->len );
dh->writepos = dh->len;
dh->data = dh->private_buffer;
}
/* allocate more memory if needed */
if ( dh->writepos + length > dh->private_len ) {
char *p;
size_t newlen = dh->private_len
+ (dh->len < ALLOC_CHUNK? ALLOC_CHUNK : length);
p = xtryrealloc ( dh->private_buffer, newlen );
if ( !p )
return mk_error (Out_Of_Core);
dh->private_buffer = p;
dh->private_len = newlen;
dh->data = dh->private_buffer;
assert ( !(dh->writepos + length > dh->private_len) );
}
memcpy ( dh->private_buffer + dh->writepos, buffer, length );
dh->writepos += length;
dh->len += length;
return 0;
}
GpgmeError
_gpgme_data_append_string ( GpgmeData dh, const char *s )
{
return _gpgme_data_append ( dh, s, s? strlen(s):0 );
}
GpgmeError
_gpgme_data_append_for_xml ( GpgmeData dh,
const char *buffer, size_t len )
{
const char *text, *s;
size_t n;
int rc = 0;
if ( !dh || !buffer )
return mk_error (Invalid_Value);
do {
for (text=NULL, s=buffer, n=len; n && !text; s++, n-- ) {
if ( *s == '<' )
text = "&lt;";
else if ( *s == '>' )
text = "&gt;"; /* not sure whether this is really needed */
else if ( *s == '&' )
text = "&amp;";
else if ( !*s )
text = "&#00;";
}
if (text) {
s--; n++;
}
if (s != buffer)
rc = _gpgme_data_append ( dh, buffer, s-buffer );
if ( !rc && text) {
rc = _gpgme_data_append_string ( dh, text );
s++; n--;
}
buffer = s;
len = n;
} while ( !rc && len );
return rc;
}
/*
* Append a string to DATA and convert it so that the result will be
* valid XML.
*/
GpgmeError
_gpgme_data_append_string_for_xml ( GpgmeData dh, const char *string )
{
return _gpgme_data_append_for_xml ( dh, string, strlen (string) );
}
static int
hextobyte( const byte *s )
{
int c;
if( *s >= '0' && *s <= '9' )
c = 16 * (*s - '0');
else if( *s >= 'A' && *s <= 'F' )
c = 16 * (10 + *s - 'A');
else if( *s >= 'a' && *s <= 'f' )
c = 16 * (10 + *s - 'a');
else
return -1;
s++;
if( *s >= '0' && *s <= '9' )
c += *s - '0';
else if( *s >= 'A' && *s <= 'F' )
c += 10 + *s - 'A';
else if( *s >= 'a' && *s <= 'f' )
c += 10 + *s - 'a';
else
return -1;
return c;
}
/*
* Append a string with percent style (%XX) escape characters as XML
*/
GpgmeError
_gpgme_data_append_percentstring_for_xml ( GpgmeData dh, const char *string )
{
const byte *s;
byte *buf, *d;
int val;
GpgmeError err;
d = buf = xtrymalloc ( strlen (string) );
for (s=string; *s; s++ ) {
if ( *s == '%' && (val=hextobyte (s+1)) != -1 ) {
*d++ = val;
s += 2;
}
else
*d++ = *s;
}
err = _gpgme_data_append_for_xml ( dh, buf, d - buf );
xfree (buf);
return err;
}

View File

@ -0,0 +1,246 @@
/* decrypt.c - decrypt functions
* 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 "util.h"
#include "context.h"
#include "ops.h"
struct decrypt_result_s {
int no_passphrase;
int okay;
int failed;
void *last_pw_handle;
};
void
_gpgme_release_decrypt_result ( DecryptResult res )
{
xfree (res);
}
static GpgmeError
create_result_struct ( GpgmeCtx ctx )
{
assert ( !ctx->result.decrypt );
ctx->result.decrypt = xtrycalloc ( 1, sizeof *ctx->result.decrypt );
if ( !ctx->result.decrypt ) {
return mk_error (Out_Of_Core);
}
ctx->result_type = RESULT_TYPE_DECRYPT;
return 0;
}
static void
decrypt_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
{
if ( ctx->out_of_core )
return;
if ( ctx->result_type == RESULT_TYPE_NONE ) {
if ( create_result_struct ( ctx ) ) {
ctx->out_of_core = 1;
return;
}
}
assert ( ctx->result_type == RESULT_TYPE_DECRYPT );
switch (code) {
case STATUS_EOF:
break;
case STATUS_NEED_PASSPHRASE:
case STATUS_NEED_PASSPHRASE_SYM:
fprintf (stderr, "need a passphrase ...\n" );
break;
case STATUS_MISSING_PASSPHRASE:
fprintf (stderr, "Missing passphrase - stop\n");;
ctx->result.decrypt->no_passphrase = 1;
break;
case STATUS_DECRYPTION_OKAY:
ctx->result.decrypt->okay = 1;
break;
case STATUS_DECRYPTION_FAILED:
ctx->result.decrypt->failed = 1;
break;
default:
/* ignore all other codes */
fprintf (stderr, "decrypt_status: code=%d not handled\n", code );
break;
}
}
static const char *
command_handler ( void *opaque, GpgStatusCode code, const char *key )
{
GpgmeCtx c = opaque;
if ( c->result_type == RESULT_TYPE_NONE ) {
if ( create_result_struct ( c ) ) {
c->out_of_core = 1;
return NULL;
}
}
if ( !code ) {
/* We have been called for cleanup */
if ( c->passphrase_cb ) {
/* Fixme: take the key in account */
c->passphrase_cb (c->passphrase_cb_value, 0,
&c->result.decrypt->last_pw_handle );
}
return NULL;
}
if ( !key || !c->passphrase_cb )
return NULL;
if ( code == STATUS_GET_HIDDEN && !strcmp (key, "passphrase.enter") ) {
return c->passphrase_cb (c->passphrase_cb_value,
"Hey, Mr. Hoover wants your passphrase!",
&c->result.decrypt->last_pw_handle );
}
return NULL;
}
GpgmeError
gpgme_op_decrypt_start ( GpgmeCtx c,
GpgmeData ciph, GpgmeData plain )
{
int rc = 0;
int i;
fail_on_pending_request( c );
c->pending = 1;
_gpgme_release_result (c);
c->out_of_core = 0;
/* do some checks */
assert ( !c->gpg );
/* create a process object */
rc = _gpgme_gpg_new ( &c->gpg );
if (rc)
goto leave;
_gpgme_gpg_set_status_handler ( c->gpg, decrypt_status_handler, c );
if (c->passphrase_cb) {
rc = _gpgme_gpg_set_command_handler ( c->gpg, command_handler, c );
if (rc)
goto leave;
}
/* build the commandline */
_gpgme_gpg_add_arg ( c->gpg, "--decrypt" );
for ( i=0; i < c->verbosity; i++ )
_gpgme_gpg_add_arg ( c->gpg, "--verbose" );
/* Check the supplied data */
if ( !ciph || gpgme_data_get_type (ciph) == GPGME_DATA_TYPE_NONE ) {
rc = mk_error (No_Data);
goto leave;
}
_gpgme_data_set_mode (ciph, GPGME_DATA_MODE_OUT );
if ( gpgme_data_get_type (plain) != GPGME_DATA_TYPE_NONE ) {
rc = mk_error (Invalid_Value);
goto leave;
}
_gpgme_data_set_mode (plain, GPGME_DATA_MODE_IN );
/* Tell the gpg object about the data */
_gpgme_gpg_add_arg ( c->gpg, "--output" );
_gpgme_gpg_add_arg ( c->gpg, "-" );
_gpgme_gpg_add_data ( c->gpg, plain, 1 );
_gpgme_gpg_add_data ( c->gpg, ciph, 0 );
/* and kick off the process */
rc = _gpgme_gpg_spawn ( c->gpg, c );
leave:
if (rc) {
c->pending = 0;
_gpgme_gpg_release ( c->gpg ); c->gpg = NULL;
}
return rc;
}
/**
* gpgme_op_decrypt:
* @c: The context
* @in: ciphertext input
* @out: plaintext output
*
* This function decrypts @in to @out.
* Other parameters are take from the context @c.
* The function does wait for the result.
*
* Return value: 0 on success or an errorcode.
**/
GpgmeError
gpgme_op_decrypt ( GpgmeCtx c,
GpgmeData in, GpgmeData out )
{
GpgmeError err = gpgme_op_decrypt_start ( c, in, out );
if ( !err ) {
gpgme_wait (c, 1);
if ( c->result_type != RESULT_TYPE_DECRYPT )
err = mk_error (General_Error);
else if ( c->out_of_core )
err = mk_error (Out_Of_Core);
else {
assert ( c->result.decrypt );
if ( c->result.decrypt->no_passphrase )
err = mk_error (No_Passphrase);
else if ( c->result.decrypt->failed )
err = mk_error (Decryption_Failed);
else if (!c->result.decrypt->okay)
err = mk_error (No_Data);
}
c->pending = 0;
}
return err;
}

View File

@ -0,0 +1,136 @@
/* encrypt.c - encrypt functions
* 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 "util.h"
#include "context.h"
#include "ops.h"
static void
encrypt_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
{
fprintf (stderr, "encrypt_status: code=%d args=`%s'\n",
code, args );
}
GpgmeError
gpgme_op_encrypt_start ( GpgmeCtx c, GpgmeRecipients recp,
GpgmeData plain, GpgmeData ciph )
{
int rc = 0;
int i;
fail_on_pending_request( c );
c->pending = 1;
/* do some checks */
assert ( !c->gpg );
if ( !gpgme_recipients_count ( recp ) ) {
/* Fixme: In this case we should do symmentric encryption */
rc = mk_error (No_Recipients);
goto leave;
}
/* create a process object */
_gpgme_gpg_release (c->gpg); c->gpg = NULL;
rc = _gpgme_gpg_new ( &c->gpg );
if (rc)
goto leave;
_gpgme_gpg_set_status_handler ( c->gpg, encrypt_status_handler, c );
/* build the commandline */
_gpgme_gpg_add_arg ( c->gpg, "--encrypt" );
if ( c->use_armor )
_gpgme_gpg_add_arg ( c->gpg, "--armor" );
for ( i=0; i < c->verbosity; i++ )
_gpgme_gpg_add_arg ( c->gpg, "--verbose" );
_gpgme_append_gpg_args_from_recipients ( recp, c->gpg );
/* Check the supplied data */
if ( gpgme_data_get_type (plain) == GPGME_DATA_TYPE_NONE ) {
rc = mk_error (No_Data);
goto leave;
}
_gpgme_data_set_mode (plain, GPGME_DATA_MODE_OUT );
if ( !ciph || gpgme_data_get_type (ciph) != GPGME_DATA_TYPE_NONE ) {
rc = mk_error (Invalid_Value);
goto leave;
}
_gpgme_data_set_mode (ciph, GPGME_DATA_MODE_IN );
/* Tell the gpg object about the data */
_gpgme_gpg_add_arg ( c->gpg, "--output" );
_gpgme_gpg_add_arg ( c->gpg, "-" );
_gpgme_gpg_add_data ( c->gpg, ciph, 1 );
_gpgme_gpg_add_arg ( c->gpg, "--" );
_gpgme_gpg_add_data ( c->gpg, plain, 0 );
/* and kick off the process */
rc = _gpgme_gpg_spawn ( c->gpg, c );
leave:
if (rc) {
c->pending = 0;
_gpgme_gpg_release ( c->gpg ); c->gpg = NULL;
}
return rc;
}
/**
* gpgme_op_encrypt:
* @c: The context
* @recp: A set of recipients
* @in: plaintext input
* @out: ciphertext output
*
* This function encrypts @in to @out for all recipients from
* @recp. Other parameters are take from the context @c.
* The function does wait for the result.
*
* Return value: 0 on success or an errorcode.
**/
GpgmeError
gpgme_op_encrypt ( GpgmeCtx c, GpgmeRecipients recp,
GpgmeData in, GpgmeData out )
{
int rc = gpgme_op_encrypt_start ( c, recp, in, out );
if ( !rc ) {
gpgme_wait (c, 1);
c->pending = 0;
}
return rc;
}

View File

@ -0,0 +1,49 @@
/* Generated automatically by mkerrors */
/* Do not edit! */
#include <stdio.h>
#include "gpgme.h"
/**
* gpgme_strerror:
* @err: Error code
*
* This function returns a textual representaion of the given
* errocode. If this is an unknown value, a string with the value
* is returned (which is hold in a static buffer).
*
* Return value: String with the error description.
**/
const char *
gpgme_strerror (GpgmeError err)
{
const char *s;
static char buf[25];
switch (err) {
case GPGME_No_Error: s="No Error"; break;
case GPGME_General_Error: s="General Error"; break;
case GPGME_Out_Of_Core: s="Out Of Core"; break;
case GPGME_Invalid_Value: s="Invalid Value"; break;
case GPGME_Busy: s="Busy"; break;
case GPGME_No_Request: s="No Request"; break;
case GPGME_Exec_Error: s="Exec Error"; break;
case GPGME_Too_Many_Procs: s="Too Many Procs"; break;
case GPGME_Pipe_Error: s="Pipe Error"; break;
case GPGME_No_Recipients: s="No Recipients"; break;
case GPGME_No_Data: s="No Data"; break;
case GPGME_Conflict: s="Conflict"; break;
case GPGME_Not_Implemented: s="Not Implemented"; break;
case GPGME_Read_Error: s="Read Error"; break;
case GPGME_Write_Error: s="Write Error"; break;
case GPGME_Invalid_Type: s="Invalid Type"; break;
case GPGME_Invalid_Mode: s="Invalid Mode"; break;
case GPGME_File_Error: s="File Error"; break;
case GPGME_Decryption_Failed: s="Decryption Failed"; break;
case GPGME_No_Passphrase: s="No Passphrase"; break;
default: sprintf (buf, "ec=%d", err ); s=buf; break;
}
return s;
}

View File

@ -0,0 +1,125 @@
/* export.c - encrypt functions
* 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 "util.h"
#include "context.h"
#include "ops.h"
static void
export_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
{
fprintf (stderr, "export_status: code=%d args=`%s'\n",
code, args );
/* FIXME: Need to do more */
}
GpgmeError
gpgme_op_export_start ( GpgmeCtx c, GpgmeRecipients recp,
GpgmeData keydata )
{
int rc = 0;
int i;
fail_on_pending_request( c );
c->pending = 1;
/* create a process object */
_gpgme_gpg_release (c->gpg); c->gpg = NULL;
rc = _gpgme_gpg_new ( &c->gpg );
if (rc)
goto leave;
_gpgme_gpg_set_status_handler ( c->gpg, export_status_handler, c );
/* build the commandline */
_gpgme_gpg_add_arg ( c->gpg, "--export" );
if ( c->use_armor )
_gpgme_gpg_add_arg ( c->gpg, "--armor" );
for ( i=0; i < c->verbosity; i++ )
_gpgme_gpg_add_arg ( c->gpg, "--verbose" );
if ( !keydata || gpgme_data_get_type (keydata) != GPGME_DATA_TYPE_NONE ) {
rc = mk_error (Invalid_Value);
goto leave;
}
_gpgme_data_set_mode (keydata, GPGME_DATA_MODE_IN );
_gpgme_gpg_add_data ( c->gpg, keydata, 1 );
_gpgme_gpg_add_arg ( c->gpg, "--" );
{
void *ec;
const char *s;
rc = gpgme_recipients_enum_open ( recp, &ec );
if ( rc )
goto leave;
while ( (s = gpgme_recipients_enum_read ( recp, &ec )) )
_gpgme_gpg_add_arg (c->gpg, s);
rc = gpgme_recipients_enum_close ( recp, &ec );
if ( rc )
goto leave;
}
rc = _gpgme_gpg_spawn ( c->gpg, c );
leave:
if (rc) {
c->pending = 0;
_gpgme_gpg_release ( c->gpg ); c->gpg = NULL;
}
return rc;
}
/**
* gpgme_op_export:
* @c: the context
* @recp: a list of recipients or NULL
* @keydata: Returns the keys
*
* This function can be used to extract public keys from the GnuPG key
* database either in armored (by using gpgme_set_armor()) or in plain
* binary form. The function expects a list of user IDs in @recp for
* whom the public keys are to be exportedkinit
*
*
* Return value: 0 for success or an error code
**/
GpgmeError
gpgme_op_export ( GpgmeCtx c, GpgmeRecipients recp, GpgmeData keydata )
{
int rc = gpgme_op_export_start ( c, recp, keydata );
if ( !rc ) {
gpgme_wait (c, 1);
c->pending = 0;
}
return rc;
}

View File

@ -0,0 +1,202 @@
/* genkey.c - key generation
* 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 "util.h"
#include "context.h"
#include "ops.h"
static void
genkey_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
{
if ( code == STATUS_PROGRESS && *args ) {
if (ctx->progress_cb) {
char *p;
int type=0, current=0, total=0;
if ( (p = strchr (args, ' ')) ) {
*p++ = 0;
if (*p) {
type = *(byte*)p;
if ( (p = strchr (p+1, ' ')) ) {
*p++ = 0;
if (*p) {
current = atoi (p);
if ( (p = strchr (p+1, ' ')) ) {
*p++ = 0;
total = atoi (p);
}
}
}
}
}
if ( type != 'X' )
ctx->progress_cb ( ctx->progress_cb_value, args, type,
current, total );
}
return;
}
fprintf (stderr, "genkey_status: code=%d args=`%s'\n",
code, args );
/* FIXME: Need to do more */
}
/*
* Here is how the parms should be formatted:
<GnupgKeyParms format="internal">
Key-Type: DSA
Key-Length: 1024
Subkey-Type: ELG-E
Subkey-Length: 1024
Name-Real: Joe Tester
Name-Comment: with stupid passphrase
Name-Email: joe@foo.bar
Expire-Date: 0
Passphrase: abc
</GnupgKeyParms>
* Strings should be given in UTF-8 encoding. The format we support for now
* "internal". The content of the <GnupgKeyParms> container is passed
* verbatim to GnuPG. Control statements (e.g. %pubring) are not allowed.
*/
GpgmeError
gpgme_op_genkey_start ( GpgmeCtx c, const char *parms,
GpgmeData pubkey, GpgmeData seckey )
{
int rc = 0;
int i;
const char *s, *s2, *sx;
fail_on_pending_request( c );
c->pending = 1;
gpgme_data_release (c->help_data_1); c->help_data_1 = NULL;
/* create a process object */
_gpgme_gpg_release (c->gpg); c->gpg = NULL;
rc = _gpgme_gpg_new ( &c->gpg );
if (rc)
goto leave;
/* We need a special mechanism to get the fd of a pipe here, so
* that we can use this for the %pubring and %secring parameters.
* We don't have this yet, so we implement only the adding to the
* standard keyrings */
if ( pubkey || seckey ) {
rc = mk_error (Not_Implemented);
goto leave;
}
_gpgme_gpg_set_status_handler ( c->gpg, genkey_status_handler, c );
/* build the commandline */
_gpgme_gpg_add_arg ( c->gpg, "--gen-key" );
if ( c->use_armor )
_gpgme_gpg_add_arg ( c->gpg, "--armor" );
for ( i=0; i < c->verbosity; i++ )
_gpgme_gpg_add_arg ( c->gpg, "--verbose" );
if ( !pubkey && !seckey )
; /* okay: Add key to the keyrings */
else if ( !pubkey
|| gpgme_data_get_type (pubkey) != GPGME_DATA_TYPE_NONE ) {
rc = mk_error (Invalid_Value);
goto leave;
}
else if ( !seckey
|| gpgme_data_get_type (seckey) != GPGME_DATA_TYPE_NONE ) {
rc = mk_error (Invalid_Value);
goto leave;
}
if ( pubkey ) {
_gpgme_data_set_mode (pubkey, GPGME_DATA_MODE_IN );
_gpgme_data_set_mode (seckey, GPGME_DATA_MODE_IN );
/* need some more things here */
}
if ( (parms = strstr (parms, "<GnupgKeyParms "))
&& (s = strchr (parms, '>'))
&& (sx = strstr (parms, "format=\"internal\""))
&& sx < s
&& (s2 = strstr (s+1, "</GnupgKeyParms>")) ) {
/* fixme: check that there are no control statements inside */
rc = gpgme_data_new_from_mem ( &c->help_data_1, s+1, s2-s-1, 1 );
}
else
rc = mk_error (Invalid_Value);
if (rc )
goto leave;
_gpgme_data_set_mode (c->help_data_1, GPGME_DATA_MODE_OUT );
_gpgme_gpg_add_data (c->gpg, c->help_data_1, 0);
rc = _gpgme_gpg_spawn ( c->gpg, c );
leave:
if (rc) {
c->pending = 0;
_gpgme_gpg_release ( c->gpg ); c->gpg = NULL;
}
return rc;
}
/**
* gpgme_op_genkey:
* @c: the context
* @parms: XML string with the key parameters
* @pubkey: Returns the public key
* @seckey: Returns the secret key
*
* Generate a new key and store the key in the default keyrings if both
* @pubkey and @seckey are NULL. If @pubkey and @seckey are given, the newly
* created key will be returned in these data objects.
* See gpgme_op_genkey_start() for a description of @parms.
*
* Return value: 0 for success or an error code
**/
GpgmeError
gpgme_op_genkey( GpgmeCtx c, const char *parms,
GpgmeData pubkey, GpgmeData seckey )
{
int rc = gpgme_op_genkey_start ( c, parms, pubkey, seckey );
if ( !rc ) {
gpgme_wait (c, 1);
c->pending = 0;
}
return rc;
}

View File

@ -0,0 +1,93 @@
#!/bin/sh
prefix=@prefix@
exec_prefix=@exec_prefix@
exec_prefix_set=no
gpgme_libs="@GPGME_LIBS@"
gpgme_cflags="@GPGME_CFLAGS@"
usage()
{
cat <<EOF
Usage: gpgme-config [OPTIONS]
Options:
[--prefix[=DIR]]
[--exec-prefix[=DIR]]
[--version]
[--libs]
[--cflags]
EOF
exit $1
}
if test $# -eq 0; then
usage 1 1>&2
fi
while test $# -gt 0; do
case "$1" in
-*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
*) optarg= ;;
esac
case $1 in
--prefix=*)
prefix=$optarg
if test $exec_prefix_set = no ; then
exec_prefix=$optarg
fi
;;
--prefix)
echo_prefix=yes
;;
--exec-prefix=*)
exec_prefix=$optarg
exec_prefix_set=yes
;;
--exec-prefix)
echo_exec_prefix=yes
;;
--version)
echo "@VERSION@"
exit 0
;;
--cflags)
echo_cflags=yes
;;
--libs)
echo_libs=yes
;;
*)
usage 1 1>&2
;;
esac
shift
done
if test "$echo_prefix" = "yes"; then
echo $prefix
fi
if test "$echo_exec_prefix" = "yes"; then
echo $exec_prefix
fi
if test "$echo_cflags" = "yes"; then
if test "@includedir@" != "/usr/include" ; then
includes="-I@includedir@"
for i in $gpgme_cflags ; do
if test "$i" = "-I@includedir@" ; then
includes=""
fi
done
fi
echo $includes $gpgme_cflags
fi
if test "$echo_libs" = "yes"; then
echo ${gpgme_libs}
fi

View File

@ -0,0 +1,36 @@
/* gpgme-memory.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 GPGME_MEMORY_H
#define GPGME_MEMORY_H
void *xmalloc ( size_t n );
void *xtrymalloc (size_t n );
void *xcalloc ( size_t n, size_t m );
void *xtrycalloc (size_t n, size_t m );
void *xrealloc (void *p, size_t n);
void *xtryrealloc (void *p, size_t n);
void xfree ( void *a );
#endif /* GPGME_MEMORY_H */

View File

@ -0,0 +1,38 @@
/* gpgme-types.h - GnuPG Made Easy
* 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 GPGME_TYPES_H
#define GPGME_TYPES_H
#include "gpgme.h"
struct gpgme_context_s {
int initialized;
};
#endif /* GPGME_TYPES_H */

View File

@ -0,0 +1,210 @@
/* gpgme.c - GnuPG Made Easy
* 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 <assert.h>
#include "util.h"
#include "context.h"
#include "ops.h"
#define my_isdigit(a) ( (a) >='0' && (a) <= '9' )
#define my_isxdigit(a) ( my_isdigit((a)) \
|| ((a) >= 'A' && (a) <= 'F') \
|| ((a) >= 'f' && (a) <= 'f') )
/**
* gpgme_new:
* @r_ctx: Returns the new context
*
* Create a new context to be used with most of the other GPGME
* functions. Use gpgme_release_contect() to release all resources
*
* Return value: An error code
**/
GpgmeError
gpgme_new (GpgmeCtx *r_ctx)
{
GpgmeCtx c;
c = xtrycalloc ( 1, sizeof *c );
if (!c)
return mk_error (Out_Of_Core);
c->verbosity = 1;
c->use_armor = 1; /* fixme: reset this to 0 */
*r_ctx = c;
return 0;
}
/**
* gpgme_release:
* @c: Context to be released.
*
* Release all resources associated with the given context.
**/
void
gpgme_release ( GpgmeCtx c )
{
if (!c)
return;
_gpgme_gpg_release ( c->gpg );
_gpgme_release_result ( c );
_gpgme_key_release ( c->tmp_key );
gpgme_data_release ( c->help_data_1 );
gpgme_data_release ( c->notation );
/* fixme: release the key_queue */
xfree (c);
}
void
_gpgme_release_result ( GpgmeCtx c )
{
switch (c->result_type) {
case RESULT_TYPE_NONE:
break;
case RESULT_TYPE_VERIFY:
_gpgme_release_verify_result ( c->result.verify );
break;
case RESULT_TYPE_DECRYPT:
_gpgme_release_decrypt_result ( c->result.decrypt );
break;
case RESULT_TYPE_SIGN:
_gpgme_release_sign_result ( c->result.sign );
break;
}
c->result.verify = NULL;
c->result_type = RESULT_TYPE_NONE;
}
/**
* gpgme_get_notation:
* @c: the context
*
* If there is notation data available from the last signature check, this
* function may be used to return this notation data as a string. The string
* is an XML represantaton of that data embedded in a %<notation> container.
*
* Return value: An XML string or NULL if no notation data is available.
**/
char *
gpgme_get_notation ( GpgmeCtx c )
{
if ( !c->notation )
return NULL;
return _gpgme_data_get_as_string ( c->notation );
}
/**
* gpgme_set_armor:
* @c: the contect
* @yes: boolean value to set or clear that flag
*
* Enable or disable the use of an ascii armor for all output.
**/
void
gpgme_set_armor ( GpgmeCtx c, int yes )
{
if ( !c )
return; /* oops */
c->use_armor = yes;
}
/**
* gpgme_set_textmode:
* @c: the context
* @yes: boolean flag whether textmode should be enabled
*
* Enable or disable the use of the special textmode. Textmode is for example
* used for MIME (RFC2015) signatures
**/
void
gpgme_set_textmode ( GpgmeCtx c, int yes )
{
if ( !c )
return; /* oops */
c->use_textmode = yes;
}
/**
* gpgme_set_passphrase_cb:
* @c: the context
* @cb: A callback function
* @cb_value: The value passed to the callback function
*
* This function sets a callback function to be used to pass a passphrase
* to gpg. The preferred way to handle this is by using the gpg-agent, but
* because that beast is not ready for real use, you can use this passphrase
* thing.
*
* The callback function is defined as:
* <literal>
* typedef const char *(*GpgmePassphraseCb)(void*cb_value,
* const char *desc,
* void *r_hd);
* </literal>
* and called whenever gpgme needs a passphrase. DESC will have a nice
* text, to be used to prompt for the passphrase and R_HD is just a parameter
* to be used by the callback it self. Becuase the callback returns a const
* string, the callback might want to know when it can releae resources
* assocated with that returned string; gpgme helps here by calling this
* passphrase callback with an DESC of %NULL as soon as it does not need
* the returned string anymore. The callback function might then choose
* to release resources depending on R_HD.
*
**/
void
gpgme_set_passphrase_cb ( GpgmeCtx c, GpgmePassphraseCb cb, void *cb_value )
{
c->passphrase_cb = cb;
c->passphrase_cb_value = cb_value;
}
/**
* gpgme_set_pprogress_cb:
* @c: the context
* @cb: A callback function
* @cb_value: The value passed to the callback function
*
* This function sets a callback function to be used as a progress indicator.
*
* The callback function is defined as:
* <literal>
* typedef void (*GpgmeProgressCb) (void*cb_value,
* const char *what, int type,
* int curretn, int total);
* </literal>
* For details on the progress events, see the entry for the PROGRESS
* status in the file doc/DETAILS of the GnuPG distribution.
**/
void
gpgme_set_progress_cb ( GpgmeCtx c, GpgmeProgressCb cb, void *cb_value )
{
c->progress_cb = cb;
c->progress_cb_value = cb_value;
}

View File

@ -0,0 +1,215 @@
/* gpgme.h - GnuPG Made Easy
* 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 GPGME_H
#define GPGME_H
#ifdef __cplusplus
extern "C" {
#if 0 /* just to make Emacs auto-indent happy */
}
#endif
#endif
/*
* The version of this header should match the one of the library
* It should not be used by a program because gpgme_check_version(NULL)
* does return the same version. The purpose of this macro is to
* let autoconf (using the AM_PATH_GPGME macro) check that this
* header matches the installed library.
* Warning: Do not edit the next line. configure will do that for you! */
#define GPGME_VERSION "0.1.3"
struct gpgme_context_s;
typedef struct gpgme_context_s *GpgmeCtx;
struct gpgme_data_s;
typedef struct gpgme_data_s *GpgmeData;
struct gpgme_recipients_s;
typedef struct gpgme_recipients_s *GpgmeRecipients;
struct gpgme_key_s;
typedef struct gpgme_key_s *GpgmeKey;
typedef enum {
GPGME_EOF = -1,
GPGME_No_Error = 0,
GPGME_General_Error = 1,
GPGME_Out_Of_Core = 2,
GPGME_Invalid_Value = 3,
GPGME_Busy = 4,
GPGME_No_Request = 5,
GPGME_Exec_Error = 6,
GPGME_Too_Many_Procs = 7,
GPGME_Pipe_Error = 8,
GPGME_No_Recipients = 9,
GPGME_No_Data = 10,
GPGME_Conflict = 11,
GPGME_Not_Implemented = 12,
GPGME_Read_Error = 13,
GPGME_Write_Error = 14,
GPGME_Invalid_Type = 15,
GPGME_Invalid_Mode = 16,
GPGME_File_Error = 17, /* errno is set in this case */
GPGME_Decryption_Failed = 18,
GPGME_No_Passphrase = 19,
} GpgmeError;
typedef enum {
GPGME_DATA_TYPE_NONE = 0,
GPGME_DATA_TYPE_MEM = 1,
GPGME_DATA_TYPE_FD = 2,
GPGME_DATA_TYPE_FILE = 3,
GPGME_DATA_TYPE_CB = 4
} GpgmeDataType;
typedef enum {
GPGME_SIG_STAT_NONE = 0,
GPGME_SIG_STAT_GOOD = 1,
GPGME_SIG_STAT_BAD = 2,
GPGME_SIG_STAT_NOKEY = 3,
GPGME_SIG_STAT_NOSIG = 4,
GPGME_SIG_STAT_ERROR = 5
} GpgmeSigStat;
typedef enum {
GPGME_SIG_MODE_NORMAL = 0,
GPGME_SIG_MODE_DETACH = 1,
GPGME_SIG_MODE_CLEAR = 2
} GpgmeSigMode;
typedef const char *(*GpgmePassphraseCb)(void*,
const char *desc, void *r_hd);
typedef void (*GpgmeProgressCb)(void *opaque,
const char *what,
int type, int current, int total );
/* Context management */
GpgmeError gpgme_new (GpgmeCtx *r_ctx);
void gpgme_release (GpgmeCtx c);
GpgmeCtx gpgme_wait (GpgmeCtx c, int hang);
char *gpgme_get_notation (GpgmeCtx c);
void gpgme_set_armor (GpgmeCtx c, int yes);
void gpgme_set_textmode (GpgmeCtx c, int yes);
void gpgme_set_passphrase_cb (GpgmeCtx c,
GpgmePassphraseCb cb, void *cb_value);
void gpgme_set_progress_cb (GpgmeCtx c, GpgmeProgressCb cb, void *cb_value);
/* Functions to handle recipients */
GpgmeError gpgme_recipients_new (GpgmeRecipients *r_rset);
void gpgme_recipients_release ( GpgmeRecipients rset);
GpgmeError gpgme_recipients_add_name (GpgmeRecipients rset,
const char *name);
unsigned int gpgme_recipients_count ( const GpgmeRecipients rset );
GpgmeError gpgme_recipients_enum_open (const GpgmeRecipients rset,void **ctx);
const char *gpgme_recipients_enum_read (const GpgmeRecipients rset,void **ctx);
GpgmeError gpgme_recipients_enum_close (const GpgmeRecipients rset,void **ctx);
/* Functions to handle data sources */
GpgmeError gpgme_data_new ( GpgmeData *r_dh );
GpgmeError gpgme_data_new_from_mem ( GpgmeData *r_dh,
const char *buffer, size_t size,
int copy );
GpgmeError gpgme_data_new_with_read_cb ( GpgmeData *r_dh,
int (*read_cb)(void*,char *,size_t,size_t*),
void *read_cb_value );
GpgmeError gpgme_data_new_from_file ( GpgmeData *r_dh,
const char *fname,
int copy );
void gpgme_data_release ( GpgmeData dh );
char * gpgme_data_release_and_get_mem ( GpgmeData dh, size_t *r_len );
GpgmeDataType gpgme_data_get_type ( GpgmeData dh );
GpgmeError gpgme_data_rewind ( GpgmeData dh );
GpgmeError gpgme_data_read ( GpgmeData dh,
char *buffer, size_t length, size_t *nread );
/* Key functions */
char *gpgme_key_get_as_xml ( GpgmeKey key );
/* Basic GnuPG functions */
GpgmeError gpgme_op_encrypt_start ( GpgmeCtx c,
GpgmeRecipients recp,
GpgmeData in, GpgmeData out );
GpgmeError gpgme_op_decrypt_start ( GpgmeCtx c,
GpgmeData ciph, GpgmeData plain );
GpgmeError gpgme_op_sign_start ( GpgmeCtx c,
GpgmeData in, GpgmeData out,
GpgmeSigMode mode );
GpgmeError gpgme_op_verify_start ( GpgmeCtx c,
GpgmeData sig, GpgmeData text );
GpgmeError gpgme_op_import_start ( GpgmeCtx c, GpgmeData keydata );
GpgmeError gpgme_op_export_start ( GpgmeCtx c, GpgmeRecipients recp,
GpgmeData keydata );
GpgmeError gpgme_op_genkey_start ( GpgmeCtx c, const char *parms,
GpgmeData pubkey, GpgmeData seckey );
/* Key management functions */
GpgmeError gpgme_op_keylist_start ( GpgmeCtx c,
const char *pattern, int secret_only );
GpgmeError gpgme_op_keylist_next ( GpgmeCtx c, GpgmeKey *r_key );
/* Convenience functions for normal usage */
GpgmeError gpgme_op_encrypt ( GpgmeCtx c, GpgmeRecipients recp,
GpgmeData in, GpgmeData out );
GpgmeError gpgme_op_decrypt ( GpgmeCtx c,
GpgmeData in, GpgmeData out );
GpgmeError gpgme_op_sign ( GpgmeCtx c, GpgmeData in, GpgmeData out,
GpgmeSigMode mode);
GpgmeError gpgme_op_verify ( GpgmeCtx c, GpgmeData sig, GpgmeData text,
GpgmeSigStat *r_status );
GpgmeError gpgme_op_import ( GpgmeCtx c, GpgmeData keydata );
GpgmeError gpgme_op_export ( GpgmeCtx c, GpgmeRecipients recp,
GpgmeData keydata );
GpgmeError gpgme_op_genkey ( GpgmeCtx c, const char *parms,
GpgmeData pubkey, GpgmeData seckey );
/* miscellaneous functions */
const char *gpgme_check_version ( const char *req_version );
const char *gpgme_strerror (GpgmeError err);
const char *gpgme_get_prompt ( GpgmeCtx c, int which );
#ifdef __cplusplus
}
#endif
#endif /* GPGME_H */

View File

@ -0,0 +1,170 @@
dnl Autoconf macros for libgpgme
dnl $Id$
# Configure paths for GPGME
# Shamelessly stolen from the one of XDELTA by Owen Taylor
# Werner Koch 2000-11-17
dnl AM_PATH_GPGME([MINIMUM-VERSION,
dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]])
dnl Test for gpgme, and define GPGME_CFLAGS and GPGME_LIBS
dnl
AC_DEFUN(AM_PATH_GPGME,
[dnl
dnl Get the cflags and libraries from the gpgme-config script
dnl
AC_ARG_WITH(gpgme-prefix,
[ --with-gpgme-prefix=PFX Prefix where gpgme is installed (optional)],
gpgme_config_prefix="$withval", gpgme_config_prefix="")
AC_ARG_ENABLE(gpgmetest,
[ --disable-gpgmetest Do not try to compile and run a test gpgme program],
, enable_gpgmetest=yes)
if test x$gpgme_config_prefix != x ; then
gpgme_config_args="$gpgme_config_args --prefix=$gpgme_config_prefix"
if test x${GPGME_CONFIG+set} != xset ; then
GPGME_CONFIG=$gpgme_config_prefix/bin/gpgme-config
fi
fi
AC_PATH_PROG(GPGME_CONFIG, gpgme-config, no)
min_gpgme_version=ifelse([$1], ,1.0.0,$1)
AC_MSG_CHECKING(for gpgme - version >= $min_gpgme_version)
no_gpgme=""
if test "$GPGME_CONFIG" = "no" ; then
no_gpgme=yes
else
GPGME_CFLAGS=`$GPGME_CONFIG $gpgme_config_args --cflags`
GPGME_LIBS=`$GPGME_CONFIG $gpgme_config_args --libs`
gpgme_config_version=`$GPGME_CONFIG $gpgme_config_args --version`
if test "x$enable_gpgmetest" = "xyes" ; then
ac_save_CFLAGS="$CFLAGS"
ac_save_LIBS="$LIBS"
CFLAGS="$CFLAGS $GPGME_CFLAGS"
LIBS="$LIBS $GPGME_LIBS"
dnl
dnl Now check if the installed gpgme is sufficiently new. Also sanity
dnl checks the results of gpgme-config to some extent
dnl
rm -f conf.gpgmetest
AC_TRY_RUN([
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gpgme.h>
int
main ()
{
system ("touch conf.gpgmetest");
if( strcmp( gpgme_check_version(NULL), "$gpgme_config_version" ) )
{
printf("\n"
"*** 'gpgme-config --version' returned %s, but GPGME (%s) was found!\n",
"$gpgme_config_version", gpgme_check_version(NULL) );
printf(
"*** If gpgme-config was correct, then it is best to remove the old\n"
"*** version of GPGME. You may also be able to fix the error\n"
"*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"
"*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"
"*** required on your system.\n"
"*** If gpgme-config was wrong, set the environment variable GPGME_CONFIG\n"
"*** to point to the correct copy of gpgme-config, \n"
"*** and remove the file config.cache before re-running configure\n"
);
}
else if ( strcmp(gpgme_check_version(NULL), GPGME_VERSION ) )
{
printf("\n*** GPGME header file (version %s) does not match\n",
GPGME_VERSION);
printf("*** library (version %s)\n", gpgme_check_version(NULL) );
}
else
{
if ( gpgme_check_version( "$min_gpgme_version" ) )
return 0;
printf("no\n"
"*** An old version of GPGME (%s) was found.\n", gpgme_check_version(NULL) );
printf(
"*** You need a version of GPGME newer than %s.\n", "$min_gpgme_version" );
printf(
"*** The latest version of GPGME is always available at\n"
"*** ftp://ftp.gnupg.org/pub/gcrypt/alpha/gpgme/\n"
"*** \n"
"*** If you have already installed a sufficiently new version, this error\n"
"*** probably means that the wrong copy of the gpgme-config shell script is\n"
"*** being found. The easiest way to fix this is to remove the old version\n"
"*** of GPGME, but you can also set the GPGME_CONFIG environment to point to\n"
"*** the correct copy of gpgme-config. (In this case, you will have to\n"
"*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"
"*** so that the correct libraries are found at run-time).\n"
);
}
return 1;
}
],, no_gpgme=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
fi
fi
if test "x$no_gpgme" = x ; then
AC_MSG_RESULT(yes)
ifelse([$2], , :, [$2])
else
if test -f conf.gpgmetest ; then
:
else
AC_MSG_RESULT(no)
fi
if test "$GPGME_CONFIG" = "no" ; then
echo "*** The gpgme-config script installed by GPGME could not be found"
echo "*** If GPGME was installed in PREFIX, make sure PREFIX/bin is in"
echo "*** your path, or set the GPGME_CONFIG environment variable to the"
echo "*** full path to gpgme-config."
else
if test -f conf.gpgmetest ; then
:
else
echo "*** Could not run gpgme test program, checking why..."
CFLAGS="$CFLAGS $GPGME_CFLAGS"
LIBS="$LIBS $GPGME_LIBS"
AC_TRY_LINK([
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gpgme.h>
], [ gpgme_check_version(NULL); return 0 ],
[
echo "*** The test program compiled, but did not run. This usually means"
echo "*** that the run-time linker is not finding GPGME or finding the wrong"
echo "*** version of GPGME. If it is not finding GPGME, you'll need to set your"
echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
echo "*** to the installed location Also, make sure you have run ldconfig if"
echo "*** that is required on your system"
echo "***"
echo "*** If you have an old version installed, it is best to remove it,"
echo "*** although you may also be able to get things to work by"
echo "*** modifying LD_LIBRARY_PATH"
echo "***"
],
[
echo "*** The test program failed to compile or link. See the file config.log"
echo "*** for the exact error that occured. This usually means GPGME was"
echo "*** incorrectly installed or that you have moved GPGME since it was"
echo "*** installed. In the latter case, you may want to edit the"
echo "*** gpgme-config script: $GPGME_CONFIG"
])
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
fi
fi
GPGME_CFLAGS=""
GPGME_LIBS=""
ifelse([$3], , :, [$3])
fi
AC_SUBST(GPGME_CFLAGS)
AC_SUBST(GPGME_LIBS)
rm -f conf.gpgmetest
])

View File

@ -0,0 +1,98 @@
/* impoirt.c - encrypt functions
* 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 "util.h"
#include "context.h"
#include "ops.h"
static void
import_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
{
fprintf (stderr, "import_status: code=%d args=`%s'\n",
code, args );
/* FIXME: We have to check here whether the import actually worked
* and maybe it is a good idea to save some statistics and provide
* a progress callback */
}
GpgmeError
gpgme_op_import_start ( GpgmeCtx c, GpgmeData keydata )
{
int rc = 0;
int i;
fail_on_pending_request( c );
c->pending = 1;
/* create a process object */
_gpgme_gpg_release (c->gpg); c->gpg = NULL;
rc = _gpgme_gpg_new ( &c->gpg );
if (rc)
goto leave;
_gpgme_gpg_set_status_handler ( c->gpg, import_status_handler, c );
/* build the commandline */
_gpgme_gpg_add_arg ( c->gpg, "--import" );
for ( i=0; i < c->verbosity; i++ )
_gpgme_gpg_add_arg ( c->gpg, "--verbose" );
/* Check the supplied data */
if ( gpgme_data_get_type (keydata) == GPGME_DATA_TYPE_NONE ) {
rc = mk_error (No_Data);
goto leave;
}
_gpgme_data_set_mode (keydata, GPGME_DATA_MODE_OUT );
_gpgme_gpg_add_data ( c->gpg, keydata, 0 );
rc = _gpgme_gpg_spawn ( c->gpg, c );
leave:
if (rc) {
c->pending = 0;
_gpgme_gpg_release ( c->gpg ); c->gpg = NULL;
}
return rc;
}
GpgmeError
gpgme_op_import ( GpgmeCtx c, GpgmeData keydata )
{
int rc = gpgme_op_import_start ( c, keydata );
if ( !rc ) {
gpgme_wait (c, 1);
c->pending = 0;
}
return rc;
}

View File

@ -0,0 +1,67 @@
/* io.h - I/O functions
* 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 IO_H
#define IO_H
#include "types.h"
struct spawn_fd_item_s {
int fd;
int dup_to;
};
struct io_select_fd_s {
int fd;
int is_closed;
int for_read;
int for_write;
int signaled;
int frozen;
void *opaque;
};
/* These function are either defined in posix-io.c or w32-io.c */
int _gpgme_io_read ( int fd, void *buffer, size_t count );
int _gpgme_io_write ( int fd, const void *buffer, size_t count );
int _gpgme_io_pipe ( int filedes[2], int inherit_idx );
int _gpgme_io_close ( int fd );
int _gpgme_io_set_nonblocking ( int fd );
int _gpgme_io_spawn ( const char *path, char **argv,
struct spawn_fd_item_s *fd_child_list,
struct spawn_fd_item_s *fd_parent_list );
int _gpgme_io_waitpid ( int pid, int hang, int *r_status, int *r_signal );
int _gpgme_io_select ( struct io_select_fd_s *fds, size_t nfds);
#endif /* IO_H */

View File

@ -0,0 +1,325 @@
/* key.c - Key and keyList objects
* 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 <assert.h>
#include "util.h"
#include "ops.h"
#include "key.h"
#define ALLOC_CHUNK 1024
#define my_isdigit(a) ( (a) >='0' && (a) <= '9' )
GpgmeError
_gpgme_key_new( GpgmeKey *r_key )
{
GpgmeKey key;
*r_key = NULL;
key = xtrycalloc ( 1, sizeof *key );
if (!key)
return mk_error (Out_Of_Core);
*r_key = key;
return 0;
}
struct subkey_s *
_gpgme_key_add_subkey (GpgmeKey key)
{
struct subkey_s *k, *kk;
k = xtrycalloc (1, sizeof *k);
if (!k)
return NULL;
if( !(kk=key->keys.next) )
key->keys.next = k;
else {
while ( kk->next )
kk = kk->next;
kk->next = k;
}
return k;
}
void
_gpgme_key_release ( GpgmeKey key )
{
struct user_id_s *u, *u2;
struct subkey_s *k, *k2;
if (!key)
return;
xfree (key->keys.fingerprint);
for (k = key->keys.next; k; k = k2 ) {
k2 = k->next;
xfree (k->fingerprint);
xfree (k);
}
for (u = key->uids; u; u = u2 ) {
u2 = u->next;
xfree (u);
}
xfree (key);
}
/*
* Take a name from the --with-colon listing, remove certain escape sequences
* sequences and put it into the list of UIDs
*/
GpgmeError
_gpgme_key_append_name ( GpgmeKey key, const char *s )
{
struct user_id_s *uid;
char *d;
assert (key);
/* we can malloc a buffer of the same length, because the converted
* string will never be larger */
uid = xtrymalloc ( sizeof *uid + strlen (s) );
if ( !uid )
return mk_error (Out_Of_Core);
uid->validity = 0;
d = uid->name;
while ( *s ) {
if ( *s != '\\' )
*d++ = *s++;
else if ( s[1] == '\\' ) {
s++;
*d++ = *s++;
}
else if ( s[1] == 'n' ) {
s += 2;
*d++ = '\n';
}
else if ( s[1] == 'r' ) {
s += 2;
*d++ = '\r';
}
else if ( s[1] == 'v' ) {
s += 2;
*d++ = '\v';
}
else if ( s[1] == 'b' ) {
s += 2;
*d++ = '\b';
}
else if ( s[1] == '0' ) {
/* Hmmm: no way to express this */
s += 2;
*d++ = '\\';
*d++ = '\0';
}
else if ( s[1] == 'x' && my_isdigit (s[2]) && my_isdigit (s[3]) ) {
unsigned int val = (s[2]-'0')*16 + (s[3]-'0');
if ( !val ) {
*d++ = '\\';
*d++ = '\0';
}
else
*(byte*)d++ = val;
s += 3;
}
else { /* should not happen */
s++;
*d++ = '\\';
*d++ = *s++;
}
}
uid->next = key->uids;
key->uids = uid;
return 0;
}
static void
add_otag ( GpgmeData d, const char *tag )
{
_gpgme_data_append_string ( d, " <" );
_gpgme_data_append_string ( d, tag );
_gpgme_data_append_string ( d, ">" );
}
static void
add_ctag ( GpgmeData d, const char *tag )
{
_gpgme_data_append_string ( d, "</" );
_gpgme_data_append_string ( d, tag );
_gpgme_data_append_string ( d, ">\n" );
}
static void
add_tag_and_string ( GpgmeData d, const char *tag, const char *string )
{
add_otag (d, tag);
_gpgme_data_append_string_for_xml ( d, string );
add_ctag (d, tag);
}
static void
add_user_id_name ( GpgmeData d, const char *buf, size_t len )
{
while ( len && (buf[len-1] == ' ' || buf[len-1] == '\t') )
len--;
if (len) {
add_otag (d, "name" );
_gpgme_data_append_for_xml ( d, buf, len );
add_ctag (d, "name");
}
}
static void
add_user_id ( GpgmeData d, const char *string )
{
const char *s, *start=NULL;
int in_name = 0;
int in_email = 0;
int in_comment = 0;
for (s=string; *s; s++ ) {
if ( in_email ) {
if ( *s == '<' )
in_email++; /* not legal but anyway */
else if (*s== '>') {
if ( !--in_email ) {
_gpgme_data_append_for_xml ( d, start, s-start );
add_ctag (d, "email");
}
}
}
else if ( in_comment ) {
if ( *s == '(' )
in_comment++;
else if (*s== ')') {
if ( !--in_comment ) {
_gpgme_data_append_for_xml ( d, start, s-start );
add_ctag (d, "comment");
}
}
}
else if ( *s == '<' ) {
if ( in_name ) {
add_user_id_name (d, start, s-start );
in_name = 0;
}
in_email = 1;
add_otag ( d, "email" );
start = s+1;
}
else if ( *s == '(' ) {
if ( in_name ) {
add_user_id_name (d, start, s-start );
in_name = 0;
}
in_comment = 1;
add_otag ( d, "comment" );
start = s+1;
}
else if ( !in_name && *s != ' ' && *s != '\t' ) {
in_name = 1;
start = s;
}
}
if ( in_name )
add_user_id_name (d, start, s-start );
}
static void
add_tag_and_uint ( GpgmeData d, const char *tag, unsigned int val )
{
char buf[30];
sprintf (buf, "%u", val );
add_tag_and_string ( d, tag, buf );
}
static void
add_tag_and_time ( GpgmeData d, const char *tag, time_t val )
{
char buf[30];
if (!val || val == (time_t)-1 )
return;
sprintf (buf, "%lu", (unsigned long)val );
add_tag_and_string ( d, tag, buf );
}
char *
gpgme_key_get_as_xml ( GpgmeKey key )
{
GpgmeData d;
struct user_id_s *u;
struct subkey_s *k;
if ( !key )
return NULL;
if ( gpgme_data_new ( &d ) )
return NULL;
_gpgme_data_append_string ( d, "<GnupgKeyblock>\n"
" <mainkey>\n" );
add_tag_and_string (d, "keyid", key->keys.keyid );
if (key->keys.fingerprint)
add_tag_and_string (d, "fpr", key->keys.fingerprint );
add_tag_and_uint (d, "algo", key->keys.key_algo );
add_tag_and_uint (d, "len", key->keys.key_len );
add_tag_and_time (d, "created", key->keys.timestamp );
/*add_tag_and_time (d, "expires", key->expires );*/
_gpgme_data_append_string (d, " </mainkey>\n");
/* Now the user IDs */
for ( u = key->uids; u; u = u->next ) {
_gpgme_data_append_string (d, " <userid>\n");
add_tag_and_string ( d, "raw", u->name );
add_user_id ( d, u->name );
_gpgme_data_append_string (d, " </userid>\n");
}
for (k=key->keys.next; k; k = k->next ) {
_gpgme_data_append_string (d, " <subkey>\n");
add_tag_and_string (d, "keyid", k->keyid );
if (k->fingerprint)
add_tag_and_string (d, "fpr", k->fingerprint );
add_tag_and_uint (d, "algo", k->key_algo );
add_tag_and_uint (d, "len", k->key_len );
add_tag_and_time (d, "created", k->timestamp );
_gpgme_data_append_string (d, " </subkey>\n");
}
_gpgme_data_append_string ( d, "</GnupgKeyblock>\n" );
return _gpgme_data_release_and_return_string (d);
}

View File

@ -0,0 +1,62 @@
/* key.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 KEY_H
#define KEY_H
#include <time.h>
#include "types.h"
#include "context.h"
struct subkey_s {
struct subkey_s *next;
struct {
unsigned int revoked:1 ;
unsigned int expired:1 ;
unsigned int disabled:1 ;
} flags;
unsigned int key_algo;
unsigned int key_len;
char keyid[16+1];
char *fingerprint; /* malloced hex digits */
time_t timestamp; /* -1 for invalid, 0 for not available */
};
struct gpgme_key_s {
struct {
unsigned int revoked:1 ;
unsigned int expired:1 ;
unsigned int disabled:1 ;
} gloflags;
struct subkey_s keys;
struct user_id_s *uids;
};
struct subkey_s *_gpgme_key_add_subkey (GpgmeKey key);
GpgmeError _gpgme_key_append_name ( GpgmeKey key, const char *s );
#endif /* KEY_H */

View File

@ -0,0 +1,426 @@
/* keylist.c - key listing
* 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 <time.h>
#include <assert.h>
#include "util.h"
#include "context.h"
#include "ops.h"
#include "key.h"
#define my_isdigit(a) ( (a) >='0' && (a) <= '9' )
static void finish_key ( GpgmeCtx ctx );
static void
keylist_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
{
if ( ctx->out_of_core )
return;
switch (code) {
case STATUS_EOF:
if (ctx->tmp_key)
finish_key (ctx);
break;
default:
/* ignore all other codes */
fprintf (stderr, "keylist_status: code=%d not handled\n", code );
break;
}
}
static time_t
parse_timestamp ( char *p )
{
struct tm tm;
int i;
if (!*p )
return 0;
if (strlen(p) < 10 || p[4] != '-' || p[7] != '-' )
return (time_t)-1;
p[4] = 0;
p[7] = 0;
p[10] = 0; /* just in case the time part follows */
memset (&tm, 0, sizeof tm);
i = atoi (p);
if ( i < 1900 )
return (time_t)-1;
tm.tm_year = i - 1900;
i = atoi (p+5);
if ( i < 1 || i > 12 )
return (time_t)-1;
tm.tm_mon = i-1;
i = atoi (p+8);
if ( i < 1 || i > 31 )
return (time_t)-1;
tm.tm_mday = i;
return mktime (&tm);
}
static void
set_mainkey_trust_info ( GpgmeKey key, const char *s )
{
/* look at letters and stop at the first digit */
for (; *s && !my_isdigit (*s); s++ ) {
switch (*s) {
case 'e': key->keys.flags.expired = 1; break;
case 'r': key->keys.flags.revoked = 1; break;
case 'd': key->keys.flags.disabled = 1; break;
case 'n': key->uids->validity = 1; break;
case 'm': key->uids->validity = 2; break;
case 'f': key->uids->validity = 3; break;
case 'u': key->uids->validity = 4; break;
}
}
}
static void
set_subkey_trust_info ( struct subkey_s *k, const char *s )
{
/* look at letters and stop at the first digit */
for (; *s && !my_isdigit (*s); s++ ) {
switch (*s) {
case 'e': k->flags.expired = 1; break;
case 'r': k->flags.revoked = 1; break;
case 'd': k->flags.disabled = 1; break;
}
}
}
/* Note: we are allowed to modify line */
static void
keylist_colon_handler ( GpgmeCtx ctx, char *line )
{
char *p, *pend;
int field = 0;
enum {
RT_NONE, RT_SIG, RT_UID, RT_SUB, RT_PUB, RT_FPR, RT_SSB, RT_SEC
} rectype = RT_NONE;
GpgmeKey key = ctx->tmp_key;
int i;
const char *trust_info = NULL;
struct subkey_s *sk = NULL;
if ( ctx->out_of_core )
return;
if (!line)
return; /* EOF */
for (p = line; p; p = pend) {
field++;
pend = strchr (p, ':');
if (pend)
*pend++ = 0;
if ( field == 1 ) {
if ( !strcmp ( p, "sig" ) )
rectype = RT_SIG;
else if ( !strcmp ( p, "uid" ) && key ) {
rectype = RT_UID;
key = ctx->tmp_key;
}
else if ( !strcmp ( p, "sub" ) && key ) {
/* start a new subkey */
rectype = RT_SUB;
if ( !(sk = _gpgme_key_add_subkey (key)) ) {
ctx->out_of_core=1;
return;
}
}
else if ( !strcmp ( p, "pub" ) ) {
/* start a new keyblock */
if ( _gpgme_key_new ( &key ) ) {
ctx->out_of_core=1; /* the only kind of error we can get */
return;
}
rectype = RT_PUB;
if ( ctx->tmp_key )
finish_key ( ctx );
assert ( !ctx->tmp_key );
ctx->tmp_key = key;
}
else if ( !strcmp ( p, "fpr" ) && key )
rectype = RT_FPR;
else if ( !strcmp ( p, "ssb" ) )
rectype = RT_SSB;
else if ( !strcmp ( p, "sec" ) )
rectype = RT_SEC;
else
rectype = RT_NONE;
}
else if ( rectype == RT_PUB ) {
switch (field) {
case 2: /* trust info */
trust_info = p; /*save for later */
break;
case 3: /* key length */
i = atoi (p);
if ( i > 1 ) /* ignore invalid values */
key->keys.key_len = i;
break;
case 4: /* pubkey algo */
i = atoi (p);
if ( i > 1 && i < 128 )
key->keys.key_algo = i;
break;
case 5: /* long keyid */
if ( strlen (p) == DIM(key->keys.keyid)-1 )
strcpy (key->keys.keyid, p);
break;
case 6: /* timestamp (1998-02-28) */
key->keys.timestamp = parse_timestamp (p);
break;
case 7: /* valid for n days */
break;
case 8: /* reserved (LID) */
break;
case 9: /* ownertrust */
break;
case 10: /* This is the first name listed */
if ( _gpgme_key_append_name ( key, p) )
ctx->out_of_core = 1;
else {
if (trust_info)
set_mainkey_trust_info (key, trust_info);
}
break;
case 11: /* signature class */
break;
case 12:
pend = NULL; /* we can stop here */
break;
}
}
else if ( rectype == RT_SUB && sk ) {
switch (field) {
case 2: /* trust info */
set_subkey_trust_info ( sk, p);
break;
case 3: /* key length */
i = atoi (p);
if ( i > 1 ) /* ignore invalid values */
sk->key_len = i;
break;
case 4: /* pubkey algo */
i = atoi (p);
if ( i > 1 && i < 128 )
sk->key_algo = i;
break;
case 5: /* long keyid */
if ( strlen (p) == DIM(sk->keyid)-1 )
strcpy (sk->keyid, p);
break;
case 6: /* timestamp (1998-02-28) */
sk->timestamp = parse_timestamp (p);
break;
case 7: /* valid for n days */
break;
case 8: /* reserved (LID) */
break;
case 9: /* ownertrust */
break;
case 10:/* user ID n/a for a subkey */
break;
case 11: /* signature class */
break;
case 12:
pend = NULL; /* we can stop here */
break;
}
}
else if ( rectype == RT_UID ) {
switch (field) {
case 2: /* trust info */
trust_info = p; /*save for later */
break;
case 10: /* the 2nd, 3rd,... user ID */
if ( _gpgme_key_append_name ( key, p) )
ctx->out_of_core = 1;
else {
if (trust_info)
set_mainkey_trust_info (key, trust_info);
}
pend = NULL; /* we can stop here */
break;
}
}
else if ( rectype == RT_FPR ) {
switch (field) {
case 10: /* fingerprint (take only the first one)*/
if ( !key->keys.fingerprint && *p ) {
key->keys.fingerprint = xtrystrdup (p);
if ( !key->keys.fingerprint )
ctx->out_of_core = 1;
}
pend = NULL; /* that is all we want */
break;
}
}
}
}
/*
* We have read an entire key into ctx->tmp_key and should now finish
* it. It is assumed that this releases ctx->tmp_key.
*/
static void
finish_key ( GpgmeCtx ctx )
{
GpgmeKey key = ctx->tmp_key;
struct key_queue_item_s *q, *q2;
assert (key);
ctx->tmp_key = NULL;
q = xtrymalloc ( sizeof *q );
if ( !q ) {
_gpgme_key_release (key);
ctx->out_of_core = 1;
return;
}
q->key = key;
q->next = NULL;
/* fixme: lock queue. Use a tail pointer? */
if ( !(q2 = ctx->key_queue) )
ctx->key_queue = q;
else {
for ( ; q2->next; q2 = q2->next )
;
q2->next = q;
}
ctx->key_cond = 1;
/* fixme: unlock queue */
}
GpgmeError
gpgme_op_keylist_start ( GpgmeCtx c, const char *pattern, int secret_only )
{
GpgmeError rc = 0;
int i;
fail_on_pending_request( c );
c->pending = 1;
_gpgme_release_result (c);
c->out_of_core = 0;
if ( c->gpg ) {
_gpgme_gpg_release ( c->gpg );
c->gpg = NULL;
}
_gpgme_key_release (c->tmp_key);
c->tmp_key = NULL;
/* Fixme: release key_queue */
rc = _gpgme_gpg_new ( &c->gpg );
if (rc)
goto leave;
_gpgme_gpg_set_status_handler ( c->gpg, keylist_status_handler, c );
rc = _gpgme_gpg_set_colon_line_handler ( c->gpg,
keylist_colon_handler, c );
if (rc)
goto leave;
/* build the commandline */
for ( i=0; i < c->verbosity; i++ )
_gpgme_gpg_add_arg ( c->gpg, "--verbose" );
_gpgme_gpg_add_arg ( c->gpg, "--with-colons" );
_gpgme_gpg_add_arg ( c->gpg, "--with-fingerprint" );
/*_gpgme_gpg_add_arg ( c->gpg, "--fast-list-mode" );*/
_gpgme_gpg_add_arg ( c->gpg, secret_only?
"--list-secret-keys":"--list-keys" );
/* Tell the gpg object about the data */
_gpgme_gpg_add_arg ( c->gpg, "--" );
if (pattern && *pattern)
_gpgme_gpg_add_arg ( c->gpg, pattern );
/* and kick off the process */
rc = _gpgme_gpg_spawn ( c->gpg, c );
leave:
if (rc) {
c->pending = 0;
_gpgme_gpg_release ( c->gpg ); c->gpg = NULL;
}
return rc;
}
GpgmeError
gpgme_op_keylist_next ( GpgmeCtx c, GpgmeKey *r_key )
{
struct key_queue_item_s *q;
if (!r_key)
return mk_error (Invalid_Value);
*r_key = NULL;
if (!c)
return mk_error (Invalid_Value);
if ( !c->pending )
return mk_error (No_Request);
if ( c->out_of_core )
return mk_error (Out_Of_Core);
if ( !c->key_queue ) {
_gpgme_wait_on_condition (c, 1, &c->key_cond );
if ( c->out_of_core )
return mk_error (Out_Of_Core);
if ( !c->key_cond )
return mk_error (EOF);
c->key_cond = 0;
assert ( c->key_queue );
}
q = c->key_queue;
c->key_queue = q->next;
*r_key = q->key;
xfree (q);
return 0;
}

83
tags/GPGME-0-1-3/gpgme/mkerrors Executable file
View File

@ -0,0 +1,83 @@
#!/bin/sh
# mkerrors - Extract error strings from gpgme.h
# and create C source for gpgme_strerror
# 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
cat <<EOF
/* Generated automatically by mkerrors */
/* Do not edit! */
#include <stdio.h>
#include "gpgme.h"
/**
* gpgme_strerror:
* @err: Error code
*
* This function returns a textual representaion of the given
* errocode. If this is an unknown value, a string with the value
* is returned (which is hold in a static buffer).
*
* Return value: String with the error description.
**/
const char *
gpgme_strerror (GpgmeError err)
{
const char *s;
static char buf[25];
switch (err) {
EOF
awk '
/GPGME_No_Error/ { okay=1 }
!okay {next}
/}/ { exit 0 }
/GPGME_[A-Za-z_]*/ { print_code($1) }
function print_code( s )
{
printf " case %s: s=\"", s ;
gsub(/_/, " ", s );
printf "%s\"; break;\n", substr(s,7);
}
'
cat <<EOF
default: sprintf (buf, "ec=%d", err ); s=buf; break;
}
return s;
}
EOF

55
tags/GPGME-0-1-3/gpgme/mkstatus Executable file
View File

@ -0,0 +1,55 @@
#!/bin/sh
# mkstatus - Extract error strings from rungpg.h
# and create a lookup table
# 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
cat <<EOF
/* Generated automatically by mkstatus */
/* Do not edit! */
struct status_table_s {
const char *name;
GpgStatusCode code;
};
static struct status_table_s status_table[] =
{
EOF
awk '
/STATUS_ENTER/ { okay=1 }
!okay {next}
/}/ { exit 0 }
/STATUS_[A-Za-z_]*/ { printf " { \"%s\", %s },\n", substr($1,8), $1 }
' | sort
cat <<EOF
{NULL, 0}
};
EOF

View File

@ -0,0 +1,82 @@
/* ops.h - internal operations stuff
* 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 OPS_H
#define OPS_H
#include "types.h"
/*-- gpgme.c --*/
void _gpgme_release_result ( GpgmeCtx c );
/*-- wait.c --*/
GpgmeCtx _gpgme_wait_on_condition ( GpgmeCtx c,
int hang, volatile int *cond );
void _gpgme_freeze_fd ( int fd );
void _gpgme_thaw_fd ( int fd );
/*-- recipient.c --*/
void _gpgme_append_gpg_args_from_recipients (
const GpgmeRecipients rset,
GpgObject gpg );
/*-- data.c --*/
char * _gpgme_data_release_and_return_string ( GpgmeData dh );
GpgmeDataMode _gpgme_data_get_mode ( GpgmeData dh );
void _gpgme_data_set_mode ( GpgmeData dh, GpgmeDataMode mode );
char * _gpgme_data_get_as_string ( GpgmeData dh );
GpgmeError _gpgme_data_append ( GpgmeData dh,
const char *buffer, size_t length );
GpgmeError _gpgme_data_append_string ( GpgmeData dh, const char *s );
GpgmeError _gpgme_data_append_string_for_xml ( GpgmeData dh,
const char *s);
GpgmeError _gpgme_data_append_for_xml ( GpgmeData dh,
const char *buffer,
size_t len );
GpgmeError _gpgme_data_append_percentstring_for_xml ( GpgmeData dh,
const char *string );
GpgmeError _gpgme_data_unread (GpgmeData dh,
const char *buffer, size_t length );
/*-- key.c --*/
GpgmeError _gpgme_key_new( GpgmeKey *r_key );
void _gpgme_key_release ( GpgmeKey key );
/*-- verify.c --*/
void _gpgme_release_verify_result ( VerifyResult res );
/*-- decrypt.c --*/
void _gpgme_release_decrypt_result ( DecryptResult res );
/*-- sign.c --*/
void _gpgme_release_sign_result ( SignResult res );
#endif /* OPS_H */

View File

@ -0,0 +1,308 @@
/* posix-io.c - Posix I/O functions
* 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>
#ifndef 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 <sys/wait.h>
#include <signal.h>
#include <fcntl.h>
#include "syshdr.h"
#include "io.h"
#define DEBUG_SELECT_ENABLED 0
#if DEBUG_SELECT_ENABLED
# define DEBUG_SELECT(a) fprintf a
#else
# define DEBUG_SELECT(a) do { } while(0)
#endif
int
_gpgme_io_read ( int fd, void *buffer, size_t count )
{
int nread;
do {
nread = read (fd, buffer, count);
} while (nread == -1 && errno == EINTR );
return nread;
}
int
_gpgme_io_write ( int fd, const void *buffer, size_t count )
{
int nwritten;
do {
nwritten = write (fd, buffer, count);
} while (nwritten == -1 && errno == EINTR );
return nwritten;
}
int
_gpgme_io_pipe ( int filedes[2], int inherit_idx )
{
/* we don't need inherit_idx in this implementation */
return pipe ( filedes );
}
int
_gpgme_io_close ( int fd )
{
if ( fd == -1 )
return -1;
return close (fd);
}
int
_gpgme_io_set_nonblocking ( int fd )
{
int flags;
flags = fcntl (fd, F_GETFL, 0);
if (flags == -1)
return -1;
flags |= O_NONBLOCK;
return fcntl (fd, F_SETFL, flags);
}
int
_gpgme_io_spawn ( const char *path, char **argv,
struct spawn_fd_item_s *fd_child_list,
struct spawn_fd_item_s *fd_parent_list )
{
static volatile int fixed_signals;
pid_t pid;
int i;
if ( !fixed_signals ) {
struct sigaction act;
sigaction( SIGPIPE, NULL, &act );
if( act.sa_handler == SIG_DFL ) {
act.sa_handler = SIG_IGN;
sigemptyset( &act.sa_mask );
act.sa_flags = 0;
sigaction( SIGPIPE, &act, NULL);
}
fixed_signals = 1;
/* fixme: This is not really MT safe */
}
pid = fork ();
if (pid == -1)
return -1;
if ( !pid ) { /* child */
int duped_stdin = 0;
int duped_stderr = 0;
/* first close all fds which will not be duped */
for (i=0; fd_child_list[i].fd != -1; i++ ) {
if (fd_child_list[i].dup_to == -1 )
close (fd_child_list[i].fd);
}
/* and now dup and close the rest */
for (i=0; fd_child_list[i].fd != -1; i++ ) {
if (fd_child_list[i].dup_to != -1 ) {
if ( dup2 (fd_child_list[i].fd,
fd_child_list[i].dup_to ) == -1 ) {
fprintf (stderr, "dup2 failed in child: %s\n",
strerror (errno));
_exit (8);
}
if ( fd_child_list[i].dup_to == 0 )
duped_stdin=1;
if ( fd_child_list[i].dup_to == 2 )
duped_stderr=1;
close (fd_child_list[i].fd);
}
}
if( !duped_stdin || !duped_stderr ) {
int fd = open ( "/dev/null", O_RDWR );
if ( fd == -1 ) {
fprintf (stderr,"can't open `/dev/null': %s\n",
strerror (errno) );
_exit (8);
}
/* Make sure that the process has a connected stdin */
if ( !duped_stdin ) {
if ( dup2 ( fd, 0 ) == -1 ) {
fprintf (stderr,"dup2(/dev/null, 0) failed: %s\n",
strerror (errno) );
_exit (8);
}
}
/* We normally don't want all the normal output */
if ( !duped_stderr ) {
if (!getenv ("GPGME_DEBUG") ) {
if ( dup2 ( fd, 2 ) == -1 ) {
fprintf (stderr,"dup2(dev/null, 2) failed: %s\n",
strerror (errno) );
_exit (8);
}
}
}
close (fd);
}
execv ( path, argv );
/* Hmm: in that case we could write a special status code to the
* status-pipe */
fprintf (stderr,"exec of `%s' failed\n", path );
_exit (8);
} /* end child */
/* .dup_to is not used in the parent list */
for (i=0; fd_parent_list[i].fd != -1; i++ ) {
close (fd_parent_list[i].fd);
}
return (int)pid;
}
int
_gpgme_io_waitpid ( int pid, int hang, int *r_status, int *r_signal )
{
int status;
*r_status = 0;
*r_signal = 0;
if ( waitpid ( pid, &status, hang? 0 : WNOHANG ) == pid ) {
if ( WIFSIGNALED (status) ) {
*r_status = 4; /* Need some value here */
*r_signal = WTERMSIG (status);
}
else if ( WIFEXITED (status) ) {
*r_status = WEXITSTATUS (status);
}
else {
*r_status = 4; /* oops */
}
return 1;
}
return 0;
}
/*
* Select on the list of fds.
* Returns: -1 = error
* 0 = timeout or nothing to select
* >0 = number of signaled fds
*/
int
_gpgme_io_select ( struct io_select_fd_s *fds, size_t nfds )
{
static fd_set readfds;
static fd_set writefds;
int any, i, max_fd, n, count;
struct timeval timeout = { 1, 0 }; /* Use a one second timeout */
FD_ZERO ( &readfds );
FD_ZERO ( &writefds );
max_fd = 0;
DEBUG_SELECT ((stderr, "gpgme:select on [ "));
any = 0;
for ( i=0; i < nfds; i++ ) {
if ( fds[i].fd == -1 )
continue;
if ( fds[i].for_read ) {
assert ( !FD_ISSET ( fds[i].fd, &readfds ) );
FD_SET ( fds[i].fd, &readfds );
if ( fds[i].fd > max_fd )
max_fd = fds[i].fd;
DEBUG_SELECT ((stderr, "r%d ", fds[i].fd ));
any = 1;
}
else if ( fds[i].for_write ) {
assert ( !FD_ISSET ( fds[i].fd, &writefds ) );
FD_SET ( fds[i].fd, &writefds );
if ( fds[i].fd > max_fd )
max_fd = fds[i].fd;
DEBUG_SELECT ((stderr, "w%d ", fds[i].fd ));
any = 1;
}
fds[i].signaled = 0;
}
DEBUG_SELECT ((stderr, "]\n" ));
if ( !any )
return 0;
do {
count = select ( max_fd+1, &readfds, &writefds, NULL, &timeout );
} while ( count < 0 && errno == EINTR);
if ( count < 0 ) {
fprintf (stderr, "_gpgme_io_select failed: %s\n", strerror (errno) );
return -1; /* error */
}
#if DEBUG_SELECT_ENABLED
fprintf (stderr, "gpgme:select OK [ " );
for (i=0; i <= max_fd; i++ ) {
if (FD_ISSET (i, &readfds) )
fprintf (stderr, "r%d ", i );
if (FD_ISSET (i, &writefds) )
fprintf (stderr, "w%d ", i );
}
fprintf (stderr, "]\n" );
#endif
/* n is used to optimize it a little bit */
for ( n=count, i=0; i < nfds && n ; i++ ) {
if ( fds[i].fd == -1 )
;
else if ( fds[i].for_read ) {
if ( FD_ISSET ( fds[i].fd, &readfds ) ) {
fds[i].signaled = 1;
n--;
}
}
else if ( fds[i].for_write ) {
if ( FD_ISSET ( fds[i].fd, &writefds ) ) {
fds[i].signaled = 1;
n--;
}
}
}
return count;
}
#endif /*!HAVE_DOSISH_SYSTEM*/

View File

@ -0,0 +1,137 @@
/* recipient.c - mainatin recipient sets
* 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 <assert.h>
#include "util.h"
#include "context.h"
#include "rungpg.h"
GpgmeError
gpgme_recipients_new (GpgmeRecipients *r_rset)
{
GpgmeRecipients rset;
rset = xtrycalloc ( 1, sizeof *rset );
if (!rset)
return mk_error (Out_Of_Core);
*r_rset = rset;
return 0;
}
void
gpgme_recipients_release ( GpgmeRecipients rset )
{
/* fixme: release the linked list */
xfree ( rset );
}
GpgmeError
gpgme_recipients_add_name (GpgmeRecipients rset, const char *name )
{
struct user_id_s *r;
if (!name || !rset )
return mk_error (Invalid_Value);
r = xtrymalloc ( sizeof *r + strlen (name) );
if (!r)
return mk_error (Out_Of_Core);
strcpy (r->name, name );
r->next = rset->list;
rset->list = r;
return 0;
}
unsigned int
gpgme_recipients_count ( const GpgmeRecipients rset )
{
struct user_id_s *r;
unsigned int count = 0;
if ( rset ) {
for (r=rset->list ; r; r = r->next )
count++;
}
return count;
}
GpgmeError
gpgme_recipients_enum_open ( const GpgmeRecipients rset, void **ctx )
{
if (!rset || !ctx)
return mk_error (Invalid_Value);
*ctx = rset->list;
return 0;
}
const char *
gpgme_recipients_enum_read ( const GpgmeRecipients rset, void **ctx )
{
struct user_id_s *r;
if (!rset || !ctx)
return NULL; /* oops */
r = *ctx;
if ( r ) {
const char *s = r->name;
r = r->next;
*ctx = r;
return s;
}
return NULL;
}
GpgmeError
gpgme_recipients_enum_close ( const GpgmeRecipients rset, void **ctx )
{
if (!rset || !ctx)
return mk_error (Invalid_Value);
*ctx = NULL;
return 0;
}
void
_gpgme_append_gpg_args_from_recipients (
const GpgmeRecipients rset,
GpgObject gpg )
{
struct user_id_s *r;
assert (rset);
for (r=rset->list ; r; r = r->next ) {
_gpgme_gpg_add_arg ( gpg, "-r" );
_gpgme_gpg_add_arg ( gpg, r->name );
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,121 @@
/* rungpg.h - gpg calling functions
* 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 RUNGPG_H
#define RUNGPG_H
#include "types.h"
typedef enum {
STATUS_EOF ,
/* mkstatus starts here */
STATUS_ENTER ,
STATUS_LEAVE ,
STATUS_ABORT ,
STATUS_GOODSIG ,
STATUS_BADSIG ,
STATUS_ERRSIG ,
STATUS_BADARMOR ,
STATUS_RSA_OR_IDEA ,
STATUS_SIGEXPIRED ,
STATUS_KEYREVOKED ,
STATUS_TRUST_UNDEFINED ,
STATUS_TRUST_NEVER ,
STATUS_TRUST_MARGINAL ,
STATUS_TRUST_FULLY ,
STATUS_TRUST_ULTIMATE ,
STATUS_SHM_INFO ,
STATUS_SHM_GET ,
STATUS_SHM_GET_BOOL ,
STATUS_SHM_GET_HIDDEN ,
STATUS_NEED_PASSPHRASE ,
STATUS_VALIDSIG ,
STATUS_SIG_ID ,
STATUS_ENC_TO ,
STATUS_NODATA ,
STATUS_BAD_PASSPHRASE ,
STATUS_NO_PUBKEY ,
STATUS_NO_SECKEY ,
STATUS_NEED_PASSPHRASE_SYM,
STATUS_DECRYPTION_FAILED ,
STATUS_DECRYPTION_OKAY ,
STATUS_MISSING_PASSPHRASE ,
STATUS_GOOD_PASSPHRASE ,
STATUS_GOODMDC ,
STATUS_BADMDC ,
STATUS_ERRMDC ,
STATUS_IMPORTED ,
STATUS_IMPORT_RES ,
STATUS_FILE_START ,
STATUS_FILE_DONE ,
STATUS_FILE_ERROR ,
STATUS_BEGIN_DECRYPTION ,
STATUS_END_DECRYPTION ,
STATUS_BEGIN_ENCRYPTION ,
STATUS_END_ENCRYPTION ,
STATUS_DELETE_PROBLEM ,
STATUS_GET_BOOL ,
STATUS_GET_LINE ,
STATUS_GET_HIDDEN ,
STATUS_GOT_IT ,
STATUS_PROGRESS ,
STATUS_SIG_CREATED ,
STATUS_SESSION_KEY ,
STATUS_NOTATION_NAME ,
STATUS_NOTATION_DATA ,
STATUS_POLICY_URL ,
STATUS_BEGIN_STREAM ,
STATUS_END_STREAM
} GpgStatusCode;
typedef void (*GpgStatusHandler)( GpgmeCtx, GpgStatusCode code, char *args );
typedef void (*GpgColonLineHandler)( GpgmeCtx, char *line );
typedef const char *(*GpgCommandHandler)(void*, GpgStatusCode code,
const char *keyword);
GpgmeError _gpgme_gpg_new ( GpgObject *r_gpg );
void _gpgme_gpg_release ( GpgObject gpg );
void _gpgme_gpg_enable_pipemode ( GpgObject gpg );
GpgmeError _gpgme_gpg_add_arg ( GpgObject gpg, const char *arg );
GpgmeError _gpgme_gpg_add_data ( GpgObject gpg, GpgmeData data, int dup_to );
GpgmeError _gpgme_gpg_add_pm_data ( GpgObject gpg, GpgmeData data, int what );
void _gpgme_gpg_set_status_handler ( GpgObject gpg,
GpgStatusHandler fnc,
void *fnc_value );
GpgmeError _gpgme_gpg_set_colon_line_handler ( GpgObject gpg,
GpgColonLineHandler fnc,
void *fnc_value );
GpgmeError _gpgme_gpg_set_command_handler ( GpgObject gpg,
GpgCommandHandler fnc,
void *fnc_value );
GpgmeError _gpgme_gpg_spawn ( GpgObject gpg, void *opaque );
#endif /* RUNGPG_H */

View File

@ -0,0 +1,254 @@
/* sign.c - signing functions
* 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 "util.h"
#include "context.h"
#include "ops.h"
struct sign_result_s {
int no_passphrase;
int okay;
void *last_pw_handle;
};
void
_gpgme_release_sign_result ( SignResult res )
{
xfree (res);
}
static void
sign_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
{
if ( ctx->out_of_core )
return;
if ( ctx->result_type == RESULT_TYPE_NONE ) {
assert ( !ctx->result.sign );
ctx->result.sign = xtrycalloc ( 1, sizeof *ctx->result.sign );
if ( !ctx->result.sign ) {
ctx->out_of_core = 1;
return;
}
ctx->result_type = RESULT_TYPE_SIGN;
}
assert ( ctx->result_type == RESULT_TYPE_SIGN );
switch (code) {
case STATUS_EOF:
break;
case STATUS_NEED_PASSPHRASE:
case STATUS_NEED_PASSPHRASE_SYM:
fprintf (stderr, "Ooops: Need a passphrase - use the agent\n");
break;
case STATUS_MISSING_PASSPHRASE:
fprintf (stderr, "Missing passphrase - stop\n");;
ctx->result.sign->no_passphrase = 1;
break;
case STATUS_SIG_CREATED:
/* fixme: we have no error return for multible signatures */
ctx->result.sign->okay =1;
break;
default:
fprintf (stderr, "sign_status: code=%d not handled\n", code );
break;
}
}
static const char *
command_handler ( void *opaque, GpgStatusCode code, const char *key )
{
GpgmeCtx c = opaque;
if ( c->result_type == RESULT_TYPE_NONE ) {
assert ( !c->result.sign );
c->result.sign = xtrycalloc ( 1, sizeof *c->result.sign );
if ( !c->result.sign ) {
c->out_of_core = 1;
return NULL;
}
c->result_type = RESULT_TYPE_SIGN;
}
if ( !code ) {
/* We have been called for cleanup */
if ( c->passphrase_cb ) {
/* Fixme: take the key in account */
c->passphrase_cb (c->passphrase_cb_value, 0,
&c->result.sign->last_pw_handle );
}
return NULL;
}
if ( !key || !c->passphrase_cb )
return NULL;
if ( code == STATUS_GET_HIDDEN && !strcmp (key, "passphrase.enter") ) {
return c->passphrase_cb (c->passphrase_cb_value,
"Please enter your Friedrich Willem!",
&c->result.sign->last_pw_handle );
}
return NULL;
}
GpgmeError
gpgme_op_sign_start ( GpgmeCtx c, GpgmeData in, GpgmeData out,
GpgmeSigMode mode )
{
int rc = 0;
int i;
fail_on_pending_request( c );
c->pending = 1;
_gpgme_release_result (c);
c->out_of_core = 0;
if ( mode != GPGME_SIG_MODE_NORMAL
&& mode != GPGME_SIG_MODE_DETACH
&& mode != GPGME_SIG_MODE_CLEAR )
return mk_error (Invalid_Value);
/* create a process object */
_gpgme_gpg_release (c->gpg);
c->gpg = NULL;
rc = _gpgme_gpg_new ( &c->gpg );
if (rc)
goto leave;
_gpgme_gpg_set_status_handler ( c->gpg, sign_status_handler, c );
if (c->passphrase_cb) {
rc = _gpgme_gpg_set_command_handler ( c->gpg, command_handler, c );
if (rc)
goto leave;
}
/* build the commandline */
if ( mode == GPGME_SIG_MODE_CLEAR ) {
_gpgme_gpg_add_arg ( c->gpg, "--clearsign" );
}
else {
_gpgme_gpg_add_arg ( c->gpg, "--sign" );
if ( mode == GPGME_SIG_MODE_DETACH )
_gpgme_gpg_add_arg ( c->gpg, "--detach" );
if ( c->use_armor )
_gpgme_gpg_add_arg ( c->gpg, "--armor" );
if ( c->use_textmode )
_gpgme_gpg_add_arg ( c->gpg, "--textmode" );
}
for ( i=0; i < c->verbosity; i++ )
_gpgme_gpg_add_arg ( c->gpg, "--verbose" );
/* Check the supplied data */
if ( gpgme_data_get_type (in) == GPGME_DATA_TYPE_NONE ) {
rc = mk_error (No_Data);
goto leave;
}
_gpgme_data_set_mode (in, GPGME_DATA_MODE_OUT );
if ( !out || gpgme_data_get_type (out) != GPGME_DATA_TYPE_NONE ) {
rc = mk_error (Invalid_Value);
goto leave;
}
_gpgme_data_set_mode (out, GPGME_DATA_MODE_IN );
/* Tell the gpg object about the data */
_gpgme_gpg_add_data ( c->gpg, in, 0 );
_gpgme_gpg_add_data ( c->gpg, out, 1 );
/* and kick off the process */
rc = _gpgme_gpg_spawn ( c->gpg, c );
leave:
if (rc) {
c->pending = 0;
_gpgme_gpg_release ( c->gpg ); c->gpg = NULL;
}
return rc;
}
/**
* gpgme_op_sign:
* @c: The context
* @in: Data to be signed
* @out: Detached signature
* @mode: Signature creation mode
*
* Create a detached signature for @in and write it to @out.
* The data will be signed using either the default key or the ones
* defined through @c.
* The defined modes for signature create are:
* <literal>
* GPGME_SIG_MODE_NORMAL (or 0)
* GPGME_SIG_MODE_DETACH
* GPGME_SIG_MODE_CLEAR
* </literal>
* Note that the settings done by gpgme_set_armor() and gpgme_set_textmode()
* are ignore for @mode GPGME_SIG_MODE_CLEAR.
*
* Return value: 0 on success or an error code.
**/
GpgmeError
gpgme_op_sign ( GpgmeCtx c, GpgmeData in, GpgmeData out, GpgmeSigMode mode )
{
GpgmeError err = gpgme_op_sign_start ( c, in, out, mode );
if ( !err ) {
gpgme_wait (c, 1);
if ( c->result_type != RESULT_TYPE_SIGN )
err = mk_error (General_Error);
else if ( c->out_of_core )
err = mk_error (Out_Of_Core);
else {
assert ( c->result.sign );
if ( c->result.sign->no_passphrase )
err = mk_error (No_Passphrase);
else if (!c->result.sign->okay)
err = mk_error (No_Data); /* Hmmm: choose a better error? */
}
c->pending = 0;
}
return err;
}

View File

@ -0,0 +1,70 @@
/* Generated automatically by mkstatus */
/* Do not edit! */
struct status_table_s {
const char *name;
GpgStatusCode code;
};
static struct status_table_s status_table[] =
{
{ "ABORT", STATUS_ABORT },
{ "BADARMOR", STATUS_BADARMOR },
{ "BADMDC", STATUS_BADMDC },
{ "BADSIG", STATUS_BADSIG },
{ "BAD_PASSPHRASE", STATUS_BAD_PASSPHRASE },
{ "BEGIN_DECRYPTION", STATUS_BEGIN_DECRYPTION },
{ "BEGIN_ENCRYPTION", STATUS_BEGIN_ENCRYPTION },
{ "BEGIN_STREAM", STATUS_BEGIN_STREAM },
{ "DECRYPTION_FAILED", STATUS_DECRYPTION_FAILED },
{ "DECRYPTION_OKAY", STATUS_DECRYPTION_OKAY },
{ "DELETE_PROBLEM", STATUS_DELETE_PROBLEM },
{ "ENC_TO", STATUS_ENC_TO },
{ "END_DECRYPTION", STATUS_END_DECRYPTION },
{ "END_ENCRYPTION", STATUS_END_ENCRYPTION },
{ "END_STREAM", STATUS_END_STREAM },
{ "ENTER", STATUS_ENTER },
{ "ERRMDC", STATUS_ERRMDC },
{ "ERRSIG", STATUS_ERRSIG },
{ "FILE_DONE", STATUS_FILE_DONE },
{ "FILE_ERROR", STATUS_FILE_ERROR },
{ "FILE_START", STATUS_FILE_START },
{ "GET_BOOL", STATUS_GET_BOOL },
{ "GET_HIDDEN", STATUS_GET_HIDDEN },
{ "GET_LINE", STATUS_GET_LINE },
{ "GOODMDC", STATUS_GOODMDC },
{ "GOODSIG", STATUS_GOODSIG },
{ "GOOD_PASSPHRASE", STATUS_GOOD_PASSPHRASE },
{ "GOT_IT", STATUS_GOT_IT },
{ "IMPORTED", STATUS_IMPORTED },
{ "IMPORT_RES", STATUS_IMPORT_RES },
{ "KEYREVOKED", STATUS_KEYREVOKED },
{ "LEAVE", STATUS_LEAVE },
{ "MISSING_PASSPHRASE", STATUS_MISSING_PASSPHRASE },
{ "NEED_PASSPHRASE", STATUS_NEED_PASSPHRASE },
{ "NEED_PASSPHRASE_SYM,", STATUS_NEED_PASSPHRASE_SYM, },
{ "NODATA", STATUS_NODATA },
{ "NOTATION_DATA", STATUS_NOTATION_DATA },
{ "NOTATION_NAME", STATUS_NOTATION_NAME },
{ "NO_PUBKEY", STATUS_NO_PUBKEY },
{ "NO_SECKEY", STATUS_NO_SECKEY },
{ "POLICY_URL", STATUS_POLICY_URL },
{ "PROGRESS", STATUS_PROGRESS },
{ "RSA_OR_IDEA", STATUS_RSA_OR_IDEA },
{ "SESSION_KEY", STATUS_SESSION_KEY },
{ "SHM_GET", STATUS_SHM_GET },
{ "SHM_GET_BOOL", STATUS_SHM_GET_BOOL },
{ "SHM_GET_HIDDEN", STATUS_SHM_GET_HIDDEN },
{ "SHM_INFO", STATUS_SHM_INFO },
{ "SIGEXPIRED", STATUS_SIGEXPIRED },
{ "SIG_CREATED", STATUS_SIG_CREATED },
{ "SIG_ID", STATUS_SIG_ID },
{ "TRUST_FULLY", STATUS_TRUST_FULLY },
{ "TRUST_MARGINAL", STATUS_TRUST_MARGINAL },
{ "TRUST_NEVER", STATUS_TRUST_NEVER },
{ "TRUST_ULTIMATE", STATUS_TRUST_ULTIMATE },
{ "TRUST_UNDEFINED", STATUS_TRUST_UNDEFINED },
{ "VALIDSIG", STATUS_VALIDSIG },
{NULL, 0}
};

View File

@ -0,0 +1,66 @@
/* types.h - Some type definitions
* 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 TYPES_H
#define TYPES_H
#include "gpgme.h" /* external objects and prototypes */
typedef unsigned char byte;
typedef enum {
GPGME_DATA_MODE_NONE = 0,
GPGME_DATA_MODE_IN = 1,
GPGME_DATA_MODE_OUT = 2,
GPGME_DATA_MODE_INOUT = 3
} GpgmeDataMode;
/*
* Declaration of internal objects
*/
/*-- rungpg.c --*/
struct gpg_object_s;
typedef struct gpg_object_s *GpgObject;
/*-- verify.c --*/
struct verify_result_s;
typedef struct verify_result_s *VerifyResult;
/*-- decrypt.c --*/
struct decrypt_result_s;
typedef struct decrypt_result_s *DecryptResult;
/*-- sign.c --*/
struct sign_result_s;
typedef struct sign_result_s *SignResult;
/*-- key.c --*/
#endif /* TYPES_H */

View File

@ -0,0 +1,79 @@
/* util.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 "util.h"
void *
_gpgme_malloc (size_t n )
{
return malloc (n);
}
void *
_gpgme_calloc (size_t n, size_t m )
{
return calloc (n, m);
}
void *
_gpgme_realloc (void *p, size_t n)
{
return realloc (p, n );
}
char *
_gpgme_strdup (const char *p)
{
return strdup (p);
}
void
_gpgme_free ( void *a )
{
free (a);
}
/*********************************************
********** missing string functions *********
*********************************************/
#ifndef HAVE_STPCPY
char *
stpcpy (char *a, const char *b)
{
while( *b )
*a++ = *b++;
*a = 0;
return a;
}
#endif

View File

@ -0,0 +1,56 @@
/* 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 HAVE_STPCPY
char *stpcpy (char *a, const char *b);
#endif
#endif /* UTIL_H */

View File

@ -0,0 +1,277 @@
/* verify.c - signature verification
* 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 "util.h"
#include "context.h"
#include "ops.h"
struct verify_result_s {
GpgmeSigStat status;
GpgmeData notation; /* we store an XML fragment here */
int notation_in_data; /* private to add_notation() */
};
void
_gpgme_release_verify_result ( VerifyResult res )
{
gpgme_data_release ( res->notation );
xfree (res);
}
static void
add_notation ( GpgmeCtx ctx, GpgStatusCode code, const char *data )
{
GpgmeData dh = ctx->result.verify->notation;
if ( !dh ) {
if ( gpgme_data_new ( &dh ) ) {
ctx->out_of_core = 1;
return;
}
ctx->result.verify->notation = dh;
_gpgme_data_append_string (dh, " <notation>\n");
}
if ( code == STATUS_NOTATION_DATA ) {
if ( !ctx->result.verify->notation_in_data )
_gpgme_data_append_string (dh, " <data>");
_gpgme_data_append_percentstring_for_xml (dh, data);
ctx->result.verify->notation_in_data = 1;
return;
}
if ( ctx->result.verify->notation_in_data ) {
_gpgme_data_append_string (dh, "</data>\n");
ctx->result.verify->notation_in_data = 0;
}
if ( code == STATUS_NOTATION_NAME ) {
_gpgme_data_append_string (dh, " <name>");
_gpgme_data_append_percentstring_for_xml (dh, data);
_gpgme_data_append_string (dh, "</name>\n");
}
else if ( code == STATUS_POLICY_URL ) {
_gpgme_data_append_string (dh, " <policy>");
_gpgme_data_append_percentstring_for_xml (dh, data);
_gpgme_data_append_string (dh, "</policy>\n");
}
else {
assert (0);
}
}
static void
verify_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
{
if ( ctx->out_of_core )
return;
if ( ctx->result_type == RESULT_TYPE_NONE ) {
assert ( !ctx->result.verify );
ctx->result.verify = xtrycalloc ( 1, sizeof *ctx->result.verify );
if ( !ctx->result.verify ) {
ctx->out_of_core = 1;
return;
}
ctx->result_type = RESULT_TYPE_VERIFY;
}
assert ( ctx->result_type == RESULT_TYPE_VERIFY );
/* FIXME: For now we handle only one signature */
/* FIXME: Collect useful information
and return them as XML */
switch (code) {
case STATUS_GOODSIG:
ctx->result.verify->status = GPGME_SIG_STAT_GOOD;
break;
case STATUS_BADSIG:
ctx->result.verify->status = GPGME_SIG_STAT_BAD;
break;
case STATUS_ERRSIG:
ctx->result.verify->status = GPGME_SIG_STAT_ERROR;
/* FIXME: distinguish between a regular error and a missing key.
* this is encoded in the args. */
break;
case STATUS_NOTATION_NAME:
case STATUS_NOTATION_DATA:
case STATUS_POLICY_URL:
add_notation ( ctx, code, args );
break;
case STATUS_END_STREAM:
break;
default:
/* ignore all other codes */
fprintf (stderr, "verify_status: code=%d not handled\n", code );
break;
}
}
GpgmeError
gpgme_op_verify_start ( GpgmeCtx c, GpgmeData sig, GpgmeData text )
{
int rc = 0;
int i;
int pipemode = 0 /*!!text*/; /* use pipemode for detached sigs */
fail_on_pending_request( c );
c->pending = 1;
_gpgme_release_result (c);
c->out_of_core = 0;
if ( !pipemode ) {
_gpgme_gpg_release ( c->gpg );
c->gpg = NULL;
}
if ( !c->gpg )
rc = _gpgme_gpg_new ( &c->gpg );
if (rc)
goto leave;
if (pipemode)
_gpgme_gpg_enable_pipemode ( c->gpg );
_gpgme_gpg_set_status_handler ( c->gpg, verify_status_handler, c );
/* build the commandline */
_gpgme_gpg_add_arg ( c->gpg, pipemode?"--pipemode" : "--verify" );
for ( i=0; i < c->verbosity; i++ )
_gpgme_gpg_add_arg ( c->gpg, "--verbose" );
/* Check the supplied data */
if ( gpgme_data_get_type (sig) == GPGME_DATA_TYPE_NONE ) {
rc = mk_error (No_Data);
goto leave;
}
if ( text && gpgme_data_get_type (text) == GPGME_DATA_TYPE_NONE ) {
rc = mk_error (No_Data);
goto leave;
}
_gpgme_data_set_mode (sig, GPGME_DATA_MODE_OUT );
if (text) /* detached signature */
_gpgme_data_set_mode (text, GPGME_DATA_MODE_OUT );
/* Tell the gpg object about the data */
_gpgme_gpg_add_arg ( c->gpg, "--" );
if (pipemode) {
_gpgme_gpg_add_pm_data ( c->gpg, sig, 0 );
_gpgme_gpg_add_pm_data ( c->gpg, text, 1 );
}
else {
_gpgme_gpg_add_data ( c->gpg, sig, -1 );
if (text) {
_gpgme_gpg_add_arg ( c->gpg, "-" );
_gpgme_gpg_add_data ( c->gpg, text, 0 );
}
}
/* and kick off the process */
rc = _gpgme_gpg_spawn ( c->gpg, c );
leave:
if (rc) {
c->pending = 0;
_gpgme_gpg_release ( c->gpg ); c->gpg = NULL;
}
return rc;
}
/**
* gpgme_op_verify:
* @c: the context
* @sig: the signature data
* @text: the signed text
* @r_stat: returns the status of the signature
*
* Perform a signature check on the signature given in @sig. Currently it is
* assumed that this is a detached signature for the material given in @text.
* The result of this operation is returned in @r_stat which can take these
* values:
* GPGME_SIG_STAT_NONE: No status - should not happen
* GPGME_SIG_STAT_GOOD: The signature is valid
* GPGME_SIG_STAT_BAD: The signature is not valid
* GPGME_SIG_STAT_NOKEY: The signature could not be checked due to a
* missing key
* GPGME_SIG_STAT_NOSIG: This is not a signature
* GPGME_SIG_STAT_ERROR: Due to some other error the check could not be done.
* FIXME: What do we return if only some o the signatures ae valid?
*
* Return value: 0 on success or an errorcode if something not related to
* the signature itself did go wrong.
**/
GpgmeError
gpgme_op_verify ( GpgmeCtx c, GpgmeData sig, GpgmeData text,
GpgmeSigStat *r_stat )
{
int rc;
if ( !r_stat )
return mk_error (Invalid_Value);
gpgme_data_release (c->notation);
c->notation = NULL;
*r_stat = GPGME_SIG_STAT_NONE;
rc = gpgme_op_verify_start ( c, sig, text );
if ( !rc ) {
gpgme_wait (c, 1);
if ( c->result_type != RESULT_TYPE_VERIFY )
rc = mk_error (General_Error);
else if ( c->out_of_core )
rc = mk_error (Out_Of_Core);
else {
assert ( c->result.verify );
if ( c->result.verify->notation ) {
GpgmeData dh = c->result.verify->notation;
if ( c->result.verify->notation_in_data ) {
_gpgme_data_append_string (dh, "</data>\n");
c->result.verify->notation_in_data = 0;
}
_gpgme_data_append_string (dh, "</notation>\n");
c->notation = dh;
c->result.verify->notation = NULL;
}
*r_stat = c->result.verify->status;
}
c->pending = 0;
}
return rc;
}

View File

@ -0,0 +1,104 @@
/* version.c - version check
* 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 <ctype.h>
#include "gpgme.h"
static const char*
parse_version_number ( const char *s, int *number )
{
int val = 0;
if ( *s == '0' && isdigit(s[1]) )
return NULL; /* leading zeros are not allowed */
for ( ; isdigit(*s); s++ ) {
val *= 10;
val += *s - '0';
}
*number = val;
return val < 0? NULL : s;
}
static const char *
parse_version_string( const char *s, int *major, int *minor, int *micro )
{
s = parse_version_number ( s, major );
if ( !s || *s != '.' )
return NULL;
s++;
s = parse_version_number ( s, minor );
if ( !s || *s != '.' )
return NULL;
s++;
s = parse_version_number ( s, micro );
if ( !s )
return NULL;
return s; /* patchlevel */
}
/**
* 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.
*
* Return value: The version string or NULL
**/
const char *
gpgme_check_version ( const char *req_version )
{
const char *ver = VERSION;
int my_major, my_minor, my_micro;
int rq_major, rq_minor, rq_micro;
const char *my_plvl, *rq_plvl;
if ( !req_version )
return ver;
my_plvl = parse_version_string ( ver, &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 );
if ( !rq_plvl )
return NULL; /* req version string is invalid */
if ( my_major > rq_major
|| (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 ver;
}
return NULL;
}

View File

@ -0,0 +1,602 @@
/* w32-io.c - W32 API I/O functions
* 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>
#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"
#include "io.h"
#define DEBUG_SELECT_ENABLED 0
#if DEBUG_SELECT_ENABLED
# define DEBUG_SELECT(a) fprintf a
#else
# define DEBUG_SELECT(a) do { } while(0)
#endif
/*
* We assume that a HANDLE can be represented by an int which should be true
* for all i386 systems (HANDLE is defined as void *) and these are the only
* systems for which Windows is available.
* Further we assume that -1 denotes an invalid handle.
*/
#define fd_to_handle(a) ((HANDLE)(a))
#define handle_to_fd(a) ((int)(a))
#define pid_to_handle(a) ((HANDLE)(a))
#define handle_to_pid(a) ((int)(a))
int
_gpgme_io_read ( int fd, void *buffer, size_t count )
{
int nread = 0;
HANDLE h = fd_to_handle (fd);
DEBUG_SELECT ((stderr,"** fd %d: about to read %d bytes\n", fd, (int)count ));
if ( !ReadFile ( h, buffer, count, &nread, NULL) ) {
fprintf (stderr, "** ReadFile failed: ec=%d\n", (int)GetLastError ());
return -1;
}
DEBUG_SELECT ((stderr,"** fd %d: got %d bytes\n", fd, nread ));
return nread;
}
int
_gpgme_io_write ( int fd, const void *buffer, size_t count )
{
int nwritten;
HANDLE h = fd_to_handle (fd);
DEBUG_SELECT ((stderr,"** fd %d: about to write %d bytes\n", fd, (int)count ));
if ( !WriteFile ( h, buffer, count, &nwritten, NULL) ) {
fprintf (stderr, "** WriteFile failed: ec=%d\n", (int)GetLastError ());
return -1;
}
DEBUG_SELECT ((stderr,"** fd %d: wrote %d bytes\n", fd, nwritten ));
return nwritten;
}
int
_gpgme_io_pipe ( int filedes[2], int inherit_idx )
{
HANDLE r, w;
SECURITY_ATTRIBUTES sec_attr;
memset (&sec_attr, 0, sizeof sec_attr );
sec_attr.nLength = sizeof sec_attr;
sec_attr.bInheritHandle = FALSE;
if (!CreatePipe ( &r, &w, &sec_attr, 0))
return -1;
/* make one end inheritable */
if ( inherit_idx == 0 ) {
HANDLE h;
if (!DuplicateHandle( GetCurrentProcess(), r,
GetCurrentProcess(), &h, 0,
TRUE, DUPLICATE_SAME_ACCESS ) ) {
fprintf (stderr, "** DuplicateHandle failed: ec=%d\n",
(int)GetLastError());
CloseHandle (r);
CloseHandle (w);
return -1;
}
CloseHandle (r);
r = h;
}
else if ( inherit_idx == 1 ) {
HANDLE h;
if (!DuplicateHandle( GetCurrentProcess(), w,
GetCurrentProcess(), &h, 0,
TRUE, DUPLICATE_SAME_ACCESS ) ) {
fprintf (stderr, "** DuplicateHandle failed: ec=%d\n",
(int)GetLastError());
CloseHandle (r);
CloseHandle (w);
return -1;
}
CloseHandle (w);
w = h;
}
filedes[0] = handle_to_fd (r);
filedes[1] = handle_to_fd (w);
DEBUG_SELECT ((stderr,"** create pipe %p %p %d %d inherit=%d\n", r, w,
filedes[0], filedes[1], inherit_idx ));
return 0;
}
int
_gpgme_io_close ( int fd )
{
if ( fd == -1 )
return -1;
DEBUG_SELECT ((stderr,"** closing handle for fd %d\n", fd));
if ( !CloseHandle (fd_to_handle (fd)) ) {
fprintf (stderr, "** CloseHandle for fd %d failed: ec=%d\n",
fd, (int)GetLastError ());
return -1;
}
return 0;
}
int
_gpgme_io_set_nonblocking ( int fd )
{
return 0;
}
static char *
build_commandline ( char **argv )
{
int i, n = 0;
char *buf, *p;
/* FIXME: we have to quote some things because under Windows the
* program parses the commandline and does some unquoting */
for (i=0; argv[i]; i++)
n += strlen (argv[i]) + 1;
buf = p = xtrymalloc (n);
if ( !buf )
return NULL;
*buf = 0;
if ( argv[0] )
p = stpcpy (p, argv[0]);
for (i = 1; argv[i]; i++)
p = stpcpy (stpcpy (p, " "), argv[i]);
return buf;
}
int
_gpgme_io_spawn ( const char *path, char **argv,
struct spawn_fd_item_s *fd_child_list,
struct spawn_fd_item_s *fd_parent_list )
{
SECURITY_ATTRIBUTES sec_attr;
PROCESS_INFORMATION pi = {
NULL, /* returns process handle */
0, /* returns primary thread handle */
0, /* returns pid */
0 /* returns tid */
};
STARTUPINFO si;
char *envblock = NULL;
int cr_flags = CREATE_DEFAULT_ERROR_MODE
| GetPriorityClass (GetCurrentProcess ());
int i;
char *arg_string;
int duped_stdin = 0;
int duped_stderr = 0;
HANDLE hnul = INVALID_HANDLE_VALUE;
int debug_me = !!getenv ("GPGME_DEBUG");
memset (&sec_attr, 0, sizeof sec_attr );
sec_attr.nLength = sizeof sec_attr;
sec_attr.bInheritHandle = FALSE;
arg_string = build_commandline ( argv );
if (!arg_string )
return -1;
memset (&si, 0, sizeof si);
si.cb = sizeof (si);
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
si.wShowWindow = debug_me? SW_SHOW : SW_MINIMIZE;
si.hStdInput = GetStdHandle (STD_INPUT_HANDLE);
si.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE);
si.hStdError = GetStdHandle (STD_ERROR_HANDLE);
for (i=0; fd_child_list[i].fd != -1; i++ ) {
if (fd_child_list[i].dup_to == 0 ) {
si.hStdInput = fd_to_handle (fd_child_list[i].fd);
DEBUG_SELECT ((stderr,"** using %d for stdin\n", fd_child_list[i].fd ));
duped_stdin=1;
}
else if (fd_child_list[i].dup_to == 1 ) {
si.hStdOutput = fd_to_handle (fd_child_list[i].fd);
DEBUG_SELECT ((stderr,"** using %d for stdout\n", fd_child_list[i].fd ));
}
else if (fd_child_list[i].dup_to == 2 ) {
si.hStdError = fd_to_handle (fd_child_list[i].fd);
DEBUG_SELECT ((stderr,"** using %d for stderr\n", fd_child_list[i].fd ));
duped_stderr = 1;
}
}
if( !duped_stdin || !duped_stderr ) {
SECURITY_ATTRIBUTES sa;
memset (&sa, 0, sizeof sa );
sa.nLength = sizeof sa;
sa.bInheritHandle = TRUE;
hnul = CreateFile ( "/dev/nul",
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
&sa,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL );
if ( hnul == INVALID_HANDLE_VALUE ) {
fprintf (stderr,"can't open `/dev/nul': ec=%d\n",
(int)GetLastError () );
xfree (arg_string);
return -1;
}
/* Make sure that the process has a connected stdin */
if ( !duped_stdin ) {
si.hStdInput = hnul;
DEBUG_SELECT ((stderr,"** using %d for stdin\n", (int)hnul ));
}
/* We normally don't want all the normal output */
if ( !duped_stderr ) {
if (!debug_me) {
si.hStdError = hnul;
DEBUG_SELECT ((stderr,"** using %d for stderr\n", (int)hnul ));
}
}
}
DEBUG_SELECT ((stderr,"** CreateProcess ...\n"));
DEBUG_SELECT ((stderr,"** args=`%s'\n", arg_string));
cr_flags |= CREATE_SUSPENDED;
if ( !CreateProcessA (GPG_PATH,
arg_string,
&sec_attr, /* process security attributes */
&sec_attr, /* thread security attributes */
TRUE, /* inherit handles */
cr_flags, /* creation flags */
envblock, /* environment */
NULL, /* use current drive/directory */
&si, /* startup information */
&pi /* returns process information */
) ) {
fprintf (stderr, "** CreateProcess failed: ec=%d\n",
(int) GetLastError ());
xfree (arg_string);
return -1;
}
/* close the /dev/nul handle if used */
if (hnul != INVALID_HANDLE_VALUE ) {
if ( !CloseHandle ( hnul ) )
fprintf (stderr, "** CloseHandle(hnul) failed: ec=%d\n",
(int)GetLastError());
}
/* Close the other ends of the pipes */
for (i=0; fd_parent_list[i].fd != -1; i++ ) {
DEBUG_SELECT ((stderr,"** Closing fd %d\n", fd_parent_list[i].fd ));
if ( !CloseHandle ( fd_to_handle (fd_parent_list[i].fd) ) )
fprintf (stderr, "** CloseHandle failed: ec=%d\n",
(int)GetLastError());
}
DEBUG_SELECT ((stderr,"** CreateProcess ready\n"
"** hProcess=%p hThread=%p\n"
"** dwProcessID=%d dwThreadId=%d\n",
pi.hProcess, pi.hThread,
(int) pi.dwProcessId, (int) pi.dwThreadId));
if ( ResumeThread ( pi.hThread ) < 0 ) {
fprintf (stderr, "** ResumeThread failed: ec=%d\n",
(int)GetLastError ());
}
if ( !CloseHandle (pi.hThread) ) {
fprintf (stderr, "** CloseHandle of thread failed: ec=%d\n",
(int)GetLastError ());
}
return handle_to_pid (pi.hProcess);
}
int
_gpgme_io_waitpid ( int pid, int hang, int *r_status, int *r_signal )
{
HANDLE proc = fd_to_handle (pid);
int code, exc, ret = 0;
*r_status = 0;
*r_signal = 0;
code = WaitForSingleObject ( proc, hang? INFINITE : 0 );
switch (code) {
case WAIT_FAILED:
fprintf (stderr, "** WFSO pid=%d failed: %d\n",
(int)pid, (int)GetLastError () );
break;
case WAIT_OBJECT_0:
if (!GetExitCodeProcess (proc, &exc)) {
fprintf (stderr, "** GECP pid=%d failed: ec=%d\n",
(int)pid, (int)GetLastError () );
*r_status = 4;
}
else {
DEBUG_SELECT ((stderr,"** GECP pid=%d exit code=%d\n",
(int)pid, exc));
*r_status = exc;
}
ret = 1;
break;
case WAIT_TIMEOUT:
DEBUG_SELECT ((stderr,"** WFSO pid=%d timed out\n", (int)pid));
break;
default:
fprintf (stderr, "** WFSO pid=%d returned %d\n", (int)pid, code );
break;
}
return ret;
}
/*
* Select on the list of fds.
* Returns: -1 = error
* 0 = timeout or nothing to select
* >0 = number of signaled fds
*/
int
_gpgme_io_select ( struct io_select_fd_s *fds, size_t nfds )
{
#if 0 /* We can't use WFMO becaus a pipe handle is not a suitable object */
HANDLE waitbuf[MAXIMUM_WAIT_OBJECTS];
int code, nwait;
int i, any, any_write;
int count;
restart:
DEBUG_SELECT ((stderr, "gpgme:select on [ "));
any = any_write = 0;
nwait = 0;
for ( i=0; i < nfds; i++ ) {
if ( fds[i].fd == -1 )
continue;
if ( fds[i].for_read || fds[i].for_write ) {
if ( nwait >= DIM (waitbuf) ) {
DEBUG_SELECT ((stderr,stderr, "oops ]\n" ));
fprintf (stderr, "** Too many objects for WFMO!\n" );
return -1;
}
else {
if ( fds[i].for_read )
waitbuf[nwait++] = fd_to_handle (fds[i].fd);
DEBUG_SELECT ((stderr, "%c%d ",
fds[i].for_read? 'r':'w',fds[i].fd ));
any = 1;
}
}
fds[i].signaled = 0;
}
DEBUG_SELECT ((stderr, "]\n" ));
if (!any)
return 0;
count = 0;
for ( i=0; i < nfds; i++ ) {
if ( fds[i].fd == -1 )
continue;
if ( fds[i].for_write ) {
fds[i].signaled = 1;
any_write =1;
count++;
}
}
code = WaitForMultipleObjects ( nwait, waitbuf, 0, any_write? 0:1000);
if (code == WAIT_FAILED ) {
int le = (int)GetLastError ();
if ( le == ERROR_INVALID_HANDLE || le == ERROR_INVALID_EVENT_COUNT ) {
any = 0;
for ( i=0; i < nfds; i++ ) {
if ( fds[i].fd == -1 )
continue;
if ( fds[i].for_read /*|| fds[i].for_write*/ ) {
int navail;
if (PeekNamedPipe (fd_to_handle (fds[i].fd),
NULL, 0, NULL,
&navail, NULL) && navail ) {
fds[i].signaled = 1;
any = 1;
count++;
}
}
}
if (any)
return count;
/* find that handle and remove it from the list*/
for (i=0; i < nwait; i++ ) {
code = WaitForSingleObject ( waitbuf[i], NULL );
if (!code) {
int k, j = handle_to_fd (waitbuf[i]);
fprintf (stderr, "** handle meanwhile signaled %d\n", j);
for (k=0 ; k < nfds; k++ ) {
if ( fds[k].fd == j ) {
fds[k].signaled = 1;
count++;
return count;
}
}
fprintf (stderr, "** oops, or not???\n");
}
if ( GetLastError () == ERROR_INVALID_HANDLE) {
int k, j = handle_to_fd (waitbuf[i]);
fprintf (stderr, "** WFMO invalid handle %d removed\n", j);
for (k=0 ; k < nfds; i++ ) {
if ( fds[k].fd == j ) {
fds[k].for_read = fds[k].for_write = 0;
goto restart;
}
}
fprintf (stderr, "** oops, or not???\n");
}
}
}
fprintf (stderr, "** WFMO failed: %d\n", le );
count = -1;
}
else if ( code == WAIT_TIMEOUT ) {
fprintf (stderr, "** WFMO timed out\n" );
}
else if ( code >= WAIT_OBJECT_0 && code < WAIT_OBJECT_0 + nwait ) {
/* This WFMO is a really silly function: It does return either
* the index of the signaled object or if 2 objects have been
* signalled at the same time, the index of the object with the
* lowest object is returned - so and how do we find out
* how many objects have been signaled???.
* The only solution I can imagine is to test each object starting
* with the returned index individually - how dull.
*/
any = 0;
for (i=code - WAIT_OBJECT_0; i < nwait; i++ ) {
if (WaitForSingleObject ( waitbuf[i], NULL ) == WAIT_OBJECT_0) {
fds[i].signaled = 1;
any = 1;
count++;
}
}
if (!any) {
fprintf (stderr,
"** Oops: No signaled objects found after WFMO\n");
count = -1;
}
}
else {
fprintf (stderr, "** WFMO returned %d\n", code );
count = -1;
}
return count;
#else /* This is the code we use */
int i, any, count;
int once_more = 0;
DEBUG_SELECT ((stderr, "gpgme:fakedselect on [ "));
any = 0;
for ( i=0; i < nfds; i++ ) {
if ( fds[i].fd == -1 )
continue;
if ( fds[i].for_read || fds[i].for_write ) {
DEBUG_SELECT ((stderr, "%c%d ",
fds[i].for_read? 'r':'w',fds[i].fd ));
any = 1;
}
fds[i].signaled = 0;
}
DEBUG_SELECT ((stderr, "]\n" ));
if (!any)
return 0;
restart:
count = 0;
/* no way to see whether a handle is ready fro writing, signal all */
for ( i=0; i < nfds; i++ ) {
if ( fds[i].fd == -1 )
continue;
if ( fds[i].for_write ) {
fds[i].signaled = 1;
count++;
}
}
/* now peek on all read handles */
for ( i=0; i < nfds; i++ ) {
if ( fds[i].fd == -1 )
continue;
if ( fds[i].for_read ) {
int navail;
if ( !PeekNamedPipe (fd_to_handle (fds[i].fd),
NULL, 0, NULL, &navail, NULL) ) {
fprintf (stderr, "** select: PeekFile failed: ec=%d\n",
(int)GetLastError ());
}
else if ( navail ) {
/*fprintf (stderr, "** fd %d has %d bytes to read\n",
fds[i].fd, navail );*/
fds[i].signaled = 1;
count++;
}
}
}
if ( !once_more && !count ) {
/* once more but after relinquishing our timeslot */
once_more = 1;
Sleep (0);
goto restart;
}
if ( count ) {
DEBUG_SELECT ((stderr, "gpgme: signaled [ "));
for ( i=0; i < nfds; i++ ) {
if ( fds[i].fd == -1 )
continue;
if ( (fds[i].for_read || fds[i].for_write) && fds[i].signaled ) {
DEBUG_SELECT ((stderr, "%c%d ",
fds[i].for_read? 'r':'w',fds[i].fd ));
}
}
DEBUG_SELECT ((stderr, "]\n" ));
}
return count;
#endif
}
#endif /*HAVE_DOSISH_SYSTEM*/

View File

@ -0,0 +1,368 @@
/* wait.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/types.h>
#include "syshdr.h"
#include "util.h"
#include "context.h"
#include "ops.h"
#include "wait.h"
#include "io.h"
/* Fixme: implement the following stuff to make the code MT safe.
* To avoid the need to link against a specific threads lib, such
* an implementation should require the caller to register a function
* which does this task.
* enter_crit() and leave_crit() are used to embrace an area of code
* which should be executed only by one thread at a time.
* lock_xxxx() and unlock_xxxx() protect access to an data object.
* */
#define enter_crit() do { } while (0)
#define leave_crit() do { } while (0)
#define lock_table() do { } while (0)
#define unlock_table() do { } while (0)
struct wait_item_s {
volatile int active;
int (*handler)(void*,int,int);
void *handler_value;
int pid;
int inbound; /* this is an inbound data handler fd */
int exited;
int exit_status;
int exit_signal;
GpgmeCtx ctx;
};
static int fd_table_size;
static struct io_select_fd_s *fd_table;
static int do_select ( void );
static struct wait_item_s *
queue_item_from_context ( GpgmeCtx ctx )
{
struct wait_item_s *q;
int i;
for (i=0; i < fd_table_size; i++ ) {
if ( fd_table[i].fd != -1 && (q=fd_table[i].opaque) && q->ctx == ctx )
return q;
}
return NULL;
}
static void
propagate_term_results ( const struct wait_item_s *first_q )
{
struct wait_item_s *q;
int i;
for (i=0; i < fd_table_size; i++ ) {
if ( fd_table[i].fd != -1 && (q=fd_table[i].opaque)
&& q != first_q && !q->exited
&& q->pid == first_q->pid ) {
q->exited = first_q->exited;
q->exit_status = first_q->exit_status;
q->exit_signal = first_q->exit_signal;
}
}
}
static int
count_active_fds ( int pid )
{
struct wait_item_s *q;
int i, count = 0;
for (i=0; i < fd_table_size; i++ ) {
if ( fd_table[i].fd != -1 && (q=fd_table[i].opaque)
&& q->active && q->pid == pid )
count++;
}
return count;
}
static void
clear_active_fds ( int pid )
{
struct wait_item_s *q;
int i;
for (i=0; i < fd_table_size; i++ ) {
if ( fd_table[i].fd != -1 && (q=fd_table[i].opaque)
&& q->active && q->pid == pid )
q->active = 0;
}
}
/* remove the given process from the queue */
static void
remove_process ( int pid )
{
struct wait_item_s *q;
int i;
for (i=0; i < fd_table_size; i++ ) {
if (fd_table[i].fd != -1 && (q=fd_table[i].opaque) && q->pid == pid ) {
xfree (q);
fd_table[i].opaque = NULL;
if ( !fd_table[i].is_closed ) {
_gpgme_io_close (fd_table[i].fd);
fd_table[i].is_closed = 1;
}
fd_table[i].fd = -1;
}
}
}
/**
* gpgme_wait:
* @c:
* @hang:
*
* Wait for a finished request, if @c is given the function does only
* wait on a finsihed request for that context, otherwise it will return
* on any request. When @hang is true the function will wait, otherwise
* it will return immediately when there is no pending finished request.
*
* Return value: Context of the finished request or NULL if @hang is false
* and no (or the given) request has finished.
**/
GpgmeCtx
gpgme_wait ( GpgmeCtx c, int hang )
{
return _gpgme_wait_on_condition ( c, hang, NULL );
}
GpgmeCtx
_gpgme_wait_on_condition ( GpgmeCtx c, int hang, volatile int *cond )
{
struct wait_item_s *q;
do {
int did_work = do_select();
if ( cond && *cond )
hang = 0;
if ( !did_work ) {
/* We did no read/write - see whether the process is still
* alive */
assert (c); /* !c is not yet implemented */
q = queue_item_from_context ( c );
assert (q);
if (q->exited) {
/* this is the second time we reached this and we got no
* more data from the pipe (which may happen to to buffering).
* Set all FDs inactive.
*/
clear_active_fds (q->pid);
}
else if ( _gpgme_io_waitpid (q->pid, 0,
&q->exit_status, &q->exit_signal)){
q->exited = 1;
propagate_term_results (q);
}
if ( q->exited ) {
if ( !count_active_fds (q->pid) ) {
/* Hmmm, as long as we don't have a callback for
* the exit status, we have no use for these
* values and therefore we can remove this from
* the queue */
remove_process (q->pid);
hang = 0;
}
}
}
} while (hang);
return c;
}
/*
* We use this function to do the select stuff for all running
* gpgs. A future version might provide a facility to delegate
* those selects to the GDK select stuff.
* This function must be called only by one thread!!
* Returns: 0 = nothing to run
* 1 = did run something
*/
static int
do_select ( void )
{
struct wait_item_s *q;
int i, n;
int any=0;
n = _gpgme_io_select ( fd_table, fd_table_size );
if ( n <= 0 )
return 0; /* error or timeout */
for (i=0; i < fd_table_size && n; i++ ) {
if ( fd_table[i].fd != -1 && fd_table[i].signaled
&& !fd_table[i].frozen ) {
q = fd_table[i].opaque;
assert (n);
n--;
if ( q->active )
any = 1;
if ( q->active && q->handler (q->handler_value,
q->pid, fd_table[i].fd ) ) {
q->active = 0;
fd_table[i].for_read = 0;
fd_table[i].for_write = 0;
fd_table[i].is_closed = 1;
}
}
}
return any;
}
/*
* called by rungpg.c to register something for select()
*/
GpgmeError
_gpgme_register_pipe_handler ( void *opaque,
int (*handler)(void*,int,int),
void *handler_value,
int pid, int fd, int inbound )
{
GpgmeCtx ctx = opaque;
struct wait_item_s *q;
int i;
assert (opaque);
assert (handler);
q = xtrycalloc ( 1, sizeof *q );
if ( !q )
return mk_error (Out_Of_Core);
q->inbound = inbound;
q->handler = handler;
q->handler_value = handler_value;
q->pid = pid;
q->ctx = ctx;
q->active = 1;
lock_table ();
again:
for (i=0; i < fd_table_size; i++ ) {
if ( fd_table[i].fd == -1 ) {
fd_table[i].fd = fd;
fd_table[i].is_closed = 0;
fd_table[i].for_read = inbound;
fd_table[i].for_write = !inbound;
fd_table[i].signaled = 0;
fd_table[i].frozen = 0;
fd_table[i].opaque = q;
unlock_table ();
return 0;
}
}
if ( fd_table_size < 50 ) {
/* FIXME: We have to wait until there are no other readers of the
* table, i.e that the io_select is not active in another thread */
struct io_select_fd_s *tmp;
tmp = xtryrealloc ( fd_table, (fd_table_size + 10) * sizeof *tmp );
if ( tmp ) {
for (i=0; i < 10; i++ )
tmp[fd_table_size+i].fd = -1;
fd_table_size += i;
fd_table = tmp;
goto again;
}
}
unlock_table ();
xfree (q);
return mk_error (Too_Many_Procs);
}
void
_gpgme_freeze_fd ( int fd )
{
int i;
lock_table ();
for (i=0; i < fd_table_size; i++ ) {
if ( fd_table[i].fd == fd ) {
fd_table[i].frozen = 1;
/*fprintf (stderr, "** FD %d frozen\n", fd );*/
break;
}
}
unlock_table ();
}
void
_gpgme_thaw_fd ( int fd )
{
int i;
lock_table ();
for (i=0; i < fd_table_size; i++ ) {
if ( fd_table[i].fd == fd ) {
fd_table[i].frozen = 0;
/*fprintf (stderr, "** FD %d thawed\n", fd );*/
break;
}
}
unlock_table ();
}

View File

@ -0,0 +1,42 @@
/* wait.h - definitions for wait.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
*/
#ifndef WAIT_H
#define WAIT_H
#include "gpgme.h"
#define SIZEOF_WAIT_QUEUE 10
GpgmeError _gpgme_register_pipe_handler(
void *opaque,
int (*handler)(void*,int,int),
void *handler_value,
int pid, int fd, int inbound );
#endif /* WAIT_H */

View File

@ -0,0 +1,41 @@
2000-07-26 10:02:51 Werner Koch (wk@habibti.openit.de)
* stringhelp.c.: Add stdarg.h
* argparse.h: s/ulong/unsigned long/ although this should be defined
by types.h.
2000-06-28 19:40:23 Werner Koch (wk@habibti.openit.de)
* Makefile.am: Replaced second logging.c by .h
2000-05-24 08:58:15 Werner Koch (wk@habibti.openit.de)
* logging.c (log_get_errorcount): New.
2000-05-24 08:44:47 Werner Koch (wk@habibti.openit.de)
* stringhelp.c: Added a few filename related helper functions.
2000-05-11 18:04:43 Werner Koch (wk@habibti.openit.de)
* xmalloc.c (xstrcat2): Replaced stpcpy to quickly address W32
problems.
2000-05-02 19:43:38 Werner Koch (wk@habibti.openit.de)
* xmalloc.c (xstrcat2): New.
Mon Jan 24 13:04:28 CET 2000 Werner Koch <wk@gnupg.de>
* README: New.
* Makefile.am: new.
* argparse.c argparse.h logging.c logging.h
mischelp.h stringhelp.c stringhelp.h xmalloc.c
xmalloc.h dotlock.c: Moved from ../util to here.
* dotlock.h: New.
* libjnlib-config.h: New.
* logging.c (log_set_file): New.
(log_printf): New.
(do_logv): Add kludge to insert LFs.

View File

@ -0,0 +1,7 @@
jnlib - this is a collection of utility function which are
too small to put into a library.
libjnlib-config.h should be be modified for each project
to make these functions fit into the software. Mainly these
are memory functions in case you need another allocator.

View File

@ -0,0 +1,995 @@
/* [argparse.c wk 17.06.97] Argument Parser for option handling
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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 <ctype.h>
#include <string.h>
#include "libjnlib-config.h"
#include "mischelp.h"
#include "stringhelp.h"
#include "logging.h"
#include "argparse.h"
/*********************************
* @Summary arg_parse
* #include <wk/lib.h>
*
* typedef struct {
* char *argc; pointer to argc (value subject to change)
* char ***argv; pointer to argv (value subject to change)
* unsigned flags; Global flags (DO NOT CHANGE)
* int err; print error about last option
* 1 = warning, 2 = abort
* int r_opt; return option
* int r_type; type of return value (0 = no argument found)
* union {
* int ret_int;
* long ret_long
* ulong ret_ulong;
* char *ret_str;
* } r; Return values
* struct {
* int idx;
* const char *last;
* void *aliases;
* } internal; DO NOT CHANGE
* } ARGPARSE_ARGS;
*
* typedef struct {
* int short_opt;
* const char *long_opt;
* unsigned flags;
* } ARGPARSE_OPTS;
*
* int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts );
*
* @Description
* This is my replacement for getopt(). See the example for a typical usage.
* Global flags are:
* Bit 0 : Do not remove options form argv
* Bit 1 : Do not stop at last option but return other args
* with r_opt set to -1.
* Bit 2 : Assume options and real args are mixed.
* Bit 3 : Do not use -- to stop option processing.
* Bit 4 : Do not skip the first arg.
* Bit 5 : allow usage of long option with only one dash
* Bit 6 : ignore --version
* all other bits must be set to zero, this value is modified by the
* function, so assume this is write only.
* Local flags (for each option):
* Bit 2-0 : 0 = does not take an argument
* 1 = takes int argument
* 2 = takes string argument
* 3 = takes long argument
* 4 = takes ulong argument
* Bit 3 : argument is optional (r_type will the be set to 0)
* Bit 4 : allow 0x etc. prefixed values.
* Bit 7 : this is a command and not an option
* You stop the option processing by setting opts to NULL, the function will
* then return 0.
* @Return Value
* Returns the args.r_opt or 0 if ready
* r_opt may be -2/-7 to indicate an unknown option/command.
* @See Also
* ArgExpand
* @Notes
* You do not need to process the options 'h', '--help' or '--version'
* because this function includes standard help processing; but if you
* specify '-h', '--help' or '--version' you have to do it yourself.
* The option '--' stops argument processing; if bit 1 is set the function
* continues to return normal arguments.
* To process float args or unsigned args you must use a string args and do
* the conversion yourself.
* @Example
*
* ARGPARSE_OPTS opts[] = {
* { 'v', "verbose", 0 },
* { 'd', "debug", 0 },
* { 'o', "output", 2 },
* { 'c', "cross-ref", 2|8 },
* { 'm', "my-option", 1|8 },
* { 500, "have-no-short-option-for-this-long-option", 0 },
* {0} };
* ARGPARSE_ARGS pargs = { &argc, &argv, 0 }
*
* while( ArgParse( &pargs, &opts) ) {
* switch( pargs.r_opt ) {
* case 'v': opt.verbose++; break;
* case 'd': opt.debug++; break;
* case 'o': opt.outfile = pargs.r.ret_str; break;
* case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break;
* case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break;
* case 500: opt.a_long_one++; break
* default : pargs.err = 1; break; -- force warning output --
* }
* }
* if( argc > 1 )
* log_fatal( "Too many args");
*
*/
typedef struct alias_def_s *ALIAS_DEF;
struct alias_def_s {
ALIAS_DEF next;
char *name; /* malloced buffer with name, \0, value */
const char *value; /* ptr into name */
};
static const char *(*strusage_handler)( int ) = NULL;
static int set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s);
static void show_help(ARGPARSE_OPTS *opts, unsigned flags);
static void show_version(void);
static void
initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno )
{
if( !(arg->flags & (1<<15)) ) { /* initialize this instance */
arg->internal.idx = 0;
arg->internal.last = NULL;
arg->internal.inarg = 0;
arg->internal.stopped = 0;
arg->internal.aliases = NULL;
arg->internal.cur_alias = NULL;
arg->err = 0;
arg->flags |= 1<<15; /* mark initialized */
if( *arg->argc < 0 )
jnlib_log_bug("Invalid argument for ArgParse\n");
}
if( arg->err ) { /* last option was erroneous */
const char *s;
if( filename ) {
if( arg->r_opt == -6 )
s = "%s:%u: argument not expected\n";
else if( arg->r_opt == -5 )
s = "%s:%u: read error\n";
else if( arg->r_opt == -4 )
s = "%s:%u: keyword too long\n";
else if( arg->r_opt == -3 )
s = "%s:%u: missing argument\n";
else if( arg->r_opt == -7 )
s = "%s:%u: invalid command\n";
else if( arg->r_opt == -10 )
s = "%s:%u: invalid alias definition\n";
else
s = "%s:%u: invalid option\n";
jnlib_log_error(s, filename, *lineno );
}
else {
if( arg->r_opt == -3 )
s = "Missing argument for option \"%.50s\"\n";
else if( arg->r_opt == -6 )
s = "Option \"%.50s\" does not expect an argument\n";
else if( arg->r_opt == -7 )
s = "Invalid command \"%.50s\"\n";
else if( arg->r_opt == -8 )
s = "Option \"%.50s\" is ambiguous\n";
else if( arg->r_opt == -9 )
s = "Command \"%.50s\" is ambiguous\n";
else
s = "Invalid option \"%.50s\"\n";
jnlib_log_error(s, arg->internal.last? arg->internal.last:"[??]" );
}
if( arg->err != 1 )
exit(2);
arg->err = 0;
}
/* clearout the return value union */
arg->r.ret_str = NULL;
arg->r.ret_long= 0;
}
static void
store_alias( ARGPARSE_ARGS *arg, char *name, char *value )
{
/* TODO: replace this dummy function with a rea one
* and fix the probelms IRIX has with (ALIAS_DEV)arg..
* used as lvalue
*/
#if 0
ALIAS_DEF a = jnlib_xmalloc( sizeof *a );
a->name = name;
a->value = value;
a->next = (ALIAS_DEF)arg->internal.aliases;
(ALIAS_DEF)arg->internal.aliases = a;
#endif
}
/****************
* Get options from a file.
* Lines starting with '#' are comment lines.
* Syntax is simply a keyword and the argument.
* Valid keywords are all keywords from the long_opt list without
* the leading dashes. The special keywords "help", "warranty" and "version"
* are not valid here.
* The special keyword "alias" may be used to store alias definitions,
* which are later expanded like long options.
* Caller must free returned strings.
* If called with FP set to NULL command line args are parse instead.
*
* Q: Should we allow the syntax
* keyword = value
* and accept for boolean options a value of 1/0, yes/no or true/false?
* Note: Abbreviation of options is here not allowed.
*/
int
optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
{
int state, i, c;
int idx=0;
char keyword[100];
char *buffer = NULL;
size_t buflen = 0;
int inverse=0;
int in_alias=0;
if( !fp ) /* same as arg_parse() in this case */
return arg_parse( arg, opts );
initialize( arg, filename, lineno );
/* find the next keyword */
state = i = 0;
for(;;) {
c=getc(fp);
if( c == '\n' || c== EOF ) {
if( c != EOF )
++*lineno;
if( state == -1 )
break;
else if( state == 2 ) {
keyword[i] = 0;
for(i=0; opts[i].short_opt; i++ )
if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) )
break;
idx = i;
arg->r_opt = opts[idx].short_opt;
if( inverse ) /* this does not have an effect, hmmm */
arg->r_opt = -arg->r_opt;
if( !opts[idx].short_opt ) /* unknown command/option */
arg->r_opt = (opts[idx].flags & 256)? -7:-2;
else if( (opts[idx].flags & 8) ) /* no argument */
arg->r_opt = -3; /* error */
else /* no or optional argument */
arg->r_type = 0; /* okay */
break;
}
else if( state == 3 ) { /* no argument found */
if( in_alias )
arg->r_opt = -3; /* error */
else if( !(opts[idx].flags & 7) ) /* does not take an arg */
arg->r_type = 0; /* okay */
else if( (opts[idx].flags & 8) ) /* no optional argument */
arg->r_type = 0; /* okay */
else /* no required argument */
arg->r_opt = -3; /* error */
break;
}
else if( state == 4 ) { /* have an argument */
if( in_alias ) {
if( !buffer )
arg->r_opt = -6;
else {
char *p;
buffer[i] = 0;
p = strpbrk( buffer, " \t" );
if( p ) {
*p++ = 0;
trim_spaces( p );
}
if( !p || !*p ) {
jnlib_free( buffer );
arg->r_opt = -10;
}
else {
store_alias( arg, buffer, p );
}
}
}
else if( !(opts[idx].flags & 7) ) /* does not take an arg */
arg->r_opt = -6; /* error */
else {
char *p;
if( !buffer ) {
keyword[i] = 0;
buffer = jnlib_xstrdup(keyword);
}
else
buffer[i] = 0;
trim_spaces( buffer );
p = buffer;
if( *p == '"' ) { /* remove quotes */
p++;
if( *p && p[strlen(p)-1] == '"' )
p[strlen(p)-1] = 0;
}
if( !set_opt_arg(arg, opts[idx].flags, p) )
jnlib_free(buffer);
}
break;
}
else if( c == EOF ) {
if( ferror(fp) )
arg->r_opt = -5; /* read error */
else
arg->r_opt = 0; /* eof */
break;
}
state = 0;
i = 0;
}
else if( state == -1 )
; /* skip */
else if( !state && isspace(c) )
; /* skip leading white space */
else if( !state && c == '#' )
state = 1; /* start of a comment */
else if( state == 1 )
; /* skip comments */
else if( state == 2 && isspace(c) ) {
keyword[i] = 0;
for(i=0; opts[i].short_opt; i++ )
if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) )
break;
idx = i;
arg->r_opt = opts[idx].short_opt;
if( !opts[idx].short_opt ) {
if( !strcmp( keyword, "alias" ) ) {
in_alias = 1;
state = 3;
}
else {
arg->r_opt = (opts[idx].flags & 256)? -7:-2;
state = -1; /* skip rest of line and leave */
}
}
else
state = 3;
}
else if( state == 3 ) { /* skip leading spaces of the argument */
if( !isspace(c) ) {
i = 0;
keyword[i++] = c;
state = 4;
}
}
else if( state == 4 ) { /* collect the argument */
if( buffer ) {
if( i < buflen-1 )
buffer[i++] = c;
else {
buflen += 50;
buffer = jnlib_xrealloc(buffer, buflen);
buffer[i++] = c;
}
}
else if( i < DIM(keyword)-1 )
keyword[i++] = c;
else {
buflen = DIM(keyword)+50;
buffer = jnlib_xmalloc(buflen);
memcpy(buffer, keyword, i);
buffer[i++] = c;
}
}
else if( i >= DIM(keyword)-1 ) {
arg->r_opt = -4; /* keyword to long */
state = -1; /* skip rest of line and leave */
}
else {
keyword[i++] = c;
state = 2;
}
}
return arg->r_opt;
}
static int
find_long_option( ARGPARSE_ARGS *arg,
ARGPARSE_OPTS *opts, const char *keyword )
{
int i;
size_t n;
/* Would be better if we can do a binary search, but it is not
possible to reorder our option table because we would mess
up our help strings - What we can do is: Build a nice option
lookup table wehn this function is first invoked */
if( !*keyword )
return -1;
for(i=0; opts[i].short_opt; i++ )
if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) )
return i;
#if 0
{
ALIAS_DEF a;
/* see whether it is an alias */
for( a = args->internal.aliases; a; a = a->next ) {
if( !strcmp( a->name, keyword) ) {
/* todo: must parse the alias here */
args->internal.cur_alias = a;
return -3; /* alias available */
}
}
}
#endif
/* not found, see whether it is an abbreviation */
/* aliases may not be abbreviated */
n = strlen( keyword );
for(i=0; opts[i].short_opt; i++ ) {
if( opts[i].long_opt && !strncmp( opts[i].long_opt, keyword, n ) ) {
int j;
for(j=i+1; opts[j].short_opt; j++ ) {
if( opts[j].long_opt
&& !strncmp( opts[j].long_opt, keyword, n ) )
return -2; /* abbreviation is ambiguous */
}
return i;
}
}
return -1;
}
int
arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
{
int idx;
int argc;
char **argv;
char *s, *s2;
int i;
initialize( arg, NULL, NULL );
argc = *arg->argc;
argv = *arg->argv;
idx = arg->internal.idx;
if( !idx && argc && !(arg->flags & (1<<4)) ) { /* skip the first entry */
argc--; argv++; idx++;
}
next_one:
if( !argc ) { /* no more args */
arg->r_opt = 0;
goto leave; /* ready */
}
s = *argv;
arg->internal.last = s;
if( arg->internal.stopped && (arg->flags & (1<<1)) ) {
arg->r_opt = -1; /* not an option but a argument */
arg->r_type = 2;
arg->r.ret_str = s;
argc--; argv++; idx++; /* set to next one */
}
else if( arg->internal.stopped ) { /* ready */
arg->r_opt = 0;
goto leave;
}
else if( *s == '-' && s[1] == '-' ) { /* long option */
char *argpos;
arg->internal.inarg = 0;
if( !s[2] && !(arg->flags & (1<<3)) ) { /* stop option processing */
arg->internal.stopped = 1;
argc--; argv++; idx++;
goto next_one;
}
argpos = strchr( s+2, '=' );
if( argpos )
*argpos = 0;
i = find_long_option( arg, opts, s+2 );
if( argpos )
*argpos = '=';
if( i < 0 && !strcmp( "help", s+2) )
show_help(opts, arg->flags);
else if( i < 0 && !strcmp( "version", s+2) ) {
if( !(arg->flags & (1<<6)) ) {
show_version();
exit(0);
}
}
else if( i < 0 && !strcmp( "warranty", s+2) ) {
puts( strusage(16) );
exit(0);
}
else if( i < 0 && !strcmp( "dump-options", s+2) ) {
for(i=0; opts[i].short_opt; i++ ) {
if( opts[i].long_opt )
printf( "--%s\n", opts[i].long_opt );
}
fputs("--dump-options\n--help\n--version\n--warranty\n", stdout );
exit(0);
}
if( i == -2 ) /* ambiguous option */
arg->r_opt = -8;
else if( i == -1 ) {
arg->r_opt = -2;
arg->r.ret_str = s+2;
}
else
arg->r_opt = opts[i].short_opt;
if( i < 0 )
;
else if( (opts[i].flags & 7) ) {
if( argpos ) {
s2 = argpos+1;
if( !*s2 )
s2 = NULL;
}
else
s2 = argv[1];
if( !s2 && (opts[i].flags & 8) ) { /* no argument but it is okay*/
arg->r_type = 0; /* because it is optional */
}
else if( !s2 ) {
arg->r_opt = -3; /* missing argument */
}
else if( !argpos && *s2 == '-' && (opts[i].flags & 8) ) {
/* the argument is optional and the next seems to be
* an option. We do not check this possible option
* but assume no argument */
arg->r_type = 0;
}
else {
set_opt_arg(arg, opts[i].flags, s2);
if( !argpos ) {
argc--; argv++; idx++; /* skip one */
}
}
}
else { /* does not take an argument */
if( argpos )
arg->r_type = -6; /* argument not expected */
else
arg->r_type = 0;
}
argc--; argv++; idx++; /* set to next one */
}
else if( (*s == '-' && s[1]) || arg->internal.inarg ) { /* short option */
int dash_kludge = 0;
i = 0;
if( !arg->internal.inarg ) {
arg->internal.inarg++;
if( arg->flags & (1<<5) ) {
for(i=0; opts[i].short_opt; i++ )
if( opts[i].long_opt && !strcmp( opts[i].long_opt, s+1)) {
dash_kludge=1;
break;
}
}
}
s += arg->internal.inarg;
if( !dash_kludge ) {
for(i=0; opts[i].short_opt; i++ )
if( opts[i].short_opt == *s )
break;
}
if( !opts[i].short_opt && ( *s == 'h' || *s == '?' ) )
show_help(opts, arg->flags);
arg->r_opt = opts[i].short_opt;
if( !opts[i].short_opt ) {
arg->r_opt = (opts[i].flags & 256)? -7:-2;
arg->internal.inarg++; /* point to the next arg */
arg->r.ret_str = s;
}
else if( (opts[i].flags & 7) ) {
if( s[1] && !dash_kludge ) {
s2 = s+1;
set_opt_arg(arg, opts[i].flags, s2);
}
else {
s2 = argv[1];
if( !s2 && (opts[i].flags & 8) ) { /* no argument but it is okay*/
arg->r_type = 0; /* because it is optional */
}
else if( !s2 ) {
arg->r_opt = -3; /* missing argument */
}
else if( *s2 == '-' && s2[1] && (opts[i].flags & 8) ) {
/* the argument is optional and the next seems to be
* an option. We do not check this possible option
* but assume no argument */
arg->r_type = 0;
}
else {
set_opt_arg(arg, opts[i].flags, s2);
argc--; argv++; idx++; /* skip one */
}
}
s = "x"; /* so that !s[1] yields false */
}
else { /* does not take an argument */
arg->r_type = 0;
arg->internal.inarg++; /* point to the next arg */
}
if( !s[1] || dash_kludge ) { /* no more concatenated short options */
arg->internal.inarg = 0;
argc--; argv++; idx++;
}
}
else if( arg->flags & (1<<2) ) {
arg->r_opt = -1; /* not an option but a argument */
arg->r_type = 2;
arg->r.ret_str = s;
argc--; argv++; idx++; /* set to next one */
}
else {
arg->internal.stopped = 1; /* stop option processing */
goto next_one;
}
leave:
*arg->argc = argc;
*arg->argv = argv;
arg->internal.idx = idx;
return arg->r_opt;
}
static int
set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s)
{
int base = (flags & 16)? 0 : 10;
switch( arg->r_type = (flags & 7) ) {
case 1: /* takes int argument */
arg->r.ret_int = (int)strtol(s,NULL,base);
return 0;
case 3: /* takes long argument */
arg->r.ret_long= strtol(s,NULL,base);
return 0;
case 4: /* takes ulong argument */
arg->r.ret_ulong= strtoul(s,NULL,base);
return 0;
case 2: /* takes string argument */
default:
arg->r.ret_str = s;
return 1;
}
}
static size_t
long_opt_strlen( ARGPARSE_OPTS *o )
{
size_t n = strlen(o->long_opt);
if( o->description && *o->description == '|' ) {
const char *s;
s=o->description+1;
if( *s != '=' )
n++;
for(; *s && *s != '|'; s++ )
n++;
}
return n;
}
/****************
* Print formatted help. The description string has some special
* meanings:
* - A description string which is "@" suppresses help output for
* this option
* - a description,ine which starts with a '@' and is followed by
* any other characters is printed as is; this may be used for examples
* ans such.
* - A description which starts with a '|' outputs the string between this
* bar and the next one as arguments of the long option.
*/
static void
show_help( ARGPARSE_OPTS *opts, unsigned flags )
{
const char *s;
show_version();
putchar('\n');
s = strusage(41);
puts(s);
if( opts[0].description ) { /* auto format the option description */
int i,j, indent;
/* get max. length of long options */
for(i=indent=0; opts[i].short_opt; i++ ) {
if( opts[i].long_opt )
if( !opts[i].description || *opts[i].description != '@' )
if( (j=long_opt_strlen(opts+i)) > indent && j < 35 )
indent = j;
}
/* example: " -v, --verbose Viele Sachen ausgeben" */
indent += 10;
if( *opts[0].description != '@' )
puts("Options:");
for(i=0; opts[i].short_opt; i++ ) {
s = _( opts[i].description );
if( s && *s== '@' && !s[1] ) /* hide this line */
continue;
if( s && *s == '@' ) { /* unindented comment only line */
for(s++; *s; s++ ) {
if( *s == '\n' ) {
if( s[1] )
putchar('\n');
}
else
putchar(*s);
}
putchar('\n');
continue;
}
j = 3;
if( opts[i].short_opt < 256 ) {
printf(" -%c", opts[i].short_opt );
if( !opts[i].long_opt ) {
if(s && *s == '|' ) {
putchar(' '); j++;
for(s++ ; *s && *s != '|'; s++, j++ )
putchar(*s);
if( *s )
s++;
}
}
}
else
fputs(" ", stdout);
if( opts[i].long_opt ) {
j += printf("%c --%s", opts[i].short_opt < 256?',':' ',
opts[i].long_opt );
if(s && *s == '|' ) {
if( *++s != '=' ) {
putchar(' ');
j++;
}
for( ; *s && *s != '|'; s++, j++ )
putchar(*s);
if( *s )
s++;
}
fputs(" ", stdout);
j += 3;
}
for(;j < indent; j++ )
putchar(' ');
if( s ) {
if( *s && j > indent ) {
putchar('\n');
for(j=0;j < indent; j++ )
putchar(' ');
}
for(; *s; s++ ) {
if( *s == '\n' ) {
if( s[1] ) {
putchar('\n');
for(j=0;j < indent; j++ )
putchar(' ');
}
}
else
putchar(*s);
}
}
putchar('\n');
}
if( flags & 32 )
puts("\n(A single dash may be used instead of the double ones)");
}
if( (s=strusage(19)) ) { /* bug reports to ... */
putchar('\n');
fputs(s, stdout);
}
fflush(stdout);
exit(0);
}
static void
show_version()
{
const char *s;
int i;
/* version line */
fputs(strusage(11), stdout);
if( (s=strusage(12)) )
printf(" (%s)", s );
printf(" %s\n", strusage(13) );
/* additional version lines */
for(i=20; i < 30; i++ )
if( (s=strusage(i)) )
printf("%s\n", s );
/* copyright string */
if( (s=strusage(14)) )
printf("%s\n", s );
/* copying conditions */
if( (s=strusage(15)) )
fputs(s, stdout);
/* thanks */
if( (s=strusage(18)) )
fputs(s, stdout);
/* additional program info */
for(i=30; i < 40; i++ )
if( (s=strusage(i)) )
fputs( (const byte*)s, stdout);
fflush(stdout);
}
void
usage( int level )
{
if( !level ) {
fprintf(stderr,"%s %s; %s\n", strusage(11), strusage(13),
strusage(14) );
fflush(stderr);
}
else if( level == 1 ) {
fputs(strusage(40),stderr);
exit(2);
}
else if( level == 2 ) {
puts(strusage(41));
exit(0);
}
}
/* Level
* 0: Copyright String auf stderr ausgeben
* 1: Kurzusage auf stderr ausgeben und beenden
* 2: Langusage auf stdout ausgeben und beenden
* 11: name of program
* 12: optional name of package which includes this program.
* 13: version string
* 14: copyright string
* 15: Short copying conditions (with LFs)
* 16: Long copying conditions (with LFs)
* 17: Optional printable OS name
* 18: Optional thanks list (with LFs)
* 19: Bug report info
*20..29: Additional lib version strings.
*30..39: Additional program info (with LFs)
* 40: short usage note (with LF)
* 41: long usage note (with LF)
*/
const char *
strusage( int level )
{
const char *p = strusage_handler? strusage_handler(level) : NULL;
if( p )
return p;
switch( level ) {
case 11: p = "foo"; break;
case 13: p = "0.0"; break;
case 14: p = "Copyright (C) 2000 Free Software Foundation, Inc."; break;
case 15: p =
"This program comes with ABSOLUTELY NO WARRANTY.\n"
"This is free software, and you are welcome to redistribute it\n"
"under certain conditions. See the file COPYING for details.\n"; break;
case 16: p =
"This is free software; you can redistribute it and/or modify\n"
"it under the terms of the GNU General Public License as published by\n"
"the Free Software Foundation; either version 2 of the License, or\n"
"(at your option) any later version.\n\n"
"It is distributed in the hope that it will be useful,\n"
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
"GNU General Public License for more details.\n\n"
"You should have received a copy of the GNU General Public License\n"
"along with this program; if not, write to the Free Software\n"
"Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n";
break;
case 40: /* short and long usage */
case 41: p = ""; break;
}
return p;
}
void
set_strusage( const char *(*f)( int ) )
{
strusage_handler = f;
}
#ifdef TEST
static struct {
int verbose;
int debug;
char *outfile;
char *crf;
int myopt;
int echo;
int a_long_one;
}opt;
int
main(int argc, char **argv)
{
ARGPARSE_OPTS opts[] = {
{ 'v', "verbose", 0 , "Laut sein"},
{ 'e', "echo" , 0 , "Zeile ausgeben, damit wir sehen, was wir einegegeben haben"},
{ 'd', "debug", 0 , "Debug\nfalls mal etasws\nSchief geht"},
{ 'o', "output", 2 },
{ 'c', "cross-ref", 2|8, "cross-reference erzeugen\n" },
{ 'm', "my-option", 1|8 },
{ 500, "a-long-option", 0 },
{0} };
ARGPARSE_ARGS pargs = { &argc, &argv, 2|4|32 };
int i;
while( ArgParse( &pargs, opts) ) {
switch( pargs.r_opt ) {
case -1 : printf( "arg=`%s'\n", pargs.r.ret_str); break;
case 'v': opt.verbose++; break;
case 'e': opt.echo++; break;
case 'd': opt.debug++; break;
case 'o': opt.outfile = pargs.r.ret_str; break;
case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break;
case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break;
case 500: opt.a_long_one++; break;
default : pargs.err = 1; break; /* force warning output */
}
}
for(i=0; i < argc; i++ )
printf("%3d -> (%s)\n", i, argv[i] );
puts("Options:");
if( opt.verbose )
printf(" verbose=%d\n", opt.verbose );
if( opt.debug )
printf(" debug=%d\n", opt.debug );
if( opt.outfile )
printf(" outfile=`%s'\n", opt.outfile );
if( opt.crf )
printf(" crffile=`%s'\n", opt.crf );
if( opt.myopt )
printf(" myopt=%d\n", opt.myopt );
if( opt.a_long_one )
printf(" a-long-one=%d\n", opt.a_long_one );
if( opt.echo )
printf(" echo=%d\n", opt.echo );
return 0;
}
#endif
/**** bottom of file ****/

View File

@ -0,0 +1,67 @@
/* argparse.h
* Copyright (C) 1998,1999 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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 LIBJNLIB_ARGPARSE_H
#define LIBJNLIB_ARGPARSE_H
#include <stdio.h>
#include "types.h"
typedef struct {
int *argc; /* pointer to argc (value subject to change) */
char ***argv; /* pointer to argv (value subject to change) */
unsigned flags; /* Global flags (DO NOT CHANGE) */
int err; /* print error about last option */
/* 1 = warning, 2 = abort */
int r_opt; /* return option */
int r_type; /* type of return value (0 = no argument found)*/
union {
int ret_int;
long ret_long;
unsigned long ret_ulong;
char *ret_str;
} r; /* Return values */
struct {
int idx;
int inarg;
int stopped;
const char *last;
void *aliases;
const void *cur_alias;
} internal; /* DO NOT CHANGE */
} ARGPARSE_ARGS;
typedef struct {
int short_opt;
const char *long_opt;
unsigned flags;
const char *description; /* optional option description */
} ARGPARSE_OPTS;
int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts);
int optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts);
void usage( int level );
const char *strusage( int level );
void set_strusage( const char *(*f)( int ) );
#endif /*LIBJNLIB_ARGPARSE_H*/

View File

@ -0,0 +1,346 @@
/* dotlock.c - dotfile locking
* Copyright (C) 1998,2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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 <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <errno.h>
#include <unistd.h>
#ifndef HAVE_DOSISH_SYSTEM
#include <sys/utsname.h>
#endif
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include "libjnlib-config.h"
#include "dotlock.h"
struct dotlock_handle {
struct dotlock_handle *next;
char *tname; /* name of lockfile template */
char *lockname; /* name of the real lockfile */
int locked; /* lock status */
};
static DOTLOCK all_lockfiles;
static int read_lockfile( const char *name );
static void remove_lockfiles(void);
/****************
* Create a lockfile with the given name and return an object of
* type DOTLOCK which may be used later to actually do the lock.
* A cleanup routine gets installed to cleanup left over locks
* or other files used together with the lockmechanism.
* Althoug the function is called dotlock, this does not necessarily
* mean that real lockfiles are used - the function may decide to
* use fcntl locking. Calling the function with NULL only install
* the atexit handler and maybe used to assure that the cleanup
* is called after all other atexit handlers.
*
* Notes: This function creates a lock file in the same directory
* as file_to_lock with the name "file_to_lock.lock"
* A temporary file ".#lk.<hostname>.pid[.threadid] is used.
* This function does nothing for Windoze.
*/
DOTLOCK
create_dotlock( const char *file_to_lock )
{
static int initialized;
DOTLOCK h;
int fd = -1;
char pidstr[16];
#ifndef HAVE_DOSISH_SYSTEM
struct utsname utsbuf;
#endif
const char *nodename;
const char *dirpart;
int dirpartlen;
if( !initialized ) {
atexit( remove_lockfiles );
initialized = 1;
}
if( !file_to_lock )
return NULL;
h = jnlib_xcalloc( 1, sizeof *h );
#ifndef HAVE_DOSISH_SYSTEM
sprintf( pidstr, "%10d\n", (int)getpid() );
/* fixme: add the hostname to the second line (FQDN or IP addr?) */
/* create a temporary file */
if( uname( &utsbuf ) )
nodename = "unknown";
else
nodename = utsbuf.nodename;
if( !(dirpart = strrchr( file_to_lock, '/' )) ) {
dirpart = ".";
dirpartlen = 1;
}
else {
dirpartlen = dirpart - file_to_lock;
dirpart = file_to_lock;
}
#ifdef _REENTRANT
/* fixme: aquire mutex on all_lockfiles */
#endif
h->next = all_lockfiles;
all_lockfiles = h;
h->tname = jnlib_xmalloc( dirpartlen + 6+30+ strlen(nodename) + 11 );
sprintf( h->tname, "%.*s/.#lk%p.%s.%d",
dirpartlen, dirpart, h, nodename, (int)getpid() );
do {
errno = 0;
fd = open( h->tname, O_WRONLY|O_CREAT|O_EXCL,
S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR );
} while( fd == -1 && errno == EINTR );
if( fd == -1 ) {
all_lockfiles = h->next;
log_error( "failed to create temporary file `%s': %s\n",
h->tname, strerror(errno));
jnlib_free(h->tname);
jnlib_free(h);
return NULL;
}
if( write(fd, pidstr, 11 ) != 11 ) {
all_lockfiles = h->next;
#ifdef _REENTRANT
/* release mutex */
#endif
log_fatal( "error writing to `%s': %s\n", h->tname, strerror(errno) );
close(fd);
unlink(h->tname);
jnlib_free(h->tname);
jnlib_free(h);
return NULL;
}
if( close(fd) ) {
all_lockfiles = h->next;
#ifdef _REENTRANT
/* release mutex */
#endif
log_error( "error closing `%s': %s\n", h->tname, strerror(errno));
unlink(h->tname);
jnlib_free(h->tname);
jnlib_free(h);
return NULL;
}
#ifdef _REENTRANT
/* release mutex */
#endif
#endif /* !HAVE_DOSISH_SYSTEM */
h->lockname = jnlib_xmalloc( strlen(file_to_lock) + 6 );
strcpy(stpcpy(h->lockname, file_to_lock), ".lock");
return h;
}
static int
maybe_deadlock( DOTLOCK h )
{
DOTLOCK r;
for( r=all_lockfiles; r; r = r->next ) {
if( r != h && r->locked )
return 1;
}
return 0;
}
/****************
* Do a lock on H. A TIMEOUT of 0 returns immediately,
* -1 waits forever (hopefully not), other
* values are timeouts in milliseconds.
* Returns: 0 on success
*/
int
make_dotlock( DOTLOCK h, long timeout )
{
#ifdef HAVE_DOSISH_SYSTEM
return 0;
#else
int pid;
const char *maybe_dead="";
int backoff=0;
if( h->locked ) {
log_debug("oops, `%s' is already locked\n", h->lockname );
return 0;
}
for(;;) {
if( !link(h->tname, h->lockname) ) {
/* fixme: better use stat to check the link count */
h->locked = 1;
return 0; /* okay */
}
if( errno != EEXIST ) {
log_error( "lock not made: link() failed: %s\n", strerror(errno) );
return -1;
}
if( (pid = read_lockfile(h->lockname)) == -1 ) {
if( errno != ENOENT ) {
log_info("cannot read lockfile\n");
return -1;
}
log_info( "lockfile disappeared\n");
continue;
}
else if( pid == getpid() ) {
log_info( "Oops: lock already hold by us\n");
h->locked = 1;
return 0; /* okay */
}
else if( kill(pid, 0) && errno == ESRCH ) {
maybe_dead = " - probably dead";
#if 0 /* we should not do this without checking the permissions */
/* and the hostname */
log_info( "removing stale lockfile (created by %d)", pid );
#endif
}
if( timeout == -1 ) {
struct timeval tv;
log_info( "waiting for lock (hold by %d%s) %s...\n",
pid, maybe_dead, maybe_deadlock(h)? "(deadlock?) ":"");
/* can't use sleep, cause signals may be blocked */
tv.tv_sec = 1 + backoff;
tv.tv_usec = 0;
select(0, NULL, NULL, NULL, &tv);
if( backoff < 10 )
backoff++ ;
}
else
return -1;
}
/*not reached */
#endif /* !HAVE_DOSISH_SYSTEM */
}
/****************
* release a lock
* Returns: 0 := success
*/
int
release_dotlock( DOTLOCK h )
{
#ifdef HAVE_DOSISH_SYSTEM
return 0;
#else
int pid;
if( !h->locked ) {
log_debug("oops, `%s' is not locked\n", h->lockname );
return 0;
}
pid = read_lockfile( h->lockname );
if( pid == -1 ) {
log_error( "release_dotlock: lockfile error\n");
return -1;
}
if( pid != getpid() ) {
log_error( "release_dotlock: not our lock (pid=%d)\n", pid);
return -1;
}
if( unlink( h->lockname ) ) {
log_error( "release_dotlock: error removing lockfile `%s'",
h->lockname);
return -1;
}
/* fixme: check that the link count is now 1 */
h->locked = 0;
return 0;
#endif /* !HAVE_DOSISH_SYSTEM */
}
/****************
* Read the lock file and return the pid, returns -1 on error.
*/
static int
read_lockfile( const char *name )
{
#ifdef HAVE_DOSISH_SYSTEM
return 0;
#else
int fd, pid;
char pidstr[16];
if( (fd = open(name, O_RDONLY)) == -1 ) {
int e = errno;
log_debug("error opening lockfile `%s': %s\n", name, strerror(errno) );
errno = e;
return -1;
}
if( read(fd, pidstr, 10 ) != 10 ) { /* Read 10 digits w/o newline */
log_debug("error reading lockfile `%s'", name );
close(fd);
errno = 0;
return -1;
}
pidstr[10] = 0; /* terminate pid string */
close(fd);
pid = atoi(pidstr);
if( !pid || pid == -1 ) {
log_error("invalid pid %d in lockfile `%s'", pid, name );
errno = 0;
return -1;
}
return pid;
#endif
}
static void
remove_lockfiles()
{
#ifndef HAVE_DOSISH_SYSTEM
DOTLOCK h, h2;
h = all_lockfiles;
all_lockfiles = NULL;
while( h ) {
h2 = h->next;
if( h->locked )
unlink( h->lockname );
unlink(h->tname);
jnlib_free(h->tname);
jnlib_free(h->lockname);
jnlib_free(h);
h = h2;
}
#endif
}

View File

@ -0,0 +1,32 @@
/* dotlock.h
* Copyright (C) 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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 LIBJNLIB_DOTLOCK_H
#define LIBJNLIB_DOTLOCK_H
struct dotlock_handle;
typedef struct dotlock_handle *DOTLOCK;
DOTLOCK create_dotlock( const char *file_to_lock );
int make_dotlock( DOTLOCK h, long timeout );
int release_dotlock( DOTLOCK h );
#endif /*LIBJNLIB_DOTLOCK_H*/

View File

@ -0,0 +1,75 @@
/* libjnlib-config.h - local configuration of the jnlib functions
* Copyright (C) 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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
*/
/****************
* This header is to be included only by the files in this directory
* it should not be used by other modules.
*/
#ifndef LIBJNLIB_CONFIG_H
#define LIBJNLIB_CONFIG_H
#include "xmalloc.h"
#include "logging.h"
#ifdef USE_SIMPLE_GETTEXT
int set_gettext_file( const char *filename );
const char *gettext( const char *msgid );
#define _(a) gettext (a)
#define N_(a) (a)
#else
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif
#ifdef ENABLE_NLS
#include <libintl.h>
#define _(a) gettext (a)
#ifdef gettext_noop
#define N_(a) gettext_noop (a)
#else
#define N_(a) (a)
#endif
#else
#define _(a) (a)
#define N_(a) (a)
#endif
#endif /* !USE_SIMPLE_GETTEXT */
#define jnlib_xmalloc(a) xmalloc( (a) )
#define jnlib_xcalloc(a,b) xcalloc( (a), (b) )
#define jnlib_xrealloc(a,n) xrealloc( (a), (n) )
#define jnlib_xstrdup(a) xstrdup( (a) )
#define jnlib_free(a) free( (a) )
#define jnlib_log_debug log_debug
#define jnlib_log_info log_info
#define jnlib_log_error log_error
#define jnlib_log_fatal log_fatal
#define jnlib_log_bug log_bug
#endif /*LIBJNUTIL_CONFIG_H*/

View File

@ -0,0 +1,257 @@
/* logging.c - useful logging functions
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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
*/
/* This file should replace logger.c in the future - for now it is not
* used by GnuPG but by GPA.
* It is a quite simple implemenation but sufficient for most purposes.
*/
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#include <time.h>
#ifdef __MINGW32__
#include <io.h>
#endif
#include "libjnlib-config.h"
#include "logging.h"
enum my_log_levels {
MY_LOG_BEGIN, /* only print the timestamp if configured */
MY_LOG_CONT,
MY_LOG_INFO,
MY_LOG_WARN,
MY_LOG_ERROR,
MY_LOG_FATAL,
MY_LOG_BUG,
MY_LOG_DEBUG
};
static FILE *logstream;
static int use_time;
static int missing_lf;
static int errorcount;
#if 0
static void
write2stderr( const char *s )
{
write( 2, s, strlen(s) );
}
static void
do_die(int rc, const char *text )
{
write2stderr("\nFatal error: ");
write2stderr(text);
write2stderr("\n");
abort();
}
#endif
int
log_get_errorcount (int clear)
{
int n = errorcount;
if( clear )
errorcount = 0;
return n;
}
void
log_set_file( const char *name )
{
FILE *fp = (name && strcmp(name,"-"))? fopen(name, "a") : stderr;
if( !fp ) {
fprintf(stderr, "failed to open log file `%s': %s\n",
name, strerror(errno));
return;
}
setvbuf( fp, NULL, _IOLBF, 0 );
if( logstream && logstream != stderr )
fclose( logstream );
logstream = fp;
use_time = fp != stderr;
missing_lf = 0;
}
int
log_get_fd()
{
return fileno(logstream?logstream:stderr);
}
static void
do_logv( int level, const char *fmt, va_list arg_ptr )
{
if( !logstream )
logstream = stderr;
if( missing_lf && level != MY_LOG_CONT )
putc('\n', logstream );
missing_lf = 0;
if( use_time && level != MY_LOG_CONT ) {
/* Note this does not work for multiple line logging as we would
* need to print to a buffer first */
struct tm *tp;
time_t atime = time(NULL);
tp = localtime( &atime );
fprintf( logstream, "%04d-%02d-%02d %02d:%02d:%02d ",
1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
tp->tm_hour, tp->tm_min, tp->tm_sec );
}
switch ( level ) {
case MY_LOG_BEGIN: break;
case MY_LOG_CONT: break;
case MY_LOG_INFO: break;
case MY_LOG_WARN: break;
case MY_LOG_ERROR: break;
case MY_LOG_FATAL: fputs("Fatal: ",logstream ); break;
case MY_LOG_BUG: fputs("Ohhhh jeeee: ", logstream); break;
case MY_LOG_DEBUG: fputs("DBG: ", logstream ); break;
default: fprintf(logstream,"[Unknown log level %d]: ", level ); break;
}
if( fmt ) {
vfprintf(logstream,fmt,arg_ptr) ;
if( *fmt && fmt[strlen(fmt)-1] != '\n' )
missing_lf = 1;
}
if( level == MY_LOG_FATAL )
exit(2);
if( level == MY_LOG_BUG )
abort();
}
static void
do_log( int level, const char *fmt, ... )
{
va_list arg_ptr ;
va_start( arg_ptr, fmt ) ;
do_logv( level, fmt, arg_ptr );
va_end(arg_ptr);
}
void
log_info( const char *fmt, ... )
{
va_list arg_ptr ;
va_start( arg_ptr, fmt ) ;
do_logv( MY_LOG_INFO, fmt, arg_ptr );
va_end(arg_ptr);
}
void
log_error( const char *fmt, ... )
{
va_list arg_ptr ;
va_start( arg_ptr, fmt ) ;
do_logv( MY_LOG_ERROR, fmt, arg_ptr );
va_end(arg_ptr);
/* protect against counter overflow */
if( errorcount < 30000 )
errorcount++;
}
void
log_fatal( const char *fmt, ... )
{
va_list arg_ptr ;
va_start( arg_ptr, fmt ) ;
do_logv( MY_LOG_FATAL, fmt, arg_ptr );
va_end(arg_ptr);
abort(); /* never called, bugs it makes the compiler happy */
}
void
log_bug( const char *fmt, ... )
{
va_list arg_ptr ;
va_start( arg_ptr, fmt ) ;
do_logv( MY_LOG_BUG, fmt, arg_ptr );
va_end(arg_ptr);
abort(); /* never called, but it makes the compiler happy */
}
void
log_debug( const char *fmt, ... )
{
va_list arg_ptr ;
va_start( arg_ptr, fmt ) ;
do_logv( MY_LOG_DEBUG, fmt, arg_ptr );
va_end(arg_ptr);
}
void
log_printf( const char *fmt, ... )
{
va_list arg_ptr ;
if( !fmt ) {
do_logv( MY_LOG_BEGIN, NULL, NULL );
}
else {
va_start( arg_ptr, fmt ) ;
do_logv( MY_LOG_CONT, fmt, arg_ptr );
va_end(arg_ptr);
}
}
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
void
bug_at( const char *file, int line, const char *func )
{
do_log( MY_LOG_BUG,
("... this is a bug (%s:%d:%s)\n"), file, line, func );
abort(); /* never called, but it makes the compiler happy */
}
#else
void
bug_at( const char *file, int line )
{
do_log( MY_LOG_BUG,
_("you found a bug ... (%s:%d)\n"), file, line);
abort(); /* never called, but it makes the compiler happy */
}
#endif

View File

@ -0,0 +1,47 @@
/* logging.h
* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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 LIBJNLIB_LOGGING_H
#define LIBJNLIB_LOGGING_H
#include <stdio.h>
#include "mischelp.h"
int log_get_errorcount (int clear);
void log_set_file( const char *name );
int log_get_fd(void);
#ifdef JNLIB_GCC_M_FUNCTION
void bug_at( const char *file, int line, const char *func ) JNLIB_GCC_A_NR;
# define BUG() bug_at( __FILE__ , __LINE__, __FUNCTION__ )
#else
void bug_at( const char *file, int line );
# define BUG() bug_at( __FILE__ , __LINE__ )
#endif
void log_bug( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2);
void log_fatal( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2);
void log_error( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2);
void log_info( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2);
void log_debug( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2);
void log_printf( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2);
#endif /*LIBJNLIB_LOGGING_H*/

View File

@ -0,0 +1,43 @@
/* mischelp.h
* Copyright (C) 1999 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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 LIBJNLIB_MISCHELP_H
#define LIBJNLIB_MISCHHELP_H
#define DIM(v) (sizeof(v)/sizeof((v)[0]))
#define DIMof(type,member) DIM(((type *)0)->member)
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
# define JNLIB_GCC_M_FUNCTION 1
# define JNLIB_GCC_A_NR __attribute__ ((noreturn))
# define JNLIB_GCC_A_PRINTF( f, a ) __attribute__ ((format (printf,f,a)))
# define JNLIB_GCC_A_NR_PRINTF( f, a ) \
__attribute__ ((noreturn, format (printf,f,a)))
#else
# define JNLIB_GCC_A_NR
# define JNLIB_GCC_A_PRINTF( f, a )
# define JNLIB_GCC_A_NR_PRINTF( f, a )
#endif
#endif /*LIBJNLIB_MISCHELP_H*/

View File

@ -0,0 +1,323 @@
/* stringhelp.c - standard string helper functions
* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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 <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include "libjnlib-config.h"
#include "stringhelp.h"
/****************
* look for the substring SUB in buffer and return a pointer to that
* substring in BUF or NULL if not found.
* Comparison is case-insensitive.
*/
const char *
memistr( const char *buf, size_t buflen, const char *sub )
{
const byte *t, *s ;
size_t n;
for( t=buf, n=buflen, s=sub ; n ; t++, n-- )
if( toupper(*t) == toupper(*s) ) {
for( buf=t++, buflen = n--, s++;
n && toupper(*t) == toupper(*s); t++, s++, n-- )
;
if( !*s )
return buf;
t = buf; n = buflen; s = sub ;
}
return NULL ;
}
/****************
* Wie strncpy(), aber es werden maximal n-1 zeichen kopiert und ein
* '\0' angehängt. Ist n = 0, so geschieht nichts, ist Destination
* gleich NULL, so wird via jnlib_xmalloc Speicher besorgt, ist dann nicht
* genügend Speicher vorhanden, so bricht die funktion ab.
*/
char *
mem2str( char *dest , const void *src , size_t n )
{
char *d;
const char *s;
if( n ) {
if( !dest )
dest = jnlib_xmalloc( n ) ;
d = dest;
s = src ;
for(n--; n && *s; n-- )
*d++ = *s++;
*d = '\0' ;
}
return dest ;
}
/****************
* remove leading and trailing white spaces
*/
char *
trim_spaces( char *str )
{
char *string, *p, *mark;
string = str;
/* find first non space character */
for( p=string; *p && isspace( *(byte*)p ) ; p++ )
;
/* move characters */
for( (mark = NULL); (*string = *p); string++, p++ )
if( isspace( *(byte*)p ) ) {
if( !mark )
mark = string ;
}
else
mark = NULL ;
if( mark )
*mark = '\0' ; /* remove trailing spaces */
return str ;
}
/****************
* remove trailing white spaces
*/
char *
trim_trailing_spaces( char *string )
{
char *p, *mark;
for( mark = NULL, p = string; *p; p++ ) {
if( isspace( *(byte*)p ) ) {
if( !mark )
mark = p;
}
else
mark = NULL;
}
if( mark )
*mark = '\0' ;
return string ;
}
unsigned
trim_trailing_chars( byte *line, unsigned len, const char *trimchars )
{
byte *p, *mark;
unsigned n;
for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
if( strchr(trimchars, *p ) ) {
if( !mark )
mark = p;
}
else
mark = NULL;
}
if( mark ) {
*mark = 0;
return mark - line;
}
return len;
}
/****************
* remove trailing white spaces and return the length of the buffer
*/
unsigned
trim_trailing_ws( byte *line, unsigned len )
{
return trim_trailing_chars( line, len, " \t\r\n" );
}
/***************
* Extract from a given path the filename component.
*
*/
char *
make_basename(const char *filepath)
{
char *p;
if ( !(p=strrchr(filepath, '/')) )
#ifdef HAVE_DRIVE_LETTERS
if ( !(p=strrchr(filepath, '\\')) )
if ( !(p=strrchr(filepath, ':')) )
#endif
{
return jnlib_xstrdup(filepath);
}
return jnlib_xstrdup(p+1);
}
/***************
* Extract from a given filename the path prepended to it.
* If their isn't a path prepended to the filename, a dot
* is returned ('.').
*
*/
char *
make_dirname(const char *filepath)
{
char *dirname;
int dirname_length;
char *p;
if ( !(p=strrchr(filepath, '/')) )
#ifdef HAVE_DRIVE_LETTERS
if ( !(p=strrchr(filepath, '\\')) )
if ( !(p=strrchr(filepath, ':')) )
#endif
{
return jnlib_xstrdup(".");
}
dirname_length = p-filepath;
dirname = jnlib_xmalloc(dirname_length+1);
strncpy(dirname, filepath, dirname_length);
dirname[dirname_length] = 0;
return dirname;
}
/****************
* Construct a filename from the NULL terminated list of parts.
* Tilde expansion is done here.
*/
char *
make_filename( const char *first_part, ... )
{
va_list arg_ptr ;
size_t n;
const char *s;
char *name, *home, *p;
va_start( arg_ptr, first_part ) ;
n = strlen(first_part)+1;
while( (s=va_arg(arg_ptr, const char *)) )
n += strlen(s) + 1;
va_end(arg_ptr);
home = NULL;
if( *first_part == '~' && first_part[1] == '/'
&& (home = getenv("HOME")) && *home )
n += strlen(home);
name = jnlib_xmalloc(n);
p = home ? stpcpy(stpcpy(name,home), first_part+1)
: stpcpy(name, first_part);
va_start( arg_ptr, first_part ) ;
while( (s=va_arg(arg_ptr, const char *)) )
p = stpcpy(stpcpy(p,"/"), s);
va_end(arg_ptr);
return name;
}
int
compare_filenames( const char *a, const char *b )
{
/* ? check whether this is an absolute filename and
* resolve symlinks?
*/
#ifdef HAVE_DRIVE_LETTERS
return stricmp(a,b);
#else
return strcmp(a,b);
#endif
}
/*********************************************
********** missing string functions *********
*********************************************/
#ifndef HAVE_STPCPY
char *
stpcpy(char *a,const char *b)
{
while( *b )
*a++ = *b++;
*a = 0;
return (char*)a;
}
#endif
#ifndef HAVE_STRLWR
char *
strlwr(char *s)
{
char *p;
for(p=s; *p; p++ )
*p = tolower(*p);
return s;
}
#endif
#ifndef HAVE_STRCASECMP
int
strcasecmp( const char *a, const char *b )
{
for( ; *a && *b; a++, b++ ) {
if( *a != *b && toupper(*a) != toupper(*b) )
break;
}
return *(const byte*)a - *(const byte*)b;
}
#endif
/****************
* mingw32/cpd has a memicmp()
*/
#ifndef HAVE_MEMICMP
int
memicmp( const char *a, const char *b, size_t n )
{
for( ; n; n--, a++, b++ )
if( *a != *b && toupper(*(const byte*)a) != toupper(*(const byte*)b) )
return *(const byte *)a - *(const byte*)b;
return 0;
}
#endif

View File

@ -0,0 +1,65 @@
/* stringhelp.h
* Copyright (C) 1998,1999 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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 LIBJNLIB_STRINGHELP_H
#define LIBJNLIB_STRINGHELP_H
#include "types.h"
const char *memistr( const char *buf, size_t buflen, const char *sub );
char *mem2str( char *, const void *, size_t);
char *trim_spaces( char *string );
char *trim_trailing_spaces( char *string );
unsigned int trim_trailing_chars( unsigned char *line, unsigned len,
const char *trimchars);
unsigned int trim_trailing_ws( unsigned char *line, unsigned len );
char *make_basename(const char *filepath);
char *make_dirname(const char *filepath);
char *make_filename( const char *first_part, ... );
int compare_filenames( const char *a, const char *b );
#ifndef HAVE_MEMICMP
int memicmp( const char *a, const char *b, size_t n );
#endif
#ifndef HAVE_STPCPY
char *stpcpy(char *a,const char *b);
#endif
#ifndef HAVE_STRLWR
char *strlwr(char *a);
#endif
#ifndef HAVE_STRTOUL
#define strtoul(a,b,c) ((unsigned long)strtol((a),(b),(c)))
#endif
#ifndef HAVE_MEMMOVE
#define memmove(d, s, n) bcopy((s), (d), (n))
#endif
#ifndef HAVE_STRICMP
#define stricmp(a,b) strcasecmp( (a), (b) )
#endif
#ifndef STR
#define STR(v) #v
#endif
#define STR2(v) STR(v)
#endif /*LIBJNLIB_STRINGHELP_H*/

View File

@ -0,0 +1,101 @@
/* types.h
* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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 LIBJNLIB_TYPES_H
#define LIBJNLIB_TYPES_H
/* The AC_CHECK_SIZEOF() in configure fails for some machines.
* we provide some fallback values here */
#if !SIZEOF_UNSIGNED_SHORT
#undef SIZEOF_UNSIGNED_SHORT
#define SIZEOF_UNSIGNED_SHORT 2
#endif
#if !SIZEOF_UNSIGNED_INT
#undef SIZEOF_UNSIGNED_INT
#define SIZEOF_UNSIGNED_INT 4
#endif
#if !SIZEOF_UNSIGNED_LONG
#undef SIZEOF_UNSIGNED_LONG
#define SIZEOF_UNSIGNED_LONG 4
#endif
#include <sys/types.h>
#ifndef HAVE_BYTE_TYPEDEF
#undef byte /* maybe there is a macro with this name */
typedef unsigned char byte;
#define HAVE_BYTE_TYPEDEF
#endif
#ifndef HAVE_USHORT_TYPEDEF
#undef ushort /* maybe there is a macro with this name */
typedef unsigned short ushort;
#define HAVE_USHORT_TYPEDEF
#endif
#ifndef HAVE_ULONG_TYPEDEF
#undef ulong /* maybe there is a macro with this name */
typedef unsigned long ulong;
#define HAVE_ULONG_TYPEDEF
#endif
#ifndef HAVE_U16_TYPEDEF
#undef u16 /* maybe there is a macro with this name */
#if SIZEOF_UNSIGNED_INT == 2
typedef unsigned int u16;
#elif SIZEOF_UNSIGNED_SHORT == 2
typedef unsigned short u16;
#else
#error no typedef for u16
#endif
#define HAVE_U16_TYPEDEF
#endif
#ifndef HAVE_U32_TYPEDEF
#undef u32 /* maybe there is a macro with this name */
#if SIZEOF_UNSIGNED_INT == 4
typedef unsigned int u32;
#elif SIZEOF_UNSIGNED_LONG == 4
typedef unsigned long u32;
#else
#error no typedef for u32
#endif
#define HAVE_U32_TYPEDEF
#endif
#ifndef HAVE_U64_TYPEDEF
#undef u64 /* maybe there is a macro with this name */
#if SIZEOF_UNSIGNED_INT == 8
typedef unsigned int u64;
#define HAVE_U64_TYPEDEF
#elif SIZEOF_UNSIGNED_LONG == 8
typedef unsigned long u64;
#define HAVE_U64_TYPEDEF
#elif __GNUC__ >= 2 || defined(__SUNPRO_C)
typedef unsigned long long u64;
#define HAVE_U64_TYPEDEF
#endif
#endif
#endif /*LIBJNLIB_TYPES_H*/

View File

@ -0,0 +1,88 @@
/* xmalloc.c - standard malloc wrappers
* Copyright (C) 1999 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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 <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "libjnlib-config.h"
#include "xmalloc.h"
static void
out_of_core(void)
{
fputs("\nfatal: out of memory\n", stderr );
exit(2);
}
void *
xmalloc( size_t n )
{
void *p = malloc( n );
if( !p )
out_of_core();
return p;
}
void *
xrealloc( void *a, size_t n )
{
void *p = realloc( a, n );
if( !p )
out_of_core();
return p;
}
void *
xcalloc( size_t n, size_t m )
{
void *p = calloc( n, m );
if( !p )
out_of_core();
return p;
}
char *
xstrdup( const char *string )
{
void *p = xmalloc( strlen(string)+1 );
strcpy( p, string );
return p;
}
char *
xstrcat2( const char *a, const char *b )
{
size_t n1;
char *p;
if( !b )
return xstrdup( a );
n1 = strlen(a);
p = xmalloc( n1 + strlen(b) + 1 );
memcpy(p, a, n1 );
strcpy(p+n1, b );
return p;
}

View File

@ -0,0 +1,31 @@
/* xmalloc.h
* Copyright (C) 1999 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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 LIBJNLIB_XMALLOC_H
#define LIBJNLIB_XMALLOC_H
void *xmalloc( size_t n );
void *xrealloc( void *a, size_t n );
void *xcalloc( size_t n, size_t m );
char *xstrdup( const char *string );
char *xstrcat2( const char *a, const char *b );
#endif /*LIBJNLIB_XMALLOC_H*/

View File

@ -0,0 +1,38 @@
## Process this file with automake to create Makefile.in
TESTS_ENVIRONMENT = GNUPGHOME=.
TESTS = t-encrypt t-sign t-decrypt t-verify t-keylist t-export t-import
EXTRA_DIST = mkdemodirs pubdemo.asc secdemo.asc cipher-1.asc geheim.txt \
pubkey-1.asc seckey-1.asc
INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl
INCLUDES =
LDADD = ../gpgme/libgpgme.la
# We don't run t-genkey in the test suite, because it taes too long
noinst_PROGRAMS = $(TESTS) t-genkey
distclean-local:
$(srcdir)/mkdemodirs --clean
all-local: ./pubring.gpg ./secring.gpg
./pubring.gpg: $(srcdir)/pubdemo.asc
-gpg --homedir . --import $(srcdir)/pubdemo.asc
./secring.gpg: ./Alpha/Secret.gpg
-gpg --homedir . --allow-secret-key-import --import Alpha/Secret.gpg Zulu/Secret.gpg
./Alpha/Secret.gpg: secdemo.asc
srcdir=$(srcdir) $(srcdir)/mkdemodirs

View File

@ -0,0 +1,15 @@
-----BEGIN PGP MESSAGE-----
Version: GnuPG v1.0.4-2 (GNU/Linux)
Comment: For info see http://www.gnupg.org
hQEOA2rm1+5GqHH4EAP/Tcqiuhvrjj+RFBKnWn2A7f1ztV17U2EngYFy8TbZYGNp
JoMNdpA7GNZs7iqc/x1epaZDKfaQwWEtARZmK/4nlhB48N+oZeKTm7PXIkRPqrCZ
3fxJjCJaU0yrNGuO345DOr0QwDImVhubVEkfgs8yXK2Szx2G8X3LmiaILHAqA2oD
/1ZqjY8k+ovrLL/qe8un/NTwzSjKIPVGR6mhLFXmj8fnp2kSsbo+Bhh4MczTRR6l
SA32z25vcakKu2qn5Wa4yDcx9NcMt8RHXzmfMDLj6UFq99QqKeLK2ywcIpY9p/GL
fQyaf7r3HTVugBSaoOzegLJ+L7MfWohrStkMeLnJQnro0nYBjADVcUQuSS4N3lst
Df3XrxxA/iJvxt4F9K27u4tp5U1HDg1CIxVrkMs92LBri3S6ZtfjdoqQ7QghFwGP
Kw1lKiWayM6NH9rcCKSgk4kl4P/2l3f78XeFgiywN7UGeSoH3BLMSv9gSxl5KrAz
d2imhTMrfEvZ
=y4ng
-----END PGP MESSAGE-----

View File

@ -0,0 +1,2 @@
Wenn Sie dies lesen können, ist es wohl nicht
geheim genug.

View File

@ -0,0 +1,44 @@
#!/bin/sh
set -e
GPG="gpg --batch --quiet --no-secmem-warning"
NAMES='Alpha Bravo Charlie Delta Echo Foxtrot Golf Hotel India
Juliet Kilo Lima Mike November Oscar Papa Quebec Romeo
Sierra Tango Uniform Victor Whisky XRay Yankee Zulu'
if [ "$1" = "--clean" ]; then
(for i in $NAMES; do
[ -d $i ] && rm -r $i
done) || true
exit 0
fi
[ -z "$srcdir" ] && srcdir="../tests"
$GPG --dearmor -o secdemo.gpg --yes $srcdir/secdemo.asc
$GPG --dearmor -o pubdemo.gpg --yes $srcdir/pubdemo.asc
[ -f ./tdb.tmp ] && rm ./tdb.tmp
GPGDEMO="$GPG --homedir . --trustdb-name ./tdb.tmp --no-default-keyring
--keyring pubdemo.gpg --secret-keyring secdemo.gpg"
echo -n "Creating:"
for name in $NAMES; do
echo -n " $name"
[ -d $name ] && rm -r $name
mkdir $name
$GPGDEMO --export-secret-key -o - $name > $name/Secret.gpg
$GPG --homedir $name --allow-secret-key-import --import $name/Secret.gpg
$GPGDEMO --export -o - $name > $name/Public.gpg
$GPG --homedir $name --import $name/Public.gpg
[ -f $name/pubring.gpg~ ] && rm $name/pubring.gpg~
done
echo "."
[ -f ./tdb.tmp ] && rm ./tdb.tmp
rm pubdemo.gpg secdemo.gpg

View File

@ -0,0 +1,26 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.0.4b (GNU/Linux)
Comment: For info see http://www.gnupg.org
mQGiBDo41NoRBADSfQazKGYf8nokq6zUKH/6INtV6MypSzSGmX2XErnARkIIPPYj
cQRQ8zCbGV7ZU2ezVbzhFLUSJveE8PZUzzCrLp1O2NSyBTRcR5HVSXW95nJfY8eV
pOvZRAKul0BVLh81kYTsrfzaaCjh9VWNP26LoeN2r+PjZyktXe7gM3C4SwCgoTxK
WUVi9HoT2HCLY7p7oig5hEcEALdCJal0UYomX3nJapIVLVZg3vkidr1RICYMb2vz
58i17h8sxEtobD1vdIKNejulntaRAXs4n0tDYD9z7pRlwG1CLz1R9WxYzeOOqUDr
fnVXdmU8L/oVWABat8v1V7QQhjMMf+41fuzVwDMMGqjVPLhu4X6wp3A8uyM3YDnQ
VMN1A/4n2G5gHoOvjqxn8Ch5tBAdMGfO8gH4RjQOwzm2R1wPQss/yzUN1+tlMZGX
K2dQ2FCWC/hDUSNaEQRlI15wxxBNZ2RQwlzE2A8v113DpvyzOtv0QO95gJ1teCXC
7j/BN9asgHaBBc39JLO/TcpuI7Hf8PQ5VcP2F0UE3lczGhXbLLQ/Sm9lIFJhbmRv
bSBIYWNrZXIgKHRlc3Qga2V5IHdpdGggcGFzc3BocmFzZSAieCIpIDxqb2VAc2V0
cS5vcmc+iFcEExECABcFAjo41NoFCwcKAwQDFQMCAxYCAQIXgAAKCRCvgiRPnNn9
VXm9AJ0auCQID9AQ4ic48A05OI4tcvs24ACgjsLML1iIYUtrSP1o6QSIYdnTUZy5
AQ0EOjjU3RAEAJ50lvtCGbnQlI97VX6tJkosdPmdzeXaTWfv//A2wmSANbYnuych
GMa1LN43Ew+H6FXMWJ3MB/exs6UBFCgGsw88qmcla2bosQN/aVLA7fqXT9ujqoNG
aIVEmgdbK1MkSPFXBFyVW3hteod83D0UqFlltwp4A3ageCYFVJTp50d3AAMFA/44
YCQQbg9x9JvzHX3VH7CRX+raEDkDL3Pbz0PHas7bwI7gzZ+GFyNKaCvrHQOyuR8R
IKIbjtQYnXr1675ConCTceIXhysY32sTn5V6UFUW2t0xaRfas8sZBbLDyIJkpt4f
yD+6OaRoui9KZqXMNwt7i/XFIto/sWd/OK3SIgZkAYhGBBgRAgAGBQI6ONTdAAoJ
EK+CJE+c2f1VVJoAn36uPWUhCdGXbSLxGibYfBt7et71AJ9JgWeRlTDTIoXYN8J+
qsPN0YCxtg==
=4+Yp
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -0,0 +1,30 @@
-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: GnuPG v1.0.4b (GNU/Linux)
Comment: For info see http://www.gnupg.org
lQHPBDo41NoRBADSfQazKGYf8nokq6zUKH/6INtV6MypSzSGmX2XErnARkIIPPYj
cQRQ8zCbGV7ZU2ezVbzhFLUSJveE8PZUzzCrLp1O2NSyBTRcR5HVSXW95nJfY8eV
pOvZRAKul0BVLh81kYTsrfzaaCjh9VWNP26LoeN2r+PjZyktXe7gM3C4SwCgoTxK
WUVi9HoT2HCLY7p7oig5hEcEALdCJal0UYomX3nJapIVLVZg3vkidr1RICYMb2vz
58i17h8sxEtobD1vdIKNejulntaRAXs4n0tDYD9z7pRlwG1CLz1R9WxYzeOOqUDr
fnVXdmU8L/oVWABat8v1V7QQhjMMf+41fuzVwDMMGqjVPLhu4X6wp3A8uyM3YDnQ
VMN1A/4n2G5gHoOvjqxn8Ch5tBAdMGfO8gH4RjQOwzm2R1wPQss/yzUN1+tlMZGX
K2dQ2FCWC/hDUSNaEQRlI15wxxBNZ2RQwlzE2A8v113DpvyzOtv0QO95gJ1teCXC
7j/BN9asgHaBBc39JLO/TcpuI7Hf8PQ5VcP2F0UE3lczGhXbLP8DAwKVpe92I5n5
JGBjXsTTnVLoJ1hrWTdbLvdbn882m5pHYeqFlvkqKYXJTf0mIzpEU0FfZmFjdG9y
OgAAr0JzPBwQoEmNI3YSC1MwimZ77bpvVKP9JiM6RFNBX2ZhY3RvcjoAAK9/fVBz
g73cYbgeNWbz2uITUwNd9KEN/SYjOkRTQV9mYWN0b3I6AACvWjjITYZwah6NiH6C
YgX52m55Dy5PX7Q/Sm9lIFJhbmRvbSBIYWNrZXIgKHRlc3Qga2V5IHdpdGggcGFz
c3BocmFzZSAieCIpIDxqb2VAc2V0cS5vcmc+iFcEExECABcFAjo41NoFCwcKAwQD
FQMCAxYCAQIXgAAKCRCvgiRPnNn9VXm9AKCFQ/t23GQnQEfnnAnvbRNfRo4zIQCb
BHwILsDBASB1rQzW68UA/XHze0WdAUYEOjjU3RAEAJ50lvtCGbnQlI97VX6tJkos
dPmdzeXaTWfv//A2wmSANbYnuychGMa1LN43Ew+H6FXMWJ3MB/exs6UBFCgGsw88
qmcla2bosQN/aVLA7fqXT9ujqoNGaIVEmgdbK1MkSPFXBFyVW3hteod83D0UqFll
twp4A3ageCYFVJTp50d3AAMFA/44YCQQbg9x9JvzHX3VH7CRX+raEDkDL3Pbz0PH
as7bwI7gzZ+GFyNKaCvrHQOyuR8RIKIbjtQYnXr1675ConCTceIXhysY32sTn5V6
UFUW2t0xaRfas8sZBbLDyIJkpt4fyD+6OaRoui9KZqXMNwt7i/XFIto/sWd/OK3S
IgZkAf8DAwKVpe92I5n5JGAHRuEKSSvGU+0my6zTf17bLWPpFPnICNJdaMfyx24Y
RZZa+nDpYrRznJ89vohGBBgRAgAGBQI6ONTeAAoJEK+CJE+c2f1V7iIAn0WsYyUV
Huz4ZZ/WxxN57Ku2Eqs9AJ9Klz9imzvZoUjuE9/Ihr0y56tVng==
=lKvj
-----END PGP PRIVATE KEY BLOCK-----

View File

@ -0,0 +1,138 @@
/* t-encrypt.c - regression test
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include "../gpgme/gpgme.h"
struct passphrase_cb_info_s {
GpgmeCtx c;
int did_it;
};
#define fail_if_err(a) do { if(a) { int my_errno = errno; \
fprintf (stderr, "%s:%d: GpgmeError %s\n", \
__FILE__, __LINE__, gpgme_strerror(a)); \
if ((a) == GPGME_File_Error) \
fprintf (stderr, "\terrno=`%s'\n", strerror (my_errno)); \
exit (1); } \
} while(0)
static void
print_data ( GpgmeData dh )
{
char buf[100];
size_t nread;
GpgmeError err;
err = gpgme_data_rewind ( dh );
fail_if_err (err);
while ( !(err = gpgme_data_read ( dh, buf, 100, &nread )) ) {
fwrite ( buf, nread, 1, stdout );
}
if (err != GPGME_EOF)
fail_if_err (err);
}
static const char *
passphrase_cb ( void *opaque, const char *desc, void *r_hd )
{
const char *pass;
if ( !desc ) {
/* cleanup by looking at *r_hd */
return NULL;
}
pass = "abc";
fprintf (stderr, "%% requesting passphrase for `%s': ", desc );
fprintf (stderr, "sending `%s'\n", pass );
return pass;
}
static char *
mk_fname ( const char *fname )
{
const char *srcdir = getenv ("srcdir");
char *buf;
if (!srcdir)
srcdir = ".";
buf = malloc (strlen(srcdir) + strlen(fname) + 2 );
if (!buf )
exit (8);
strcpy (buf, srcdir);
strcat (buf, "/");
strcat (buf, fname );
return buf;
}
int
main (int argc, char **argv )
{
GpgmeCtx ctx;
GpgmeError err;
GpgmeData in, out, pwdata = NULL;
struct passphrase_cb_info_s info;
const char *cipher_1_asc = mk_fname ("cipher-1.asc");
do {
err = gpgme_new (&ctx);
fail_if_err (err);
if ( !getenv("GPG_AGENT_INFO") ) {
memset ( &info, 0, sizeof info );
info.c = ctx;
gpgme_set_passphrase_cb ( ctx, passphrase_cb, &info );
}
err = gpgme_data_new_from_file ( &in, cipher_1_asc, 1 );
fail_if_err (err);
err = gpgme_data_new ( &out );
fail_if_err (err);
err = gpgme_op_decrypt (ctx, in, out );
fail_if_err (err);
fflush (NULL);
fputs ("Begin Result:\n", stdout );
print_data (out);
fputs ("End Result.\n", stdout );
gpgme_data_release (in);
gpgme_data_release (out);
gpgme_data_release (pwdata);
gpgme_release (ctx);
} while ( argc > 1 && !strcmp( argv[1], "--loop" ) );
return 0;
}

View File

@ -0,0 +1,95 @@
/* t-encrypt.c - regression test
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "../gpgme/gpgme.h"
#define fail_if_err(a) do { if(a) { \
fprintf (stderr, "%s:%d: GpgmeError %s\n", \
__FILE__, __LINE__, gpgme_strerror(a)); \
exit (1); } \
} while(0)
static void
print_data ( GpgmeData dh )
{
char buf[100];
size_t nread;
GpgmeError err;
err = gpgme_data_rewind ( dh );
fail_if_err (err);
while ( !(err = gpgme_data_read ( dh, buf, 100, &nread )) ) {
fwrite ( buf, nread, 1, stdout );
}
if (err != GPGME_EOF)
fail_if_err (err);
}
int
main (int argc, char **argv )
{
GpgmeCtx ctx;
GpgmeError err;
GpgmeData in, out;
GpgmeRecipients rset;
do {
err = gpgme_new (&ctx);
fail_if_err (err);
err = gpgme_data_new_from_mem ( &in, "Hallo Leute\n", 12, 0 );
fail_if_err (err);
err = gpgme_data_new ( &out );
fail_if_err (err);
err = gpgme_recipients_new (&rset);
fail_if_err (err);
err = gpgme_recipients_add_name (rset, "Bob");
fail_if_err (err);
err = gpgme_recipients_add_name (rset, "Alpha");
fail_if_err (err);
err = gpgme_op_encrypt (ctx, rset, in, out );
fail_if_err (err);
fflush (NULL);
fputs ("Begin Result:\n", stdout );
print_data (out);
fputs ("End Result.\n", stdout );
gpgme_recipients_release (rset);
gpgme_data_release (in);
gpgme_data_release (out);
gpgme_release (ctx);
} while ( argc > 1 && !strcmp( argv[1], "--loop" ) );
return 0;
}

View File

@ -0,0 +1,91 @@
/* t-export.c - regression test
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "../gpgme/gpgme.h"
#define fail_if_err(a) do { if(a) { \
fprintf (stderr, "%s:%d: GpgmeError %s\n", \
__FILE__, __LINE__, gpgme_strerror(a)); \
exit (1); } \
} while(0)
static void
print_data ( GpgmeData dh )
{
char buf[100];
size_t nread;
GpgmeError err;
err = gpgme_data_rewind ( dh );
fail_if_err (err);
while ( !(err = gpgme_data_read ( dh, buf, 100, &nread )) ) {
fwrite ( buf, nread, 1, stdout );
}
if (err != GPGME_EOF)
fail_if_err (err);
}
int
main (int argc, char **argv )
{
GpgmeCtx ctx;
GpgmeError err;
GpgmeData out;
GpgmeRecipients rset;
do {
err = gpgme_new (&ctx);
fail_if_err (err);
err = gpgme_data_new ( &out );
fail_if_err (err);
err = gpgme_recipients_new (&rset);
fail_if_err (err);
err = gpgme_recipients_add_name (rset, "Bob");
fail_if_err (err);
err = gpgme_recipients_add_name (rset, "Alpha");
fail_if_err (err);
gpgme_set_armor (ctx, 1 );
err = gpgme_op_export (ctx, rset, out );
fail_if_err (err);
fflush (NULL);
fputs ("Begin Result:\n", stdout );
print_data (out);
fputs ("End Result.\n", stdout );
gpgme_recipients_release (rset);
gpgme_data_release (out);
gpgme_release (ctx);
} while ( argc > 1 && !strcmp( argv[1], "--loop" ) );
return 0;
}

View File

@ -0,0 +1,83 @@
/* t-genkey.c - regression test
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "../gpgme/gpgme.h"
#define fail_if_err(a) do { if(a) { \
fprintf (stderr, "%s:%d: GpgmeError %s\n", \
__FILE__, __LINE__, gpgme_strerror(a)); \
exit (1); } \
} while(0)
static void
progress ( void *self, const char *what, int type, int current, int total)
{
fprintf (stderr, "progress `%s' %d %d %d\n", what, type, current, total);
}
int
main (int argc, char **argv )
{
GpgmeCtx ctx;
GpgmeError err;
const char *format;
char *parms;
int count = 0;
do {
err = gpgme_new (&ctx);
fail_if_err (err);
gpgme_set_progress_cb (ctx, progress, NULL);
format = "<GnupgKeyParms format=\"internal\">\n"
"Key-Type: DSA\n"
"Key-Length: 1024\n"
"Subkey-Type: ELG-E\n"
"Subkey-Length: 1024\n"
"Name-Real: Joe Tester\n"
"Name-Comment: (pp=abc,try=%d)\n"
"Name-Email: joe@foo.bar\n"
"Expire-Date: 0\n"
"Passphrase: abc\n"
"</GnupgKeyParms>\n";
parms = malloc ( strlen (format) + 1 + 20 );
if (!parms)
exit (8);
sprintf (parms, format, ++count );
err = gpgme_op_genkey (ctx, parms, NULL, NULL );
fail_if_err (err);
free (parms);
gpgme_release (ctx);
} while ( argc > 1 && !strcmp( argv[1], "--loop" ) );
return 0;
}

View File

@ -0,0 +1,90 @@
/* t-import.c - regression test
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include "../gpgme/gpgme.h"
#define fail_if_err(a) do { if(a) { int my_errno = errno; \
fprintf (stderr, "%s:%d: GpgmeError %s\n", \
__FILE__, __LINE__, gpgme_strerror(a)); \
if ((a) == GPGME_File_Error) \
fprintf (stderr, "\terrno=`%s'\n", strerror (my_errno)); \
exit (1); } \
} while(0)
static char *
mk_fname ( const char *fname )
{
const char *srcdir = getenv ("srcdir");
char *buf;
if (!srcdir)
srcdir = ".";
buf = malloc (strlen(srcdir) + strlen(fname) + 2 );
if (!buf )
exit (8);
strcpy (buf, srcdir);
strcat (buf, "/");
strcat (buf, fname );
return buf;
}
int
main (int argc, char **argv )
{
GpgmeCtx ctx;
GpgmeError err;
GpgmeData in;
const char *pubkey_1_asc = mk_fname ("pubkey-1.asc");
const char *seckey_1_asc = mk_fname ("seckey-1.asc");
do {
err = gpgme_new (&ctx);
fail_if_err (err);
err = gpgme_data_new_from_file ( &in, pubkey_1_asc, 1 );
fail_if_err (err);
err = gpgme_op_import (ctx, in );
fail_if_err (err);
gpgme_data_release (in);
err = gpgme_data_new_from_file ( &in, seckey_1_asc, 1 );
fail_if_err (err);
err = gpgme_op_import (ctx, in );
fail_if_err (err);
gpgme_data_release (in);
gpgme_release (ctx);
} while ( argc > 1 && !strcmp( argv[1], "--loop" ) );
return 0;
}

View File

@ -0,0 +1,87 @@
/* t-keylist.c - regression test
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "../gpgme/gpgme.h"
#define fail_if_err(a) do { if(a) { \
fprintf (stderr, "%s:%d: GpgmeError %s\n", \
__FILE__, __LINE__, gpgme_strerror(a)); \
exit (1); } \
} while(0)
static void
doit ( GpgmeCtx ctx, const char *pattern )
{
GpgmeError err;
GpgmeKey key;
err = gpgme_op_keylist_start (ctx, pattern, 0 );
fail_if_err (err);
while ( !(err = gpgme_op_keylist_next ( ctx, &key )) ) {
char *p;
printf ("<!-- Begin key object (%p) -->\n", key );
p = gpgme_key_get_as_xml ( key );
if ( p )
fputs ( p, stdout );
else
fputs("<!-- Ooops: gpgme_key_get_as_xml failed -->\n", stdout );
printf ("<!-- End key object (%p) -->\n", key );
}
if ( err != GPGME_EOF )
fail_if_err (err);
}
int
main (int argc, char **argv )
{
GpgmeCtx ctx;
GpgmeError err;
int loop = 0;
const char *pattern;
if( argc ) {
argc--; argv++;
}
if (argc && !strcmp( *argv, "--loop" ) ) {
loop = 1;
argc--; argv++;
}
pattern = argc? *argv : NULL;
err = gpgme_new (&ctx);
fail_if_err (err);
do {
doit ( ctx, pattern );
} while ( loop );
gpgme_release (ctx);
return 0;
}

View File

@ -0,0 +1,137 @@
/* t-sign.c - regression test
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "../gpgme/gpgme.h"
#define fail_if_err(a) do { if(a) { \
fprintf (stderr, "%s:%d: GpgmeError %s\n", \
__FILE__, __LINE__, gpgme_strerror(a)); \
exit (1); } \
} while(0)
static void
print_data ( GpgmeData dh )
{
char buf[100];
size_t nread;
GpgmeError err;
err = gpgme_data_rewind ( dh );
fail_if_err (err);
while ( !(err = gpgme_data_read ( dh, buf, 100, &nread )) ) {
fwrite ( buf, nread, 1, stdout );
}
if (err != GPGME_EOF)
fail_if_err (err);
}
static const char *
passphrase_cb ( void *opaque, const char *desc, void *r_hd )
{
const char *pass;
if ( !desc ) {
/* cleanup by looking at *r_hd */
return NULL;
}
pass = "abc";
fprintf (stderr, "%% requesting passphrase for `%s': ", desc );
fprintf (stderr, "sending `%s'\n", pass );
return pass;
}
int
main (int argc, char **argv )
{
GpgmeCtx ctx;
GpgmeError err;
GpgmeData in, out;
do {
err = gpgme_new (&ctx);
fail_if_err (err);
if ( !getenv("GPG_AGENT_INFO") ) {
gpgme_set_passphrase_cb ( ctx, passphrase_cb, NULL );
}
gpgme_set_textmode (ctx, 1);
gpgme_set_armor (ctx, 1);
err = gpgme_data_new_from_mem ( &in, "Hallo Leute\n", 12, 0 );
fail_if_err (err);
/* first a normal signature */
err = gpgme_data_new ( &out );
fail_if_err (err);
err = gpgme_op_sign (ctx, in, out, GPGME_SIG_MODE_NORMAL );
fail_if_err (err);
fflush (NULL);
fputs ("Begin Result:\n", stdout );
print_data (out);
fputs ("End Result.\n", stdout );
gpgme_data_release (out);
gpgme_data_rewind (in);
/* now a detached signature */
err = gpgme_data_new ( &out );
fail_if_err (err);
err = gpgme_op_sign (ctx, in, out, GPGME_SIG_MODE_DETACH );
fail_if_err (err);
fflush (NULL);
fputs ("Begin Result:\n", stdout );
print_data (out);
fputs ("End Result.\n", stdout );
gpgme_data_release (out);
gpgme_data_rewind (in);
/* And finally a cleartext signature */
err = gpgme_data_new ( &out );
fail_if_err (err);
err = gpgme_op_sign (ctx, in, out, GPGME_SIG_MODE_CLEAR );
fail_if_err (err);
fflush (NULL);
fputs ("Begin Result:\n", stdout );
print_data (out);
fputs ("End Result.\n", stdout );
gpgme_data_release (out);
gpgme_data_rewind (in);
/* ready */
gpgme_data_release (in);
gpgme_release (ctx);
} while ( argc > 1 && !strcmp( argv[1], "--loop" ) );
return 0;
}

View File

@ -0,0 +1,149 @@
/* t-verify.c - regression test
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "../gpgme/gpgme.h"
static const char test_text1[] = "Just GNU it!\n";
static const char test_text1f[]= "Just GNU it?\n";
static const char test_sig1[] =
#if 0
"-----BEGIN PGP SIGNATURE-----\n"
"\n"
"iEYEABECAAYFAjoKgjIACgkQLXJ8x2hpdzQMSwCeO/xUrhysZ7zJKPf/FyXA//u1\n"
"ZgIAn0204PBR7yxSdQx6CFxugstNqmRv\n"
"=yku6\n"
"-----END PGP SIGNATURE-----\n"
#elif 0
"-----BEGIN PGP SIGNATURE-----\n"
"Version: GnuPG v1.0.4-2 (GNU/Linux)\n"
"Comment: For info see http://www.gnupg.org\n"
"\n"
"iJcEABECAFcFAjoS8/E1FIAAAAAACAAkZm9vYmFyLjF0aGlzIGlzIGEgbm90YXRp\n"
"b24gZGF0YSB3aXRoIDIgbGluZXMaGmh0dHA6Ly93d3cuZ3Uub3JnL3BvbGljeS8A\n"
"CgkQLXJ8x2hpdzQLyQCbBW/fgU8ZeWSlWPM1F8umHX17bAAAoIfSNDSp5zM85XcG\n"
"iwxMrf+u8v4r\n"
"=88Zo\n"
"-----END PGP SIGNATURE-----\n"
#elif 1
"-----BEGIN PGP SIGNATURE-----\n"
"\n"
"iN0EABECAJ0FAjoS+i9FFIAAAAAAAwA5YmFyw7bDpMO8w58gZGFzIHdhcmVuIFVt\n"
"bGF1dGUgdW5kIGpldHp0IGVpbiBwcm96ZW50JS1aZWljaGVuNRSAAAAAAAgAJGZv\n"
"b2Jhci4xdGhpcyBpcyBhIG5vdGF0aW9uIGRhdGEgd2l0aCAyIGxpbmVzGhpodHRw\n"
"Oi8vd3d3Lmd1Lm9yZy9wb2xpY3kvAAoJEC1yfMdoaXc0JBIAoIiLlUsvpMDOyGEc\n"
"dADGKXF/Hcb+AKCJWPphZCphduxSvrzH0hgzHdeQaA==\n"
"=nts1\n"
"-----END PGP SIGNATURE-----\n"
#endif
;
#define fail_if_err(a) do { if(a) { \
fprintf (stderr, "%s:%d: GpgmeError %s\n", \
__FILE__, __LINE__, gpgme_strerror(a)); \
exit (1); } \
} while(0)
static void
print_sig_stat ( GpgmeSigStat status )
{
switch ( status ) {
case GPGME_SIG_STAT_NONE:
fputs ("Verification Status: None\n", stdout);
break;
case GPGME_SIG_STAT_NOSIG:
fputs ("Verification Status: No Signature\n", stdout);
break;
case GPGME_SIG_STAT_GOOD:
fputs ("Verification Status: Good\n", stdout);
break;
case GPGME_SIG_STAT_BAD:
fputs ("Verification Status: Bad\n", stdout);
break;
case GPGME_SIG_STAT_NOKEY:
fputs ("Verification Status: No Key\n", stdout);
break;
case GPGME_SIG_STAT_ERROR:
fputs ("Verification Status: Error\n", stdout);
break;
}
}
int
main (int argc, char **argv )
{
GpgmeCtx ctx;
GpgmeError err;
GpgmeData sig, text;
GpgmeSigStat status;
char *nota;
err = gpgme_new (&ctx);
fail_if_err (err);
do {
err = gpgme_data_new_from_mem ( &text,
test_text1, strlen (test_text1), 0 );
fail_if_err (err);
#if 1
err = gpgme_data_new_from_mem ( &sig,
test_sig1, strlen (test_sig1), 0 );
#else
err = gpgme_data_new_from_file ( &sig, "xx1", 1 );
#endif
fail_if_err (err);
puts ("checking a valid message:\n");
err = gpgme_op_verify (ctx, sig, text, &status );
print_sig_stat ( status );
fail_if_err (err);
if ( (nota=gpgme_get_notation (ctx)) )
printf ("---Begin Notation---\n%s---End Notation---\n", nota );
puts ("checking a manipulated message:\n");
gpgme_data_release (text);
err = gpgme_data_new_from_mem ( &text,
test_text1f, strlen (test_text1f), 0 );
fail_if_err (err);
gpgme_data_rewind ( sig );
err = gpgme_op_verify (ctx, sig, text, &status );
print_sig_stat ( status );
fail_if_err (err);
if ( (nota=gpgme_get_notation (ctx)) )
printf ("---Begin Notation---\n%s---End Notation---\n", nota );
gpgme_data_release (sig);
gpgme_data_release (text);
} while ( argc > 1 && !strcmp( argv[1], "--loop" ) );
gpgme_release (ctx);
return 0;
}