From 611536e382771d51da4c663dd32446522300ecd7 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Fri, 4 Jan 2008 15:07:10 +0000 Subject: [PATCH] Tag release. --- tags/gpgme-1.1.6/AUTHORS | 29 + tags/gpgme-1.1.6/COPYING | 340 + tags/gpgme-1.1.6/COPYING.LESSER | 510 ++ tags/gpgme-1.1.6/ChangeLog | 811 ++ tags/gpgme-1.1.6/INSTALL | 229 + tags/gpgme-1.1.6/Makefile.am | 54 + tags/gpgme-1.1.6/NEWS | 1211 +++ tags/gpgme-1.1.6/README | 123 + tags/gpgme-1.1.6/README.SVN | 51 + tags/gpgme-1.1.6/THANKS | 32 + tags/gpgme-1.1.6/TODO | 187 + tags/gpgme-1.1.6/acinclude.m4 | 86 + tags/gpgme-1.1.6/assuan/ChangeLog | 1018 +++ tags/gpgme-1.1.6/assuan/Makefile.am | 53 + tags/gpgme-1.1.6/assuan/README.1st | 45 + tags/gpgme-1.1.6/assuan/assuan-buffer.c | 550 ++ tags/gpgme-1.1.6/assuan/assuan-client.c | 234 + tags/gpgme-1.1.6/assuan/assuan-connect.c | 85 + tags/gpgme-1.1.6/assuan/assuan-defs.h | 332 + tags/gpgme-1.1.6/assuan/assuan-handler.c | 795 ++ tags/gpgme-1.1.6/assuan/assuan-inquire.c | 241 + tags/gpgme-1.1.6/assuan/assuan-io.c | 154 + tags/gpgme-1.1.6/assuan/assuan-listen.c | 157 + tags/gpgme-1.1.6/assuan/assuan-logging.c | 316 + tags/gpgme-1.1.6/assuan/assuan-pipe-connect.c | 1000 +++ tags/gpgme-1.1.6/assuan/assuan-pipe-server.c | 189 + .../assuan/assuan-socket-connect.c | 184 + .../gpgme-1.1.6/assuan/assuan-socket-server.c | 193 + tags/gpgme-1.1.6/assuan/assuan-socket.c | 148 + tags/gpgme-1.1.6/assuan/assuan-uds.c | 313 + tags/gpgme-1.1.6/assuan/assuan-util.c | 171 + tags/gpgme-1.1.6/assuan/assuan.h | 580 ++ tags/gpgme-1.1.6/assuan/mkerrors | 248 + tags/gpgme-1.1.6/autogen.sh | 162 + tags/gpgme-1.1.6/compile | 99 + tags/gpgme-1.1.6/complus/ChangeLog | 15 + tags/gpgme-1.1.6/complus/Makefile.am | 49 + tags/gpgme-1.1.6/complus/README | 72 + tags/gpgme-1.1.6/complus/debug.c | 40 + tags/gpgme-1.1.6/complus/example.c | 598 ++ tags/gpgme-1.1.6/complus/gpgcom.c | 545 ++ tags/gpgme-1.1.6/complus/gpgcom.idl | 62 + tags/gpgme-1.1.6/complus/gpgcom.rc | 22 + tags/gpgme-1.1.6/complus/gpgcom.tlb | Bin 0 -> 18596 bytes tags/gpgme-1.1.6/complus/guidgen.c | 130 + tags/gpgme-1.1.6/complus/igpgme.c | 859 +++ tags/gpgme-1.1.6/complus/igpgme.h | 163 + tags/gpgme-1.1.6/complus/main.h | 49 + tags/gpgme-1.1.6/complus/regtlb.c | 70 + tags/gpgme-1.1.6/complus/tgpgcom.c | 157 + tags/gpgme-1.1.6/complus/utf8.c | 236 + tags/gpgme-1.1.6/complus/vbtest.html | 47 + tags/gpgme-1.1.6/complus/vbtest.vbs | 39 + tags/gpgme-1.1.6/config.guess | 1432 ++++ tags/gpgme-1.1.6/config.sub | 1537 ++++ tags/gpgme-1.1.6/configure.ac | 767 ++ tags/gpgme-1.1.6/depcomp | 472 ++ tags/gpgme-1.1.6/doc/ChangeLog | 785 ++ tags/gpgme-1.1.6/doc/Makefile.am | 34 + tags/gpgme-1.1.6/doc/gpgme.texi | 5489 +++++++++++++ tags/gpgme-1.1.6/doc/lesser.texi | 565 ++ tags/gpgme-1.1.6/doc/mdate-sh | 133 + tags/gpgme-1.1.6/doc/texinfo.tex | 6773 +++++++++++++++++ tags/gpgme-1.1.6/gpgme.spec.in | 67 + tags/gpgme-1.1.6/gpgme.txt | 90 + tags/gpgme-1.1.6/gpgme/ChangeLog | 5642 ++++++++++++++ tags/gpgme-1.1.6/gpgme/Makefile.am | 227 + tags/gpgme-1.1.6/gpgme/ath-pth.c | 178 + tags/gpgme-1.1.6/gpgme/ath-pthread.c | 175 + tags/gpgme-1.1.6/gpgme/ath.c | 169 + tags/gpgme-1.1.6/gpgme/ath.h | 89 + tags/gpgme-1.1.6/gpgme/context.h | 118 + tags/gpgme-1.1.6/gpgme/conversion.c | 420 + tags/gpgme-1.1.6/gpgme/data-compat.c | 242 + tags/gpgme-1.1.6/gpgme/data-fd.c | 78 + tags/gpgme-1.1.6/gpgme/data-mem.c | 280 + tags/gpgme-1.1.6/gpgme/data-stream.c | 101 + tags/gpgme-1.1.6/gpgme/data-user.c | 98 + tags/gpgme-1.1.6/gpgme/data.c | 326 + tags/gpgme-1.1.6/gpgme/data.h | 132 + tags/gpgme-1.1.6/gpgme/debug.c | 295 + tags/gpgme-1.1.6/gpgme/debug.h | 226 + tags/gpgme-1.1.6/gpgme/decrypt-verify.c | 103 + tags/gpgme-1.1.6/gpgme/decrypt.c | 340 + tags/gpgme-1.1.6/gpgme/delete.c | 109 + tags/gpgme-1.1.6/gpgme/edit.c | 177 + tags/gpgme-1.1.6/gpgme/encrypt-sign.c | 110 + tags/gpgme-1.1.6/gpgme/encrypt.c | 222 + tags/gpgme-1.1.6/gpgme/engine-backend.h | 118 + tags/gpgme-1.1.6/gpgme/engine-gpgconf.c | 877 +++ tags/gpgme-1.1.6/gpgme/engine-gpgsm.c | 1893 +++++ tags/gpgme-1.1.6/gpgme/engine.c | 790 ++ tags/gpgme-1.1.6/gpgme/engine.h | 142 + tags/gpgme-1.1.6/gpgme/error.c | 92 + tags/gpgme-1.1.6/gpgme/export.c | 117 + tags/gpgme-1.1.6/gpgme/funopen.c | 63 + tags/gpgme-1.1.6/gpgme/genkey.c | 206 + tags/gpgme-1.1.6/gpgme/get-env.c | 59 + tags/gpgme-1.1.6/gpgme/getauditlog.c | 81 + tags/gpgme-1.1.6/gpgme/gpgconf.c | 134 + tags/gpgme-1.1.6/gpgme/gpgme-config.in | 162 + tags/gpgme-1.1.6/gpgme/gpgme.c | 667 ++ tags/gpgme-1.1.6/gpgme/gpgme.def | 170 + tags/gpgme-1.1.6/gpgme/gpgme.h | 1883 +++++ tags/gpgme-1.1.6/gpgme/gpgme.m4 | 307 + tags/gpgme-1.1.6/gpgme/import.c | 273 + tags/gpgme-1.1.6/gpgme/isascii.c | 28 + tags/gpgme-1.1.6/gpgme/kdpipeiodevice.cpp | 940 +++ tags/gpgme-1.1.6/gpgme/kdpipeiodevice.h | 73 + tags/gpgme-1.1.6/gpgme/kdpipeiodevice.moc | 183 + tags/gpgme-1.1.6/gpgme/key.c | 722 ++ tags/gpgme-1.1.6/gpgme/keylist.c | 982 +++ tags/gpgme-1.1.6/gpgme/libgpgme.vers | 177 + tags/gpgme-1.1.6/gpgme/memrchr.c | 210 + tags/gpgme-1.1.6/gpgme/mkstatus | 52 + tags/gpgme-1.1.6/gpgme/moc_kdpipeiodevice.cpp | 60 + tags/gpgme-1.1.6/gpgme/op-support.c | 295 + tags/gpgme-1.1.6/gpgme/ops.h | 169 + tags/gpgme-1.1.6/gpgme/passphrase.c | 153 + tags/gpgme-1.1.6/gpgme/posix-io.c | 550 ++ tags/gpgme-1.1.6/gpgme/posix-sema.c | 62 + tags/gpgme-1.1.6/gpgme/posix-util.c | 67 + tags/gpgme-1.1.6/gpgme/priv-io.h | 76 + tags/gpgme-1.1.6/gpgme/progress.c | 81 + tags/gpgme-1.1.6/gpgme/putc_unlocked.c | 31 + tags/gpgme-1.1.6/gpgme/rungpg.c | 2129 ++++++ tags/gpgme-1.1.6/gpgme/sema.h | 67 + tags/gpgme-1.1.6/gpgme/setenv.c | 356 + tags/gpgme-1.1.6/gpgme/sig-notation.c | 260 + tags/gpgme-1.1.6/gpgme/sign.c | 380 + tags/gpgme-1.1.6/gpgme/signers.c | 95 + tags/gpgme-1.1.6/gpgme/stpcpy.c | 55 + tags/gpgme-1.1.6/gpgme/trust-item.c | 171 + tags/gpgme-1.1.6/gpgme/trustlist.c | 248 + tags/gpgme-1.1.6/gpgme/ttyname_r.c | 53 + tags/gpgme-1.1.6/gpgme/util.h | 107 + tags/gpgme-1.1.6/gpgme/vasprintf.c | 192 + tags/gpgme-1.1.6/gpgme/verify.c | 1003 +++ tags/gpgme-1.1.6/gpgme/version.c | 253 + tags/gpgme-1.1.6/gpgme/versioninfo.rc.in | 52 + tags/gpgme-1.1.6/gpgme/w32-glib-io.c | 771 ++ tags/gpgme-1.1.6/gpgme/w32-io.c | 1423 ++++ tags/gpgme-1.1.6/gpgme/w32-qt-io.cpp | 636 ++ tags/gpgme-1.1.6/gpgme/w32-sema.c | 115 + tags/gpgme-1.1.6/gpgme/w32-util.c | 365 + tags/gpgme-1.1.6/gpgme/wait-global.c | 384 + tags/gpgme-1.1.6/gpgme/wait-private.c | 147 + tags/gpgme-1.1.6/gpgme/wait-user.c | 122 + tags/gpgme-1.1.6/gpgme/wait.c | 211 + tags/gpgme-1.1.6/gpgme/wait.h | 82 + tags/gpgme-1.1.6/install-sh | 294 + tags/gpgme-1.1.6/lang/Makefile.am | 22 + tags/gpgme-1.1.6/lang/README | 12 + tags/gpgme-1.1.6/lang/cl/ChangeLog | 4 + tags/gpgme-1.1.6/lang/cl/Makefile.am | 29 + tags/gpgme-1.1.6/lang/cl/README | 40 + tags/gpgme-1.1.6/lang/cl/gpgme-package.lisp | 49 + tags/gpgme-1.1.6/lang/cl/gpgme.asd.in | 35 + tags/gpgme-1.1.6/lang/cl/gpgme.lisp | 2077 +++++ tags/gpgme-1.1.6/ltmain.sh | 6425 ++++++++++++++++ tags/gpgme-1.1.6/m4/ChangeLog | 35 + tags/gpgme-1.1.6/m4/glib-2.0.m4 | 215 + tags/gpgme-1.1.6/m4/glibc21.m4 | 32 + tags/gpgme-1.1.6/m4/gpg-error.m4 | 65 + tags/gpgme-1.1.6/m4/libtool.m4 | 5939 +++++++++++++++ tags/gpgme-1.1.6/m4/pkg.m4 | 157 + tags/gpgme-1.1.6/m4/pth.m4 | 402 + tags/gpgme-1.1.6/missing | 336 + tags/gpgme-1.1.6/mkinstalldirs | 111 + tags/gpgme-1.1.6/tests/ChangeLog | 770 ++ tags/gpgme-1.1.6/tests/Makefile.am | 48 + tags/gpgme-1.1.6/tests/gpg/Makefile.am | 70 + tags/gpgme-1.1.6/tests/gpg/cipher-1.asc | 15 + tags/gpgme-1.1.6/tests/gpg/cipher-2.asc | 16 + tags/gpgme-1.1.6/tests/gpg/geheim.txt | 2 + tags/gpgme-1.1.6/tests/gpg/mkdemodirs | 55 + tags/gpgme-1.1.6/tests/gpg/pubdemo.asc | 586 ++ tags/gpgme-1.1.6/tests/gpg/pubkey-1.asc | 26 + tags/gpgme-1.1.6/tests/gpg/secdemo.asc | 699 ++ tags/gpgme-1.1.6/tests/gpg/seckey-1.asc | 30 + tags/gpgme-1.1.6/tests/gpg/t-decrypt-verify.c | 141 + tags/gpgme-1.1.6/tests/gpg/t-decrypt.c | 79 + tags/gpgme-1.1.6/tests/gpg/t-edit.c | 152 + tags/gpgme-1.1.6/tests/gpg/t-encrypt-large.c | 143 + tags/gpgme-1.1.6/tests/gpg/t-encrypt-sign.c | 139 + tags/gpgme-1.1.6/tests/gpg/t-encrypt-sym.c | 98 + tags/gpgme-1.1.6/tests/gpg/t-encrypt.c | 82 + tags/gpgme-1.1.6/tests/gpg/t-eventloop.c | 225 + tags/gpgme-1.1.6/tests/gpg/t-export.c | 67 + tags/gpgme-1.1.6/tests/gpg/t-file-name.c | 99 + tags/gpgme-1.1.6/tests/gpg/t-genkey.c | 122 + tags/gpgme-1.1.6/tests/gpg/t-gpgconf.c | 305 + tags/gpgme-1.1.6/tests/gpg/t-import.c | 241 + tags/gpgme-1.1.6/tests/gpg/t-keylist-sig.c | 635 ++ tags/gpgme-1.1.6/tests/gpg/t-keylist.c | 579 ++ tags/gpgme-1.1.6/tests/gpg/t-sig-notation.c | 166 + tags/gpgme-1.1.6/tests/gpg/t-sign.c | 144 + tags/gpgme-1.1.6/tests/gpg/t-signers.c | 174 + tags/gpgme-1.1.6/tests/gpg/t-support.h | 115 + tags/gpgme-1.1.6/tests/gpg/t-thread1.c | 156 + tags/gpgme-1.1.6/tests/gpg/t-trustlist.c | 64 + tags/gpgme-1.1.6/tests/gpg/t-verify.c | 273 + tags/gpgme-1.1.6/tests/gpg/t-wait.c | 76 + .../32100C27173EF6E9C4E9A25D3D69F86D37A4F939 | 18 + tags/gpgme-1.1.6/tests/gpgsm/Makefile.am | 65 + .../tests/gpgsm/cert_dfn_pca01.der | Bin 0 -> 1224 bytes .../tests/gpgsm/cert_dfn_pca15.der | Bin 0 -> 1560 bytes .../tests/gpgsm/cert_g10code_test1.der | Bin 0 -> 793 bytes tags/gpgme-1.1.6/tests/gpgsm/t-decrypt.c | 86 + tags/gpgme-1.1.6/tests/gpgsm/t-encrypt.c | 78 + tags/gpgme-1.1.6/tests/gpgsm/t-export.c | 86 + tags/gpgme-1.1.6/tests/gpgsm/t-genkey.c | 128 + tags/gpgme-1.1.6/tests/gpgsm/t-import.c | 175 + tags/gpgme-1.1.6/tests/gpgsm/t-keylist.c | 389 + tags/gpgme-1.1.6/tests/gpgsm/t-sign.c | 127 + tags/gpgme-1.1.6/tests/gpgsm/t-support.h | 102 + tags/gpgme-1.1.6/tests/gpgsm/t-verify.c | 182 + tags/gpgme-1.1.6/tests/t-data-1.txt | 1 + tags/gpgme-1.1.6/tests/t-data-2.txt | 3 + tags/gpgme-1.1.6/tests/t-data.c | 285 + tags/gpgme-1.1.6/tests/t-engine-info.c | 93 + tags/gpgme-1.1.6/tests/t-version.c | 45 + 222 files changed, 89440 insertions(+) create mode 100644 tags/gpgme-1.1.6/AUTHORS create mode 100644 tags/gpgme-1.1.6/COPYING create mode 100644 tags/gpgme-1.1.6/COPYING.LESSER create mode 100644 tags/gpgme-1.1.6/ChangeLog create mode 100644 tags/gpgme-1.1.6/INSTALL create mode 100644 tags/gpgme-1.1.6/Makefile.am create mode 100644 tags/gpgme-1.1.6/NEWS create mode 100644 tags/gpgme-1.1.6/README create mode 100644 tags/gpgme-1.1.6/README.SVN create mode 100644 tags/gpgme-1.1.6/THANKS create mode 100644 tags/gpgme-1.1.6/TODO create mode 100644 tags/gpgme-1.1.6/acinclude.m4 create mode 100644 tags/gpgme-1.1.6/assuan/ChangeLog create mode 100644 tags/gpgme-1.1.6/assuan/Makefile.am create mode 100644 tags/gpgme-1.1.6/assuan/README.1st create mode 100644 tags/gpgme-1.1.6/assuan/assuan-buffer.c create mode 100644 tags/gpgme-1.1.6/assuan/assuan-client.c create mode 100644 tags/gpgme-1.1.6/assuan/assuan-connect.c create mode 100644 tags/gpgme-1.1.6/assuan/assuan-defs.h create mode 100644 tags/gpgme-1.1.6/assuan/assuan-handler.c create mode 100644 tags/gpgme-1.1.6/assuan/assuan-inquire.c create mode 100644 tags/gpgme-1.1.6/assuan/assuan-io.c create mode 100644 tags/gpgme-1.1.6/assuan/assuan-listen.c create mode 100644 tags/gpgme-1.1.6/assuan/assuan-logging.c create mode 100644 tags/gpgme-1.1.6/assuan/assuan-pipe-connect.c create mode 100644 tags/gpgme-1.1.6/assuan/assuan-pipe-server.c create mode 100644 tags/gpgme-1.1.6/assuan/assuan-socket-connect.c create mode 100644 tags/gpgme-1.1.6/assuan/assuan-socket-server.c create mode 100644 tags/gpgme-1.1.6/assuan/assuan-socket.c create mode 100644 tags/gpgme-1.1.6/assuan/assuan-uds.c create mode 100644 tags/gpgme-1.1.6/assuan/assuan-util.c create mode 100644 tags/gpgme-1.1.6/assuan/assuan.h create mode 100755 tags/gpgme-1.1.6/assuan/mkerrors create mode 100755 tags/gpgme-1.1.6/autogen.sh create mode 100755 tags/gpgme-1.1.6/compile create mode 100644 tags/gpgme-1.1.6/complus/ChangeLog create mode 100644 tags/gpgme-1.1.6/complus/Makefile.am create mode 100644 tags/gpgme-1.1.6/complus/README create mode 100644 tags/gpgme-1.1.6/complus/debug.c create mode 100644 tags/gpgme-1.1.6/complus/example.c create mode 100644 tags/gpgme-1.1.6/complus/gpgcom.c create mode 100644 tags/gpgme-1.1.6/complus/gpgcom.idl create mode 100644 tags/gpgme-1.1.6/complus/gpgcom.rc create mode 100644 tags/gpgme-1.1.6/complus/gpgcom.tlb create mode 100644 tags/gpgme-1.1.6/complus/guidgen.c create mode 100644 tags/gpgme-1.1.6/complus/igpgme.c create mode 100644 tags/gpgme-1.1.6/complus/igpgme.h create mode 100644 tags/gpgme-1.1.6/complus/main.h create mode 100644 tags/gpgme-1.1.6/complus/regtlb.c create mode 100644 tags/gpgme-1.1.6/complus/tgpgcom.c create mode 100644 tags/gpgme-1.1.6/complus/utf8.c create mode 100644 tags/gpgme-1.1.6/complus/vbtest.html create mode 100644 tags/gpgme-1.1.6/complus/vbtest.vbs create mode 100755 tags/gpgme-1.1.6/config.guess create mode 100755 tags/gpgme-1.1.6/config.sub create mode 100644 tags/gpgme-1.1.6/configure.ac create mode 100755 tags/gpgme-1.1.6/depcomp create mode 100644 tags/gpgme-1.1.6/doc/ChangeLog create mode 100644 tags/gpgme-1.1.6/doc/Makefile.am create mode 100644 tags/gpgme-1.1.6/doc/gpgme.texi create mode 100644 tags/gpgme-1.1.6/doc/lesser.texi create mode 100755 tags/gpgme-1.1.6/doc/mdate-sh create mode 100644 tags/gpgme-1.1.6/doc/texinfo.tex create mode 100644 tags/gpgme-1.1.6/gpgme.spec.in create mode 100644 tags/gpgme-1.1.6/gpgme.txt create mode 100644 tags/gpgme-1.1.6/gpgme/ChangeLog create mode 100644 tags/gpgme-1.1.6/gpgme/Makefile.am create mode 100644 tags/gpgme-1.1.6/gpgme/ath-pth.c create mode 100644 tags/gpgme-1.1.6/gpgme/ath-pthread.c create mode 100644 tags/gpgme-1.1.6/gpgme/ath.c create mode 100644 tags/gpgme-1.1.6/gpgme/ath.h create mode 100644 tags/gpgme-1.1.6/gpgme/context.h create mode 100644 tags/gpgme-1.1.6/gpgme/conversion.c create mode 100644 tags/gpgme-1.1.6/gpgme/data-compat.c create mode 100644 tags/gpgme-1.1.6/gpgme/data-fd.c create mode 100644 tags/gpgme-1.1.6/gpgme/data-mem.c create mode 100644 tags/gpgme-1.1.6/gpgme/data-stream.c create mode 100644 tags/gpgme-1.1.6/gpgme/data-user.c create mode 100644 tags/gpgme-1.1.6/gpgme/data.c create mode 100644 tags/gpgme-1.1.6/gpgme/data.h create mode 100644 tags/gpgme-1.1.6/gpgme/debug.c create mode 100644 tags/gpgme-1.1.6/gpgme/debug.h create mode 100644 tags/gpgme-1.1.6/gpgme/decrypt-verify.c create mode 100644 tags/gpgme-1.1.6/gpgme/decrypt.c create mode 100644 tags/gpgme-1.1.6/gpgme/delete.c create mode 100644 tags/gpgme-1.1.6/gpgme/edit.c create mode 100644 tags/gpgme-1.1.6/gpgme/encrypt-sign.c create mode 100644 tags/gpgme-1.1.6/gpgme/encrypt.c create mode 100644 tags/gpgme-1.1.6/gpgme/engine-backend.h create mode 100644 tags/gpgme-1.1.6/gpgme/engine-gpgconf.c create mode 100644 tags/gpgme-1.1.6/gpgme/engine-gpgsm.c create mode 100644 tags/gpgme-1.1.6/gpgme/engine.c create mode 100644 tags/gpgme-1.1.6/gpgme/engine.h create mode 100644 tags/gpgme-1.1.6/gpgme/error.c create mode 100644 tags/gpgme-1.1.6/gpgme/export.c create mode 100644 tags/gpgme-1.1.6/gpgme/funopen.c create mode 100644 tags/gpgme-1.1.6/gpgme/genkey.c create mode 100644 tags/gpgme-1.1.6/gpgme/get-env.c create mode 100644 tags/gpgme-1.1.6/gpgme/getauditlog.c create mode 100644 tags/gpgme-1.1.6/gpgme/gpgconf.c create mode 100644 tags/gpgme-1.1.6/gpgme/gpgme-config.in create mode 100644 tags/gpgme-1.1.6/gpgme/gpgme.c create mode 100644 tags/gpgme-1.1.6/gpgme/gpgme.def create mode 100644 tags/gpgme-1.1.6/gpgme/gpgme.h create mode 100644 tags/gpgme-1.1.6/gpgme/gpgme.m4 create mode 100644 tags/gpgme-1.1.6/gpgme/import.c create mode 100644 tags/gpgme-1.1.6/gpgme/isascii.c create mode 100644 tags/gpgme-1.1.6/gpgme/kdpipeiodevice.cpp create mode 100644 tags/gpgme-1.1.6/gpgme/kdpipeiodevice.h create mode 100644 tags/gpgme-1.1.6/gpgme/kdpipeiodevice.moc create mode 100644 tags/gpgme-1.1.6/gpgme/key.c create mode 100644 tags/gpgme-1.1.6/gpgme/keylist.c create mode 100644 tags/gpgme-1.1.6/gpgme/libgpgme.vers create mode 100644 tags/gpgme-1.1.6/gpgme/memrchr.c create mode 100755 tags/gpgme-1.1.6/gpgme/mkstatus create mode 100644 tags/gpgme-1.1.6/gpgme/moc_kdpipeiodevice.cpp create mode 100644 tags/gpgme-1.1.6/gpgme/op-support.c create mode 100644 tags/gpgme-1.1.6/gpgme/ops.h create mode 100644 tags/gpgme-1.1.6/gpgme/passphrase.c create mode 100644 tags/gpgme-1.1.6/gpgme/posix-io.c create mode 100644 tags/gpgme-1.1.6/gpgme/posix-sema.c create mode 100644 tags/gpgme-1.1.6/gpgme/posix-util.c create mode 100644 tags/gpgme-1.1.6/gpgme/priv-io.h create mode 100644 tags/gpgme-1.1.6/gpgme/progress.c create mode 100644 tags/gpgme-1.1.6/gpgme/putc_unlocked.c create mode 100644 tags/gpgme-1.1.6/gpgme/rungpg.c create mode 100644 tags/gpgme-1.1.6/gpgme/sema.h create mode 100644 tags/gpgme-1.1.6/gpgme/setenv.c create mode 100644 tags/gpgme-1.1.6/gpgme/sig-notation.c create mode 100644 tags/gpgme-1.1.6/gpgme/sign.c create mode 100644 tags/gpgme-1.1.6/gpgme/signers.c create mode 100644 tags/gpgme-1.1.6/gpgme/stpcpy.c create mode 100644 tags/gpgme-1.1.6/gpgme/trust-item.c create mode 100644 tags/gpgme-1.1.6/gpgme/trustlist.c create mode 100644 tags/gpgme-1.1.6/gpgme/ttyname_r.c create mode 100644 tags/gpgme-1.1.6/gpgme/util.h create mode 100644 tags/gpgme-1.1.6/gpgme/vasprintf.c create mode 100644 tags/gpgme-1.1.6/gpgme/verify.c create mode 100644 tags/gpgme-1.1.6/gpgme/version.c create mode 100644 tags/gpgme-1.1.6/gpgme/versioninfo.rc.in create mode 100644 tags/gpgme-1.1.6/gpgme/w32-glib-io.c create mode 100644 tags/gpgme-1.1.6/gpgme/w32-io.c create mode 100644 tags/gpgme-1.1.6/gpgme/w32-qt-io.cpp create mode 100644 tags/gpgme-1.1.6/gpgme/w32-sema.c create mode 100644 tags/gpgme-1.1.6/gpgme/w32-util.c create mode 100644 tags/gpgme-1.1.6/gpgme/wait-global.c create mode 100644 tags/gpgme-1.1.6/gpgme/wait-private.c create mode 100644 tags/gpgme-1.1.6/gpgme/wait-user.c create mode 100644 tags/gpgme-1.1.6/gpgme/wait.c create mode 100644 tags/gpgme-1.1.6/gpgme/wait.h create mode 100755 tags/gpgme-1.1.6/install-sh create mode 100644 tags/gpgme-1.1.6/lang/Makefile.am create mode 100644 tags/gpgme-1.1.6/lang/README create mode 100644 tags/gpgme-1.1.6/lang/cl/ChangeLog create mode 100644 tags/gpgme-1.1.6/lang/cl/Makefile.am create mode 100644 tags/gpgme-1.1.6/lang/cl/README create mode 100644 tags/gpgme-1.1.6/lang/cl/gpgme-package.lisp create mode 100644 tags/gpgme-1.1.6/lang/cl/gpgme.asd.in create mode 100644 tags/gpgme-1.1.6/lang/cl/gpgme.lisp create mode 100644 tags/gpgme-1.1.6/ltmain.sh create mode 100644 tags/gpgme-1.1.6/m4/ChangeLog create mode 100644 tags/gpgme-1.1.6/m4/glib-2.0.m4 create mode 100644 tags/gpgme-1.1.6/m4/glibc21.m4 create mode 100644 tags/gpgme-1.1.6/m4/gpg-error.m4 create mode 100644 tags/gpgme-1.1.6/m4/libtool.m4 create mode 100644 tags/gpgme-1.1.6/m4/pkg.m4 create mode 100644 tags/gpgme-1.1.6/m4/pth.m4 create mode 100755 tags/gpgme-1.1.6/missing create mode 100755 tags/gpgme-1.1.6/mkinstalldirs create mode 100644 tags/gpgme-1.1.6/tests/ChangeLog create mode 100644 tags/gpgme-1.1.6/tests/Makefile.am create mode 100644 tags/gpgme-1.1.6/tests/gpg/Makefile.am create mode 100644 tags/gpgme-1.1.6/tests/gpg/cipher-1.asc create mode 100644 tags/gpgme-1.1.6/tests/gpg/cipher-2.asc create mode 100644 tags/gpgme-1.1.6/tests/gpg/geheim.txt create mode 100755 tags/gpgme-1.1.6/tests/gpg/mkdemodirs create mode 100644 tags/gpgme-1.1.6/tests/gpg/pubdemo.asc create mode 100644 tags/gpgme-1.1.6/tests/gpg/pubkey-1.asc create mode 100644 tags/gpgme-1.1.6/tests/gpg/secdemo.asc create mode 100644 tags/gpgme-1.1.6/tests/gpg/seckey-1.asc create mode 100644 tags/gpgme-1.1.6/tests/gpg/t-decrypt-verify.c create mode 100644 tags/gpgme-1.1.6/tests/gpg/t-decrypt.c create mode 100644 tags/gpgme-1.1.6/tests/gpg/t-edit.c create mode 100644 tags/gpgme-1.1.6/tests/gpg/t-encrypt-large.c create mode 100644 tags/gpgme-1.1.6/tests/gpg/t-encrypt-sign.c create mode 100644 tags/gpgme-1.1.6/tests/gpg/t-encrypt-sym.c create mode 100644 tags/gpgme-1.1.6/tests/gpg/t-encrypt.c create mode 100644 tags/gpgme-1.1.6/tests/gpg/t-eventloop.c create mode 100644 tags/gpgme-1.1.6/tests/gpg/t-export.c create mode 100644 tags/gpgme-1.1.6/tests/gpg/t-file-name.c create mode 100644 tags/gpgme-1.1.6/tests/gpg/t-genkey.c create mode 100644 tags/gpgme-1.1.6/tests/gpg/t-gpgconf.c create mode 100644 tags/gpgme-1.1.6/tests/gpg/t-import.c create mode 100644 tags/gpgme-1.1.6/tests/gpg/t-keylist-sig.c create mode 100644 tags/gpgme-1.1.6/tests/gpg/t-keylist.c create mode 100644 tags/gpgme-1.1.6/tests/gpg/t-sig-notation.c create mode 100644 tags/gpgme-1.1.6/tests/gpg/t-sign.c create mode 100644 tags/gpgme-1.1.6/tests/gpg/t-signers.c create mode 100644 tags/gpgme-1.1.6/tests/gpg/t-support.h create mode 100644 tags/gpgme-1.1.6/tests/gpg/t-thread1.c create mode 100644 tags/gpgme-1.1.6/tests/gpg/t-trustlist.c create mode 100644 tags/gpgme-1.1.6/tests/gpg/t-verify.c create mode 100644 tags/gpgme-1.1.6/tests/gpg/t-wait.c create mode 100644 tags/gpgme-1.1.6/tests/gpgsm/32100C27173EF6E9C4E9A25D3D69F86D37A4F939 create mode 100644 tags/gpgme-1.1.6/tests/gpgsm/Makefile.am create mode 100644 tags/gpgme-1.1.6/tests/gpgsm/cert_dfn_pca01.der create mode 100644 tags/gpgme-1.1.6/tests/gpgsm/cert_dfn_pca15.der create mode 100644 tags/gpgme-1.1.6/tests/gpgsm/cert_g10code_test1.der create mode 100644 tags/gpgme-1.1.6/tests/gpgsm/t-decrypt.c create mode 100644 tags/gpgme-1.1.6/tests/gpgsm/t-encrypt.c create mode 100644 tags/gpgme-1.1.6/tests/gpgsm/t-export.c create mode 100644 tags/gpgme-1.1.6/tests/gpgsm/t-genkey.c create mode 100644 tags/gpgme-1.1.6/tests/gpgsm/t-import.c create mode 100644 tags/gpgme-1.1.6/tests/gpgsm/t-keylist.c create mode 100644 tags/gpgme-1.1.6/tests/gpgsm/t-sign.c create mode 100644 tags/gpgme-1.1.6/tests/gpgsm/t-support.h create mode 100644 tags/gpgme-1.1.6/tests/gpgsm/t-verify.c create mode 100644 tags/gpgme-1.1.6/tests/t-data-1.txt create mode 100644 tags/gpgme-1.1.6/tests/t-data-2.txt create mode 100644 tags/gpgme-1.1.6/tests/t-data.c create mode 100644 tags/gpgme-1.1.6/tests/t-engine-info.c create mode 100644 tags/gpgme-1.1.6/tests/t-version.c diff --git a/tags/gpgme-1.1.6/AUTHORS b/tags/gpgme-1.1.6/AUTHORS new file mode 100644 index 0000000..188792d --- /dev/null +++ b/tags/gpgme-1.1.6/AUTHORS @@ -0,0 +1,29 @@ +Package: gpgme +Maintainer: Marcus Brinkmann +Bug reports: bug-gpgme@gnupg.org +Security related bug reports: security@gnupg.org +License: LGPLv2.1+ + + +FSF + - Code taken from GnuPG 1.0: gpgme/w32-util.c, GnuPG 1.1: jnlib/. + +g10 Code GmbH + - All stuff since mid march 2001. + +Werner Koch + - Design and most stuff. + +Wojciech Polak + - gpgme.spec + + + Copyright 2001, 2002 g10 Code GmbH + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/tags/gpgme-1.1.6/COPYING b/tags/gpgme-1.1.6/COPYING new file mode 100644 index 0000000..d60c31a --- /dev/null +++ b/tags/gpgme-1.1.6/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program 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. + + This program 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 + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/tags/gpgme-1.1.6/COPYING.LESSER b/tags/gpgme-1.1.6/COPYING.LESSER new file mode 100644 index 0000000..cf9b6b9 --- /dev/null +++ b/tags/gpgme-1.1.6/COPYING.LESSER @@ -0,0 +1,510 @@ + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations +below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. +^L + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it +becomes a de-facto standard. To achieve this, non-free programs must +be allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. +^L + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control +compilation and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. +^L + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. +^L + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at least + three years, to give the same user the materials specified in + Subsection 6a, above, for a charge no more than the cost of + performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. +^L + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. +^L + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply, and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License +may add an explicit geographical distribution limitation excluding those +countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. +^L + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS +^L + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms +of the ordinary General Public License). + + To apply these terms, attach the following notices to the library. +It is safest to attach them to the start of each source file to most +effectively convey the exclusion of warranty; and each file should +have at least the "copyright" line and a pointer to where the full +notice is found. + + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or +your school, if any, to sign a "copyright disclaimer" for the library, +if necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James + Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/tags/gpgme-1.1.6/ChangeLog b/tags/gpgme-1.1.6/ChangeLog new file mode 100644 index 0000000..0f4af8c --- /dev/null +++ b/tags/gpgme-1.1.6/ChangeLog @@ -0,0 +1,811 @@ +2008-01-04 Marcus Brinkmann + + Release GPGME 1.1.6. + + * configure.ac: Support gpgconf. + +2007-09-27 Marcus Brinkmann + + * assuan-pipe-connect.c (pipe_connect_gpgme): Do not close process + handle here. Use this function also on Unix systems. + + * assuan-pipe-connect.c (pipe_connect_gpgme): Fix last change. + + * assuan-pipe-connect.c (pipe_connect_gpgme): New function, use it + if _ASSUAN_IN_GPGME_BUILD_ASSUAN. + +2007-09-17 Werner Koch + + * configure.ac: Use the svn version magic. + +2007-09-07 Marcus Brinkmann + + * configure.ac: Check for C++, Qt and support --enable-w32-qt. + * m4/pkg.m4: New file. + +2007-08-21 Marcus Brinkmann + + * configure.ac (--enable-w32-glib): Use --enableval, not + --withval. + +2007-07-16 Marcus Brinkmann + + * assuan/assuan-socket.c (_assuan_close): Always use close(). + * assuan/assuan.h (_gpgme_io_close): New prototype. + (close): New macro, define as _gpgme_io_close. + +2007-07-13 Marcus Brinkmann + + * assuan/assuan-io.c (_assuan_simple_read, _assuan_simple_write): + Always use read/write (which means _gpgme_io_read and + _gpgme_io_write). + +2007-07-09 Marcus Brinkmann + + Released 1.1.5. + + * configure.ac (LIBGPGME_LT_REVISION): Bump for release. + +2007-07-08 Marcus Brinkmann + + * configure.ac (GPGSM_DEFAULT) [*-mingw32*]: Initialize it. + (HAVE_ASSUAN_H): Set to 1 if we have it. + (funopen): Use AC_REPLACE_FUNCS. + (USE_DESCRIPTOR_PASSING): Define to 1 if we have it. Do not + define it at all if we don't. + (NETLIBS) [have_w32_system]: Add -lws2_32. + (DIRSEP_C, DIRSEP_S, EXPSEP_C, EXPSEP_S, PATHSEP_S) + [HAVE_DOSISH_SYSTEM]: Remove definitions. + + * assuan/assuan.h (_assuan_funopen): Define to _gpgme_funopen. + * assuan/funopen.c: Move to ../gpgme/funopen.c. + * assuan/Makefile.am (libassuan_la_SOURCES): Remove funopen.c. + +2007-07-04 Marcus Brinkmann + + * assuan/Makefile.am (INCLUDES): Include $(top_srcdir)/gpgme. + * assuan/assuan.h: Include instead of trying to duplicate + the definitions. + + * assuan/: Update files to 2007-07-04 version of assuan. + + * autogen.sh: Use = not == in test. + +2007-03-05 Werner Koch + + Released 1.1.4. + + * configure.ac (LIBGPGME_LT_REVISION): Bump for release. + + * autogen.sh: New option --force. + +2007-01-29 Marcus Brinkmann + + Released 1.1.3. + + * configure.ac (LIBGPGME_LT_REVISION): Bump for release. + +2007-01-26 Werner Koch + + * configure.ac: Changed gpg and gpgsm version checks to work with + arbitrary names of the gpg binary. New option --disable-gpg-test + and --disable-gpgsm-test. + +2007-01-09 Werner Koch + + * configure.ac (NEED_GPG_VERSION, NEED_GPGSM_VERSION): Must define + after it may have been changed by an option. + +2007-01-08 Werner Koch + + * configure.ac: Require gpg-error 1.4 due to the use of + gpg_error_from_syserror. + (HAVE_ASSUAN_H): New. + +2007-01-05 Marcus Brinkmann + + * configure.ac: Add options --with-gpg-version and + --with-gpgsm-version to allow overriding the minimum version + requirements. + +2006-12-17 Marcus Brinkmann + + * configure.ac: Fix two typos in last change. + +2006-12-03 Marcus Brinkmann + + * configure.ac: Use descriptor passing only if --enable-fd-passing + is provided. + + * configure.ac: Add check for use of descriptor passing. + +2006-11-29 Marcus Brinkmann + + * configure.ac (NEED_GPG_VERSION): Bump to 1.3.0. + +2006-09-19 Marcus Brinkmann + + * configure.ac: Turn stpcpy into a replacement function. + Check for unistd.h and add setenv as replacement function. + +2006-07-29 Marcus Brinkmann + + * configure.ac: Check for network libraries and set NETLIBS. + +2006-07-06 Marcus Brinkmann + + * lang, lang/cl: New subdirectories. + * lang/Makefile.am, lang/README: New files. + * configure.ac (AC_CONFIG_FILES): Add lang/Makefile, + lang/cl/Makefile and lang/cl/gpgme.asd. + * Makefile.am (SUBDIRS): Add lang. + +2006-03-02 Marcus Brinkmann + + * configure.ac (LIBGPGME_LT_REVISION): Bump for release. + +2006-02-22 Marcus Brinkmann + + Released 1.1.1. + + * configure.ac (LIBGPGME_LT_CURRENT, LIBGPGME_LT_AGE): Bump for + release. + (LIBGPGME_LT_REVISION): Reset to 0 for release. + +2006-01-05 Werner Koch + + * configure.ac: Test for inline feature. + (AH_BOTTOM): New to define the pure attribute. + +2006-01-03 Werner Koch + + * configure.ac: Append SVN revision to the version. + +2005-11-18 Werner Koch + + * configure.ac (BUILD_REVISION): New. + +2005-11-17 Marcus Brinkmann + + * configure.ac: Add support for --enable-w32-glib (disabled by + default). Invoke AM_PATH_GLIB_2_0. + +2005-11-16 Werner Koch + + * configure.ac (CFLAGS) [W32]: Make sure that -mms-bitfields are used. + +2005-11-15 Werner Koch + + * configure.ac: Create BUILD_FILEVERSION from SVN Revision. + + * autogen.sh [W32]: Build shared and static versions of the library. + +2005-10-20 Marcus Brinkmann + + * w32-dll/ChangeLog, w32-dll/build-dll, w32-dll/gpgme.def: Remove + files. + + * configure.ac: Instead checking for windres and dlltool, invoke + AC_LIBTOOL_WIN32_DLL and AC_LIBTOOL_RC. + * src/Makefile.am [HAVE_W32_SYSTEM]: Use libtool, which simplifies + the rules. + +2005-10-01 Marcus Brinkmann + + Released 1.1.0. + + * configure.ac (LIBGPGME_LT_CURRENT, LIBGPGME_LT_AGE): Bump for + release. + (LIBGPGME_LT_REVISION): Reset to 0 for release. + +2005-09-12 Marcus Brinkmann + + * configure.ac (HAVE_PTH): Don't add $PTH_CFLAGS to $CFLAGS here. + +2005-08-26 Werner Koch + + * configure.ac (SEPCONSTANTS): New to define DIRSEP_C et al. + +2005-08-19 Werner Koch + + * configure.ac [W32]: Create values for versioninfo.rc and list + substuture versioninfo.rc. + * configure.ac: Define ENABLE_GPGSM. + +2005-08-08 Werner Koch + + * configure.ac (stpcpy): Changed from replace to test. + +2005-03-24 Marcus Brinkmann + + * configure.ac (AH_BOTTOM): Removed. + +2005-03-09 Werner Koch + + * acinclude.m4 (GNUPG_CHECK_VA_COPY): Assume no when cross-compiling. + + * Makefile.am (EXTRA_DIST): Include autogen.sh + + * autogen.sh: Added the usual code to build for W32 (--build-w32). + + * configure.ac: Fixed the mingw32 host string, removed OS/2 stuff. + (HAVE_DRIVE_LETTERS): Removed. + (HAVE_W32_SYSTEM): Added. + (AC_GNU_SOURCE): New to replace the identical AH_VERBATIM. + (AH_BOTTOM): Added. + +2004-12-28 Werner Koch + + Released 1.0.2. + + * Makefile.am (AUTOMAKE_OPTIONS): Build bzip 2 version. + (ACLOCAL_AMFLAGS): Add -I m4. + * configure.ac: Require automake 1.9.3 and autoconf 2.59. + * acinclude.m4: Changed quoting for automake 1.9. + * README: Use SHA1 instead of MD5. + +2004-12-11 Marcus Brinkmann + + * configure.ac: Replace ttyname_r if it doesn't exist (and warn in + that case). + +2004-12-07 Marcus Brinkmann + + * README: Refer to COPYING.LESSER and "each file" instead of + COPYING. + * COPYING.LESSER: New file. + * gpgme.spec.in (%doc): Add COPYING.LESSER. + * acinclude.m4, configure.ac, Makefile.am: Change license to LGPL + 2.1 or later. + * TODO: Add copyright notice. + * README.CVS: Likewise. + + * configure.ac (GPGSM_VERSION): Fix filter to get it. + +2004-10-22 Marcus Brinkmann + + Released 1.0.1. + + * configure.ac (LIBGPGME_LT_REVISION): Bump up to 2. + (AC_INIT): Set version to 1.0.1. + + * configure.ac: Set HAVE_GPGSM to true only if $GPGSM is not "no". + +2004-09-30 Marcus Brinkmann + + Released 1.0.0. + + * configure.ac (LIBGPGME_LT_REVISION): Bump up to 1. + (AC_INIT): Set version to 1.0.0. + + * Makefile.am (EXTRA_DIST): Remove README-alpha. + * README-alpha: Remove file. + +2004-09-17 Marcus Brinkmann + + * configure.ac: Disable AC_CONFIG_MACRO_DIR for now. + +2004-09-14 Marcus Brinkmann + + * configure.ac: Improve diagnostics with version check. + + * configure.ac: Print diagnostics about found thread libraries at + the end. Check for the versions of GPG and GPGSM and print the + found versions at the end. + (HAVE_GPGSM): Do not require GPGSM to exist and be readable. + (AC_CONFIG_MACRO_DIR): Invoke with argument m4. + + * acinclude.m4: Add copyright notice. + (jm_GLIBC21, AM_PATH_GPG_ERROR, _AC_PTH_ERROR, _AC_PTH_VERBOSE, + AC_CHECK_PTH): Removed. + +2004-06-23 Marcus Brinkmann + + * configure.ac: Check for . + +2004-06-08 Marcus Brinkmann + + Released 0.9.0. + + * configure.ac (AC_INIT): Set version number to 0.9.0. + (LIBGPGME_LT_CURRENT, LIBGPGME_LT_AGE): Bump up by one. + (LIBGPGME_LT_REVISION): Reset to zero. + +2004-05-21 Marcus Brinkmann + + * configure.ac (GPGME_CONFIG_API_VERSION): New variable, + substitute it. + +2004-04-29 Marcus Brinkmann + + Released 0.4.7. + + * configure.ac (LIBGPGME_LT_REVISION): Bump it up. + +2004-04-02 Thomas Schwinge + + * autogen.sh: Added ACLOCAL_FLAGS. + +2004-04-06 Werner Koch + + Released 0.4.6. + + * config.guess, config.sub, ltmain.sh: Updated to those from + libtools 1.5.4. + +2004-03-07 Marcus Brinkmann + + Released 0.4.5. + + * configure.ac (NEED_GPGSM_VERSION): Bump up to 1.9.6. + + * Makefile.am (EXTRA_DIST): Remove autogen.sh and README.CVS. + +2004-02-18 Werner Koch + + * configure.ac: Make the check for funopen fail with just a + warning. + +2004-02-11 Werner Koch + + * autogen.sh (check_version): Removed bashism and simplified. + +2004-02-10 Werner Koch + + * configure.ac: Fixed funopen test change. + +2004-02-06 Moritz Schulte + + * configure.ac: Fix funopen replacement mechanism. + +2004-01-31 Marcus Brinkmann + + * configure.ac: Add invocation of AC_SYS_LARGEFILE, AC_TYPE_OFF_T + and AC_FUNC_FSEEKO. + +2004-01-12 Werner Koch + + Released 0.4.4. + + * configure.ac: Bumbed LT_Revision; now at C12/A1/R1. + (NEED_GPGSM_VERSION): Set to 1.9.3. + (min_automake_version): Added. + * README.CVS: New. + * Makefile.am (EXTRA_DIST): Added README.CVS. + * autogen.sh: Updated. + +2003-11-19 Werner Koch + + * acinclude.m4: Add AM_PATH_GPG_ERROR. + * configure.ac: Check for timegm. Made warning messages more + prominent. + +2003-10-06 Marcus Brinkmann + + Released 0.4.3. + + * configure.ac (LIBGPGME_LT_CURRENT, LIBGPGME_LT_AGE): Bump up by 1. + (LIBGPGME_LT_REVISION): Set to 0. + +2003-09-13 Marcus Brinkmann + + * configure.ac: Require libgpg-error 0.5. + + * acinclude.m4: Remove libtool cruft, add jm_GLIBC21. + * configure.ac: Add check for getenv_r, and call jm_GLIBC21. + Define HAVE_THREAD_SAFE_GETENV if appropriate. + +2003-09-03 Marcus Brinkmann + + * configure.ac: Remove GPGME_CONFIG_LIBS and GPGME_CONFIG_CFLAGS. + +2003-09-02 Marcus Brinkmann + + * configure.ac: Move invocation of AC_CANONICAL_HOST up to + suppress warning by autoconf. + +2003-08-30 Robert Schiele + + * gpgme.spec.in: %{_infodir}/dir is not packaged, + remove to prevent checking failure. + +2003-08-18 Marcus Brinkmann + + * configure.ac: If building Assuan, check for funopen and + fopencookie, and make isascii, putc_unlocked and memrchr + replacement functions. + (AM_PATH_GPG_ERROR): Require 0.3. + +2003-07-31 Marcus Brinkmann + + * configure.ac (AC_INIT): Bump version to 0.4.3. + +2003-07-30 Marcus Brinkmann + + * configure.ac (LIBGPGME_LT_REVISION): Bump up to 1. + + Released 0.4.2. + +2003-07-08 Marcus Brinkmann + + * configure.ac: Complain if libgpg-error is not found. + +2003-06-22 Marcus Brinkmann + + * configure.ac (AC_INIT): Bump version to 0.4.2. + +2003-06-06 Marcus Brinkmann + + * configure.ac (LIBGPGME_LT_CURRENT): Bump up to 11. + + * configure.ac: Use AM_PATH_GPG_ERROR. + + * configure.ac: Check for libgpg-error. Define + GPG_ERR_SOURCE_DEFAULT. + +2003-05-26 Marcus Brinkmann + + * configure.ac (NEED_GPG_VERSION): Bump up to 1.2.2. + +2003-05-18 Marcus Brinkmann + + In all files, replace the Gpgme* type names with the new gpgme_* + type names. + +2003-02-01 Marcus Brinkmann + + * assuan/: Update files to 2002-11-10 version of assuan. + +2003-01-29 Marcus Brinkmann + + * bonobo/gpgme.c, bonobo/main.c, bonobo/main.h, bonobo/Makefile, + bonobo/Makefile.am, bonobo/Makefile.in: Dead files removed. + * configure.ac: Remove automake conditional BUILD_BONOBO + (AC_CONFIG_FILES): Remove bonobo/Makefile. + * Makefile.am (bonobo): Remove variable. + (SUBDIRS): Remove ${bonobo}. + + * configure.ac: Remove all uses of GNUPG_CHECK_TYPEDEF, for byte, + ushort, ulong, u16 and u32. + * acinclude.m4 (GNUPG_CHECK_TYPEDEF): Remove macro. + +2002-12-24 Marcus Brinkmann + + * configure.ac: New conditional HAVE_LD_VERSION_SCRIPT. + Call AC_CANONICAL_HOST, use host instead target. + +2002-12-23 Marcus Brinkmann + + * configure.ac: Bump up to 0.4.1. + + Released 0.4.0. + +2002-12-23 Marcus Brinkmann + + * autogen.sh (automake_vers): Require 1.7 (really 1.7.1) for the + conditional source distribution bug fix. + +2002-12-08 Marcus Brinkmann + + * configure.ac (LIBGPGME_LT_CURRENT): Increase by one. + (LIBGPGME_LT_AGE, LIBGPGME_LT_REVISION): Set to 0. + +2002-11-28 Marcus Brinkmann + + * NEWS: Add note about moving "gpgmeplug" to the "cryptplug" + package. + * README: Remove instructions related to "gpgmeplug". + * configure.ac: Remove enable option "gpgmeplug" and automake + conditional BUILD_GPGMEPLUG, as well as the status info about it. + (GPGMEPLUG): Remove variable. + * Makefile.am (gpgmeplug): Remove variable. + (SUBDIRS): Remove ${gpgmeplug}. + * cryptplug.h, gpgme-openpgp.c, gpgmeplug.dox, gpgme-smime.c, + Makefile.am, gpgmeplug.c, ChangeLog: Files removed. + +2002-11-22 Marcus Brinkmann + + * configure.ac: Disable GPGSM for all dosish systems. + +2002-10-12 Marcus Brinkmann + + * configure.ac: Add automake conditional HAVE_GPGSM. + +2002-10-08 Marcus Brinkmann + + * configure.ac (AC_INIT): Bump version up to 0.4.0. + (NEED_GPG_VERSION): Bump up to 1.2.0. + (NEED_GPGSM_VERSION): Bump up to 0.9.0. + * README: Update version numbers. + * NEWS: Start entry for 0.4.0. + +2002-09-20 Werner Koch + + Released 0.3.11. + + * configure.ac: Bump up LIBGPGME_LT_REVISION. + + * configure.ac (AC_CHECK_HEADERS): Check for sys/select.h. + +2002-09-04 Marcus Brinkmann + + * autogen.sh (autoconf_vers): Bump up to 2.53 to get the @&t@ + quadrigraph. Always cutting the edge! + +2002-09-02 Marcus Brinkmann + + * configure.ac: Create and substitute LTLIBOBJS. + +2002-09-02 Marcus Brinkmann + + Released 0.3.10. + + * NEWS: Update for 0.3.9 release. + * configure.ac: Bump up LIBGPGME_LT_REVISION. + +2002-08-29 Marcus Brinkmann + + * gpgme.spec.in: Changed user name in Wojciech Polak's email + address from ghostface to polak per request by himself. + +2002-08-28 Werner Koch + + * acinclude.m4 (GNUPG_CHECK_VA_COPY): New. + * configure.ac: Use it. + +2002-08-23 Werner Koch + + * configure.ac (GPGME_CONFIG_CFLAGS): Renamed from GPGME_CFLAGS + and removed the libpath because it is set by the config script. + +2002-08-21 Marcus Brinkmann + + * configure.ac: Bump version number to 0.3.10. + + * NEWS: Add template for development version. + +2002-08-21 Marcus Brinkmann + + Released 0.3.9. + + * NEWS: Update for 0.3.9 release. + * Makefile.am (EXTRA_DIST): Add gpgme.spec.in. + +2002-08-21 Marcus Brinkmann + + * jnlib/argparse.c, jnlib/argparse.h, jnlib/ChangeLog, + jnlib/dotlock.c, jnlib/dotlock.h, jnlib/libjnlib-config.h, + jnlib/logging.c, jnlib/logging.h,jnlib/Makefile.am, + jnlib/mischelp.h, jnlib/README, jnlib/stringhelp.c, + jnlib/stringhelp.h, jnlib/strlist.c, jnlib/strlist.h, + jnlib/types.h, jnlib/xmalloc.c, jnlib/xmalloc.h: Remove files. + +2002-08-21 Marcus Brinkmann + + * Makefile.am (SUBDIRS): Remove jnlib. + * configure.ac: Don't check for unsigned short or unsigned long. + Don't check for memicmp, strlwr, strtoul, memmove, stricmp. + Make stpcpy a replaced function. + Don't define HAVE_JNLIB_LOGGING. + Don't generate jnlib/Makefile. + +2002-07-02 Werner Koch + + * configure.ac: Bumbed version number to 0.3.9; add a comment on + when to change it. + + * gpgme.spec.in: New. Contributed by Wojciech Polak. + * Makefile.am (dist-hook): New. + + * AUTHORS: Added Wojciech and bug reporting addresses. + +2002-06-25 Werner Koch + + Released 0.3.8. + + * configure.ac: Bumbed LT version to 9/3/0. + (NEED_GPGSM_VERSION): Need 0.3.8 due to fixed export command. + +2002-06-04 Marcus Brinkmann + + Released 0.3.7. + + * configure.ac (AC_INIT): Set version to 0.3.7. + (LIBGPGME_LT_REVISION): Add one. + + * README: Document version requirement correctly. + +2002-06-02 Marcus Brinkmann + + * acinclude.m4: Fix Pth check so that it doesn't error out if pth + is not found. + +2002-06-02 Marcus Brinkmann + + * configure.ac: Add checks for Pth and pthreads. + * acinclude.m4: Add slightly hacked check for pth (seems to be an + autoconf version problem). + +2002-05-21 Werner Koch + + * configure.ac (NEED_GPGSM_VERSION): We need gpgsm 0.3.7. + +2002-05-03 Werner Koch + + Released 0.3.6. + +2002-04-05 Marcus Brinkmann + + * acconfig.h: File removed. + * configure.ac (NEED_GPG_VERSION): Add description. + (NEED_GPGSM_VERSION): Likewise. + (HAVE_DOSISH_SYSTEM): Likewise. + (HAVE_DRIVE_LETTERS): Likewise. + (GPG_PATH): Likewise. + (GPGSM_PATH): Likewise. + * acinclude.m4 (GNUPG_CHECK_TYPEDEF): Likewise. + +2002-04-01 Werner Koch + + Released 0.3.5. + +2002-03-17 Marcus Brinkmann + + * configure.ac: Add automake conditional HAVE_DOSISH_SYSTEM. + +2002-03-04 Werner Koch + + * configure.ac: Bumbed version to 0.3.4-cvs to continue development. + + Released 0.3.4. + + * configure.ac: Bumbed LT version numbers to (7,1,0), requires + gpgsm 0.3.1. + +2002-03-03 Marcus Brinkmann + + * configure.ac (AC_INIT): Change version number to snapshot CVS + version. + +2002-02-13 Werner Koch + + * configure.ac (vasprintf,fopencookie): Add checks. + +2002-02-12 Marcus Brinkmann + + * configure.ac (AC_INIT): Bump version to 0.3.3. + * jnlib/Makefile.am: Rever to older version that includes xmalloc + but not dotlock and some other files. Reported by Stéphane + Corthésy. + +2002-02-10 Marcus Brinkmann + + * Released 0.3.2. + + * configure.ac (AC_INIT): Bump version to 0.3.2. + * jnlib/libjnlibconfig.h: Revert to older version that doesn't + expect libgcrypt. Reported by Jose Carlos Garcia Sogo + . + +2002-02-09 Marcus Brinkmann + + * Released 0.3.1. + + * configure.ac (LIBGPGME_LT_CURRENT): Bump it up to 6! + (NEED_GPGSM_VERSION): Bump it up to 0.3.0! + (AC_INIT): Bump version to 0.3.1 + +2002-01-22 Marcus Brinkmann + + * configure.ac (HAVE_JNLIB_LOGGING): Define always for assuan. + +2001-12-19 Werner Koch + + * configure.ac (VERSION,PACKAGE): Defined and subst. Used for + AM_INIT_AUTOMAKE and moved all version number more to the top. + +2001-12-18 Marcus Brinkmann + + * autogen.sh (libtool_vers): Bump to 1.4. + + * configure.ac (LIBGPGME_LT_CURRENT): Increment. + (LIBGPGME_LT_AGE): Reset. + Improve comment. + Fix wrong comment character. + +2001-12-18 Werner Koch + + * acinclude.m4 (GNUPG_FIX_HDR_VERSION): Fixed for new automake. + +2001-12-14 Marcus Brinkmann + + * configure.ac (GPG): Substitute this variable. + (GPGSM): Likewise. + +2001-11-22 Marcus Brinkmann + + * configure.ac (AC_CONFIG_FILES): Add tests/gpg/Makefile and + tests/gpgsm/Makefile. + +2001-11-21 Marcus Brinkmann + + * Makefile.am (gpgmeplug): New variable, set to gpgmeplug if + [BUILD_GPGMEPLUG]. + * configure.ac (AC_CONFIG_FILES): Add gpgmeplug/Makefile. + Support --enable-gpgmeplug. + +2001-11-21 Marcus Brinkmann + + * autogen.sh: Tighten version dependencies. + +2001-11-20 Marcus Brinkmann + + * Makefile.am (SUBDIRS): Support building the assuan library + (currently if GPGSM_PATH is set).. + * configure.ac: Support building the assuan library. + * assuan: New directory, populated with the Assuan library + (copied from the newpg repository). + +2001-11-20 Marcus Brinkmann + + * configure.ac (NEED_GPGSM_VERSION): New variable. Treat it + similarly to NEED_GPG_VERSION. + * acconfig.h: Likewise. + +2001-11-18 Marcus Brinkmann + + * configure.in: Renamed to ... + * configure.ac: ... this. Update to autoconf 2.52. Lots of small + changes in the transition. Support --with-gpg=PATH and + --with-gpgsm=PATH options. Check if test suites can be run. + * acconfig.h: Add GPGSM_PATH. + * Makefile.am: New variable `tests', set to `tests' if + RUN_GPG_TESTS. + (SUBDIRS): Replace string `tests' with variable `tests'. + +2001-10-22 Marcus Brinkmann + + * autogen.sh: Invoke automake with `-a' (add missing files). + Do not invoke configure. + +2001-09-17 Werner Koch + + Released 0.2.3. + + * configure.in (NEED_GPG_VERSION): Set to 1.0.6. Incremented LT + current and age. + + * Makefile.am (SUBDIRS): Add doc + +2001-06-12 Werner Koch + + Released 0.2.2. + +2001-04-05 Werner Koch + + * configure.in (NEED_GPG_VERSION): Set to 1.0.4g + +2001-04-02 Werner Koch + + Released 0.2.1. + + Changed the copyright notices all over the place. + +2001-02-28 Werner Koch + + Released 0.2.0. + +2001-01-18 Werner Koch + + * autogen.sh: Added option --build-w32. + + + Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007 g10 Code GmbH + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/tags/gpgme-1.1.6/INSTALL b/tags/gpgme-1.1.6/INSTALL new file mode 100644 index 0000000..54caf7c --- /dev/null +++ b/tags/gpgme-1.1.6/INSTALL @@ -0,0 +1,229 @@ +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software +Foundation, Inc. + + This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +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, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + 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 you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' 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. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +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 support 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' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + 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 machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the `--target=TYPE' option to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +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. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +will cause the specified gcc to be used as the C compiler (unless it is +overridden in the site shell script). + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--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. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/tags/gpgme-1.1.6/Makefile.am b/tags/gpgme-1.1.6/Makefile.am new file mode 100644 index 0000000..c614f44 --- /dev/null +++ b/tags/gpgme-1.1.6/Makefile.am @@ -0,0 +1,54 @@ +# Makefile.am - Top level Makefile for GPGME. +# Copyright (C) 2000 Werner Koch (dd9jn) +# Copyright (C) 2001, 2002, 2004, 2005 g10 Code GmbH +# +# This file is part of GPGME. +# +# GPGME is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser 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 + +## Process this file with automake to produce Makefile.in + +ACLOCAL_AMFLAGS = -I m4 +AUTOMAKE_OPTIONS = dist-bzip2 + +EXTRA_DIST = gpgme.spec.in autogen.sh + +if BUILD_ASSUAN +assuan = assuan +else +assuan = +endif + +if BUILD_COMPLUS +complus = complus +else +complus = +endif + +if RUN_GPG_TESTS +tests = tests +else +tests = +endif + +SUBDIRS = ${assuan} gpgme ${tests} doc ${complus} lang + +# Fix the version of the spec file and create a file named VERSION +# to be used for patch's Prereq: feature. +dist-hook: + @set -e; \ + sed -e 's/@pkg_version@/$(VERSION)/g' \ + $(top_srcdir)/gpgme.spec.in > $(distdir)/gpgme.spec + echo "$(VERSION)" > $(distdir)/VERSION diff --git a/tags/gpgme-1.1.6/NEWS b/tags/gpgme-1.1.6/NEWS new file mode 100644 index 0000000..d268942 --- /dev/null +++ b/tags/gpgme-1.1.6/NEWS @@ -0,0 +1,1211 @@ +Noteworthy changes in version 1.1.6 (2008-01-04) +------------------------------------------------ + + * Bug fixes for for W32. + + * A new, experimental (and thus undocumented and potentially + unstable) interface for accessing gpg-conf through GPGME has been + added. + + * Interface changes relative to the 1.1.1 release: + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + gpgme_signature_t EXTENDED: New field chain_model. + gpgme_op_getauditlog_start NEW. + gpgme_op_getauditlog NEW. + GPGME_AUDITLOG_HTML NEW. + GPGME_AUDITLOG_WITH_HELP NEW. + + +Noteworthy changes in version 1.1.5 (2007-07-09) +------------------------------------------------ + + * Bug and portability fixes (mainly for W32). + + +Noteworthy changes in version 1.1.4 (2007-03-05) +------------------------------------------------ + + * Detect and bail out on double plaintext messages. This is required + so that applications can properly detect the signed parts of a + message. Actual there is now a double protection as GnuPG 1.4.7 + will detect this case too. + + +Noteworthy changes in version 1.1.3 (2007-01-29) +------------------------------------------------ + + * Fixed a memory leak in gpgme_data_release_and_get_mem. + + * Fixed a bug in Windows command line quoting. + + +Noteworthy changes in version 1.1.2 (2006-03-02) +------------------------------------------------ + + * Fixed a bug in the W32 glib backend. + + +Noteworthy changes in version 1.1.1 (2006-02-23) +------------------------------------------------ + + * Fixed a bug in that the fingerprints of subkeys are not available. + + * Clarified usage of the SECRET flag in key listings. It is now + reset for stub keys. + + * Reading signature notations and policy URLs on key signatures is + supported. They can be found in the new field notations of the + gpgme_key_sig_t structure. This has to be enabled with the keylist + mode flag GPGME_KEYLIST_MODE_SIG_NOTATIONS. + + * A new gpgme_free() function solves the problem of using different + allocators in a single program. This function should now be used + instead calling free() to release the buffer returned by + gpgme_data_release_and_get_mem. It is recommended that you always + do this, but it is only necessary on certain platforms, so backwards + compatibility is provided. In other words: If free() worked for + you before, it will keep working. + + * New status codes GPGME_PKA_TRUST_GOOD and GPGME_PKA_TRUST_BAD. + They are analyzed by the verify handlers and made available in the + new PKA_TRUST and PKA_ADDRESS fields of the signature result structure. + + * Interface changes relative to the 1.1.0 release: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +gpgme_key_sig_t EXTENDED: New field notations. +GPGME_KEYLIST_MODE_SIG_NOTATIONS NEW +gpgme_free NEW +GPGME_STATUS_PKA_TRUST_BAD NEW +GPGME_STATUS_PKA_TRUST_GOOD NEW +gpgme_signature_t EXTENDED: New field pka_trust. +gpgme_signature_t EXTENDED: New field pka_address. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +Noteworthy changes in version 1.1.0 (2005-10-01) +------------------------------------------------ + + * You can now configure the backend engine file name and home + directory to be used, as default and per context. + + * Information about the recipients of an encrypted text is now + available at decryption time. + + * New status GPGME_STATUS_PLAINTEXT. This is analyzed by the decrypt + and verify handlers, the information about the plaintext filename, + if available is made available in the new field file_name of the + respective result structure. + + * The code for "automagically detecting the thread library" has been + removed from libgpgme. It is deprecated since version 0.4.3. + Since then, you had to link against libgpgme-pthread for + applications using pthread and libgpgme-pth for applications using + GNU Pth. + + The code was removed because it caused compilation problems on + systems where the pthread.h header from GNU Pth is available in + addition to the system header (FreeBSD 6 and later for example). + + * "./autogen.sh --build-w32" does now build gpgme.dll. + + * [W32] The environment variable GPGME_DEBUG now uses a semicolon as + delimiter. The standard install directory is used when locating + gpg or gpgsm before finally falling back to the hardwired name. + + * There is a new flag for keys and subkeys, is_qualified, which + indicates if a key can be used for qualified signatures according + to local government regulations. + + * You can associate a filename with a data object using the new + function gpgme_data_set_file_name(). This filename will be stored + in the output when encrypting or signing the data and will be + returned when decrypting or verifying the output data. + + * You can now set notation data at signature creation with the new + function gpgme_sig_notation_add(). + + * Interface changes relative to the 1.0.3 release: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +gpgme_set_engine_info NEW +gpgme_ctx_get_engine_info NEW +gpgme_ctx_set_engine_info NEW +gpgme_recipient_t NEW +gpgme_decrypt_result_t EXTENDED: New field recipients. +gpgme_verify_result_t EXTENDED: New fields pubkey_algo, hash_algo. +gpgme_decrypt_result_t EXTENDED: New field plaintext_filename. +gpgme_verify_result_t EXTENDED: New field plaintext_filename. +GPGME_STATUS_PLAINTEXT NEW +gpgme_key_t EXTENDED: New field is_qualified. +gpgme_subkey_t EXTENDED: New field is_qualified. +gpgme_data_get_file_name NEW +gpgme_data_set_file_name NEW +gpgme_sig_notation_flags_t NEW +GPGME_SIG_NOTATION_HUMAN_READABLE NEW +GPGME_SIG_NOTATAION_CRITICAL NEW +gpgme_sig_notation_clear NEW +gpgme_sig_notation_add NEW +gpgme_sig_notation_get NEW +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +Noteworthy changes in version 1.0.3 (2005-06-20) +------------------------------------------------ + + * Previousy, GPGME would use a default "include certs" of 1. This + has been changed. Now GPGME will use the crypto backend engines + default unless you set the value with gpgme_set_include_certs() + explicitely. A new macro GPGME_INCLUDE_CERTS_DEFAULT can be used + as a value to explicitely request the new default behaviour. + + Because the default changes, this is a slight change of the API + semantics. We consider it to be a bug fix. + + * A bug which made GPGME hang has been fixed. If you have + experienced hanging before, please try out this version and let me + know if you still experience hanging problems. + + * Interface changes relative to the 0.9.0 release: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +gpgme_set_include_certs CHANGED DEFAULT +GPGME_INCLUDE_CERTS_DEFAULT NEW +GPGME_STATUS_SIG_SUBPACKET NEW +GPGME_STATUS_NEED_PASSPHRASE_PIN NEW +GPGME_STATUS_SC_OP_FAILURE NEW +GPGME_STATUS_SC_OP_SUCCESS NEW +GPGME_STATUS_CARDCTRL NEW +GPGME_STATUS_BACKUP_KEY_CREATED NEW +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +Noteworthy changes in version 1.0.2 (2004-12-28) +------------------------------------------------ + + * Changed the license of the library to the GNU Lesser General Public + License (LGPL), version 2.1 or later. + + +Noteworthy changes in version 1.0.1 (2004-10-22) +------------------------------------------------ + + * Only bug fixes. + + +Noteworthy changes in version 1.0.0 (2004-09-30) +------------------------------------------------ + + * Version 1.0.0! We are proud to present you with a thoroughly + tested and stable version of the GPGME library. A big Thank You! + to all the people who made this possible. + + The development will be branched into a stable 1.x.y series and the + head. + + * The gpgme.m4 macro supports checking the API version. Just prepend + it to the required version string, separated by a colon. For + example, this release has the version "1:1.0.0". The last release + to which this version is (mostly) ABI compatible is "1:0.4.2", + which is the default required version. + + +Noteworthy changes in version 0.9.0 (2004-06-08) +------------------------------------------------ + + * The type gpgme_key_t has now a new field keylist_mode that contains + the keylist mode that was active at the time the key was retrieved. + + * The type gpgme_decrypt_result_t has a new field "wrong_key_usage" + that contains a flag indicating that the key should not have been + used for encryption. + + * Verifying a signature of a revoked key gives the correct result now + (GPG_ERR_CERT_REVOKED error code). + + * Clarified that the error code GPG_ERR_NO_DATA from the decrypt & + verify operations still allows you to look at the signature + verification result. + + * Clarified that patterns in keylisting operations have an upper + limit, and thus are not suited to list many keys at once by their + fingerprint. Also improve the error message if the pattern is too + long for the CMS protocol to handle. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +gpgme_key_t EXTENDED: New field keylist_mode. +gpgme_decrypt_result_t EXTENDED: New field wrong_key_usage. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +Noteworthy changes in version 0.4.7 (2004-04-29) +------------------------------------------------ + + * Correctly initialize the fields expired, revoked, invalid, and + disabled in the gpgme_key_t structures. + + * A bug fix: The flag wrong_key_usage of gpgme_signature_t was + accidently of type int instead unsigned int. + + * Interface changes relative to the 0.4.5 release: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +gpgme_signature_t CHANGED: wrong_key_usage is unsigned int now. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Noteworthy changes in version 0.4.6 (2004-04-06) +------------------------------------------------ + + * Bug fixes + + +Noteworthy changes in version 0.4.5 (2004-03-07) +------------------------------------------------ + + * GPGME is now compiled with LFS (large file support) by default. + This means that _all_ programs using GPGME must be compiled with + LFS support enabled by default. You can do this easily with + autoconf, by using the AC_SYS_LARGEFILE macro. Or you can do this + without autoconf by defining the preprocessor symbol + _FILE_OFFSET_BITS to 64 (by passing the -D_FILE_OFFSET_BITS=64 to + the C compiler command line, or by defining this preprocessor + symbol before including any system header files). For more + details, read the section on LFS in the manual. + + Up to now, it was undocumented that GPGME was not using LFS. + But the public interfaces use off_t, and file descriptors are + exchanged between the application and GPGME. This was an oversight, + and bound to cause troubles in the future. + + Writing GPGME as a dual mode library that seamlessly supports LFS + while keeping backwards compatibility is possible, but does not + solve the problem: Many applications already expect GPGME to have + LFS (they are compiled with off_t being a 64bit value). This is true + in particular for the popular Gtk+ and Qt programs. + + So, although this is an ABI (but not an API) break, we will not + change the library version to reflect that. Because the interfaces + affected are probably not used yet in any GPGME 0.4 based + application, we don't expect any real failures from this change. + In fact, applications already using LFS will have some subtle bugs + fixed. + + However, if you encounter an application using GPGME 0.4.x that + does _not_ use LFS by default (off_t is a 32bit value), _and_ + uses at least one of the functions gpgme_data_seek, + gpgme_data_new_from_filepart, or a gpgme_data_seek_cb_t with + gpgme_data_new_from_cbs, then indeed this library will be ABI + incompatible with the program. As said above, we don't believe + such a program exists. If we are in error, then you have two + options: As a quick hack, you can configure GPGME with the + --disable-largefile option. This will revert the change, and GPGME + will not use LFS. However, GPGME will be incompatible with + programs that expect GPGME to use LFS. All applications are + required to use LFS when using GPGME, so this is only good as a + temporary local work-around. + + The other option is to change the versioning of the library and + recompile all applications. We have reserved a special version of + the library for that, so you can do that without expecting a + version clash in the future. Furthermore, everyone who does this + will agree on the version to use (this is important for + distribution makers). Read the comment in configure.ac (before + LIBGPGME_LT_AGE) if you want to do this. Please don't do this + blindly: As stated above, we think it is unlikely this measure is + needed. Still, it is there if necessary. If in doubt, contact us + and we will give our advise for your specific situation. + + * New key listing mode GPGME_KEYLIST_MODE_VALIDATE for validation of + the listed keys. + + * New interface gpgme_cancel() that can be used to cancel + asynchronous operations. + + * Interface changes relative to the 0.4.4 release: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +gpgme_data_seek_cb_t CHANGED: off_t is now a largefile type. +gpgme_data_seek CHANGED: off_t is now a largefile type. +gpgme_data_new_from_filepart CHANGED: off_t is now a largefile type. +GPGME_KEYLIST_MODE_VALIDATE NEW +gpgme_cancel NEW +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Noteworthy changes in version 0.4.4 (2004-01-12) +------------------------------------------------ + + * The member "class" in gpgme_key_sig_t and gpgme_new_signature_t has + been renamed to "sig_class", to avoid clash with C++ compilers. In + the C API, the old name "class" has been preserved for backwards + compatibility, but is deprecated. + + * Interface changes relative to the 0.4.3 release: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +gpgme_key_sig_t CHANGED: class deprecated, use new sig_class. +gpgme_new_signature_t CHANGED: class deprecated, use new sig_class. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Noteworthy changes in version 0.4.3 (2003-10-06) +------------------------------------------------ + + * libgpgme should not be used for threaded programs anymore. This + never worked reliably in all cases, because you had to + be careful about the linking order and libtool wouldn't do that for + you automatically. Instead, now you have to link against + libgpgme-pthread for applications using pthread and libgpgme-pth for + applications using GNU Pth. + + The old code for automagically detecting the thread library is + still part of libgpgme, but it is DEPRECATED. + + * There are new automake macros AM_PATH_GPGME_PTH and + AM_PATH_GPGME_PTHREAD, which support checking for thread-enabled + versions of GPGME. They define GPGME_PTH_CFLAGS, GPGME_PTH_LIBS, + GPGME_PTHREAD_CFLAGS and GPGME_PTHREAD_LIBS respectively. These + variables of course also include the configuration for the thread + package itself. Alternatively, use libtool. + + * gpgme_strerror_r as a thread safe variant of gpgme_strerror was + added. + + * gpgme-config doesn't support setting the prefix or exec prefix + anymore. I don't think it ever worked correctly, and it seems to + be pointless. + + * gpgme_get_key fails with GPG_ERR_AMBIGUOUS_NAME if the key ID + provided was not unique, instead returning the first matching key. + + * gpgme_key_t and gpgme_subkey_t have a new field, can_authenticate, + that indicates if the key can be used for authentication. + + * gpgme_signature_t's status field is now correctly set to an error + with error code GPG_ERR_NO_PUBKEY if public key is not found. + + * gpgme_new_signature_t's class field is now an unsigned int, rather + than an unsigned long (the old class field is preserved for + backwards compatibility). + + * A new function gpgme_set_locale() is provided to allow configuring + the locale for the crypto backend. This is necessary for text + terminals so that programs like the pinentry can be started with + the right locale settings for the terminal the application is running + on, in case the terminal has different settings than the system + default (for example, if it is a remote terminal). You are highly + recommended to call the following functions directly after + gpgme_check_version: + + #include + + setlocale (LC_ALL, ""); + gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL)); + gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL)); + + GPGME can not do this for you, as setlocale is not thread safe, and + there is no alternative. + + * The signal action for SIGPIPE is now set to SIG_IGN by + gpgme_check_version, instead the first time a crypto engine is + started (which is not well defined). + + * In the output of gpgme_hash_algo_name, change RMD160 to RIPEMD160, + TIGER to TIGER192, CRC32-RFC1510 to CRC32RFC1510, and CRC24-RFC2440 + to CRC24RFC2440. For now, these strings can be used as the MIC + parameter for PGP/MIME (if appropriately modified). + + * Interface changes relative to the 0.4.2 release: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +gpgme_strerror_t NEW +gpgme_get_key CHANGED: Fails correctly if key ID not unique. +gpgme_key_t EXTENDED: New field can_authenticate. +gpgme_subkey_t EXTENDED: New field can_authenticate. +gpgme_new_signature_t CHANGED: New type for class field. +gpgme_set_locale NEW +gpgme_hash_algo_name CHANGED: Slight adjustment of algo names. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Noteworthy changes in version 0.4.2 (2003-07-30) +------------------------------------------------ + + * Allow gpg-error to be in non-standard place when linking the test suite. + + * Configure will fail now if gpg-error can not be found. + + * Fixed initialized memory backed data objects for writing, which + caused the test program to crash (but only on Mac OS, surprisingly). + + * Eliminate use of C99 constructs. + + * Small improvements to the manual. + + +Noteworthy changes in version 0.4.1 (2003-06-06) +------------------------------------------------ + + This is the release that 0.4.0 should have been. There are many + interface changes, please see below for the details. The changes are + sometimes the result of new functionality, but more often express a + paradigm shift. Others are an overdue cleanup to get GPGME in line + with the GNU coding standards and to make the interface more + self-consistent. Here is an overview on the changes: + + All types have been renamed to conform to the GNU coding standards, + most of the time by keeping the whole name in lowercase and inserting + underscores between words. + + All operations consistently only accept input parameters in their + invocation function, and return only an error code directly. Further + information about the result of the operation has to be retrieved + afterwards by calling one of the result functions. This unifies the + synchronous and the asynchronous interface. + + The error values have been completely replaced by a more + sophisticated model that allows GPGME to transparently and accurately + report all errors from the other GnuPG components, irregardless of + process boundaries. This is achieved by using the library + libgpg-errors, which is shared by all GnuPG components. This library + is now required for GPGME. + + The results of all operations are now provided by pointers to C + structs rather than by XML structs or in other ways. + + Objects which used to be opaque (for example a key) are now pointers + to accessible structs, so no accessor functions are necessary. + + Backward compatibility is provided where it was possible without too + much effort and did not collide with the overall sanitization effort. + However, this is only for ease of transition. NO DEPRECATED FUNCTION + OR DATA TYPE IS CONSIDERED A PART OF THE API OR ABI AND WILL BE + DROPPED IN THE FUTURE WITHOUT CHANGING THE SONAME OF THE LIBRARY. + Recommendations how to replace deprecated or removed functionality + can be found within the description of each change. + + What follows are all changes to the interface and behaviour of GPGME + in detail. + + * If gpgme.h is included in sources compiled by GCC 3.1 or later, + deprecated attributes will warn about use of obsolete functions and + type definitions. You can suppress these warnings by passing + -Wno-deprecated-declarations to the gcc command. + + * The following types have been renamed. The old types are still + available as aliases, but they are deprecated now: + Old name: New name: + GpgmeCtx gpgme_ctx_t + GpgmeData gpgme_data_t + GpgmeError gpgme_error_t + GpgmeDataEncoding gpgme_data_encoding_t + GpgmeSigStat gpgme_sig_stat_t + GpgmeSigMode gpgme_sig_mode_t + GpgmeAttr gpgme_attr_t + GpgmeValidity gpgme_validity_t + GpgmeProtocol gpgme_protocol_t + GpgmeKey gpgme_key_t + GpgmePassphraseCb gpgme_passphrase_cb_t + GpgmeProgressCb gpgme_progress_cb_t + GpgmeIOCb gpgme_io_cb_t + GpgmeRegisterIOCb gpgme_register_io_cb_t + GpgmeRemoveIOCb gpgme_remove_io_cb_t + GpgmeEventIO gpgme_event_io_t + GpgmeEventIOCb gpgme_event_io_cb_t + GpgmeIOCbs gpgme_io_cbs + GpgmeDataReadCb gpgme_data_read_cb_t + GpgmeDataWriteCb gpgme_data_write_cb_t + GpgmeDataSeekCb gpgme_data_seek_cb_t + GpgmeDataReleaseCb gpgme_data_release_cb_t + GpgmeDataCbs gpgme_data_cbs_t + GpgmeTrustItem gpgme_trust_item_t + GpgmeStatusCode gpgme_status_code_t + + * gpgme_error_t is now identical to gpg_error_t, the error type + provided by libgpg-error. More about using libgpg-error with GPGME + can be found in the manual. All error symbols have been removed! + + * All functions and types in libgpg-error have been wrapped in GPGME. + The new types are gpgme_err_code_t and gpgme_err_source_t. The new + functions are gpgme_err_code, gpgme_err_source, gpgme_error, + gpgme_err_make, gpgme_error_from_errno, gpgme_err_make_from_errno, + gpgme_err_code_from_errno, gpgme_err_code_to_errno, + gpgme_strsource. + + * GPGME_ATTR_IS_SECRET is not anymore representable as a string. + + * GnuPG 1.2.2 is required. The progress callback is now also invoked + for encrypt, sign, encrypt-sign, decrypt, verify, and + decrypt-verify operations. For verify operations on detached + signatures, the progress callback is invoked for both the detached + signature and the plaintext message, though. + + * gpgme_passphrase_cb_t has been changed to not provide a complete + description, but the UID hint, passphrase info and a flag + indicating if this is a repeated attempt individually, so the user + can compose his own description from this information. + + The passphrase is not returned as a C string, but must be written + to a file descriptor directly. This allows for secure passphrase + entries. + + The return type has been changed to gpgme_error_t value. This + allowed to remove the gpgme_cancel function; just return + the error code GPG_ERR_CANCELED in the passphrase callback directly. + + * gpgme_edit_cb_t has been changed to take a file descriptor argument. + The user is expected to write the response to the file descriptor, + followed by a newline. + + * The recipients interface has been removed. Instead, you use + NULL-terminated lists of keys for specifying the recipients of an + encryption operation. Use the new encryption flag + GPGME_ENCRYPT_ALWAYS_TRUST if you want to override the validity of + the keys (but note that in general this is not a good idea). + + This change has been made to the prototypes of gpgme_op_encrypt, + gpgme_op_encrypt_start, gpgme_op_encrypt_sign and + gpgme_op_encrypt_sign_start. + + The export interface has been changed to use pattern strings like + the keylist interface. Thus, new functions gpgme_op_export_ext and + gpgme_op_export_ext_start have been added as well. Now the + prototypes of gpgme_op_export_start and gpgme_op_export finally + make sense. + + * gpgme_op_verify and gpgme_op_decrypt_verify don't return a status + summary anymore. Use gpgme_get_sig_status to retrieve the individual + stati. + + * gpgme_io_cb_t changed from a void function to a function returning + a gpgme_error_t value. However, it will always return 0, so you + can safely ignore the return value. + + * A new I/O callback event GPGME_EVENT_START has been added. The new + requirement is that you must wait until this event until you are + allowed to call the I/O callback handlers previously registered for + this context operation. Calling I/O callback functions for this + context operation before the start event happened is unsafe because + it can lead to race conditions in a multi-threaded environment. + + * The idle function feature has been removed. It was not precisely + defined in a multi-threaded environment and is obsoleted by the + user I/O callback functions. If you still need a simple way to + call something while waiting on one or multiple asynchronous + operations to complete, don't set the HANG flag in gpgme_wait (note + that this will return to your program more often than the idle + function did). + + * gpgme_wait can return NULL even if hang is true, if an error + occurs. In that case *status contains the error code. + + * gpgme_get_engine_info was radically changed. Instead an XML + string, an info structure of the new type gpgme_engine_info_t is + returned. This makes it easier and more robust to evaluate the + information in an application. + + * The new function gpgme_get_protocol_name can be used to convert a + gpgme_protocol_t value into a string. + + * The status of a context operation is not checked anymore. Starting + a new operation will silently cancel the previous one. Calling a + function that requires you to have started an operation before without + doing so is undefined. + + * The FPR argument to gpgme_op_genkey was removed. Instead, use the + gpgme_op_genkey_result function to retrieve a gpgme_genkey_result_t + pointer to a structure which contains the fingerprint. This also + works with gpgme_op_genkey_start. The structure also provides + other information about the generated keys. + + So, instead: + + char *fpr; + err = gpgme_op_genkey (ctx, NULL, NULL, &fpr); + if (!err && fpr) + printf ("%s\n", fpr); + + you should now do: + + gpgme_genkey_result_t result; + err = gpgme_op_genkey (ctx, NULL, NULL); + if (!err) + { + result = gpgme_op_genkey_result (ctx); + if (result->fpr) + printf ("%s\n", result->fpr); + } + + * The new gpgme_op_import_result function provides detailed + information about the result of an import operation in + gpgme_import_result_t and gpgme_import_status_t objects. + Thus, the gpgme_op_import_ext variant is deprecated. + + * The new gpgme_op_sign_result function provides detailed information + about the result of a signing operation in gpgme_sign_result_t, + gpgme_invalid_key_t and gpgme_new_signature_t objects. + + * The new gpgme_op_encrypt_result function provides detailed + information about the result of an encryption operation in + a GpgmeEncryptResult object. + + * The new gpgme_op_decrypt_result function provides detailed + information about the result of a decryption operation in + a GpgmeDecryptResult object. + + * The new gpgme_op_verify_result function provides detailed + information about the result of an verify operation in + a GpgmeVerifyResult object. Because of this, the GPGME_SIG_STAT_* + values, gpgme_get_sig_status, gpgme_get_sig_ulong_attr, + gpgme_get_sig_string_attr and gpgme_get_sig_key are now deprecated, + and gpgme_get_notation is removed. + + * GpgmeTrustItem objects have now directly accessible data, so the + gpgme_trust_item_get_string_attr and gpgme_trust_item_get_ulong_attr + accessor functions are deprecated. Also, reference counting is + available through gpgme_trust_item_ref and gpgme_trust_item_unref + (the gpgme_trust_item_release alias for the latter is deprecated). + + * Keys are not cached internally anymore, so the force_update argument + to gpgme_get_key has been removed. + + * GpgmeKey objects have now directly accessible data so the + gpgme_key_get_string_attr, gpgme_key_get_ulong_attr, + gpgme_key_sig_get_string_attr and gpgme_key_sig_get_ulong_attr + functions are deprecated. Also, gpgme_key_release is now + deprecated. The gpgme_key_get_as_xml function has been dropped. + + * Because all interfaces using attributes are deprecated, the + GpgmeAttr data type is also deprecated. + + * The new gpgme_op_keylist_result function provides detailed + information about the result of a key listing operation in + a GpgmeKeyListResult object. + + * Now that each function comes with its own result retrieval + interface, the generic gpgme_get_op_info interface is not useful + anymore and dropped. + + * The type and mode of data objects is not available anymore. + + * Interface changes relative to the 0.4.0 release: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +GpgmeCtx DEPRECATED: Use gpgme_ctx_t. +GpgmeData DEPRECATED: Use gpgme_data_t. +GpgmeError DEPRECATED: Use gpgme_error_t. +GpgmeDataEncoding DEPRECATED: Use gpgme_data_encoding_t. +GpgmeSigStat DEPRECATED: Use gpgme_sig_stat_t. +GpgmeSigMode DEPRECATED: Use gpgme_sig_mode_t. +GpgmeAttr DEPRECATED: Use gpgme_attr_t. +GpgmeValidity DEPRECATED: Use gpgme_validity_t. +GpgmeProtocol DEPRECATED: Use gpgme_protocol_t. +GpgmeKey DEPRECATED: Use gpgme_key_t. +GpgmePassphraseCb DEPRECATED: Use gpgme_passphrase_cb_t. +GpgmeProgressCb DEPRECATED: Use gpgme_progress_cb_t. +GpgmeIOCb DEPRECATED: Use gpgme_io_cb_t. +GpgmeRegisterIOCb DEPRECATED: Use gpgme_register_io_cb_t. +GpgmeRemoveIOCb DEPRECATED: Use gpgme_remove_io_cb_t. +GpgmeEventIO DEPRECATED: Use gpgme_event_io_t. +GpgmeEventIOCb DEPRECATED: Use gpgme_event_io_cb_t. +GpgmeIOCbs DEPRECATED: Use gpgme_io_cbs. +GpgmeDataReadCb DEPRECATED: Use gpgme_data_read_cb_t. +GpgmeDataWriteCb DEPRECATED: Use gpgme_data_write_cb_t. +GpgmeDataSeekCb DEPRECATED: Use gpgme_data_seek_cb_t. +GpgmeDataReleaseCb DEPRECATED: Use gpgme_data_release_cb_t. +GpgmeDataCbs DEPRECATED: Use gpgme_data_cbs_t. +GpgmeTrustItem DEPRECATED: Use gpgme_trust_item_t. +GpgmeStatusCode DEPRECATED: Use gpgme_status_code_t. +gpgme_ctx_t NEW +gpgme_data_t NEW +gpgme_recipients_t NEW +gpgme_error_t NEW +gpgme_data_encoding_t NEW +gpgme_sig_stat_t NEW +gpgme_sig_mode_t NEW +gpgme_attr_t NEW +gpgme_validity_t NEW +gpgme_protocol_t NEW +gpgme_key_t NEW +gpgme_passphrase_cb_t NEW +gpgme_progress_cb_t NEW +gpgme_io_cb_t NEW +gpgme_register_io_cb_t NEW +gpgme_remove_io_cb_t NEW +gpgme_event_io_t NEW +gpgme_event_io_cb_t NEW +gpgme_io_cbs NEW +gpgme_data_read_cb_t NEW +gpgme_data_write_cb_t NEW +gpgme_data_seek_cb_t NEW +gpgme_data_release_cb_t NEW +gpgme_data_cbs_t NEW +gpgme_trust_item_t NEW +gpgme_status_code_t NEW +GPGME_{some error code} REMOVED! Use GPG_ERR_* from libgpg-error. +gpgme_err_code_t NEW +gpgme_err_source_t NEW +gpgme_err_code NEW +gpgme_err_source NEW +gpgme_error NEW +gpgme_err_make NEW +gpgme_error_from_errno NEW +gpgme_err_make_from_errno NEW +gpgme_err_code_from_errno NEW +gpgme_err_code_to_errno NEW +gpgme_strsource NEW +gpgme_io_cb_t CHANGED: Return type from void to GpgmeError. +gpgme_event_io_t CHANGED: New event type (all numbers changed). +gpgme_passphrase_cb_t CHANGED: Desc decomposed, write directly to FD. +gpgme_edit_cb_t CHANGED: Write directly to FD. +gpgme_key_get_string_attr CHANGED: Don't handle GPGME_ATTR_IS_SECRET. +gpgme_op_verify CHANGED: Drop R_STAT argument. +gpgme_op_decrypt_verify CHANGED: Drop R_STAT argument. +gpgme_wait CHANGED: Can return NULL even if hang is true. +GpgmeIdleFunc REMOVED +gpgme_register_idle REMOVED +GpgmeRecipients REMOVED +gpgme_recipients_new REMOVED +gpgme_recipients_release REMOVED +gpgme_recipients_add_name REMOVED +gpgme_recipients_add_name_with_validity REMOVED +gpgme_recipients_count REMOVED +gpgme_recipients_enum_open REMOVED +gpgme_recipients_enum_read REMOVED +gpgme_recipients_enum_close REMOVED +gpgme_encrypt_flags_t NEW +GPGME_ENCRYPT_ALWAYS_TRUST NEW +gpgme_op_encrypt CHANGED: Recipients passed as gpgme_key_t[]. +gpgme_op_encrypt_start CHANGED: Recipients passed as gpgme_key_t[]. +gpgme_op_encrypt_sign CHANGED: Recipients passed as gpgme_key_t[]. +gpgme_op_encrypt_sign_start CHANGED: Recipients passed as gpgme_key_t[]. +gpgme_op_export_start CHANGED: User IDs passed as patterns. +gpgme_op_export CHANGED: User IDs passed as patterns. +gpgme_op_export_ext_start NEW +gpgme_op_export_ext NEW +gpgme_keylist_mode_t NEW +gpgme_sigsum_t NEW +gpgme_engine_info_t NEW +gpgme_get_engine_info CHANGED: Return info structure instead XML. +gpgme_get_protocol_name NEW +gpgme_cancel REMOVED: Return error in callback directly. +gpgme_op_genkey CHANGED: FPR argument dropped. +gpgme_op_genkey_result NEW +gpgme_genkey_result_t NEW +gpgme_op_import_ext DEPRECATED: Use gpgme_op_import_result. +gpgme_op_import_result NEW +gpgme_import_status_t NEW +gpgme_import_result_t NEW +gpgme_pubkey_algo_t NEW +gpgme_hash_algo_t NEW +gpgme_invalid_key_t NEW +gpgme_new_signature_t NEW +gpgme_sign_result_t NEW +gpgme_op_sign_result NEW +gpgme_pubkey_algo_name NEW +gpgme_hash_algo_name NEW +gpgme_encrypt_result_t NEW +gpgme_op_encrypt_result NEW +gpgme_decrypt_result_t NEW +gpgme_op_decrypt_result NEW +gpgme_verify_result_t NEW +gpgme_op_verify_result NEW +gpgme_get_notation REMOVED: Access verify result directly instead. +gpgme_get_sig_key DEPRECATED: Use gpgme_get_key with fingerprint. +gpgme_get_sig_ulong_attr DEPRECATED: Use verify result directly. +gpgme_get_sig_string_attr DEPRECATED: Use verify result directly. +GPGME_SIG_STAT_* DEPRECATED: Use error value in sig status. +gpgme_get_sig_status DEPRECATED: Use verify result directly. +gpgme_trust_item_t CHANGED: Now has user accessible data members. +gpgme_trust_item_ref NEW +gpgme_trust_item_unref NEW +gpgme_trust_item_release DEPRECATED: Use gpgme_trust_item_unref. +gpgme_trust_item_get_string_attr DEPRECATED +gpgme_trust_item_get_ulong_attr DEPRECATED +gpgme_get_key CHANGED: Removed force_update argument. +gpgme_sub_key_t NEW +gpgme_key_sig_t NEW +gpgme_user_id_t NEW +gpgme_key_t CHANGED: Now has user accessible data members. +gpgme_key_get_string_attr DEPRECATED +gpgme_key_get_ulong_attr DEPRECATED +gpgme_key_sig_get_string_attr DEPRECATED +gpgme_key_sig_get_ulong_attr DEPRECATED +gpgme_key_get_as_xml REMOVED +gpgme_key_list_result_t NEW +gpgme_op_keylist_result NEW +gpgme_get_op_info REMOVED +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Noteworthy changes in version 0.4.0 (2002-12-23) +------------------------------------------------ + + * Key generation returns the fingerprint of the generated key. + + * New convenience function gpgme_get_key. + + * Supports signatures of user IDs in keys via the new + GPGME_KEYLIST_MODE_SIGS keylist mode and the + gpgme_key_sig_get_string_attr and gpgme_key_sig_get_ulong_attr + interfaces. The XML info about a key also includes the signatures + if available. + + * New data object interface, which is more flexible and transparent. + + * Interface changes relative to the 0.3.9 release: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +GpgmeDataReadCb NEW +GpgmeDataWriteCb NEW +GpgmeDataSeekCb NEW +GpgmeDataReleaseCb NEW +GpgmeDataCbs NEW +gpgme_data_read CHANGED: Match read() closely. +gpgme_data_write CHANGED: Match write() closely. +gpgme_data_seek NEW +gpgme_data_new_from_fd NEW +gpgme_data_new_from_stream NEW +gpgme_data_new_from_cbs NEW +gpgme_data_rewind DEPRECATED: Replaced by gpgme_data_seek(). +gpgme_data_new_from_read_cb DEPRECATED: Replaced by gpgme_data_from_cbs(). +gpgme_data_get_type REMOVED: No replacement. +gpgme_op_verify CHANGED: Take different data objects for + signed text and plain text. +gpgme_op_verify_start CHANGED: See gpgme_op_verify. +gpgme_check_engine REMOVED: Deprecated since 0.3.0. +gpgme_op_genkey CHANGED: New parameter FPR. +GPGME_KEYLIST_MODE_SIGS NEW +gpgme_key_sig_get_string_attr NEW +gpgme_key_sig_get_ulong_attr NEW +gpgme_get_key NEW +GPGME_ATTR_SIG_CLASS NEW +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Noteworthy changes in version 0.3.16 (2003-11-19) +------------------------------------------------- + + * Compatibility fixes for GnuPG 1.9.x + +Noteworthy changes in version 0.3.15 (2003-02-18) +------------------------------------------------- + + * The progress status is sent via the progress callbacks in + gpgme_op_edit. + + * Bug fix for signing operations with explicit signer settings for + the CMS protocol. + +Noteworthy changes in version 0.3.14 (2002-12-04) +------------------------------------------------- + + * GPGME-Plug is now in its own package "cryptplug". + + * Workaround for a setlocale problem. Fixed a segv related to not + correctly as closed marked file descriptors. + +Noteworthy changes in version 0.3.13 (2002-11-20) +------------------------------------------------- + + * Release due to changes in gpgmeplug. + +Noteworthy changes in version 0.3.12 (2002-10-15) +------------------------------------------------- + + * Fixed some bux with key listings. + + * The development has been branched to clean up some API issues. + This 0.3 series will be kept for compatibility reasons; so do don't + expect new features. + +Noteworthy changes in version 0.3.11 (2002-09-20) +------------------------------------------------- + + * Bug fixes. + +Noteworthy changes in version 0.3.10 (2002-09-02) +------------------------------------------------- + + * Setting the signing keys for the CMS protocol does now work. + + * The signers setting is honoured by gpgme_op_edit. + +Noteworthy changes in version 0.3.9 (2002-08-21) +------------------------------------------------ + + * A spec file for creating RPMs has been added. + + * An experimental interface to GnuPG's --edit-key functionality is + introduced, see gpgme_op_edit. + + * The new gpgme_import_ext function provides a convenient access to + the number of processed keys. + + * Interface changes relative to the 0.3.8 release: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +GpgmeStatusCode NEW +GpgmeEditCb NEW +gpgme_op_edit_start NEW +gpgme_op_edit NEW +gpgme_op_import_ext NEW +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Noteworthy changes in version 0.3.8 (2002-06-25) +------------------------------------------------ + + * It is possible to use an outside event loop for the I/O to the + crypto engine by setting the I/O callbacks with gpgme_set_io_cbs. + + * Interface changes relative to the 0.3.6 release: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +GpgmeIOCb NEW +GpgmeRegisterIOCb NEW +GpgmeRemoveIOCb NEW +GpgmeEventIO NEW +GpgmeEventIOCb NEW +struct GpgmeIOCbs NEW +gpgme_set_io_cbs NEW +gpgme_get_io_cbs NEW +GPGME_ATTR_ERRTOK NEW +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Noteworthy changes in version 0.3.7 (2002-06-04) +------------------------------------------------ + + * GPGME_ATTR_OTRUST is implemented now. + + * A first step toward thread safeness has been achieved, see the + documentation for details. Supported thread libraries are pthread + and Pth. + +Noteworthy changes in version 0.3.6 (2002-05-03) +------------------------------------------------ + + * All error output of the gpgsm backend is send to the bit bucket. + + * The signature verification functions are extended. Instead of + always returning GPGME_SIG_STATUS_GOOD, the functions new codes for + expired signatures. 2 new functions may be used to retrieve more + detailed information like the signature expiration time and a + validity information of the key without an extra key looking. + + * The current passphrase callback and progress meter callback can be + retrieved with the new functions gpgme_get_passphrase_cb and + gpgme_get_progress_cb respectively. + + * Interface changes relative to the 0.3.5 release: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +gpgme_get_passphrase_cb NEW +gpgme_get_progress_cb NEW +GpgmeDataEncoding NEW +gpgme_data_set_encoding NEW +gpgme_data_get_encoding NEW +GPGME_SIG_STAT_GOOD_EXP NEW +GPGME_SIG_STAT_GOOD_EXPKEY NEW +gpgme_op_verify CHANGED: Returns more status codes. +GPGME_ATTR_SIG_STATUS NEW +gpgme_get_sig_string_attr NEW +gpgme_get_sig_ulong_attr NEW +gpgme_get_protocol NEW +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Noteworthy changes in version 0.3.5 (2002-04-01) +------------------------------------------------ + + * gpgme_op_encrypt can be called with RECIPIENTS being 0. In this + case, symmetric encryption is performed. Note that this requires a + passphrase from the user. + + * More information is returned for X.509 certificates. + + * Interface changes relative to the 0.3.4 release: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +gpgme_op_encrypt EXTENDED: Symmetric encryption possible +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Noteworthy changes in version 0.3.4 (2002-03-04) +------------------------------------------------ + + * gpgme_op_encrypt does now fail with GPGME_Invalid_Recipients if + some recipients have been invalid, whereas earlier versions + succeeded in this case. The plaintext is still encrypted for all valid + recipients, so the application might take this error as a hint that + the ciphertext is not usable for all requested recipients. + Information about invalid recipients is available with gpgme_get_op_info. + + * gpgme_op_verify now allows to pass an uninitialized data object as + its plaintext argument to check for normal and cleartext + signatures. The plaintext is then returned in the data object. + + * New interfaces gpgme_set_include_certs and gpgme_get_include_certs + to set and get the number of certifications to include in S/MIME + signed messages. + + * New interfaces gpgme_op_encrypt_sign and gpgme_op_encrypt_sign_start + to encrypt and sign a message in a combined operation. + + * New interface gpgme_op_keylist_ext_start to search for multiple patterns. + + * gpgme_key_get_ulong_attr supports the GPGME_ATTR_EXPIRE attribute. + + * Interface changes relative to the 0.3.3 release: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +gpgme_op_encrypt CHANGED: Can fail with GPGME_Invalid_Recipients +gpgme_op_verify EXTENDED: Accepts uninitialized text argument +gpgme_key_get_ulong_attr EXTENDED: Supports GPGME_ATTR_EXPIRE +gpgme_set_include_certs NEW +gpgme_get_include_certs NEW +gpgme_op_encrypt_sign NEW +gpgme_op_encrypt_sign_start NEW +gpgme_op_keylist_ext_start NEW +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Noteworthy changes in version 0.3.3 (2002-02-12) +------------------------------------------------ + + * Fix the Makefile in jnlib. + + * Fix the test suite (hopefully). It should clean up all its state + with `make check' now. + + +Noteworthy changes in version 0.3.2 (2002-02-10) +------------------------------------------------ + + * Remove erroneous dependency on libgcrypt in jnlib. + + +Noteworthy changes in version 0.3.1 (2002-02-09) +------------------------------------------------ + + * There is a Texinfo manual documenting the API. + + * The gpgme_set_keylist_mode function returns an error, and changed + its meaning. It is no longer usable to select between normal and + fast mode (newer versions of GnuPG will always be fast), but + selects between local keyring, remote keyserver, or both. + For this, two new macros are defined, GPGME_KEYLIST_MODE_LOCAL + and GPGME_KEYLIST_MODE_EXTERN. To make it possible to modify the + current setting, a fucntion gpgme_get_keylist_mode was added to + retrieve the current mode. + + * gpgme_wait accepts a new argument STATUS to return the error status + of the operation on the context. Its definition is closer to + waitpid() now than before. + + * The LENGTH argument to gpgme_data_new_from_filepart changed its + type from off_t to the unsigned size_t. + + * The R_HD argument to the GpgmePassphraseCb type changed its type + from void* to void**. + + * New interface gpgme_op_trustlist_end() to match + gpgme_op_keylist_end(). + + * The CryptPlug modules have been renamed to gpgme-openpgp and + gpgme-smime, and they are installed in pkglibdir by `make install'. + + * An idle function can be registered with gpgme_register_idle(). + + * The GpgSM backend supports key generation with gpgme_op_genkey(). + + * Interface changes relative to the 0.3.0 release: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +gpgme_data_new_from_filepart CHANGED: Type of LENGTH is size_t. +GpgmePassphraseCb CHANGED: Type of R_HD is void **. +gpgme_wait CHANGED: New argument STATUS. +gpgme_set_keylist_mode CHANGED: Type of return value is GpgmeError. + The function has a new meaning! +gpgme_get_keylist_mode NEW +GPGME_KEYLIST_MODE_LOCAL NEW +GPGME_KEYLIST_MODE_EXTERN NEW +gpgme_op_trustlist_next NEW +GpgmeIdleFunc NEW +gpgme_register_idle NEW +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Noteworthy changes in version 0.3.0 (2001-12-19) +------------------------------------------------ + + * New interface gpgme_set_protocol() to set the protocol and thus the + crypto engine to be used by the context. Currently, the OpenPGP + and the CMS protocols are supported. They are specified by the new + preprocessor symbols GPGME_PROTOCOL_OpenPGP and GPGME_PROTOCOL_CMS. + A new context uses the OpenPGP engine by default. + + * gpgme_get_engine_info() returns information for all crypto engines + compiled into the library. The XML format has changed. To + reliably get the version of a crypto engine, the tag + after the appropriate tag has to be looked for. + + * New interface gpgme_engine_check_version(), obsoleting + gpgme_check_engine(). Check the version of all engines you are + supporting in your software. + + * GpgmeKey lists the user ids in the order as they are returned by + GnuPG, first the primary key with index 0, then the sub-user ids. + + * New operation gpgme_op_decrypt_verify() to decrypt and verify + signatures simultaneously. + + * The new interface gpgme_op_keylist_end() terminates a pending + keylist operation. A keylist operation is also terminated when + gpgme_op_keylist_next() returns GPGME_EOF. + + * GPGME can be compiled without GnuPG being installed (`--with-gpg=PATH'), + cross-compiled, or even compiled without support for GnuPG + (`--without-gpg'). + + * GPGME can be compiled with support for GpgSM (GnuPG for S/MIME, + `--with-gpgsm=PATH'). It is enabled by default if the `gpgsm' is found + in the path, but it can also be compiled without support for GpgSM + (`--without-gpgsm'). + + * CryptPlug modules for GPGME are included and can be enabled at + configure time (`--enable-gpgmeplug'). There is one module which + uses the GnuPG engine (`gpgmeplug') and one module which uses the + GpgSM engine (`gpgsmplug'). + + * Interface changes relative to the latest 0.2.x release: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +gpgme_key_get_as_xml CHANGED: Sub-user ids reversed in order. +gpgme_key_get_string_attr CHANGED: User ids reversed in order. +gpgme_key_get_ulong_attr CHANGED: User ids reversed in order. +gpgme_get_engine_info CHANGED: New format, extended content. +gpgme_engine_check_version NEW +gpgme_decrypt_verify_start NEW +gpgme_decrypt_verify NEW +gpgme_op_keylist_next NEW +gpgme_set_protocol NEW +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +Noteworthy changes in version 0.2.3 (2001-09-17) +------------------------------------------------ + + * New function gpgme_get_op_info which can be used to get the micalg + parameter needed for MOSS. + + * New functions gpgme_get_armor and gpgme_get_textmode. + + * The usual bug fixes and some minor functionality improvements. + + * Added a simple encryption component for MS-Windows; however the + build procedure might have some problems. + + +Noteworthy changes in version 0.2.2 (2001-06-12) +------------------------------------------------ + + * Implemented a key cache. + + * Fixed a race condition under W32 and some other bug fixes. + + +Noteworthy changes in version 0.2.1 (2001-04-02) +------------------------------------------------ + + * Changed debug output and GPGME_DEBUG variable (gpgme/debug.c) + + * Handle GnuPG's new key capabilities output and support revocation + et al. attributes + + * Made the W32 support more robust. + + + Copyright 2001, 2002, 2003, 2004, 2005, 2007 g10 Code GmbH + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/tags/gpgme-1.1.6/README b/tags/gpgme-1.1.6/README new file mode 100644 index 0000000..7594bda --- /dev/null +++ b/tags/gpgme-1.1.6/README @@ -0,0 +1,123 @@ + GPGME - GnuPG Made Easy + --------------------------- + + Copyright 2004, 2006 g10 Code GmbH + +This file is free software; as a special exception the author gives +unlimited permission to copy and/or distribute it, with or without +modifications, as long as this notice is preserved. + +This file is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. + + +Introduction +-------------- + +GnuPG Made Easy (GPGME) is a C language library that allows to add +support for cryptography to a program. It is designed to make access +to public key crypto engines like GnuPG or GpgSM easier for +applications. GPGME provides a high-level crypto API for encryption, +decryption, signing, signature verification and key management. + +GPGME uses GnuPG and GpgSM as its backends to support OpenPGP and the +Cryptographic Message Syntax (CMS). + +GPGME runs best on GNU/Linux or *BSD systems. Other Unices may +require small portability fixes, send us your patches. + +See the file COPYING.LESSER and each file for copyright and warranty +information. + + +Installation +-------------- + +See the file INSTALL for generic installation instructions. + +Check that you have unmodified sources. See below on how to do this. +Don't skip it - this is an important step! + +To build GPGME, you need to install libgpg-error. You need at least +libgpg-error 0.5. + +For support of the OpenPGP protocol (default), you should use the +latest version of GnuPG 1.2 or 1.4, available at: +ftp://ftp.gnupg.org/gcrypt/gnupg/ + +You need at least GnuPG 1.2.2. + +If configure can't find the `gpg' binary in your path, you can specify +the location with the --with-gpg=/path/to/gpg argument to configure. + +For support of the CMS (Cryptographic Message Syntax) protocol, you +need the latest CVS version of GnuPG 1.9, which is available in the +GnuPG repository: +http://www.gnupg.org/download/cvs_access.html +Use the tag `GNUPG-1-9-BRANCH'. There are also snapshots available at: +ftp://ftp.gnupg.org/gcrypt/alpha/gnupg/ + +You need at least GpgSM 1.9.6. + +If configure can't find the `gpgsm' binary in your path, you can +specify the location with the --with-gpgsm=/path/to/gpgsm argument to +configure. + +For building the CVS version of GPGME please see the file README.CVS +for more information. + + +How to Verify the Source +-------------------------- + +In order to check that the version of GPGME which you are going to +install is an original and unmodified one, you can do it in one of the +following ways: + +a) If you have a trusted Version of GnuPG installed, you can simply check + the supplied signature: + + $ gpg --verify gpgme-x.y.z.tar.gz.sig + + This checks that the detached signature gpgme-x.y.z.tar.gz.sig is + indeed a a signature of gpgme-x.y.z.tar.gz. The key used to create + this signature is either of: + + "pub 1024D/57548DCD 1998-07-07 Werner Koch (gnupg sig) " + "pub 1024D/87978569 1999-05-13 + Marcus Brinkmann + Marcus Brinkmann " + + If you do not have this key, you can get it from any keyserver. You + have to make sure that this is really the key and not a faked one. + You can do this by comparing the output of: + + $ gpg --fingerprint 0x57548DCD + + with the fingerprint published elsewhere. + +b) If you don't have any of the above programs, you have to verify + the SHA1 checksum: + + $ sha1sum gpgme-x.y.z.tar.gz + + This should yield an output _similar_ to this: + + fd9351b26b3189c1d577f0970f9dcadc3412def1 gpgme-x.y.z.tar.gz + + Now check that this checksum is _exactly_ the same as the one + published via the announcement list and probably via Usenet. + + +Documentation +--------------- + +For information how to use the library you can read the info manual, +which is also a reference book, in the doc/ directory. The programs +in the tests/gpg/ directory may also prove useful. + +Please subscribe to the gnupg-devel@gnupg.org mailing list if you want +to do serious work. + diff --git a/tags/gpgme-1.1.6/README.SVN b/tags/gpgme-1.1.6/README.SVN new file mode 100644 index 0000000..c642282 --- /dev/null +++ b/tags/gpgme-1.1.6/README.SVN @@ -0,0 +1,51 @@ +If you are building from Subversion, run the script + +./autogen.sh + +first, to make sure that you have all the necessary maintainer tools +are installed and to build the actual configuration files. If you +have just updated from SVN, you should add the option "--force" to +autogen.sh so that meta data from SVN is noticed. Then run + +./configure --enable-maintainer-mode + +followed by the usual make. + +If autogen.sh complains about insufficient versions of the required +tools, or the tools are not installed, you may use environment +variables to override the default tool names: + + AUTOMAKE_SUFFIX is used as a suffix for all tools from the automake + package. For example + AUTOMAKE_SUFFIX="-1.7" ./autogen.sh + uses "automake-1.7" and "aclocal-1.7. + AUTOMAKE_PREFIX is used as a prefix for all tools from the automake + page and may be combined with AUTOMAKE_SUFFIX. e.g.: + AUTOMAKE_PREFIX=/usr/foo/bin ./autogen.sh + uses "automake" and "aclocal" in the /usr/foo/bin + directory. + AUTOCONF_SUFFIX is used as a suffix for all tools from the automake + package + AUTOCONF_PREFIX is used as a prefix for all tools from the automake + package + GETTEXT_SUFFIX is used as a suffix for all tools from the gettext + package + GETTEXT_PREFIX is used as a prefix for all tools from the gettext + package + +It is also possible to use the variable name AUTOMAKE, AUTOCONF, +ACLOCAL, AUTOHEADER, GETTEXT and MSGMERGE to directly specify the name +of the programs to run. It is however better to use the suffix and +prefix forms as described above because that does not require +knowledge about the actual tools used by autgen.sh. + + +Please don't use autopoint, libtoolize or autoreconf unless you are +the current maintainer and want to update the standard configuration +files. All those files should be in the SVN and only updated manually +if the maintainer decides that newer versions are required. The +maintainer should also make sure that the required version of automake +et al. are properly indicated at the top of configure.ac and take care +to copy the files and not merely use symlinks. + + diff --git a/tags/gpgme-1.1.6/THANKS b/tags/gpgme-1.1.6/THANKS new file mode 100644 index 0000000..4fda3d5 --- /dev/null +++ b/tags/gpgme-1.1.6/THANKS @@ -0,0 +1,32 @@ +For a list of the authors of the source code of GPGME, please see the +file AUTHORS. The following people supported GPGME development in +various ways (for example by finding bugs or giving advice), and we +want to thank them for their help. If we forgot you, please let us +know. + +Adriaan de Groot adridg@cs.kun.nl +Albrecht Dreß albrecht.dress@arcor.de +Alfons Hoogervorst alfons@proteus.demon.nl +Enno Cramer uebergeek@web.de +Frank Heckenbach frank@g-n-u.de +Igor Belyi gpgme@katehok.ac93.org +Jan-Oliver Wagner jan@intevation.de +Johannes Poehlmann jhp@caldera.de +Jose C. García Sogo jose@jaimedelamo.eu.org +Mark Mutz mutz@kde.org +Miguel Coca mcoca@gnu.org +Noel Torres envite@rolamasao.org +Stéphane Corthésy stephane@sente.ch +Timo Schulz twoaday@freakmail.de +Tommy Reynolds reynolds@redhat.com + + + Copyright 2001, 2002, 2004 g10 Code GmbH + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/tags/gpgme-1.1.6/TODO b/tags/gpgme-1.1.6/TODO new file mode 100644 index 0000000..4bf5b9a --- /dev/null +++ b/tags/gpgme-1.1.6/TODO @@ -0,0 +1,187 @@ +Hey Emacs, this is -*- outline -*- mode! + +* Before release: +** Some gpg tests fail with gpg 1.3.4-cvs (gpg/t-keylist-sig) + The test is currently disabled there and in gpg/t-import. +** When gpg supports it, write binary subpackets directly, + and parse SUBPACKET status lines. + +* ABI's to break: +** gpgme_edit_cb_t: Add "processed" return argument + (see edit.c::command_handler). +** I/O and User Data could be made extensible. But this can be done + without breaking the ABI hopefully. +* All enums that should be enums need to have a maximum value to ensure + a certain minimum width for extensibility. +** Compatibility interfaces that can be removed in future versions: +*** gpgme_data_new_from_filepart +*** gpgme_data_new_from_file +*** gpgme_data_new_with_read_cb +*** gpgme_data_rewind +*** gpgme_op_import_ext +*** gpgme_get_sig_key +*** gpgme_get_sig_ulong_attr +*** gpgme_get_sig_string_attr +*** GPGME_SIG_STAT_* +*** gpgme_get_sig_status +*** gpgme_trust_item_release +*** gpgme_trust_item_get_string_attr +*** gpgme_trust_item_get_ulong_attr +*** gpgme_attr_t +*** All Gpgme* typedefs. + + +* Thread support: +** When GNU Pth supports sendmsg/recvmsg, wrap them properly. +** Without timegm (3) support our ISO time parser is not thread safe. + There is a configure time warning, though. + +* New features: +** Extended notation support. When gpg supports arbitrary binary + notation data, provide a user interface for that. +** notification system + We need a simple notification system, probably a simple callback + with a string and some optional arguments. This is for example + required to notify an application of a changed smartcard, The + application can then do whatever is required. There are other + usages too. This notfication system should be independent of any + contextes of course. +** --learn-code support + This might be integrated with import. we still need to work out how + to learn a card when gpg and gpgsm have support for smartcards. +** Might need a stat() for data objects and use it for length param to gpg. +** Implement support for photo ids. +** Allow selection of subkeys +** Allow to return time stamps in ISO format + This allows us to handle years later than 2037 properly. With the + time_t interface they are all mapped to 2037-12-31 +** New features requested by our dear users, but rejected or left for + later consideration: +*** Allow to export secret keys. + Rejected because this is conceptually flawed. Secret keys on a + smart card can not be exported, for example. +*** Selecting the key ring, setting the version or comment in output. + Rejected because the naive implementation is engine specific, the + configuration is part of the engine's configuration or readily + worked around in a different way +*** Selecting the symmetric cipher. +*** Exchanging keys with key servers. + +* Documentation +** Document validity and trust issues. +** In gpgme.texi: Register callbacks under the right letter in the index. + +* Engines +** Do not create/destroy engines, but create engine and then reset it. + Internally the reset operation still spawns a new engine process, + but this can be replaced with a reset later. Also, be very sure to + release everything properly at a reset and at an error. Think hard + about where to guarantee what (ie, what happens if start fails, are + the fds unregistered immediately - i think so?) + Note that we need support in gpgsm to set include-certs to default + as RESET does not reset it. +** Optimize the case where a data object has 0an underlying fd we can pass + directly to the engine. This will be automatic with socket I/O and + descriptor passing. +** Move code common to all engines up from gpg to engine. +** engine operations can return General Error on unknown protocol + (it's an internal error, as select_protocol checks already). +** When server mode is implemented properly, more care has to be taken to + release all resources on error (for example to free assuan_cmd). +* GPG breakage: +** gpg 1.4.2 lacks error reporting if sign/encrypt with revoked key. +** gpg 1.4.2 does crappy error reporting (namely none at all) when + smart card is missing for sign operation: + [GNUPG:] CARDCTRL 4 + gpg: selecting openpgp failed: ec=6.110 + gpg: signing failed: general error + [GNUPG:] BEGIN_ENCRYPTION 2 10 + gpg: test: sign+encrypt failed: general error +** Without agent and with wrong passphrase, gpg 1.4.2 enters into an + infinite loop. +** Use correct argv[0] + In rungpg.c:build_argv we use + argv[argc] = strdup ("gpg"); /* argv[0] */ + This should be changed to take the real file name used in account. + + +* Operations +** Include cert values -2, -1, 0 and 1 should be defined as macros. +** If an operation failed, make sure that the result functions don't return + corrupt partial information. !!! + NOTE: The EOF status handler is not called in this case !!! +** Verify must not fail on NODATA premature if auto-key-retrieval failed. + It should not fail silently if it knows there is an error. !!! +** All operations: Better error reporting. !! +** Export status handler need much more work. !!! +** Import should return a useful error when one happened. +*** Import does not take notice of NODATA status report. +*** When GPGSM does issue IMPORT_OK status reports, make sure to check for + them in tests/gpgs m/t-import.c. +** Verify can include info about version/algo/class, but currently + this is only available for gpg, not gpgsm. +** Return ENC_TO output in verify result. Again, this is not available + for gpgsm. +** Genkey should return something more useful than General_Error. +** If possible, use --file-setsize to set the file size for proper progress + callback handling. Write data interface for file size. +** Optimize the file descriptor list, so the number of open fds is + always known easily. +** Encryption: It should be verified that the behaviour for partially untrusted + recipients is correct. +** When GPG issues INV_something for invalid signers, catch them. + +* Error Values +** Map ASSUAN/GpgSM ERR error values in a better way than is done now. !! +** Some error values should identify the source more correctly (mostly error + values derived from status messages). + +* Tests +** Write a fake gpg-agent so that we can supply known passphrases to + gpgsm and setup the configuration files to use the agent. Without + this we are testing a currently running gpg-agent which is not a + clever idea. ! +** t-data +*** Test gpgme_data_release_and_get_mem. +*** Test gpgme_data_seek for invalid types. +** t-keylist + Write a test for ext_keylist. +** Test reading key signatures. + +* Debug +** Tracepoints should be added at: Every public interface enter/leave, + before and in every callback, at major decision points, at every + internal data point which might easily be observed by the outside + (system handles). We also trace handles and I/O support threads in + the w32 implementation because that's fragile code. + Files left to do: + data-fd.c data-mem.c data-stream.c data-user.c debug.c rungpg.c + engine.c engine-gpgsm.c funopen.c w32-glib-io.c wait.c + wait-global.c wait-private.c wait-user.c op-support.c decrypt.c + decrypt-verify.c delete.c edit.c encrypt.c encrypt-sign.c export.c + genkey.c import.c key.c keylist.c passphrase.c progress.c signers.c + sig-notation.c trust-item.c trustlist.c verify.c +** Handle malloc and vasprintf errors. But decide first if they should be + ignored (and logged with 255?!), or really be assertions. ! + +* Build suite +** Make sure everything is cleaned correctly (esp. test area). +** Enable AC_CONFIG_MACRO_DIR and bump up autoconf version requirement. + (To fix "./autogen.sh; ./configure --enable-maintainer-mode; touch + configure.ac; make"). Currently worked around with ACLOCAL_AMFLAGS??? + +* Error checking +** engine-gpgsm, with-validation + Add error checking some time after releasing a new gpgsm. + + +Copyright 2004, 2005 g10 Code GmbH + +This file is free software; as a special exception the author gives +unlimited permission to copy and/or distribute it, with or without +modifications, as long as this notice is preserved. + +This file is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. diff --git a/tags/gpgme-1.1.6/acinclude.m4 b/tags/gpgme-1.1.6/acinclude.m4 new file mode 100644 index 0000000..9676656 --- /dev/null +++ b/tags/gpgme-1.1.6/acinclude.m4 @@ -0,0 +1,86 @@ +dnl Macros to configure GPGME +dnl Copyright (C) 2004 g10 Code GmbH +dnl +dnl This file is part of GPGME. +dnl +dnl GPGME is free software; you can redistribute it and/or modify it +dnl under the terms of the GNU Lesser General Public License as +dnl published by the Free Software Foundation; either version 2.1 of the +dnl License, or (at your option) any later version. +dnl +dnl GPGME is distributed in the hope that it will be useful, but WITHOUT +dnl ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +dnl or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General +dnl Public License for more details. +dnl +dnl You should have received a copy of the GNU Lesser General Public +dnl License along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +dnl GNUPG_FIX_HDR_VERSION(FILE, NAME) +dnl Make the version number stored in NAME in the header file FILE the +dnl same as the one here. This is easier than to have a .in file just +dnl for one substitution. +dnl We must use a temp file in the current directory because make +dnl distcheck installs all sourcefiles RO. +dnl (wk 2001-12-18) +AC_DEFUN([GNUPG_FIX_HDR_VERSION], + [ sed "s/^#define $2 \".*/#define $2 \"$VERSION\"/" $srcdir/$1 > fixhdr.tmp + if cmp -s $srcdir/$1 fixhdr.tmp 2>/dev/null; then + rm -f fixhdr.tmp + else + rm -f $srcdir/$1 + if mv fixhdr.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 fixhdr.tmp +***]]) + fi + AC_MSG_WARN([fixed the $2 macro in $1]) + fi + ]) + +dnl GNUPG_CHECK_VA_COPY() +dnl Do some check on how to implement va_copy. +dnl May define MUST_COPY_VA_BY_VAL. +dnl Actual test code taken from glib-1.1. +AC_DEFUN([GNUPG_CHECK_VA_COPY], +[ AC_MSG_CHECKING(whether va_lists must be copied by value) + AC_CACHE_VAL(gnupg_cv_must_copy_va_byval,[ + if test "$cross_compiling" = yes; then + gnupg_cv_must_copy_va_byval=no + else + gnupg_cv_must_copy_va_byval=no + AC_TRY_RUN([ + #include + void f (int i, ...) + { + va_list args1, args2; + va_start (args1, i); + args2 = args1; + if (va_arg (args2, int) != 42 || va_arg (args1, int) != 42) + exit (1); + va_end (args1); + va_end (args2); + } + + int main() + { + f (0, 42); + return 0; + } + ],gnupg_cv_must_copy_va_byval=yes) + fi + ]) + if test "$gnupg_cv_must_copy_va_byval" = yes; then + AC_DEFINE(MUST_COPY_VA_BYVAL,1,[used to implement the va_copy macro]) + fi + if test "$cross_compiling" = yes; then + AC_MSG_RESULT(assuming $gnupg_cv_must_copy_va_byval) + else + AC_MSG_RESULT($gnupg_cv_must_copy_va_byval) + fi +]) diff --git a/tags/gpgme-1.1.6/assuan/ChangeLog b/tags/gpgme-1.1.6/assuan/ChangeLog new file mode 100644 index 0000000..4b24712 --- /dev/null +++ b/tags/gpgme-1.1.6/assuan/ChangeLog @@ -0,0 +1,1018 @@ +2007-09-25 Werner Koch + + * assuan.h (_assuan_gpg_strerror_r, _assuan_gpg_strsource): Add + new wrappers. + +2007-09-03 Marcus Brinkmann + + * assuan.h [_ASSUAN_EXT_SYM_PREFIX]: Add missing symbol renames + with _ASSUAN_PREFIX. + +2007-08-02 Werner Koch + + * assuan-pipe-connect.c (pipe_connect_w32): A bit more debug output. + (pipe_connect_w32): Use DETACHED_PROCESS flag. + * assuan-logging.c (log_level): New. Use this to disable logging. + (assuan_set_assuan_log_level): New. + * assuan.h: Add prototype. + +2007-07-12 Werner Koch + + * assuan-handler.c (assuan_get_active_fds): Use get_osfhandle for + the data fp. + * assuan-socket.c (_assuan_close) [W32]: Use CloseHandle and not close. + + * assuan-io.c (_assuan_simple_write, _assuan_simple_read): Map + ERROR_BROKEN_PIPE to EPIPE. + +2007-07-08 Marcus Brinkmann + + * assuan-defs.h (struct assuan_context_s): Have partial peercred + structure even if HAVE_W32_SYSTEM, and have full peercred + structure only if HAVE_SO_PEERCRED. + * assuan-connect.c (assuan_get_peercred) [!HAVE_SO_PEERCRED]: Do + not try to set PID, UID and GID. + +2007-07-04 Marcus Brinkmann + + Change _WIN32 to HAVE_W32_SYSTEM for consistency. + + * assuan-defs.h (struct assuan_context_s): Have full peercred + structure even if not HAVE_SO_PEERCRED, but not if + HAVE_W32_SYSTEM. + +2007-06-18 Werner Koch + + * assuan-logging.c (load_libgpg_error, _assuan_gpg_strerror_r) + (_assuan_gpg_strsource): New. + * assuan-handler.c (process_request) [W32]: Use these new + functions for human understable error codes. + +2007-06-12 Werner Koch + + * assuan-io.c (_assuan_simple_read): Hack to allow reading from a + socket. + (_assuan_simple_write): Likewise. + +2007-06-11 Werner Koch + + * assuan-io-pth.c (_assuan_simple_read, _assuan_simple_write): Use + pth versions also for W32. + +2007-05-29 Werner Koch + + * assuan-io-pth.c: Include sys/socket.h only if available. Remove + double inclusion of sys/wait.h + + * assuan-pipe-connect.c (build_w32_commandline): Make ARGV const. + + * assuan-pipe-server.c (is_valid_socket) [W32]: Do not define. + + * assuan-socket-server.c [W32]: Include ws2tcpip.h to define + socklen_t. + * assuan-defs.h (struct assuan_context_s): Define most peercred + members only if we can really set them. + (_assuan_simple_sendmsg, _assuan_simple_recvmsg) [W32]: Use a + different prototype. + * assuan.h (assuan_get_peercred) [W32]: Do not define. + * assuan-io.c (_assuan_simple_sendmsg, _assuan_simple_recvmsg) + [w32]: Use another prototype. + +2007-05-09 Werner Koch + + * libassuan.m4: Print found version on success. + +2007-05-01 Werner Koch + + * assuan-uds.c (uds_reader): Cast void ptr for arithmetics. + Reported by Peter O'Gorman. + +2006-12-03 Marcus Brinkmann + + * assuan-handler.c (assuan_command_parse_fd): Also allow white + space after FD. + +2006-12-02 Marcus Brinkmann + + * assuan-uds.c (uds_reader): Return 0 if recvmsg returns 0. + +2006-12-01 Marcus Brinkmann + + * assuan-client.c (assuan_transact): Also translate some of the + legacy error codes. + +2006-11-22 Werner Koch + + * assuan-handler.c (fun1_cookie_write, fun2_cookie_write): New. + (assuan_get_data_fp) [HAVE_FUNOPEN]: Use it. + +2006-11-21 Werner Koch + + * Makefile.am (libassuan_pth_a_CFLAGS): New. + + * assuan-pipe-server.c (_assuan_release_context): Free CMDTBL. + +2006-11-14 Werner Koch + + * libassuan.m4 (AM_CHECK_LIBASSUAN): New. + + * assuan-handler.c (assuan_register_post_cmd_notify) + (assuan_register_post_cmd_notify): New. + * assuan-util.c (assuan_set_io_monitor): New. + * assuan-buffer.c (_assuan_read_line): Use it. + (_assuan_write_line): Ditto. + (_assuan_cookie_write_data): Ditto. + (_assuan_cookie_write_flush): Ditto. + +2006-10-18 Werner Koch + + * libassuan.m4: Pass "pthread" to the common macro. Reported by + Rex Dieter. + +2006-10-16 Werner Koch + + * mkerrors: Map ASSUAN_Not_Confirmed. + +2006-10-10 Werner Koch + + * libassuan.m4 (AM_PATH_LIBASSUAN_PTH) + (AM_PATH_LIBASSUAN_PTHREAD): Fixed. + + * assuan-buffer.c (assuan_sendfd): Implement a runtime detection + of implemented descripotr passing. + + * assuan-uds.c: Take care of USE_DESCRIPTOR_PASSING. + + * assuan-defs.h: Add missing semicolon. + +2006-10-09 Werner Koch + + * assuan-handler.c (process_request): Use weak pragma for the sake + of old gcc's. Reported by Alain Guibert. + + * assuan-io.c: Removed Pth support. + * assuan-io-pth.c: New. Based on assuan-io.c + +2006-10-06 Werner Koch + + * libassuan-config.in: New options --api-version and --thread. + +2006-10-04 Werner Koch + + * assuan-client.c (assuan_transact): Need to map old assuan status + codes so that for example CANCELED is correctly mapped. + +2006-09-28 Marcus Brinkmann + + * assuan-client.c (assuan_transact): Do not convert error on + status line, it is already a gpg-error. Do convert + ASSUAN_Server_Fault. + +2006-09-19 Marcus Brinkmann + + * assuan.h (assuan_init_socket_server_ext) + [_ASSUAN_EXT_SYM_PREFIX]: Fix typo in macro. + +2006-09-19 Werner Koch + + * assuan-defs.h (putc_unlocked): Add prototype. + + * assuan-socket-server.c (accept_connection): Made LEN a socklen_t. + + * assuan.h: Replaced assuan error code enum by simple defines and + made assuan_error_t an int. + * mkerrors: Changed parser accordingly. + +2006-09-19 Marcus Brinkmann + + * assuan-pipe-connect.c: Add hacks for Slowaris. + * assuan-socket.c: Likewise here. + + * assuan.h (enum): Avoid trailing comma in enumerator list. Ugh. + + * mkerrors (_assuan_error): Change return type to assuan_error_t. + * assuan-buffer.c (_assuan_read_line): Change return type to + assuan_error_t. Map returned value of -1. + (_assuan_write_line): Change type of RC to assuan_error_t. + * assuan-defs.h (_assuan_read_line, _assuan_error): Likewise for + prototypes. + + * assuan-defs.h (unsetenv): Define correctly. + +2006-09-14 Werner Koch + + * assuan-io.c (_assuan_waitpid): New. Changed all waitpid calls + to this. + + * assuan.h (_ASSUAN_DEPRECATED): New internal macro. + (assuan_pipe_connect2): Declare deprecated. + (assuan_init_connected_socket_server): Declare deprecated. + + * assuan-connect.c (assuan_get_peercred): New. + * assuan-socket-server.c (accept_connection_bottom): Save uid and gid. + +2006-09-13 Werner Koch + + * assuan-client.c (assuan_transact): Need to map the error code. + * mkerrors: Need to map ASSUAN_No_Secret_Key. + + * assuan-pipe-server.c (is_valid_socket): New. + (assuan_init_pipe_server): Use UDS with the environmet variable is + set and a valid descriptor is given. Ignore FILEDES in this case. + + * assuan-socket-server.c (assuan_init_socket_server_ext): New. + Changed other init fucntions to make use of it. + + * assuan-handler.c (assuan_command_parse_fd): Allow for lowercase + "fd". + (std_handler_reset): Close pending fds. + * assuan-uds.c (uds_receivefd): Fixed. + (_assuan_uds_close_fds): New. + + * assuan-socket-connect.c (assuan_socket_connect_ext): New. Takes + all code of assuan_socket_connect plus an option to use sendmsg. + * assuan-pipe-connect.c (assuan_pipe_connect_ext): New arg FLAGS. + +2006-09-12 Werner Koch + + * assuan-buffer.c (_assuan_write_line): Also log the prefix. + + * assuan-defs.h (DIM, DIMof): New. + + * assuan-domain-server.c: Removed. + * assuan-domain-connect.c: Renamed to .. + * assuan-uds.c: this. + (domain_reader, domain_writer, domain_sendfd, domain_receivefd) + (assuan_domain_connect, _assuan_domain_init): Removed. + (uds_reader, uds_writer, uds_sendfd, uds_receivefd) + (_assuan_init_uds_io): New. + (_assuan_uds_deinit): New. + + * assuan-io.c (_assuan_simple_sendmsg, _assuan_simple_recvmsg): New. + (my_pth_fdmode, my_pth_select): New. + +2006-09-11 Werner Koch + + * assuan-pipe-server.c (assuan_init_pipe_server): Allow for + FILEDES to be NULL and try to start as a socketpair server in this + case. + + * assuan-pipe-connect.c (assuan_pipe_connect2): Split up into two + functions (unix and w32) for clarity. + (pipe_connect_unix): This is the new fucntion. Add USE_CMSG flag. + (pipe_connect_w32): Ditto. + (initial_handshake): Factored out code. + (socketpair_connect): New. + (assuan_pipe_connect_ext): New. + (do_finish): Handle case if outbound and inbound fd are the same. + This is to support socketpairs. + +2006-09-10 Werner Koch + + * assuan-util.c (_assuan_log_print_buffer) + (_assuan_log_sanitized_string,assuan_set_log_stream): Moved to .. + * assuan-logging.c: .. here. + (_assuan_log_print_buffer): Only print the leading bytes in hex + log mode unless the new env variable ASSUAN_FULL_LOGGING has been + set. + (_assuan_set_default_log_stream): Test this env variable. + +2006-09-06 Werner Koch + + * assuan.h (_ASSUAN_ONLY_GPG_ERRORS): New. + + * assuan-handler.c (dispatch_command): Use Syntax_Error instead of + Invalid_Command. + + * assuan-domain-connect.c: Changed alloc malloc/free/realloc to + xtrymalloc et al. + (read_int, write_int): Make args void pointers. + (domain_receivefd): Take care of realloc shrinking failure. + + * assuan-buffer.c (_assuan_read_line, _assuan_write_line) + (assuan_write_line, _assuan_cookie_write_data) + (_assuan_cookie_write_flush): Print the inbound fd instead of the + address of the context when logging I/0. This makes it more + readable. + +2006-09-05 Werner Koch + + * assuan-defs.h (err_code, err_is_eof): New. + + * mkerrors (_assuan_error): New. Wrapped all error code + assignments in a call to this. + (assuan_strerror): Map gpg-style error codes back. Also print a + string for the old EOF code. + (assuan_set_assuan_err_source): New. + + * assuan-logging.c (_assuan_log_printf): Do not change ERRNO and + print the pid. + + * assuan-domain-connect.c (domain_reader): Replaced plain printf + by assuan_log function. + +2005-10-24 Werner Koch + + * putc_unlocked.c, memrchr.c, isascii.c, funopen.c: Changed + distribution terms to LGPL. This are small and trivial files so + there are no obstacles of doing so. + * assuan-socket.c: Likewise, the stated GPL was not intended. + +2005-10-08 Marcus Brinkmann + + * assuan-defs.h (setenv, unsetenv, clearenv) [!HAVE_SETENV]: + Define to _assuan_*. + * setenv.c: Include "assuan-defs.h". + (__add_to_environ): Make static. + +2005-10-07 Marcus Brinkmann + + * assuan-defs.h (memrchr) [!HAVE_MEMRCHR]: New prototype. + (stpcpy) [!HAVE_STPCPY]: Likewise. + * stpcpy.c: New LGPL'ed file from the GNU C Library. + * setenv.c: New file. + * assuan-domain-connect.c (read_int): New function. + (write_int): New function. + (domain_reader): Use read_int. + (domain_sendfd): Use write_int. + +2005-10-01 Marcus Brinkmann + + * assuan.h (assuan_pipe_connect, assuan_pipe_connect2): Make type + of ARGV parameter const in prototype. + * assuan-pipe-connect.c (assuan_pipe_connect, + assuan_pipe_connect2): Likewise in declaration. + (assuan_pipe_connect2): Add braindead cast to make execv happy. + + * assuan-client.c (assuan_transact): Change LINE, S and D from + unsigned char * to char * to silence gcc warning. + * assuan-util.c (_assuan_log_sanitized_string): Add explicit cast + to silence gcc warning. + * assuan-inquire.c (assuan_inquire): Likewise. + +2005-08-19 Werner Koch + + * funopen.c, assuan-socket.c: Copied from libassuan CVS. + * assuan-pipe-connect.c (assuan_pipe_connect2): Add missing + declaration of PID. + +2005-08-09 Werner Koch + + * README.1st: Adjusted to cope with changes done in upstream Assuan. + + Merged changes for W32 support from libassuan. + + * assuan.h [_ASSUAN_EXT_SYM_PREFIX]: New. + * assuan-io.c [_ASSUAN_NO_PTH]: New. + * assuan-pipe-connect.c (fix_signals) [_ASSUAN_NO_FIXED_SIGNALS]: New. + (assuan_pipe_connect2) [_ASSUAN_USE_DOUBLE_FORK]: Use double fork. + (fix_signals) [_ASSUAN_USE_DOUBLE_FORK]: Do not wait.. + * assuan-logging.c, assuan-io.c: Include config.h + Replaced all usages of _WIN32 by the new HAVE_W32_SYSTEM because + there is nothing winning in this API. + * assuan-pipe-connect.c (assuan_pipe_connect2) [_WIN32]: Return + error Not Imlemented. + * assuan-logging.c (_assuan_w32_strerror): New. + * assuan-defs.h (w32_strerror): new. + * assuan-pipe-connect.c (assuan_pipe_connect2, fix_signals): + Factored signal code out to new function. + (build_w32_commandline, create_inheritable_pipe): New. Taken + from gnupg 1.9. + (assuan_pipe_connect2) [W32]: Implemented for W32. + * assuan-pipe-server.c (assuan_init_pipe_server) [W32]: Map file + descriptors using _get_osfhandle. + * assuan-socket-connect.c (assuan_socket_connect) [W32]: Allow for + a drive letter in the path. + * assuan-client.c (assuan_transact): Handle empty and comment + commands correctly. + * assuan-util.c (_assuan_calloc): Avoid integer overflow. + * assuan-util.c (assuan_set_flag, assuan_get_flag): New. + * assuan-defs.h (struct assuan_context_s): New field flags. + * assuan.h (assuan_flag_t): New with one flag value + ASSUAN_NO_WAITPID for now. + * assuan-pipe-connect.c (do_finish): Take care of the no_waitpid + flag. + * mkerrors: Include config.h into assuan-errors.c. This is + required so that assuan.h knows about the W32 macro. + +2005-08-09 Timo Schulz (ported from libassuan by wk) + + * assuan-io.c (_assuan_simple_read, _assuan_simple_write): W32 + support. + * assuan-socket.c (_assuan_close): New. + (_assuan_sock_new): New. + (_assuan_sock_bind): New. + +2005-03-22 Werner Koch + + * assuan-defs.h (struct assuan_io): Renamed elements READ and + WRITE to READFNC and WRITEFNC to avoid problems with read defined + as macro. Changed callers. Noted by Ville Skyttä. + +2004-12-16 Marcus Brinkmann + + * assuan-pipe-connect.c (do_finish): Do not wait for child to finish. + (assuan_pipe_connect): Use double-fork approach. + * assuan-connect.c (assuan_disconnect): Do not write BYE to the + status line. + +2004-12-07 Marcus Brinkmann + + * README.1st: Add copyright notice. + +2004-06-23 Marcus Brinkmann + + * assuan-domain-connect.c [HAVE_SYS_UIO_H]: Include . + + * assuan-handler.c: Include . + +2004-06-08 Marcus Brinkmann + + * assuan-buffer.c (assuan_write_line): If the line is longer than + the maximum line length, bail out early. + +2004-04-21 Werner Koch + + * assuan-socket-server.c (accept_connection_bottom): Save the pid + of the peer if it is available. + * assuan-socket-connect.c (assuan_socket_connect): Do not save the + dummy SERVED_PID arg. + * assuan-pipe-connect.c (do_finish): Don't wait if the pid is 0. + (assuan_pipe_connect2): Store the parents pid in the environment + of the child. + * assuan-pipe-server.c (assuan_init_pipe_server): Initialize the + peer's pid from the environment. + * assuan-connect.c (assuan_get_pid): Do not return 0 as a PID. + +2004-04-19 Werner Koch + + * assuan-socket-server.c, assuan-socket-connect.c: Includes + sys/types.h. Reported by Michael Nottebrock. + * assuan-domain-connect.c: Ditto. + +2004-04-13 Werner Koch + + * assuan-util.c (_assuan_log_print_buffer): Relaxed quoting. + (_assuan_log_sanitized_string): Ditto. + +2004-03-14 Werner Koch + + * assuan-handler.c: Include . Reported by Bernd Kuhls. + +2004-02-18 Werner Koch + + * libassuan-config.in: Ignore setting of --prefix. + + * assuan-handler.c (assuan_get_data_fp): Fail with ENOSYS if we + can't implement this. + +2004-02-15 Werner Koch + + * memrchr.c (memrchr): Fixed implementation. Taken from gpgme. + +2004-02-13 Werner Koch + + * assuan-domain-connect.c: Removed the unneeded alloca.h. + +2004-01-24 Werner Koch + + * assuan-pipe-connect.c (assuan_pipe_connect2): New as an + extension of assuan_pipe_connect. Made the latter call this one. + +2004-01-14 Werner Koch + + * assuan-buffer.c (_assuan_cookie_write_data): Return the + requested size to indicate successful operation. Fixes a spurious + bug we previously fixed using fflush(). + +2003-12-22 Werner Koch + + * assuan.h (ASSUAN_Locale_Problem): Added. + * assuan-errors.c (assuan_strerror): Ditto. + +2003-12-18 Werner Koch + + * assuan.h (AssuanCommand): Clarified that these are now + deprecated and actually useless. + (assuan_error_t): Clarified and added ASSUAN_USER_ERROR_FIRST, + ASSUAN_USER_ERROR_LAST. + +2003-12-16 Werner Koch + + * assuan-buffer.c: Changed formatting of the debug output prefix. + * assuan-util.c (assuan_set_log_stream): Set global log stream if + it has not been done yet. + * assuan-logging.c (_assuan_set_default_log_stream): New. + (assuan_set_assuan_log_prefix): New. + +2003-12-11 Werner Koch + + * funopen.c (_assuan_funopen): Renamed from funopen, to keep the + name space clean and avoid duplicate definitions if another + library uses the same replacement. + * assuan-defs.h (funopen): Renamed prototype and add a macro. + +2003-12-08 Werner Koch + + * TODO: Removed. + +2003-11-12 Werner Koch + + * assuan-handler.c (process_request): Kludge to print better error + messages for gpg-error enabled programs. + +2003-11-06 Werner Koch + + * assuan.h (assuan_context_t): New. Should be used in favor of + ASSUAN_CONTEXT. + (assuan_error_t): New. To be used instead of AssuanError. + +2003-11-11 Moritz Schulte + + * assuan-socket-connect.c (assuan_socket_connect): Fix computation + of socket address length. + +2003-08-13 Werner Koch + + * assuan-inquire.c (assuan_inquire): Increase length of cmdbuf to + the Assuan limit. + +2003-06-24 Werner Koch + + * mkerrors: Kludge to print libgpg-error values in an easier + readable way. + +2003-04-29 Werner Koch + + * libassuan.m4: New. Based on libgrypt.m4. + * Makefile.am (m4data_DATA): New. + + * assuan.h (AssuanCommand): Removed. + + * assuan-handler.c: Remove the cmd_id element, + (assuan_register_command): Likewise. Note that semantics changed. + (_assuan_register_std_commands): Adjusted. + +2003-02-22 Neal H. Walfield + + * Makefile.am (bin_SCRIPTS): Renamed from bin_PROGRAMS. + +2003-02-18 Neal H. Walfield + + * Makefile.am (libassuan_a_LIBADD): New variable. + * funopen.c: Move from ../common. + * isascii.c: Likewise. + * memrchr.c: Likewise. + * putc_unlocked.c: Likewise. + +2003-02-18 Neal H. Walfield + + * assuan-handler.c (_IO_cookie_io_functions_t): Remove. + (cookie_io_functions_t): Remove. + (fopencookie): Remove prototype. + (assuan_get_data_fp): Use funopen, not fopencookie. + +2003-02-18 Neal H. Walfield + + * libassuan-config.in: New file. + * Makefile.am (bin_PROGRAMS): New variable. + +2003-02-17 Neal H. Walfield + + * .cvsignore: New file. + +2003-02-17 Neal H. Walfield + + * Makefile.am (lib_LIBRARIES): Use this instead of . . . + (noinst_LIBRARIES): . . . this. + (include_HEADERS): New variable. + (libassuan_a_SOURCES): Remove assuan.h, add assuan-logging.c. + + * assuan.h (assuan_set_assuan_log_stream): New prototype. + (assuan_get_assuan_log_stream): Likewise. + (assuan_get_assuan_log_prefix): Likewise. + * assuan-logging.c: New file. + + * assuan-buffer.c [HAVE_JNLIB_LOGGIN]: Do not include + "../jnlib/logging.h". + (my_log_prefix): Remove function. + (_assuan_read_line): Use assuan_get_assuan_log_prefix in lieu of + my_log_prefix. + (assuan_write_line): Likewise. + (_assuan_cookie_write_data): Likewise. + (_assuan_cookie_write_flush): Likewise. + * assuan-domain-connect.c (LOGERROR, LOGERROR1, LOGERROR2, + LOGERRORX): Remove. + (LOG): New macro. + (domain_reader): Use it. + (domain_writer): Likewise. + (domain_sendfd): Likewise. + (domain_receivefd): Likewise. + (_assuan_domain_init): Likewise. + (assuan_domain_connect): Likewise. + * assuan-pipe-connect.c [HAVE_JNLIB_LOGGIN]: Do not include + "../jnlib/logging.h". + (LOGERROR, LOGERROR1, LOGERROR2, LOGERRORX): Remove. + (LOG): New macro. + (assuan_pipe_connect): Use it. + * assuan-socket-connect.c [HAVE_JNLIB_LOGGIN]: Do not include + "../jnlib/logging.h". + (LOGERROR, LOGERROR1, LOGERROR2, LOGERRORX): Remove. + (LOG): New macro. + (assuan_socket_connect): Use it. + (socket_reader): Remove dead code. + (socket_writer): Likewise. + * assuan-util.c [HAVE_JNLIB_LOGGIN]: Do not include + "../jnlib/logging.h". + (_assuan_log_sanitized_string): Use assuan_get_assuan_log_stream, + not jnlib. + +2002-11-24 Neal H. Walfield + + * assuan.h (assuan_command_parse_fd): New prototype. + * assuan-handler.c (assuan_command_parse_fd): Rename from + parse_cmd_input_output. Export. + (std_handler_input): Update to use assuan_command_parse_fd. + (std_handler_output): Likewise. + +2002-11-24 Neal H. Walfield + + * assuan.h (assuan_sendfd): New prototype. + (assuan_receivefd): New prototype. + * assuan-buffer.c (assuan_sendfd): New function. + (assuan_receivefd): New function. + * assuan-handler.c (parse_cmd_input_output): Recognize incoming + file descriptors and act appropriately. + * assuan-defs.h (struct assuan_io): Add fields sendfd and + receivefd. + (struct assuan_context_s): Add fields pendingfds and + pendingfdscount. + * assuan-pipe-server.c (_assuan_new_context): Update IO to reflect + new features. + * assuan-domain-connect.c (do_deinit): Cleanup any unreceived file + descriptors. + (domain_reader): Receive file descriptors. + (domain_sendfd): New function. + (domain_receivefd): New function. + (_assuan_domain_init): Update initialization code to reflect new + features. + +2002-11-24 Neal H. Walfield + + * assuan-domain-connect.c (do_finish): Remove. + (_assuan_domain_init): Use default handlers where possible. + Add an assert and update comments. + * assuan-domain-server.c (accept_connection): Remove. + (assuan_init_domain_server): Use default handlers where possible. + Put the server in pipe mode: it can only be used by a single + client. + +2002-11-24 Neal H. Walfield + + * assuan.h: Add prototype for assuan_domain_connect and + assuan_init_domain_server. + * assuan-defs.h: Include . + Add prototype for _assuan_domain_init. + * assuan-domain-connect.c: New file. + * assuan-domain-server.c: New file. + * Makefile.am (libassuan_a_SOURCES): Add assuan-domain-connect.c + and assuan-domain-server.c + +2002-11-23 Neal H. Walfield + + * Makefile.am (libassuan_a_SOURCES): Add assuan-io.c. + * assuan-io.c: Restore. + (_assuan_simple_read): Rename from _assuan_read. + (_assuan_simple_write): Rename from _assuan_write. + * assuan-defs.h (_assuan_simple_read): New prototype. + (_assuan_simple_write): Likewise. + * assuan-pipe-server.c (pipe_reader): Remove. + (pipe_writer): Remove. + (_assuan_new_context): Initialize IO is with _assuan_simple_read + and _assuan_simple_write. + * assuan-socket-connect.c (socket_reader): Remove. + (socket_writer): Remove. + (assuan_socket_connect): Initialize IO is with _assuan_simple_read + and _assuan_simple_write. + * assuan-socket-server.c (io): New local variable. + (assuan_init_socket_server): Initialize CTX->io. + (assuan_init_connected_socket_server): Likewise. + +2002-11-23 Neal H. Walfield + + * assuan-buffer.c (readline): Use memrchr. + (_assuan_read_line): Rewritten to use the string functions. + +2002-11-20 Neal H. Walfield + + * assuan-socket-connect.c (assuan_socket_connect): Pass PF_LOCAL + to socket(), not AF_UNIX: it expects a PF_* macro and the former + is more portable. + (assuan_socket_connect): Use AF_LOCAL, not AF_UNIX which is more + POSIXy. + +2002-11-20 Neal H. Walfield + + * assuan-defs.h (struct assuan_io): New structure. + (struct assuan_context_s): New field, io. + (_assuan_read): Depreciated. + (_assuan_write): Likewise. + * assuan-pipe-server.c: Include . + (pipe_reader): New function. + (pipe_writer): Likewise. + (_assuan_new_context.IO): New local static. Set to pipe_reader + and pipe_writer. Use it to initialize new context. + * assuan-socket-connect.c (socket_reader): New function. + (socket_writer): New function. + (assuan_socket_connect.IO): New local static. Set to socket_reader + and socket_writer. Use it to initialize new context. + * assuan-buffer.c (writen): Take an ASSUAN_CONTEXT rather than a + file descriptor. Do not use _assuan_write but the write method + in the supplied context. + (readline): Likewise for _assuan_read. + (assuan_write_line): When calling writen, pass CTX; not the file + descriptor directly. + (_assuan_cookie_write_data): Likewise. + (_assuan_cookie_write_flush): Likewise. + (_assuan_read_line): Likewise for readline. + * Makefile.am (libassuan_a_SOURCES): Remove assuan-io.c. + * assuan-io.c: Removed. + +2002-11-10 Werner Koch + + * assuan-pipe-connect.c (assuan_pipe_connect): Changed the order + of the dups to handle cases where we have already used fd 2 for + other things. + +2002-10-31 Neal H. Walfield + + * assuan-util.c: Include . + (_assuan_log_print_buffer): Elide the magic numbers preferring the + standard isfoo functions. Use putc_unlocked where possible. + (_assuan_log_sanitized_string): Rewrite to use putc_unlocked and + the isfoo functions. + +2002-09-05 Neal H. Walfield + + * assuan-defs.h (_assuan_read_wrapper): Depreciated. + * assuan-util.c (_assuan_read_wrapper): Removed. + * assuan-defs.h (_assuan_write_wrapper): Depreciated. + * assuan-util.c (_assuan_write_wrapper): Removed. + * assuan.h (assuan_set_io_fun): Depreciated. + * assuan-util.c (assuan_set_io_fun): Removed. + + * assuan-defs.h (_assuan_read): New function. + (_assuan_write): Likewise. + * assuan-io.c: New file. + + * assuan-buffer.c (writen): Use _assuan_write rather than doing + the work here. + (readline): Likewise for _assuan_read. + + * Makefile.am (libassuan_a_SOURCES): Add assuan-io.c. + +2002-08-16 Werner Koch + + * assuan.h: Renamed Bad_Certificate_Path to Bad_Certificate_Chain. + +2002-07-30 Werner Koch + + Changed the license from GPL to LGPL. + +2002-07-23 Werner Koch + + * assuan-handler.c (_IO_cookie_io_functions_t): Define it here if + it does not exists. + +2002-06-27 Werner Koch + + * assuan-pipe-connect.c (assuan_pipe_connect): No special handling + for the log_fd and stderr. Connect stderr to /dev/null if it + should not be retained. + +2002-06-26 Werner Koch + + * assuan-buffer.c (assuan_write_line): Make sure we never + accidently print an extra LF. + +2002-05-23 Werner Koch + + * assuan-util.c (assuan_set_io_func): New. + * assuan-buffer.c (writen, readline): Use the new functions + instead of pth. + * assuan-socket-server.c (accept_connection): Don't use the + pth_accept - using the assuan included accept code would be a bad + idea within Pth so we don't need a replacement function. + +2002-05-22 Werner Koch + + * assuan-socket-server.c (assuan_init_connected_socket_server): New. + (accept_connection): Factored most code out to.. + (accept_connection_bottom): .. new function. + +2002-04-04 Werner Koch + + * assuan-buffer.c (my_log_prefix): New. Use it for all i/o debug + output. + +2002-03-06 Werner Koch + + * assuan-client.c (_assuan_read_from_server): Detect END. + (assuan_transact): Pass it to the data callback. + +2002-02-27 Werner Koch + + * assuan-client.c (assuan_transact): Add 2 more arguments to + support status lines. Passing NULL yields the old behaviour. + + * assuan-handler.c (process_request): Flush data lines send + without using the data fp. + +2002-02-14 Werner Koch + + * assuan-inquire.c (assuan_inquire): Check for a cancel command + and return ASSUAN_Canceled. Allow for non-data inquiry. + + * assuan.h: Add a few token specific error codes. + +2002-02-13 Werner Koch + + * assuan-defs.h (assuan_context_s): New var CLIENT_PID. + * assuan-pipe-server.c (_assuan_new_context): set default value. + * assuan-socket-server.c (accept_connection): get the actual pid. + +2002-02-12 Werner Koch + + * assuan-buffer.c (writen,readline) [USE_GNU_PT]: Use pth_read/write. + * assuan-socket-server.c (accept_connection) [USE_GNU_PTH]: Ditto. + +2002-02-01 Marcus Brinkmann + + * Makefile.am (MOSTLYCLEANFILES): New variable. + +2002-01-23 Werner Koch + + * assuan-socket-connect.c (LOGERRORX): and removed typo. + +2002-01-22 Marcus Brinkmann + + * assuan-socket-connect.c (LOGERRORX): Reverse arguments to fputs. + +2002-01-21 Werner Koch + + * assuan-connect.c: Move all except assuan_get_pid to... + * assuan-pipe-connect.c: this. + (assuan_pipe_disconnect): Removed. + (do_finish, do_deinit): New + (assuan_pipe_connect): and set them into the context. + * assuan-socket-connect.c: New. + + * assuan-util.c (_assuan_log_sanitized_string): New. + + * assuan-pipe-server.c (assuan_init_pipe_server): Factored most + code out to ... + (_assuan_new_context): new func. + (_assuan_release_context): New + * assuan-connect.c (assuan_pipe_connect): Use the new functions. + +2002-01-20 Werner Koch + + * assuan.h: Added Invalid Option error code. + + * assuan-handler.c (std_handler_option): New. + (std_cmd_tbl): Add OPTION as standard command. + (assuan_register_option_handler): New. + (dispatch_command): Use case insensitive matching as a fallback. + (my_strcasecmp): New. + +2002-01-19 Werner Koch + + * assuan-buffer.c (_assuan_read_line): Add output logging. + (assuan_write_line): Ditto. + (_assuan_cookie_write_data): Ditto. + (_assuan_cookie_write_flush): Ditto. + * assuan-util.c (_assuan_log_print_buffer): New. + (assuan_set_log_stream): New. + (assuan_begin_confidential): New. + (assuan_end_confidential): New. + + * assuan-defs.h: Add a few handler variables. + * assuan-pipe-server.c (assuan_deinit_pipe_server): Removed. + (deinit_pipe_server): New. + (assuan_deinit_server): New. Changed all callers to use this. + * assuan-listen.c (assuan_accept): Use the accept handler. + * assuan-handler.c (process_request): Use the close Handler. + * assuan-socket-server.c: New. + +2002-01-14 Werner Koch + + * assuan-client.c (_assuan_read_from_server): Skip spaces after + the keyword. + +2002-01-03 Werner Koch + + * assuan-handler.c (assuan_set_okay_line): New. + (process_request): And use it here. + +2002-01-02 Werner Koch + + * assuan-inquire.c (init_membuf,put_membuf,get_membuf): Apply a + hidden 0 behind the buffer so that the buffer can be used as a + string in certain contexts. + +2001-12-14 Marcus Brinkmann + + * assuan-connect.c (assuan_pipe_connect): New argument + FD_CHILD_LIST. Don't close those fds. + * assuan.h: Likewise for prototype. + +2001-12-14 Werner Koch + + * assuan-listen.c (assuan_close_input_fd): New. + (assuan_close_output_fd): New. + * assuan-handler.c (std_handler_reset): Always close them after a + reset command. + (std_handler_bye): Likewise. + +2001-12-14 Marcus Brinkmann + + * assuan-buffer.c (_assuan_read_line): New variable ATTICLEN, use + it to save the length of the attic line. + Rediddle the code a bit to make it more clear what happens. + +2001-12-14 Marcus Brinkmann + + * assuan-defs.h (LINELENGTH): Define as ASSUAN_LINELENGTH. + assuan.h: Define ASSUAN_LINELENGTH. + +2001-12-13 Marcus Brinkmann + + * assuan-buffer.c (assuan_read_line): Fix order of execution to + get correct return values. + +2001-12-13 Werner Koch + + * assuan-handler.c (assuan_get_active_fds): Fixed silly bug, + pretty obvious that nobody ever tested this function. + +2001-12-12 Werner Koch + + * assuan-connect.c (assuan_pipe_connect): Implemented the inital + handshake. + * assuan-client.c (read_from_server): Renamed to + (_assuan_read_from_server): this and made external. + + * assuan-listen.c (assuan_set_hello_line): New. + (assuan_accept): Use a custom hello line is available. + + * assuan-buffer.c (assuan_read_line): New. + (assuan_pending_line): New. + (_assuan_write_line): Renamed to .. + (assuan_write_line): this, made public and changed all callers. + +2001-12-04 Werner Koch + + * assuan-connect.c (assuan_pipe_connect): Add more error reporting. + * assuan-client.c: New. + + * assuan-inquire.c: New. + * assuan-handler.c (process_request): Check for nested invocations. + +2001-11-27 Werner Koch + + * assuan-handler.c (assuan_register_input_notify): New. + (assuan_register_output_notify): New. + +2001-11-26 Werner Koch + + * assuan.h: Added more status codes. + +2001-11-25 Werner Koch + + * assuan-handler.c (assuan_register_bye_notify) + (assuan_register_reset_notify) + (assuan_register_cancel_notify): New and call them from the + standard handlers. + (assuan_process): Moved bulk of function to .. + (process_request): .. new. + (assuan_process_next): One shot version of above. + (assuan_get_active_fds): New. + +2001-11-24 Werner Koch + + * assuan-connect.c (assuan_get_pid): New. + + * assuan-buffer.c (_assuan_read_line): Deal with reads of more + than a line. + * assuan-defs.h: Add space in the context for this. + + + Copyright 2001, 2002, 2006 Free Software Foundation, Inc. + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/tags/gpgme-1.1.6/assuan/Makefile.am b/tags/gpgme-1.1.6/assuan/Makefile.am new file mode 100644 index 0000000..4607bc7 --- /dev/null +++ b/tags/gpgme-1.1.6/assuan/Makefile.am @@ -0,0 +1,53 @@ +# Assuan Makefile +# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. +# +# This file is part of Assuan. +# +# Assuan is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Assuan 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +## Process this file with automake to produce Makefile.in + +EXTRA_DIST = mkerrors +INCLUDES = -I.. -I$(top_srcdir)/gpgme +BUILT_SOURCES = assuan-errors.c +MOSTLYCLEANFILES = assuan-errors.c + +noinst_LTLIBRARIES = libassuan.la + +AM_CPPFLAGS = -D_ASSUAN_IN_GPGME_BUILD_ASSUAN + +#libassuan_la_LDFLAGS = +libassuan_la_SOURCES = \ + assuan.h \ + assuan-defs.h \ + assuan-util.c \ + assuan-errors.c \ + assuan-buffer.c \ + assuan-handler.c \ + assuan-inquire.c \ + assuan-listen.c \ + assuan-connect.c \ + assuan-client.c \ + assuan-pipe-server.c \ + assuan-socket-server.c \ + assuan-pipe-connect.c \ + assuan-socket-connect.c \ + assuan-uds.c \ + assuan-io.c \ + assuan-logging.c \ + assuan-socket.c + +assuan-errors.c : assuan.h mkerrors + $(srcdir)/mkerrors < $(srcdir)/assuan.h > assuan-errors.c diff --git a/tags/gpgme-1.1.6/assuan/README.1st b/tags/gpgme-1.1.6/assuan/README.1st new file mode 100644 index 0000000..46f1bb0 --- /dev/null +++ b/tags/gpgme-1.1.6/assuan/README.1st @@ -0,0 +1,45 @@ +This is a modified copy of the libassuan library. Don't modify it, +but instead modify the original Assuan library and merge the changes +back into this copy. + +The changes to the original libassuan, that have to preserved when +updating this directory, are: + +* Makefile.am +** Build the library with libtool as a convenience library, which can + be linked into the shared library GPGME. +** Do not install the library or the header file. +** Define -D_ASSUAN_IN_GPGME_BUILD_ASSUAN to wrap some POSIX functions + with ATH replacements. + +* assuan.h +** Preserve the block between "Begin/End GPGME specific modifications". + In particular make sure that + #define _ASSUAN_EXT_SYM_PREFIX _gpgme_ + #define _ASSUAN_NO_PTH + #define _ASSUAN_NO_FIXED_SIGNALS + #define _ASSUAN_USE_DOUBLE_FORK + are defined. This puts all exported Assuan functions in the _gpgme + namespace. It also wraps all system functions that are wrapped by + GNU Pth to _gpgme wrappers. + +* assuan-io-pth.c + We don't need this file as GPGME doesn't use sendmsg and recvmsg. + If it would, we would need to pick up the W32 implementation. + +* assuan-io.c +** _assuan_simple_read() and _assuan_simple_write() must always use + read()/write() (which actually translates to _gpgme_io_read() and + _gpgme_io_write()). _assuan_close must always() use close() (which + translates to _gpgme_io_close()). + + + Copyright 2004, 2007 g10 Code GmbH + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/tags/gpgme-1.1.6/assuan/assuan-buffer.c b/tags/gpgme-1.1.6/assuan/assuan-buffer.c new file mode 100644 index 0000000..1fad0b5 --- /dev/null +++ b/tags/gpgme-1.1.6/assuan/assuan-buffer.c @@ -0,0 +1,550 @@ +/* assuan-buffer.c - read and send data + * Copyright (C) 2001, 2002, 2003, 2004, 2006 Free Software Foundation, Inc. + * + * This file is part of Assuan. + * + * Assuan is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Assuan 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_W32_SYSTEM +#include +#endif +#include "assuan-defs.h" + + +/* Extended version of write(2) to guarantee that all bytes are + written. Returns 0 on success or -1 and ERRNO on failure. */ +static int +writen (assuan_context_t ctx, const char *buffer, size_t length) +{ + while (length) + { + ssize_t nwritten = ctx->io->writefnc (ctx, buffer, length); + + if (nwritten < 0) + { + if (errno == EINTR) + continue; + return -1; /* write error */ + } + length -= nwritten; + buffer += nwritten; + } + return 0; /* okay */ +} + +/* Read an entire line. Returns 0 on success or -1 and ERRNo on + failure. EOF is indictated by setting the integer at address + R_EOF. */ +static int +readline (assuan_context_t ctx, char *buf, size_t buflen, + int *r_nread, int *r_eof) +{ + size_t nleft = buflen; + char *p; + + *r_eof = 0; + *r_nread = 0; + while (nleft > 0) + { + ssize_t n = ctx->io->readfnc (ctx, buf, nleft); + + if (n < 0) + { + if (errno == EINTR) + continue; + return -1; /* read error */ + } + else if (!n) + { + *r_eof = 1; + break; /* allow incomplete lines */ + } + p = buf; + nleft -= n; + buf += n; + *r_nread += n; + + p = memrchr (p, '\n', n); + if (p) + break; /* at least one full line available - that's enough for now */ + } + + return 0; +} + + +/* Function returns an Assuan error. */ +assuan_error_t +_assuan_read_line (assuan_context_t ctx) +{ + char *line = ctx->inbound.line; + int nread, atticlen; + int rc; + char *endp = 0; + + if (ctx->inbound.eof) + return _assuan_error (-1); + + atticlen = ctx->inbound.attic.linelen; + if (atticlen) + { + memcpy (line, ctx->inbound.attic.line, atticlen); + ctx->inbound.attic.linelen = 0; + + endp = memchr (line, '\n', atticlen); + if (endp) + /* Found another line in the attic. */ + { + rc = 0; + nread = atticlen; + atticlen = 0; + } + else + /* There is pending data but not a full line. */ + { + assert (atticlen < LINELENGTH); + rc = readline (ctx, line + atticlen, + LINELENGTH - atticlen, &nread, &ctx->inbound.eof); + } + } + else + /* No pending data. */ + rc = readline (ctx, line, LINELENGTH, + &nread, &ctx->inbound.eof); + if (rc) + { + if (ctx->log_fp) + fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [Error: %s (%d)]\n", + assuan_get_assuan_log_prefix (), + (unsigned int)getpid (), ctx->inbound.fd, + strerror (errno), errno); + return _assuan_error (ASSUAN_Read_Error); + } + if (!nread) + { + assert (ctx->inbound.eof); + if (ctx->log_fp) + fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [EOF]\n", + assuan_get_assuan_log_prefix (), + (unsigned int)getpid (), ctx->inbound.fd); + return _assuan_error (-1); + } + + ctx->inbound.attic.pending = 0; + nread += atticlen; + + if (! endp) + endp = memchr (line, '\n', nread); + + if (endp) + { + unsigned monitor_result; + int n = endp - line + 1; + + if (n < nread) + /* LINE contains more than one line. We copy it to the attic + now as handlers are allowed to modify the passed + buffer. */ + { + int len = nread - n; + memcpy (ctx->inbound.attic.line, endp + 1, len); + ctx->inbound.attic.pending = memrchr (endp + 1, '\n', len) ? 1 : 0; + ctx->inbound.attic.linelen = len; + } + + if (endp != line && endp[-1] == '\r') + endp --; + *endp = 0; + + ctx->inbound.linelen = endp - line; + + monitor_result = (ctx->io_monitor + ? ctx->io_monitor (ctx, 0, + ctx->inbound.line, + ctx->inbound.linelen) + : 0); + if ( (monitor_result & 2) ) + ctx->inbound.linelen = 0; + + if (ctx->log_fp && !(monitor_result & 1)) + { + fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- ", + assuan_get_assuan_log_prefix (), + (unsigned int)getpid (), ctx->inbound.fd); + if (ctx->confidential) + fputs ("[Confidential data not shown]", ctx->log_fp); + else + _assuan_log_print_buffer (ctx->log_fp, + ctx->inbound.line, + ctx->inbound.linelen); + putc ('\n', ctx->log_fp); + } + return 0; + } + else + { + if (ctx->log_fp) + fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [Invalid line]\n", + assuan_get_assuan_log_prefix (), + (unsigned int)getpid (), ctx->inbound.fd); + *line = 0; + ctx->inbound.linelen = 0; + return _assuan_error (ctx->inbound.eof + ? ASSUAN_Line_Not_Terminated + : ASSUAN_Line_Too_Long); + } +} + + +/* Read the next line from the client or server and return a pointer + in *LINE to a buffer holding the line. LINELEN is the length of + *LINE. The buffer is valid until the next read operation on it. + The caller may modify the buffer. The buffer is invalid (i.e. must + not be used) if an error is returned. + + Returns 0 on success or an assuan error code. + See also: assuan_pending_line(). +*/ +assuan_error_t +assuan_read_line (assuan_context_t ctx, char **line, size_t *linelen) +{ + assuan_error_t err; + + if (!ctx) + return _assuan_error (ASSUAN_Invalid_Value); + + err = _assuan_read_line (ctx); + *line = ctx->inbound.line; + *linelen = ctx->inbound.linelen; + return err; +} + + +/* Return true if a full line is buffered (i.e. an entire line may be + read without any I/O). */ +int +assuan_pending_line (assuan_context_t ctx) +{ + return ctx && ctx->inbound.attic.pending; +} + + +assuan_error_t +_assuan_write_line (assuan_context_t ctx, const char *prefix, + const char *line, size_t len) +{ + assuan_error_t rc = 0; + size_t prefixlen = prefix? strlen (prefix):0; + unsigned int monitor_result; + + /* Make sure that the line is short enough. */ + if (len + prefixlen + 2 > ASSUAN_LINELENGTH) + { + if (ctx->log_fp) + fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> " + "[supplied line too long -truncated]\n", + assuan_get_assuan_log_prefix (), + (unsigned int)getpid (), ctx->inbound.fd); + if (prefixlen > 5) + prefixlen = 5; + if (len > ASSUAN_LINELENGTH - prefixlen - 2) + len = ASSUAN_LINELENGTH - prefixlen - 2 - 1; + } + + monitor_result = (ctx->io_monitor + ? ctx->io_monitor (ctx, 1, line, len) + : 0); + + /* Fixme: we should do some kind of line buffering. */ + if (ctx->log_fp && !(monitor_result & 1)) + { + fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> ", + assuan_get_assuan_log_prefix (), + (unsigned int)getpid (), ctx->inbound.fd); + if (ctx->confidential) + fputs ("[Confidential data not shown]", ctx->log_fp); + else + { + if (prefixlen) + _assuan_log_print_buffer (ctx->log_fp, prefix, prefixlen); + _assuan_log_print_buffer (ctx->log_fp, line, len); + } + putc ('\n', ctx->log_fp); + } + + if (prefixlen && !(monitor_result & 2)) + { + rc = writen (ctx, prefix, prefixlen); + if (rc) + rc = _assuan_error (ASSUAN_Write_Error); + } + if (!rc && !(monitor_result & 2)) + { + rc = writen (ctx, line, len); + if (rc) + rc = _assuan_error (ASSUAN_Write_Error); + if (!rc) + { + rc = writen (ctx, "\n", 1); + if (rc) + rc = _assuan_error (ASSUAN_Write_Error); + } + } + return rc; +} + + +assuan_error_t +assuan_write_line (assuan_context_t ctx, const char *line) +{ + size_t len; + const char *s; + + if (!ctx) + return _assuan_error (ASSUAN_Invalid_Value); + + /* Make sure that we never take a LF from the user - this might + violate the protocol. */ + s = strchr (line, '\n'); + len = s? (s-line) : strlen (line); + + if (ctx->log_fp && s) + fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> " + "[supplied line contained a LF - truncated]\n", + assuan_get_assuan_log_prefix (), + (unsigned int)getpid (), ctx->inbound.fd); + + return _assuan_write_line (ctx, NULL, line, len); +} + + + +/* Write out the data in buffer as datalines with line wrapping and + percent escaping. This function is used for GNU's custom streams. */ +int +_assuan_cookie_write_data (void *cookie, const char *buffer, size_t orig_size) +{ + assuan_context_t ctx = cookie; + size_t size = orig_size; + char *line; + size_t linelen; + + if (ctx->outbound.data.error) + return 0; + + line = ctx->outbound.data.line; + linelen = ctx->outbound.data.linelen; + line += linelen; + while (size) + { + unsigned int monitor_result; + + /* Insert data line header. */ + if (!linelen) + { + *line++ = 'D'; + *line++ = ' '; + linelen += 2; + } + + /* Copy data, keep space for the CRLF and to escape one character. */ + while (size && linelen < LINELENGTH-2-2) + { + if (*buffer == '%' || *buffer == '\r' || *buffer == '\n') + { + sprintf (line, "%%%02X", *(unsigned char*)buffer); + line += 3; + linelen += 3; + buffer++; + } + else + { + *line++ = *buffer++; + linelen++; + } + size--; + } + + + monitor_result = (ctx->io_monitor + ? ctx->io_monitor (ctx, 1, + ctx->outbound.data.line, linelen) + : 0); + + if (linelen >= LINELENGTH-2-2) + { + if (ctx->log_fp && !(monitor_result & 1)) + { + fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> ", + assuan_get_assuan_log_prefix (), + (unsigned int)getpid (), ctx->inbound.fd); + + if (ctx->confidential) + fputs ("[Confidential data not shown]", ctx->log_fp); + else + _assuan_log_print_buffer (ctx->log_fp, + ctx->outbound.data.line, + linelen); + putc ('\n', ctx->log_fp); + } + *line++ = '\n'; + linelen++; + if ( !(monitor_result & 2) + && writen (ctx, ctx->outbound.data.line, linelen)) + { + ctx->outbound.data.error = _assuan_error (ASSUAN_Write_Error); + return 0; + } + line = ctx->outbound.data.line; + linelen = 0; + } + } + + ctx->outbound.data.linelen = linelen; + return (int)orig_size; +} + + +/* Write out any buffered data + This function is used for GNU's custom streams */ +int +_assuan_cookie_write_flush (void *cookie) +{ + assuan_context_t ctx = cookie; + char *line; + size_t linelen; + unsigned int monitor_result; + + if (ctx->outbound.data.error) + return 0; + + line = ctx->outbound.data.line; + linelen = ctx->outbound.data.linelen; + line += linelen; + + monitor_result = (ctx->io_monitor + ? ctx->io_monitor (ctx, 1, + ctx->outbound.data.line, linelen) + : 0); + + if (linelen) + { + if (ctx->log_fp && !(monitor_result & 1)) + { + fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> ", + assuan_get_assuan_log_prefix (), + (unsigned int)getpid (), ctx->inbound.fd); + if (ctx->confidential) + fputs ("[Confidential data not shown]", ctx->log_fp); + else + _assuan_log_print_buffer (ctx->log_fp, + ctx->outbound.data.line, linelen); + putc ('\n', ctx->log_fp); + } + *line++ = '\n'; + linelen++; + if ( !(monitor_result & 2) + && writen (ctx, ctx->outbound.data.line, linelen)) + { + ctx->outbound.data.error = _assuan_error (ASSUAN_Write_Error); + return 0; + } + ctx->outbound.data.linelen = 0; + } + return 0; +} + + +/** + * assuan_send_data: + * @ctx: An assuan context + * @buffer: Data to send or NULL to flush + * @length: length of the data to send/ + * + * This function may be used by the server or the client to send data + * lines. The data will be escaped as required by the Assuan protocol + * and may get buffered until a line is full. To force sending the + * data out @buffer may be passed as NULL (in which case @length must + * also be 0); however when used by a client this flush operation does + * also send the terminating "END" command to terminate the reponse on + * a INQUIRE response. However, when assuan_transact() is used, this + * function takes care of sending END itself. + * + * Return value: 0 on success or an error code + **/ + +assuan_error_t +assuan_send_data (assuan_context_t ctx, const void *buffer, size_t length) +{ + if (!ctx) + return _assuan_error (ASSUAN_Invalid_Value); + if (!buffer && length) + return _assuan_error (ASSUAN_Invalid_Value); + + if (!buffer) + { /* flush what we have */ + _assuan_cookie_write_flush (ctx); + if (ctx->outbound.data.error) + return ctx->outbound.data.error; + if (!ctx->is_server) + return assuan_write_line (ctx, "END"); + } + else + { + _assuan_cookie_write_data (ctx, buffer, length); + if (ctx->outbound.data.error) + return ctx->outbound.data.error; + } + + return 0; +} + +assuan_error_t +assuan_sendfd (assuan_context_t ctx, int fd) +{ + /* It is explicitly allowed to use (NULL, -1) as a runtime test to + check whether descriptor passing is available. */ + if (!ctx && fd == -1) +#ifdef USE_DESCRIPTOR_PASSING + return 0; +#else + return _assuan_error (ASSUAN_Not_Implemented); +#endif + + if (! ctx->io->sendfd) + return set_error (ctx, Not_Implemented, + "server does not support sending and receiving " + "of file descriptors"); + return ctx->io->sendfd (ctx, fd); +} + +assuan_error_t +assuan_receivefd (assuan_context_t ctx, int *fd) +{ + if (! ctx->io->receivefd) + return set_error (ctx, Not_Implemented, + "server does not support sending and receiving " + "of file descriptors"); + return ctx->io->receivefd (ctx, fd); +} diff --git a/tags/gpgme-1.1.6/assuan/assuan-client.c b/tags/gpgme-1.1.6/assuan/assuan-client.c new file mode 100644 index 0000000..7b3d266 --- /dev/null +++ b/tags/gpgme-1.1.6/assuan/assuan-client.c @@ -0,0 +1,234 @@ +/* assuan-client.c - client functions + * Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. + * + * This file is part of Assuan. + * + * Assuan is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Assuan 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include +#include +#include +#include +#include +#include + +#include "assuan-defs.h" + +#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \ + *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10)) +#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1)) + + +assuan_error_t +_assuan_read_from_server (assuan_context_t ctx, int *okay, int *off) +{ + char *line; + int linelen; + assuan_error_t rc; + + *okay = 0; + *off = 0; + do + { + rc = _assuan_read_line (ctx); + if (rc) + return rc; + line = ctx->inbound.line; + linelen = ctx->inbound.linelen; + } + while (*line == '#' || !linelen); + + if (linelen >= 1 + && line[0] == 'D' && line[1] == ' ') + { + *okay = 2; /* data line */ + *off = 2; + } + else if (linelen >= 1 + && line[0] == 'S' + && (line[1] == '\0' || line[1] == ' ')) + { + *okay = 4; + *off = 1; + while (line[*off] == ' ') + ++*off; + } + else if (linelen >= 2 + && line[0] == 'O' && line[1] == 'K' + && (line[2] == '\0' || line[2] == ' ')) + { + *okay = 1; + *off = 2; + while (line[*off] == ' ') + ++*off; + } + else if (linelen >= 3 + && line[0] == 'E' && line[1] == 'R' && line[2] == 'R' + && (line[3] == '\0' || line[3] == ' ')) + { + *okay = 0; + *off = 3; + while (line[*off] == ' ') + ++*off; + } + else if (linelen >= 7 + && line[0] == 'I' && line[1] == 'N' && line[2] == 'Q' + && line[3] == 'U' && line[4] == 'I' && line[5] == 'R' + && line[6] == 'E' + && (line[7] == '\0' || line[7] == ' ')) + { + *okay = 3; + *off = 7; + while (line[*off] == ' ') + ++*off; + } + else if (linelen >= 3 + && line[0] == 'E' && line[1] == 'N' && line[2] == 'D' + && (line[3] == '\0' || line[3] == ' ')) + { + *okay = 5; /* end line */ + *off = 3; + } + else + rc = _assuan_error (ASSUAN_Invalid_Response); + return rc; +} + + + +/** + * assuan_transact: + * @ctx: The Assuan context + * @command: Command line to be send to the server + * @data_cb: Callback function for data lines + * @data_cb_arg: first argument passed to @data_cb + * @inquire_cb: Callback function for a inquire response + * @inquire_cb_arg: first argument passed to @inquire_cb + * @status_cb: Callback function for a status response + * @status_cb_arg: first argument passed to @status_cb + * + * FIXME: Write documentation + * + * Return value: 0 on success or error code. The error code may be + * the one one returned by the server in error lines or from the + * callback functions. Take care: When a callback returns an error + * this function returns immediately with an error and thus the caller + * will altter return an Assuan error (write erro in most cases). + **/ +assuan_error_t +assuan_transact (assuan_context_t ctx, + const char *command, + int (*data_cb)(void *, const void *, size_t), + void *data_cb_arg, + int (*inquire_cb)(void*, const char *), + void *inquire_cb_arg, + int (*status_cb)(void*, const char *), + void *status_cb_arg) +{ + assuan_error_t rc; + int okay, off; + char *line; + int linelen; + + rc = assuan_write_line (ctx, command); + if (rc) + return rc; + + if (*command == '#' || !*command) + return 0; /* Don't expect a response for a comment line. */ + + again: + rc = _assuan_read_from_server (ctx, &okay, &off); + if (rc) + return rc; /* error reading from server */ + + line = ctx->inbound.line + off; + linelen = ctx->inbound.linelen - off; + + if (!okay) + { + rc = atoi (line); + if (rc > 0 && rc < 100) + rc = _assuan_error (ASSUAN_Server_Fault); + else if (rc > 0 && rc <= 405) + rc = _assuan_error (rc); + } + else if (okay == 2) + { + if (!data_cb) + rc = _assuan_error (ASSUAN_No_Data_Callback); + else + { + char *s, *d; + + for (s=d=line; linelen; linelen--) + { + if (*s == '%' && linelen > 2) + { /* handle escaping */ + s++; + *d++ = xtoi_2 (s); + s += 2; + linelen -= 2; + } + else + *d++ = *s++; + } + *d = 0; /* add a hidden string terminator */ + rc = data_cb (data_cb_arg, line, d - line); + if (!rc) + goto again; + } + } + else if (okay == 3) + { + if (!inquire_cb) + { + assuan_write_line (ctx, "END"); /* get out of inquire mode */ + _assuan_read_from_server (ctx, &okay, &off); /* dummy read */ + rc = _assuan_error (ASSUAN_No_Inquire_Callback); + } + else + { + rc = inquire_cb (inquire_cb_arg, line); + if (!rc) + rc = assuan_send_data (ctx, NULL, 0); /* flush and send END */ + if (!rc) + goto again; + } + } + else if (okay == 4) + { + if (status_cb) + rc = status_cb (status_cb_arg, line); + if (!rc) + goto again; + } + else if (okay == 5) + { + if (!data_cb) + rc = _assuan_error (ASSUAN_No_Data_Callback); + else + { + rc = data_cb (data_cb_arg, NULL, 0); + if (!rc) + goto again; + } + } + + return rc; +} + diff --git a/tags/gpgme-1.1.6/assuan/assuan-connect.c b/tags/gpgme-1.1.6/assuan/assuan-connect.c new file mode 100644 index 0000000..b50b17b --- /dev/null +++ b/tags/gpgme-1.1.6/assuan/assuan-connect.c @@ -0,0 +1,85 @@ +/* assuan-connect.c - Establish a connection (client) + * Copyright (C) 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Assuan. + * + * Assuan is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Assuan 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#ifndef HAVE_W32_SYSTEM +#include +#endif + +#include "assuan-defs.h" + +/* Disconnect and release the context CTX. */ +void +assuan_disconnect (assuan_context_t ctx) +{ + if (ctx) + { + assuan_write_line (ctx, "BYE"); + ctx->finish_handler (ctx); + ctx->deinit_handler (ctx); + ctx->deinit_handler = NULL; + _assuan_release_context (ctx); + } +} + +/* Return the PID of the peer or -1 if not known. This function works + in some situations where assuan_get_ucred fails. */ +pid_t +assuan_get_pid (assuan_context_t ctx) +{ + return (ctx && ctx->pid)? ctx->pid : -1; +} + + +#ifndef HAVE_W32_SYSTEM +/* Return user credentials. PID, UID and GID amy be gived as NULL if + you are not interested in this value. For getting the pid of the + peer the assuan_get_pid is usually better suited. */ +assuan_error_t +assuan_get_peercred (assuan_context_t ctx, pid_t *pid, uid_t *uid, gid_t *gid) +{ + if (!ctx) + return _assuan_error (ASSUAN_Invalid_Value); + if (!ctx->peercred.valid) + return _assuan_error (ASSUAN_General_Error); + +#ifdef HAVE_SO_PEERCRED + if (pid) + *pid = ctx->peercred.pid; + if (uid) + *uid = ctx->peercred.uid; + if (gid) + *gid = ctx->peercred.gid; +#endif + + return 0; +} +#endif /* HAVE_W32_SYSTEM */ diff --git a/tags/gpgme-1.1.6/assuan/assuan-defs.h b/tags/gpgme-1.1.6/assuan/assuan-defs.h new file mode 100644 index 0000000..b1d9f3e --- /dev/null +++ b/tags/gpgme-1.1.6/assuan/assuan-defs.h @@ -0,0 +1,332 @@ +/* assuan-defs.c - Internal definitions to Assuan + * Copyright (C) 2001, 2002, 2004, 2005 Free Software Foundation, Inc. + * + * This file is part of Assuan. + * + * Assuan is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Assuan 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#ifndef ASSUAN_DEFS_H +#define ASSUAN_DEFS_H + +#include +#ifndef HAVE_W32_SYSTEM +#include +#include +#else +#include +#endif +#include + +#include "assuan.h" + +#ifndef HAVE_W32_SYSTEM +#define DIRSEP_C '/' +#else +#define DIRSEP_C '\\' +#endif + +#ifdef HAVE_W32_SYSTEM +#define AF_LOCAL AF_UNIX +/* We need to prefix the structure with a sockaddr_in header so we can + use it later for sendto and recvfrom. */ +struct sockaddr_un +{ + short sun_family; + unsigned short sun_port; + struct in_addr sun_addr; + char sun_path[108-2-4]; /* Path name. */ +}; + +/* Not needed anymore because the current mingw32 defines this in + sys/types.h */ +/* typedef int ssize_t; */ + +/* Missing W32 functions */ +int putc_unlocked (int c, FILE *stream); +void * memrchr (const void *block, int c, size_t size); +char * stpcpy (char *dest, const char *src); +#endif + +#define LINELENGTH ASSUAN_LINELENGTH + + +struct cmdtbl_s +{ + const char *name; + int (*handler)(assuan_context_t, char *line); +}; + + +/* A structure to dispatch I/O functions. All these functions need to + return 0 on success and set ERRNO on failure. */ +struct assuan_io +{ + /* Routine to read from input_fd. */ + ssize_t (*readfnc) (assuan_context_t, void *, size_t); + /* Routine to write to output_fd. */ + ssize_t (*writefnc) (assuan_context_t, const void *, size_t); + /* Send a file descriptor. */ + assuan_error_t (*sendfd) (assuan_context_t, int); + /* Receive a file descriptor. */ + assuan_error_t (*receivefd) (assuan_context_t, int *); +}; + + +/* The context we use with most functions. */ +struct assuan_context_s +{ + assuan_error_t err_no; + const char *err_str; + int os_errno; /* Last system error number used with certain + error codes. */ + + /* Context specific flags (cf. assuan_flag_t). */ + struct + { + unsigned int no_waitpid:1; /* See ASSUAN_NO_WAITPID. */ + } flags; + + int confidential; + int is_server; /* Set if this is context belongs to a server */ + int in_inquire; + char *hello_line; + char *okay_line; /* See assuan_set_okay_line() */ + + void *user_pointer; /* For assuan_get_pointer and assuan_set_pointer (). */ + + FILE *log_fp; + + struct { + int fd; + int eof; + char line[LINELENGTH]; + int linelen; /* w/o CR, LF - might not be the same as + strlen(line) due to embedded nuls. However a nul + is always written at this pos. */ + struct { + char line[LINELENGTH]; + int linelen ; + int pending; /* i.e. at least one line is available in the attic */ + } attic; + } inbound; + + struct { + int fd; + struct { + FILE *fp; + char line[LINELENGTH]; + int linelen; + int error; + } data; + } outbound; + + int pipe_mode; /* We are in pipe mode, i.e. we can handle just one + connection and must terminate then. */ + pid_t pid; /* The pid of the peer. */ + int listen_fd; /* The fd we are listening on (used by socket servers) */ + int connected_fd; /* helper */ + + struct { + int valid; /* Whether this structure has valid information. */ +#ifdef HAVE_SO_PEERCRED + pid_t pid; /* The pid of the peer. */ + uid_t uid; /* The uid of the peer. */ + gid_t gid; /* The gid of the peer. */ +#endif /* HAVE_SO_PEERCRED */ + } peercred; + + /* Used for Unix domain sockets. */ + struct sockaddr_un myaddr; + struct sockaddr_un serveraddr; + + /* Structure used for unix domain socket buffering. FIXME: We don't + use datagrams anymore thus we could get away with a simpler + buffering approach. */ + struct { + void *buffer; /* Malloced buffer. */ + int bufferallocated; /* Memory allocated. */ + int bufferoffset; /* Offset of start of buffer. */ + int buffersize; /* Bytes buffered. */ + + int pendingfds[5]; /* Array to save received descriptors. */ + int pendingfdscount; /* Number of received descriptors. */ + } uds; + + void (*deinit_handler)(assuan_context_t); + int (*accept_handler)(assuan_context_t); + int (*finish_handler)(assuan_context_t); + + struct cmdtbl_s *cmdtbl; + size_t cmdtbl_used; /* used entries */ + size_t cmdtbl_size; /* allocated size of table */ + + void (*bye_notify_fnc)(assuan_context_t); + void (*reset_notify_fnc)(assuan_context_t); + void (*cancel_notify_fnc)(assuan_context_t); + int (*option_handler_fnc)(assuan_context_t,const char*, const char*); + void (*input_notify_fnc)(assuan_context_t, const char *); + void (*output_notify_fnc)(assuan_context_t, const char *); + + /* This function is called right after a command has been processed. + It may be used to command related cleanup. */ + void (*post_cmd_notify_fnc)(assuan_context_t, int); + + /* If set, this is called right before logging an I/O line. With + DIRECTION set to 1 it is called for an output oeration; 0 means + an input operation. If bit 0 is set in the return value, the + logging of the will be suppressed. With bit 1 set, the entire + line will be ignored. */ + unsigned int (*io_monitor)(assuan_context_t ctx, + int direction, + const char *line, + size_t linelen); + + int input_fd; /* set by INPUT command */ + int output_fd; /* set by OUTPUT command */ + + /* io routines. */ + struct assuan_io *io; +}; + +/*-- assuan-pipe-server.c --*/ +int _assuan_new_context (assuan_context_t *r_ctx); +void _assuan_release_context (assuan_context_t ctx); + +/*-- assuan-uds.c --*/ +void _assuan_uds_close_fds (assuan_context_t ctx); +void _assuan_uds_deinit (assuan_context_t ctx); +void _assuan_init_uds_io (assuan_context_t ctx); + + +/*-- assuan-handler.c --*/ +int _assuan_register_std_commands (assuan_context_t ctx); + +/*-- assuan-buffer.c --*/ +assuan_error_t _assuan_read_line (assuan_context_t ctx); +int _assuan_cookie_write_data (void *cookie, const char *buffer, size_t size); +int _assuan_cookie_write_flush (void *cookie); +assuan_error_t _assuan_write_line (assuan_context_t ctx, const char *prefix, + const char *line, size_t len); + +/*-- assuan-client.c --*/ +assuan_error_t _assuan_read_from_server (assuan_context_t ctx, + int *okay, int *off); + +/*-- assuan-error.c --*/ + + +/* Map error codes as used in this implementaion to the libgpg-error + codes. */ +assuan_error_t _assuan_error (int oldcode); + +/* Extrac the erro code from A. This works for both the old and the + new style error codes. This needs to be whenever an error code is + compared. */ +#define err_code(a) ((a) & 0x00ffffff) + +/* Check whether A is the erro code for EOF. We allow forold and new + style EOF error codes here. */ +#define err_is_eof(a) ((a) == (-1) || err_code (a) == 16383) + + + +/*-- assuan-util.c --*/ +void *_assuan_malloc (size_t n); +void *_assuan_calloc (size_t n, size_t m); +void *_assuan_realloc (void *p, size_t n); +void _assuan_free (void *p); + +#define xtrymalloc(a) _assuan_malloc ((a)) +#define xtrycalloc(a,b) _assuan_calloc ((a),(b)) +#define xtryrealloc(a,b) _assuan_realloc((a),(b)) +#define xfree(a) _assuan_free ((a)) + +#define set_error(c,e,t) \ + assuan_set_error ((c), _assuan_error (ASSUAN_ ## e), (t)) + +#ifdef HAVE_W32_SYSTEM +const char *_assuan_w32_strerror (int ec); +#define w32_strerror(e) _assuan_w32_strerror ((e)) +int _assuan_gpg_strerror_r (unsigned int err, char *buf, size_t buflen); +const char *_assuan_gpg_strsource (unsigned int err); +#endif /*HAVE_W32_SYSTEM*/ + + +/*-- assuan-logging.c --*/ +void _assuan_set_default_log_stream (FILE *fp); + +void _assuan_log_printf (const char *format, ...) +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ) + __attribute__ ((format (printf,1,2))) +#endif + ; +void _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length); +void _assuan_log_sanitized_string (const char *string); + + +/*-- assuan-io.c --*/ +pid_t _assuan_waitpid (pid_t pid, int *status, int options); + +ssize_t _assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size); +ssize_t _assuan_simple_write (assuan_context_t ctx, const void *buffer, + size_t size); +#ifdef HAVE_W32_SYSTEM +int _assuan_simple_sendmsg (assuan_context_t ctx, void *msg); +int _assuan_simple_recvmsg (assuan_context_t ctx, void *msg); +#else +ssize_t _assuan_simple_sendmsg (assuan_context_t ctx, struct msghdr *msg); +ssize_t _assuan_simple_recvmsg (assuan_context_t ctx, struct msghdr *msg); +#endif + +/*-- assuan-socket.c --*/ +int _assuan_close (int fd); +int _assuan_sock_new (int domain, int type, int proto); +int _assuan_sock_bind (int sockfd, struct sockaddr *addr, int addrlen); +int _assuan_sock_connect (int sockfd, struct sockaddr *addr, int addrlen); + +#ifdef HAVE_FOPENCOOKIE +/* We have to implement funopen in terms of glibc's fopencookie. */ +FILE *_assuan_funopen(void *cookie, + cookie_read_function_t *readfn, + cookie_write_function_t *writefn, + cookie_seek_function_t *seekfn, + cookie_close_function_t *closefn); +#define funopen(a,r,w,s,c) _assuan_funopen ((a), (r), (w), (s), (c)) +#endif /*HAVE_FOPENCOOKIE*/ + +/* Prototypes for replacement functions. */ +#ifndef HAVE_MEMRCHR +void *memrchr (const void *block, int c, size_t size); +#endif +#ifndef HAVE_STPCPY +char *stpcpy (char *dest, const char *src); +#endif +#ifndef HAVE_SETENV +#define setenv _assuan_setenv +#define unsetenv _assuan_unsetenv +#define clearenv _assuan_clearenv +int setenv (const char *name, const char *value, int replace); +#endif +#ifndef HAVE_PUTC_UNLOCKED +int putc_unlocked (int c, FILE *stream); +#endif + +#define DIM(v) (sizeof(v)/sizeof((v)[0])) +#define DIMof(type,member) DIM(((type *)0)->member) + + +#endif /*ASSUAN_DEFS_H*/ diff --git a/tags/gpgme-1.1.6/assuan/assuan-handler.c b/tags/gpgme-1.1.6/assuan/assuan-handler.c new file mode 100644 index 0000000..d1b29cf --- /dev/null +++ b/tags/gpgme-1.1.6/assuan/assuan-handler.c @@ -0,0 +1,795 @@ +/* assuan-handler.c - dispatch commands + * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of Assuan. + * + * Assuan is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Assuan 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include +#include +#include +#include +#include + +#include "assuan-defs.h" + + + +#define spacep(p) (*(p) == ' ' || *(p) == '\t') +#define digitp(a) ((a) >= '0' && (a) <= '9') + +static int my_strcasecmp (const char *a, const char *b); + + + +static int +dummy_handler (assuan_context_t ctx, char *line) +{ + return set_error (ctx, Server_Fault, "no handler registered"); +} + + +static int +std_handler_nop (assuan_context_t ctx, char *line) +{ + return 0; /* okay */ +} + +static int +std_handler_cancel (assuan_context_t ctx, char *line) +{ + if (ctx->cancel_notify_fnc) + ctx->cancel_notify_fnc (ctx); + return set_error (ctx, Not_Implemented, NULL); +} + +static int +std_handler_option (assuan_context_t ctx, char *line) +{ + char *key, *value, *p; + + for (key=line; spacep (key); key++) + ; + if (!*key) + return set_error (ctx, Syntax_Error, "argument required"); + if (*key == '=') + return set_error (ctx, Syntax_Error, "no option name given"); + for (value=key; *value && !spacep (value) && *value != '='; value++) + ; + if (*value) + { + if (spacep (value)) + *value++ = 0; /* terminate key */ + for (; spacep (value); value++) + ; + if (*value == '=') + { + *value++ = 0; /* terminate key */ + for (; spacep (value); value++) + ; + if (!*value) + return set_error (ctx, Syntax_Error, "option argument expected"); + } + if (*value) + { + for (p = value + strlen(value) - 1; p > value && spacep (p); p--) + ; + if (p > value) + *++p = 0; /* strip trailing spaces */ + } + } + + if (*key == '-' && key[1] == '-' && key[2]) + key += 2; /* the double dashes are optional */ + if (*key == '-') + return set_error (ctx, Syntax_Error, + "option should not begin with one dash"); + + if (ctx->option_handler_fnc) + return ctx->option_handler_fnc (ctx, key, value); + return 0; +} + +static int +std_handler_bye (assuan_context_t ctx, char *line) +{ + if (ctx->bye_notify_fnc) + ctx->bye_notify_fnc (ctx); + assuan_close_input_fd (ctx); + assuan_close_output_fd (ctx); + return -1; /* pretty simple :-) */ +} + +static int +std_handler_auth (assuan_context_t ctx, char *line) +{ + return set_error (ctx, Not_Implemented, NULL); +} + +static int +std_handler_reset (assuan_context_t ctx, char *line) +{ + if (ctx->reset_notify_fnc) + ctx->reset_notify_fnc (ctx); + assuan_close_input_fd (ctx); + assuan_close_output_fd (ctx); + _assuan_uds_close_fds (ctx); + return 0; +} + +static int +std_handler_end (assuan_context_t ctx, char *line) +{ + return set_error (ctx, Not_Implemented, NULL); +} + +assuan_error_t +assuan_command_parse_fd (assuan_context_t ctx, char *line, int *rfd) +{ + char *endp; + + if ((strncmp (line, "FD", 2) && strncmp (line, "fd", 2)) + || (line[2] != '=' && line[2] != '\0' && !spacep(&line[2]))) + return set_error (ctx, Syntax_Error, "FD[=] expected"); + line += 2; + if (*line == '=') + { + line ++; + if (!digitp (*line)) + return set_error (ctx, Syntax_Error, "number required"); + *rfd = strtoul (line, &endp, 10); + /* Remove that argument so that a notify handler won't see it. */ + memset (line, ' ', endp? (endp-line):strlen(line)); + + if (*rfd == ctx->inbound.fd) + return set_error (ctx, Parameter_Conflict, "fd same as inbound fd"); + if (*rfd == ctx->outbound.fd) + return set_error (ctx, Parameter_Conflict, "fd same as outbound fd"); + return 0; + } + else + /* Our peer has sent the file descriptor. */ + return assuan_receivefd (ctx, rfd); +} + +/* Format is INPUT FD= */ +static int +std_handler_input (assuan_context_t ctx, char *line) +{ + int rc, fd; + + rc = assuan_command_parse_fd (ctx, line, &fd); + if (rc) + return rc; + ctx->input_fd = fd; + if (ctx->input_notify_fnc) + ctx->input_notify_fnc (ctx, line); + return 0; +} + +/* Format is OUTPUT FD= */ +static int +std_handler_output (assuan_context_t ctx, char *line) +{ + int rc, fd; + + rc = assuan_command_parse_fd (ctx, line, &fd); + if (rc) + return rc; + ctx->output_fd = fd; + if (ctx->output_notify_fnc) + ctx->output_notify_fnc (ctx, line); + return 0; +} + + + + + +/* This is a table with the standard commands and handler for them. + The table is used to initialize a new context and associate strings + with default handlers */ +static struct { + const char *name; + int (*handler)(assuan_context_t, char *line); + int always; /* always initialize this command */ +} std_cmd_table[] = { + { "NOP", std_handler_nop, 1 }, + { "CANCEL", std_handler_cancel, 1 }, + { "OPTION", std_handler_option, 1 }, + { "BYE", std_handler_bye, 1 }, + { "AUTH", std_handler_auth, 1 }, + { "RESET", std_handler_reset, 1 }, + { "END", std_handler_end, 1 }, + + { "INPUT", std_handler_input }, + { "OUTPUT", std_handler_output }, + { "OPTION", std_handler_option, 1 }, + { NULL } +}; + + +/** + * assuan_register_command: + * @ctx: the server context + * @cmd_name: A string with the command name + * @handler: The handler function to be called or NULL to use a default + * handler. + * + * Register a handler to be used for a given command. Note that + * several default handlers are already regsitered with a new context. + * This function however allows to override them. + * + * Return value: 0 on success or an error code + **/ +int +assuan_register_command (assuan_context_t ctx, + const char *cmd_name, + int (*handler)(assuan_context_t, char *)) +{ + int i; + const char *s; + + if (cmd_name && !*cmd_name) + cmd_name = NULL; + + if (!cmd_name) + return _assuan_error (ASSUAN_Invalid_Value); + + if (!handler) + { /* find a default handler. */ + for (i=0; (s=std_cmd_table[i].name) && strcmp (cmd_name, s); i++) + ; + if (!s) + { /* Try again but case insensitive. */ + for (i=0; (s=std_cmd_table[i].name) + && my_strcasecmp (cmd_name, s); i++) + ; + } + if (s) + handler = std_cmd_table[i].handler; + if (!handler) + handler = dummy_handler; /* Last resort is the dummy handler. */ + } + + if (!ctx->cmdtbl) + { + ctx->cmdtbl_size = 50; + ctx->cmdtbl = xtrycalloc ( ctx->cmdtbl_size, sizeof *ctx->cmdtbl); + if (!ctx->cmdtbl) + return _assuan_error (ASSUAN_Out_Of_Core); + ctx->cmdtbl_used = 0; + } + else if (ctx->cmdtbl_used >= ctx->cmdtbl_size) + { + struct cmdtbl_s *x; + + x = xtryrealloc ( ctx->cmdtbl, (ctx->cmdtbl_size+10) * sizeof *x); + if (!x) + return _assuan_error (ASSUAN_Out_Of_Core); + ctx->cmdtbl = x; + ctx->cmdtbl_size += 50; + } + + ctx->cmdtbl[ctx->cmdtbl_used].name = cmd_name; + ctx->cmdtbl[ctx->cmdtbl_used].handler = handler; + ctx->cmdtbl_used++; + return 0; +} + +int +assuan_register_post_cmd_notify (assuan_context_t ctx, + void (*fnc)(assuan_context_t, int)) +{ + if (!ctx) + return _assuan_error (ASSUAN_Invalid_Value); + ctx->post_cmd_notify_fnc = fnc; + return 0; +} + +int +assuan_register_bye_notify (assuan_context_t ctx, + void (*fnc)(assuan_context_t)) +{ + if (!ctx) + return _assuan_error (ASSUAN_Invalid_Value); + ctx->bye_notify_fnc = fnc; + return 0; +} + +int +assuan_register_reset_notify (assuan_context_t ctx, + void (*fnc)(assuan_context_t)) +{ + if (!ctx) + return _assuan_error (ASSUAN_Invalid_Value); + ctx->reset_notify_fnc = fnc; + return 0; +} + +int +assuan_register_cancel_notify (assuan_context_t ctx, + void (*fnc)(assuan_context_t)) +{ + if (!ctx) + return _assuan_error (ASSUAN_Invalid_Value); + ctx->cancel_notify_fnc = fnc; + return 0; +} + +int +assuan_register_option_handler (assuan_context_t ctx, + int (*fnc)(assuan_context_t, + const char*, const char*)) +{ + if (!ctx) + return _assuan_error (ASSUAN_Invalid_Value); + ctx->option_handler_fnc = fnc; + return 0; +} + +int +assuan_register_input_notify (assuan_context_t ctx, + void (*fnc)(assuan_context_t, const char *)) +{ + if (!ctx) + return _assuan_error (ASSUAN_Invalid_Value); + ctx->input_notify_fnc = fnc; + return 0; +} + +int +assuan_register_output_notify (assuan_context_t ctx, + void (*fnc)(assuan_context_t, const char *)) +{ + if (!ctx) + return _assuan_error (ASSUAN_Invalid_Value); + ctx->output_notify_fnc = fnc; + return 0; +} + + +/* Helper to register the standards commands */ +int +_assuan_register_std_commands (assuan_context_t ctx) +{ + int i, rc; + + for (i=0; std_cmd_table[i].name; i++) + { + if (std_cmd_table[i].always) + { + rc = assuan_register_command (ctx, std_cmd_table[i].name, NULL); + if (rc) + return rc; + } + } + return 0; +} + + + +/* Process the special data lines. The "D " has already been removed + from the line. As all handlers this function may modify the line. */ +static int +handle_data_line (assuan_context_t ctx, char *line, int linelen) +{ + return set_error (ctx, Not_Implemented, NULL); +} + +/* like ascii_strcasecmp but assume that B is already uppercase */ +static int +my_strcasecmp (const char *a, const char *b) +{ + if (a == b) + return 0; + + for (; *a && *b; a++, b++) + { + if (((*a >= 'a' && *a <= 'z')? (*a&~0x20):*a) != *b) + break; + } + return *a == *b? 0 : (((*a >= 'a' && *a <= 'z')? (*a&~0x20):*a) - *b); +} + +/* Parse the line, break out the command, find it in the command + table, remove leading and white spaces from the arguments, call the + handler with the argument line and return the error */ +static int +dispatch_command (assuan_context_t ctx, char *line, int linelen) +{ + char *p; + const char *s; + int shift, i; + + if (*line == 'D' && line[1] == ' ') /* divert to special handler */ + return handle_data_line (ctx, line+2, linelen-2); + + for (p=line; *p && *p != ' ' && *p != '\t'; p++) + ; + if (p==line) + return set_error (ctx, Syntax_Error, "leading white-space"); + if (*p) + { /* Skip over leading WS after the keyword */ + *p++ = 0; + while ( *p == ' ' || *p == '\t') + p++; + } + shift = p - line; + + for (i=0; (s=ctx->cmdtbl[i].name); i++) + { + if (!strcmp (line, s)) + break; + } + if (!s) + { /* and try case insensitive */ + for (i=0; (s=ctx->cmdtbl[i].name); i++) + { + if (!my_strcasecmp (line, s)) + break; + } + } + if (!s) + return set_error (ctx, Unknown_Command, NULL); + line += shift; + linelen -= shift; + +/* fprintf (stderr, "DBG-assuan: processing %s `%s'\n", s, line); */ + return ctx->cmdtbl[i].handler (ctx, line); +} + + + + +static int +process_request (assuan_context_t ctx) +{ + int rc; + + if (ctx->in_inquire) + return _assuan_error (ASSUAN_Nested_Commands); + + rc = _assuan_read_line (ctx); + if (rc) + return rc; + if (*ctx->inbound.line == '#' || !ctx->inbound.linelen) + return 0; /* comment line - ignore */ + + ctx->outbound.data.error = 0; + ctx->outbound.data.linelen = 0; + /* dispatch command and return reply */ + rc = dispatch_command (ctx, ctx->inbound.line, ctx->inbound.linelen); + /* check from data write errors */ + if (ctx->outbound.data.fp) + { /* Flush the data lines */ + fclose (ctx->outbound.data.fp); + ctx->outbound.data.fp = NULL; + if (!rc && ctx->outbound.data.error) + rc = ctx->outbound.data.error; + } + else /* flush any data send w/o using the data fp */ + { + assuan_send_data (ctx, NULL, 0); + if (!rc && ctx->outbound.data.error) + rc = ctx->outbound.data.error; + } + /* Error handling */ + if (!rc) + { + rc = assuan_write_line (ctx, ctx->okay_line? ctx->okay_line : "OK"); + } + else if (err_is_eof (rc)) + { /* No error checking because the peer may have already disconnect. */ + assuan_write_line (ctx, "OK closing connection"); + ctx->finish_handler (ctx); + } + else + { + char errline[300]; + + if (rc < 100) + sprintf (errline, "ERR %d server fault (%.50s)", + _assuan_error (ASSUAN_Server_Fault), assuan_strerror (rc)); + else + { + const char *text = ctx->err_no == rc? ctx->err_str:NULL; + +#if defined(HAVE_W32_SYSTEM) + unsigned int source, code; + char ebuf[50]; + const char *esrc; + + source = ((rc >> 24) & 0xff); + code = (rc & 0x00ffffff); + if (source + && !_assuan_gpg_strerror_r (rc, ebuf, sizeof ebuf) + && (esrc=_assuan_gpg_strsource (rc))) + { + /* Assume this is an libgpg-error. */ + sprintf (errline, "ERR %d %.50s <%.30s>%s%.100s", + rc, ebuf, esrc, + text? " - ":"", text?text:""); + } + else +#elif defined(__GNUC__) && defined(__ELF__) + /* If we have weak symbol support we try to use the error + strings from libgpg-error without creating a dependency. + They are used for debugging purposes only, so there is no + problem if they are not available. We need to make sure + that we are using ELF because only this guarantees that + weak symbol support is available in case GNU ld is not + used. It seems that old gcc versions don't implement the + weak attribute properly but it works with the weak + pragma. */ + + unsigned int source, code; + + int gpg_strerror_r (unsigned int err, char *buf, size_t buflen) + __attribute__ ((weak)); + const char *gpg_strsource (unsigned int err) + __attribute__ ((weak)); +#if __GNUC__ < 3 +#pragma weak gpg_strerror_r +#pragma weak gpg_strsource +#endif + + source = ((rc >> 24) & 0xff); + code = (rc & 0x00ffffff); + if (source && gpg_strsource && gpg_strerror_r) + { + /* Assume this is an libgpg-error. */ + char ebuf[50]; + + gpg_strerror_r (rc, ebuf, sizeof ebuf ); + sprintf (errline, "ERR %d %.50s <%.30s>%s%.100s", + rc, + ebuf, + gpg_strsource (rc), + text? " - ":"", text?text:""); + } + else +#endif /* __GNUC__ && __ELF__ */ + sprintf (errline, "ERR %d %.50s%s%.100s", + rc, assuan_strerror (rc), text? " - ":"", text?text:""); + } + rc = assuan_write_line (ctx, errline); + } + + if (ctx->post_cmd_notify_fnc) + ctx->post_cmd_notify_fnc (ctx, rc); + + ctx->confidential = 0; + if (ctx->okay_line) + { + xfree (ctx->okay_line); + ctx->okay_line = NULL; + } + return rc; +} + +/** + * assuan_process: + * @ctx: assuan context + * + * This function is used to handle the assuan protocol after a + * connection has been established using assuan_accept(). This is the + * main protocol handler. + * + * Return value: 0 on success or an error code if the assuan operation + * failed. Note, that no error is returned for operational errors. + **/ +int +assuan_process (assuan_context_t ctx) +{ + int rc; + + do { + rc = process_request (ctx); + } while (!rc); + + if (err_is_eof (rc)) + rc = 0; + + return rc; +} + + +/** + * assuan_process_next: + * @ctx: Assuan context + * + * Same as assuan_process() but the user has to provide the outer + * loop. He should loop as long as the return code is zero and stop + * otherwise; -1 is regular end. + * + * See also: assuan_get_active_fds() + * Return value: -1 for end of server, 0 on success or an error code + **/ +int +assuan_process_next (assuan_context_t ctx) +{ + return process_request (ctx); +} + + +/** + * assuan_get_active_fds: + * @ctx: Assuan context + * @what: 0 for read fds, 1 for write fds + * @fdarray: Caller supplied array to store the FDs + * @fdarraysize: size of that array + * + * Return all active filedescriptors for the given context. This + * function can be used to select on the fds and call + * assuan_process_next() if there is an active one. The first fd in + * the array is the one used for the command connection. + * + * Note, that write FDs are not yet supported. + * + * Return value: number of FDs active and put into @fdarray or -1 on + * error which is most likely a too small fdarray. + **/ +int +assuan_get_active_fds (assuan_context_t ctx, int what, + int *fdarray, int fdarraysize) +{ + int n = 0; + + if (!ctx || fdarraysize < 2 || what < 0 || what > 1) + return -1; + + if (!what) + { + if (ctx->inbound.fd != -1) + fdarray[n++] = ctx->inbound.fd; + } + else + { + if (ctx->outbound.fd != -1) + fdarray[n++] = ctx->outbound.fd; + if (ctx->outbound.data.fp) +#ifdef HAVE_W32_SYSTEM + fdarray[n++] = _get_osfhandle (fileno (ctx->outbound.data.fp)); +#else + fdarray[n++] = fileno (ctx->outbound.data.fp); +#endif + } + + return n; +} + + +/* Two simple wrappers to make the expected function types match. */ +#ifdef HAVE_FUNOPEN +static int +fun1_cookie_write (void *cookie, const char *buffer, int orig_size) +{ + return _assuan_cookie_write_data (cookie, buffer, orig_size); +} +#endif /*HAVE_FUNOPEN*/ +#ifdef HAVE_FOPENCOOKIE +static ssize_t +fun2_cookie_write (void *cookie, const char *buffer, size_t orig_size) +{ + return _assuan_cookie_write_data (cookie, buffer, orig_size); +} +#endif /*HAVE_FOPENCOOKIE*/ + +/* Return a FP to be used for data output. The FILE pointer is valid + until the end of a handler. So a close is not needed. Assuan does + all the buffering needed to insert the status line as well as the + required line wappping and quoting for data lines. + + We use GNU's custom streams here. There should be an alternative + implementaion for systems w/o a glibc, a simple implementation + could use a child process */ +FILE * +assuan_get_data_fp (assuan_context_t ctx) +{ +#if defined (HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN) + if (ctx->outbound.data.fp) + return ctx->outbound.data.fp; + +#ifdef HAVE_FUNOPEN + ctx->outbound.data.fp = funopen (ctx, 0, fun1_cookie_write, + 0, _assuan_cookie_write_flush); +#else + ctx->outbound.data.fp = funopen (ctx, 0, fun2_cookie_write, + 0, _assuan_cookie_write_flush); +#endif + + ctx->outbound.data.error = 0; + return ctx->outbound.data.fp; +#else + errno = ENOSYS; + return NULL; +#endif +} + + +/* Set the text used for the next OK reponse. This string is + automatically reset to NULL after the next command. */ +assuan_error_t +assuan_set_okay_line (assuan_context_t ctx, const char *line) +{ + if (!ctx) + return _assuan_error (ASSUAN_Invalid_Value); + if (!line) + { + xfree (ctx->okay_line); + ctx->okay_line = NULL; + } + else + { + /* FIXME: we need to use gcry_is_secure() to test whether + we should allocate the entire line in secure memory */ + char *buf = xtrymalloc (3+strlen(line)+1); + if (!buf) + return _assuan_error (ASSUAN_Out_Of_Core); + strcpy (buf, "OK "); + strcpy (buf+3, line); + xfree (ctx->okay_line); + ctx->okay_line = buf; + } + return 0; +} + + + +assuan_error_t +assuan_write_status (assuan_context_t ctx, + const char *keyword, const char *text) +{ + char buffer[256]; + char *helpbuf; + size_t n; + assuan_error_t ae; + + if ( !ctx || !keyword) + return _assuan_error (ASSUAN_Invalid_Value); + if (!text) + text = ""; + + n = 2 + strlen (keyword) + 1 + strlen (text) + 1; + if (n < sizeof (buffer)) + { + strcpy (buffer, "S "); + strcat (buffer, keyword); + if (*text) + { + strcat (buffer, " "); + strcat (buffer, text); + } + ae = assuan_write_line (ctx, buffer); + } + else if ( (helpbuf = xtrymalloc (n)) ) + { + strcpy (helpbuf, "S "); + strcat (helpbuf, keyword); + if (*text) + { + strcat (helpbuf, " "); + strcat (helpbuf, text); + } + ae = assuan_write_line (ctx, helpbuf); + xfree (helpbuf); + } + else + ae = 0; + return ae; +} diff --git a/tags/gpgme-1.1.6/assuan/assuan-inquire.c b/tags/gpgme-1.1.6/assuan/assuan-inquire.c new file mode 100644 index 0000000..d8c52d0 --- /dev/null +++ b/tags/gpgme-1.1.6/assuan/assuan-inquire.c @@ -0,0 +1,241 @@ +/* assuan-inquire.c - handle inquire stuff + * Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. + * + * This file is part of Assuan. + * + * Assuan is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Assuan 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include +#include +#include +#include + +#include "assuan-defs.h" + +#define digitp(a) ((a) >= '0' && (a) <= '9') +#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \ + *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10)) +#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1)) + + +struct membuf +{ + size_t len; + size_t size; + char *buf; + int out_of_core; + int too_large; + size_t maxlen; +}; + + + +/* A simple implemnation of a dynamic buffer. Use init_membuf() to + create a buffer, put_membuf to append bytes and get_membuf to + release and return the buffer. Allocation errors are detected but + only returned at the final get_membuf(), this helps not to clutter + the code with out of core checks. */ + +static void +init_membuf (struct membuf *mb, int initiallen, size_t maxlen) +{ + mb->len = 0; + mb->size = initiallen; + mb->out_of_core = 0; + mb->too_large = 0; + mb->maxlen = maxlen; + /* we need to allocate one byte more for get_membuf */ + mb->buf = xtrymalloc (initiallen+1); + if (!mb->buf) + mb->out_of_core = 1; +} + +static void +put_membuf (struct membuf *mb, const void *buf, size_t len) +{ + if (mb->out_of_core || mb->too_large) + return; + + if (mb->maxlen && mb->len + len > mb->maxlen) + { + mb->too_large = 1; + return; + } + + if (mb->len + len >= mb->size) + { + char *p; + + mb->size += len + 1024; + /* we need to allocate one byte more for get_membuf */ + p = xtryrealloc (mb->buf, mb->size+1); + if (!p) + { + mb->out_of_core = 1; + return; + } + mb->buf = p; + } + memcpy (mb->buf + mb->len, buf, len); + mb->len += len; +} + +static void * +get_membuf (struct membuf *mb, size_t *len) +{ + char *p; + + if (mb->out_of_core || mb->too_large) + { + xfree (mb->buf); + mb->buf = NULL; + return NULL; + } + + mb->buf[mb->len] = 0; /* there is enough space for the hidden eos */ + p = mb->buf; + *len = mb->len; + mb->buf = NULL; + mb->out_of_core = 1; /* don't allow a reuse */ + return p; +} + +static void +free_membuf (struct membuf *mb) +{ + xfree (mb->buf); + mb->buf = NULL; +} + + +/** + * assuan_inquire: + * @ctx: An assuan context + * @keyword: The keyword used for the inquire + * @r_buffer: Returns an allocated buffer + * @r_length: Returns the length of this buffer + * @maxlen: If not 0, the size limit of the inquired data. + * + * A Server may use this to Send an inquire. r_buffer, r_length and + * maxlen may all be NULL/0 to indicate that no real data is expected. + * + * Return value: 0 on success or an ASSUAN error code + **/ +assuan_error_t +assuan_inquire (assuan_context_t ctx, const char *keyword, + unsigned char **r_buffer, size_t *r_length, size_t maxlen) +{ + assuan_error_t rc; + struct membuf mb; + char cmdbuf[LINELENGTH-10]; /* (10 = strlen ("INQUIRE ")+CR,LF) */ + unsigned char *line, *p; + int linelen; + int nodataexpected; + + if (!ctx || !keyword || (10 + strlen (keyword) >= sizeof (cmdbuf))) + return _assuan_error (ASSUAN_Invalid_Value); + nodataexpected = !r_buffer && !r_length && !maxlen; + if (!nodataexpected && (!r_buffer || !r_length)) + return _assuan_error (ASSUAN_Invalid_Value); + if (!ctx->is_server) + return _assuan_error (ASSUAN_Not_A_Server); + if (ctx->in_inquire) + return _assuan_error (ASSUAN_Nested_Commands); + + ctx->in_inquire = 1; + if (nodataexpected) + memset (&mb, 0, sizeof mb); /* avoid compiler warnings */ + else + init_membuf (&mb, maxlen? maxlen:1024, maxlen); + + strcpy (stpcpy (cmdbuf, "INQUIRE "), keyword); + rc = assuan_write_line (ctx, cmdbuf); + if (rc) + goto leave; + + for (;;) + { + do + { + rc = _assuan_read_line (ctx); + if (rc) + goto leave; + line = (unsigned char *) ctx->inbound.line; + linelen = ctx->inbound.linelen; + } + while (*line == '#' || !linelen); + if (line[0] == 'E' && line[1] == 'N' && line[2] == 'D' + && (!line[3] || line[3] == ' ')) + break; /* END command received*/ + if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N') + { + rc = _assuan_error (ASSUAN_Canceled); + goto leave; + } + if (line[0] != 'D' || line[1] != ' ' || nodataexpected) + { + rc = _assuan_error (ASSUAN_Unexpected_Command); + goto leave; + } + if (linelen < 3) + continue; + line += 2; + linelen -= 2; + + p = line; + while (linelen) + { + for (;linelen && *p != '%'; linelen--, p++) + ; + put_membuf (&mb, line, p-line); + if (linelen > 2) + { /* handle escaping */ + unsigned char tmp[1]; + p++; + *tmp = xtoi_2 (p); + p += 2; + linelen -= 3; + put_membuf (&mb, tmp, 1); + } + line = p; + } + if (mb.too_large) + { + rc = _assuan_error (ASSUAN_Too_Much_Data); + goto leave; + } + } + + if (!nodataexpected) + { + *r_buffer = get_membuf (&mb, r_length); + if (!*r_buffer) + rc = _assuan_error (ASSUAN_Out_Of_Core); + } + + leave: + if (!nodataexpected) + free_membuf (&mb); + ctx->in_inquire = 0; + return rc; +} + + + + + + diff --git a/tags/gpgme-1.1.6/assuan/assuan-io.c b/tags/gpgme-1.1.6/assuan/assuan-io.c new file mode 100644 index 0000000..a7f8449 --- /dev/null +++ b/tags/gpgme-1.1.6/assuan/assuan-io.c @@ -0,0 +1,154 @@ +/* assuan-io.c - Wraps the read and write functions. + * Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc. + * + * This file is part of Assuan. + * + * Assuan is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Assuan 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#ifdef HAVE_SYS_SOCKET_H +# include +#endif +#include +#include +#ifdef HAVE_W32_SYSTEM +# include +#else +# include +#endif + +#include "assuan-defs.h" + + +#ifndef HAVE_W32_SYSTEM +pid_t +_assuan_waitpid (pid_t pid, int *status, int options) +{ + return waitpid (pid, status, options); +} +#endif + + +ssize_t +_assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size) +{ +#if defined(HAVE_W32_SYSTEM) && !defined(_ASSUAN_IN_GPGME_BUILD_ASSUAN) + /* Due to the peculiarities of the W32 API we can't use read for a + network socket and thus we try to use recv first and fallback to + read if recv detects that it is not a network socket. */ + int n; + + n = recv (ctx->inbound.fd, buffer, size, 0); + if (n == -1 && WSAGetLastError () == WSAENOTSOCK) + { + DWORD nread = 0; + + n = ReadFile ((HANDLE)ctx->inbound.fd, buffer, size, &nread, NULL); + if (!n) + { + switch (GetLastError()) + { + case ERROR_BROKEN_PIPE: errno = EPIPE; break; + default: errno = EIO; + } + n = -1; + } + else + n = (int)nread; + } + return n; +#else /*!HAVE_W32_SYSTEM*/ + return read (ctx->inbound.fd, buffer, size); +#endif /*!HAVE_W32_SYSTEM*/ +} + +ssize_t +_assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size) +{ +#if defined(HAVE_W32_SYSTEM) && !defined(_ASSUAN_IN_GPGME_BUILD_ASSUAN) + /* Due to the peculiarities of the W32 API we can't use write for a + network socket and thus we try to use send first and fallback to + write if send detects that it is not a network socket. */ + int n; + + n = send (ctx->outbound.fd, buffer, size, 0); + if (n == -1 && WSAGetLastError () == WSAENOTSOCK) + { + DWORD nwrite; + + n = WriteFile ((HANDLE)ctx->outbound.fd, buffer, size, &nwrite, NULL); + if (!n) + { + switch (GetLastError ()) + { + case ERROR_BROKEN_PIPE: + case ERROR_NO_DATA: errno = EPIPE; break; + default: errno = EIO; break; + } + n = -1; + } + else + n = (int)nwrite; + } + return n; +#else /*!HAVE_W32_SYSTEM*/ + return write (ctx->outbound.fd, buffer, size); +#endif /*!HAVE_W32_SYSTEM*/ +} + + +#ifdef HAVE_W32_SYSTEM +int +_assuan_simple_sendmsg (assuan_context_t ctx, void *msg) +#else +ssize_t +_assuan_simple_sendmsg (assuan_context_t ctx, struct msghdr *msg) +#endif +{ +#ifdef HAVE_W32_SYSTEM + return _assuan_error (ASSUAN_Not_Implemented); +#else + int ret; + while ( (ret = sendmsg (ctx->outbound.fd, msg, 0)) == -1 && errno == EINTR) + ; + return ret; +#endif +} + + +#ifdef HAVE_W32_SYSTEM +int +_assuan_simple_recvmsg (assuan_context_t ctx, void *msg) +#else +ssize_t +_assuan_simple_recvmsg (assuan_context_t ctx, struct msghdr *msg) +#endif +{ +#ifdef HAVE_W32_SYSTEM + return _assuan_error (ASSUAN_Not_Implemented); +#else + int ret; + while ( (ret = recvmsg (ctx->inbound.fd, msg, 0)) == -1 && errno == EINTR) + ; + return ret; +#endif +} diff --git a/tags/gpgme-1.1.6/assuan/assuan-listen.c b/tags/gpgme-1.1.6/assuan/assuan-listen.c new file mode 100644 index 0000000..04db68c --- /dev/null +++ b/tags/gpgme-1.1.6/assuan/assuan-listen.c @@ -0,0 +1,157 @@ +/* assuan-listen.c - Wait for a connection (server) + * Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc. + * + * This file is part of Assuan. + * + * Assuan is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Assuan 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include +#include +#include +#include +#include +#include + +#include "assuan-defs.h" + +assuan_error_t +assuan_set_hello_line (assuan_context_t ctx, const char *line) +{ + if (!ctx) + return _assuan_error (ASSUAN_Invalid_Value); + if (!line) + { + xfree (ctx->hello_line); + ctx->hello_line = NULL; + } + else + { + char *buf = xtrymalloc (3+strlen(line)+1); + if (!buf) + return _assuan_error (ASSUAN_Out_Of_Core); + if (strchr (line, '\n')) + strcpy (buf, line); + else + { + strcpy (buf, "OK "); + strcpy (buf+3, line); + } + xfree (ctx->hello_line); + ctx->hello_line = buf; + } + return 0; +} + + +/** + * assuan_accept: + * @ctx: context + * + * Cancel any existing connection and wait for a connection from a + * client. The initial handshake is performed which may include an + * initial authentication or encryption negotiation. + * + * Return value: 0 on success or an error if the connection could for + * some reason not be established. + **/ +assuan_error_t +assuan_accept (assuan_context_t ctx) +{ + int rc; + const char *p, *pend; + + if (!ctx) + return _assuan_error (ASSUAN_Invalid_Value); + + if (ctx->pipe_mode > 1) + return -1; /* second invocation for pipemode -> terminate */ + ctx->finish_handler (ctx); + + rc = ctx->accept_handler (ctx); + if (rc) + return rc; + + /* Send the hello. */ + p = ctx->hello_line; + if (p && (pend = strchr (p, '\n'))) + { /* This is a multi line hello. Send all but the last line as + comments. */ + do + { + rc = _assuan_write_line (ctx, "# ", p, pend - p); + if (rc) + return rc; + p = pend + 1; + pend = strchr (p, '\n'); + } + while (pend); + rc = _assuan_write_line (ctx, "OK ", p, strlen (p)); + } + else if (p) + rc = assuan_write_line (ctx, p); + else + rc = assuan_write_line (ctx, "OK Pleased to meet you"); + if (rc) + return rc; + + if (ctx->pipe_mode) + ctx->pipe_mode = 2; + + return 0; +} + + + +int +assuan_get_input_fd (assuan_context_t ctx) +{ + return ctx? ctx->input_fd : -1; +} + + +int +assuan_get_output_fd (assuan_context_t ctx) +{ + return ctx? ctx->output_fd : -1; +} + + +/* Close the fd descriptor set by the command INPUT FD=n. We handle + this fd inside assuan so that we can do some initial checks */ +assuan_error_t +assuan_close_input_fd (assuan_context_t ctx) +{ + if (!ctx || ctx->input_fd == -1) + return _assuan_error (ASSUAN_Invalid_Value); + _assuan_close (ctx->input_fd); + ctx->input_fd = -1; + return 0; +} + +/* Close the fd descriptor set by the command OUTPUT FD=n. We handle + this fd inside assuan so that we can do some initial checks */ +assuan_error_t +assuan_close_output_fd (assuan_context_t ctx) +{ + if (!ctx || ctx->output_fd == -1) + return _assuan_error (ASSUAN_Invalid_Value); + + _assuan_close (ctx->output_fd); + ctx->output_fd = -1; + return 0; +} + diff --git a/tags/gpgme-1.1.6/assuan/assuan-logging.c b/tags/gpgme-1.1.6/assuan/assuan-logging.c new file mode 100644 index 0000000..41ada91 --- /dev/null +++ b/tags/gpgme-1.1.6/assuan/assuan-logging.c @@ -0,0 +1,316 @@ +/* assuan-logging.c - Default logging function. + * Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc. + * + * This file is part of Assuan. + * + * Assuan is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Assuan 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#ifdef HAVE_W32_SYSTEM +#include +#endif /*HAVE_W32_SYSTEM*/ +#include +#include + +#include "assuan-defs.h" + +static char prefix_buffer[80]; +static FILE *_assuan_log; +static int full_logging; +static int log_level = 1; /* Defaults to logging enabled. */ + + +/* Set the log level for general assuan commands. 0 is no logging at + all, 1 is the standard logging and the default. Higher leveles may + be defined in the future. Passing a level of -1 will not change + the current log level. Returns previosu log level. */ +int +assuan_set_assuan_log_level (int level) +{ + int old = log_level; + + if (level != -1) + log_level = level; + return old; +} + + +void +_assuan_set_default_log_stream (FILE *fp) +{ + if (!_assuan_log) + { + _assuan_log = fp; + full_logging = !!getenv ("ASSUAN_FULL_LOGGING"); + } +} + +void +assuan_set_assuan_log_stream (FILE *fp) +{ + _assuan_log = fp; +} + + +/* Set the per context log stream. Also enable the default log stream + if it has not been set. */ +void +assuan_set_log_stream (assuan_context_t ctx, FILE *fp) +{ + if (ctx) + { + if (ctx->log_fp) + fflush (ctx->log_fp); + ctx->log_fp = fp; + _assuan_set_default_log_stream (fp); + } +} + + +FILE * +assuan_get_assuan_log_stream (void) +{ + return _assuan_log ? _assuan_log : stderr; +} + + +/* Set the prefix to be used for logging to TEXT or + resets it to the default if TEXT is NULL. */ +void +assuan_set_assuan_log_prefix (const char *text) +{ + if (text) + { + strncpy (prefix_buffer, text, sizeof (prefix_buffer)-1); + prefix_buffer[sizeof (prefix_buffer)-1] = 0; + } + else + *prefix_buffer = 0; +} + +const char * +assuan_get_assuan_log_prefix (void) +{ + return prefix_buffer; +} + + +void +_assuan_log_printf (const char *format, ...) +{ + va_list arg_ptr; + FILE *fp; + const char *prf; + int save_errno = errno; + + if (!log_level) + return; + + fp = assuan_get_assuan_log_stream (); + prf = assuan_get_assuan_log_prefix (); + if (*prf) + fprintf (fp, "%s[%u]: ", prf, (unsigned int)getpid ()); + + va_start (arg_ptr, format); + vfprintf (fp, format, arg_ptr ); + va_end (arg_ptr); + errno = save_errno; +} + + +/* Dump a possibly binary string (used for debugging). Distinguish + ascii text from binary and print it accordingly. This function + takes FILE pointer arg becuase logging may be enabled on a per + context basis. */ +void +_assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length) +{ + const unsigned char *s; + int n; + + if (!log_level) + return; + + for (n=length,s=buffer; n; n--, s++) + if ((!isascii (*s) || iscntrl (*s) || !isprint (*s)) && !(*s >= 0x80)) + break; + + s = buffer; + if (!n && *s != '[') + fwrite (buffer, length, 1, fp); + else + { +#ifdef HAVE_FLOCKFILE + flockfile (fp); +#endif + putc_unlocked ('[', fp); + if ( length > 16 && !full_logging) + { + for (n=0; n < 12; n++, s++) + fprintf (fp, " %02x", *s); + fprintf (fp, " ...(%d bytes skipped)", (int)length - 12); + } + else + { + for (n=0; n < length; n++, s++) + fprintf (fp, " %02x", *s); + } + putc_unlocked (' ', fp); + putc_unlocked (']', fp); +#ifdef HAVE_FUNLOCKFILE + funlockfile (fp); +#endif + } +} + +/* Log a user supplied string. Escapes non-printable before + printing. */ +void +_assuan_log_sanitized_string (const char *string) +{ + const unsigned char *s = (const unsigned char *) string; + FILE *fp; + + if (!log_level) + return; + + if (!*s) + return; + + fp = assuan_get_assuan_log_stream (); + +#ifdef HAVE_FLOCKFILE + flockfile (fp); +#endif + + for (; *s; s++) + { + int c = 0; + + switch (*s) + { + case '\r': + c = 'r'; + break; + + case '\n': + c = 'n'; + break; + + case '\f': + c = 'f'; + break; + + case '\v': + c = 'v'; + break; + + case '\b': + c = 'b'; + break; + + default: + if ((isascii (*s) && isprint (*s)) || (*s >= 0x80)) + putc_unlocked (*s, fp); + else + { + putc_unlocked ('\\', fp); + fprintf (fp, "x%02x", *s); + } + } + + if (c) + { + putc_unlocked ('\\', fp); + putc_unlocked (c, fp); + } + } + +#ifdef HAVE_FUNLOCKFILE + funlockfile (fp); +#endif +} + + + +#ifdef HAVE_W32_SYSTEM +const char * +_assuan_w32_strerror (int ec) +{ + static char strerr[256]; + + if (ec == -1) + ec = (int)GetLastError (); + FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, ec, + MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), + strerr, sizeof (strerr)-1, NULL); + return strerr; +} + +static int (*my_strerror_r) (unsigned int err, char *buf, size_t buflen); +static const char * (*my_strsource) (unsigned int err); + +static int +load_libgpg_error (void) +{ + /* This code is not race free but suitable for our purpose. */ + static volatile int initialized; + void *handle; + + if (initialized) + return (my_strerror_r && my_strsource)? 0:-1; + handle = LoadLibrary ("libgpg-error-0.dll"); + if (handle) + { + void *foo, *bar; + foo = GetProcAddress (handle, "gpg_strerror_r"); + bar = GetProcAddress (handle, "gpg_strsource"); + if (foo && bar) + { + my_strerror_r = foo; + my_strsource = bar; + } + else + CloseHandle (handle); + } + initialized = 1; + return 0; +} + +int +_assuan_gpg_strerror_r (unsigned int err, char *buf, size_t buflen) +{ + if (load_libgpg_error ()) + return -1; + return my_strerror_r (err, buf, buflen); +} + + +const char * +_assuan_gpg_strsource (unsigned int err) +{ + if (load_libgpg_error ()) + return NULL; + return my_strsource (err); +} +#endif /*HAVE_W32_SYSTEM*/ diff --git a/tags/gpgme-1.1.6/assuan/assuan-pipe-connect.c b/tags/gpgme-1.1.6/assuan/assuan-pipe-connect.c new file mode 100644 index 0000000..e38b787 --- /dev/null +++ b/tags/gpgme-1.1.6/assuan/assuan-pipe-connect.c @@ -0,0 +1,1000 @@ +/* assuan-pipe-connect.c - Establish a pipe connection (client) + * Copyright (C) 2001, 2002, 2003, 2005, 2006 Free Software Foundation, Inc. + * + * This file is part of Assuan. + * + * Assuan is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Assuan 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef HAVE_W32_SYSTEM +#include +#else +#include +#endif + +#include "assuan-defs.h" + +/* Hacks for Slowaris. */ +#ifndef PF_LOCAL +# ifdef PF_UNIX +# define PF_LOCAL PF_UNIX +# else +# define PF_LOCAL AF_UNIX +# endif +#endif +#ifndef AF_LOCAL +# define AF_LOCAL AF_UNIX +#endif + + +#ifdef _POSIX_OPEN_MAX +#define MAX_OPEN_FDS _POSIX_OPEN_MAX +#else +#define MAX_OPEN_FDS 20 +#endif + +#ifdef HAVE_W32_SYSTEM +/* 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)) +#endif /*HAVE_W32_SYSTEM*/ + + +/* This should be called to make sure that SIGPIPE gets ignored. */ +static void +fix_signals (void) +{ +#ifndef _ASSUAN_NO_FIXED_SIGNALS +#ifndef HAVE_DOSISH_SYSTEM /* No SIGPIPE for these systems. */ + static int fixed_signals; + + 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 MT safe */ + } +#endif /*HAVE_DOSISH_SYSTEM*/ +#endif /*!_ASSUAN_NO_FIXED_SIGNALS*/ +} + + +#ifndef HAVE_W32_SYSTEM +static int +writen (int fd, const char *buffer, size_t length) +{ + while (length) + { + int nwritten = write (fd, buffer, length); + + if (nwritten < 0) + { + if (errno == EINTR) + continue; + return -1; /* write error */ + } + length -= nwritten; + buffer += nwritten; + } + return 0; /* okay */ +} +#endif + +static int +do_finish (assuan_context_t ctx) +{ + if (ctx->inbound.fd != -1) + { + _assuan_close (ctx->inbound.fd); + if (ctx->inbound.fd == ctx->outbound.fd) + ctx->outbound.fd = -1; + ctx->inbound.fd = -1; + } + if (ctx->outbound.fd != -1) + { + _assuan_close (ctx->outbound.fd); + ctx->outbound.fd = -1; + } + if (ctx->pid != -1 && ctx->pid) + { +#ifndef HAVE_W32_SYSTEM +#ifndef _ASSUAN_USE_DOUBLE_FORK + if (!ctx->flags.no_waitpid) + _assuan_waitpid (ctx->pid, NULL, 0); + ctx->pid = -1; +#endif +#endif /*!HAVE_W32_SYSTEM*/ + } + return 0; +} + +static void +do_deinit (assuan_context_t ctx) +{ + do_finish (ctx); +} + + +/* Helper for pipe_connect. */ +static assuan_error_t +initial_handshake (assuan_context_t *ctx) +{ + int okay, off; + assuan_error_t err; + + err = _assuan_read_from_server (*ctx, &okay, &off); + if (err) + _assuan_log_printf ("can't connect server: %s\n", + assuan_strerror (err)); + else if (okay != 1) + { + _assuan_log_printf ("can't connect server: `%s'\n", + (*ctx)->inbound.line); + err = _assuan_error (ASSUAN_Connect_Failed); + } + + if (err) + { + assuan_disconnect (*ctx); + *ctx = NULL; + } + return err; +} + + +#ifndef _ASSUAN_IN_GPGME_BUILD_ASSUAN + +#ifndef HAVE_W32_SYSTEM +#define pipe_connect pipe_connect_unix +/* Unix version of the pipe connection code. We use an extra macro to + make ChangeLog entries easier. */ +static assuan_error_t +pipe_connect_unix (assuan_context_t *ctx, + const char *name, const char *const argv[], + int *fd_child_list, + void (*atfork) (void *opaque, int reserved), + void *atforkvalue) +{ + assuan_error_t err; + int rp[2]; + int wp[2]; + char mypidstr[50]; + + if (!ctx || !name || !argv || !argv[0]) + return _assuan_error (ASSUAN_Invalid_Value); + + fix_signals (); + + sprintf (mypidstr, "%lu", (unsigned long)getpid ()); + + if (pipe (rp) < 0) + return _assuan_error (ASSUAN_General_Error); + + if (pipe (wp) < 0) + { + close (rp[0]); + close (rp[1]); + return _assuan_error (ASSUAN_General_Error); + } + + err = _assuan_new_context (ctx); + if (err) + { + close (rp[0]); + close (rp[1]); + close (wp[0]); + close (wp[1]); + return err; + } + (*ctx)->pipe_mode = 1; + (*ctx)->inbound.fd = rp[0]; /* Our inbound is read end of read pipe. */ + (*ctx)->outbound.fd = wp[1]; /* Our outbound is write end of write pipe. */ + (*ctx)->deinit_handler = do_deinit; + (*ctx)->finish_handler = do_finish; + + /* FIXME: For GPGME we should better use _gpgme_io_spawn. The PID + stored here is actually soon useless. */ + (*ctx)->pid = fork (); + if ((*ctx)->pid < 0) + { + close (rp[0]); + close (rp[1]); + close (wp[0]); + close (wp[1]); + _assuan_release_context (*ctx); + return _assuan_error (ASSUAN_General_Error); + } + + if ((*ctx)->pid == 0) + { +#ifdef _ASSUAN_USE_DOUBLE_FORK + pid_t pid; + + if ((pid = fork ()) == 0) +#endif + { + int i, n; + char errbuf[512]; + int *fdp; + + if (atfork) + atfork (atforkvalue, 0); + + /* Dup handles to stdin/stdout. */ + if (rp[1] != STDOUT_FILENO) + { + if (dup2 (rp[1], STDOUT_FILENO) == -1) + { + _assuan_log_printf ("dup2 failed in child: %s\n", + strerror (errno)); + _exit (4); + } + } + if (wp[0] != STDIN_FILENO) + { + if (dup2 (wp[0], STDIN_FILENO) == -1) + { + _assuan_log_printf ("dup2 failed in child: %s\n", + strerror (errno)); + _exit (4); + } + } + + /* Dup stderr to /dev/null unless it is in the list of FDs to be + passed to the child. */ + fdp = fd_child_list; + if (fdp) + { + for (; *fdp != -1 && *fdp != STDERR_FILENO; fdp++) + ; + } + if (!fdp || *fdp == -1) + { + int fd = open ("/dev/null", O_WRONLY); + if (fd == -1) + { + _assuan_log_printf ("can't open `/dev/null': %s\n", + strerror (errno)); + _exit (4); + } + if (dup2 (fd, STDERR_FILENO) == -1) + { + _assuan_log_printf ("dup2(dev/null, 2) failed: %s\n", + strerror (errno)); + _exit (4); + } + } + + + /* Close all files which will not be duped and are not in the + fd_child_list. */ + n = sysconf (_SC_OPEN_MAX); + if (n < 0) + n = MAX_OPEN_FDS; + for (i=0; i < n; i++) + { + if ( i == STDIN_FILENO || i == STDOUT_FILENO + || i == STDERR_FILENO) + continue; + fdp = fd_child_list; + if (fdp) + { + while (*fdp != -1 && *fdp != i) + fdp++; + } + + if (!(fdp && *fdp != -1)) + close(i); + } + errno = 0; + + /* We store our parents pid in the environment so that the + execed assuan server is able to read the actual pid of the + client. The server can't use getppid because it might have + been double forked before the assuan server has been + initialized. */ + setenv ("_assuan_pipe_connect_pid", mypidstr, 1); + + /* Make sure that we never pass a connection fd variable + when using a simple pipe. */ + unsetenv ("_assuan_connection_fd"); + + execv (name, (char *const *) argv); + /* oops - use the pipe to tell the parent about it */ + snprintf (errbuf, sizeof(errbuf)-1, + "ERR %d can't exec `%s': %.50s\n", + _assuan_error (ASSUAN_Problem_Starting_Server), + name, strerror (errno)); + errbuf[sizeof(errbuf)-1] = 0; + writen (1, errbuf, strlen (errbuf)); + _exit (4); + } +#ifdef _ASSUAN_USE_DOUBLE_FORK + if (pid == -1) + _exit (1); + else + _exit (0); +#endif + } + +#ifdef _ASSUAN_USE_DOUBLE_FORK + _assuan_waitpid ((*ctx)->pid, NULL, 0); + (*ctx)->pid = -1; +#endif + + close (rp[1]); + close (wp[0]); + + return initial_handshake (ctx); +} +#endif /*!HAVE_W32_SYSTEM*/ +#endif /* _ASSUAN_IN_GPGME_BUILD_ASSUAN */ + + +#ifndef HAVE_W32_SYSTEM +/* This function is similar to pipe_connect but uses a socketpair and + sets the I/O up to use sendmsg/recvmsg. */ +static assuan_error_t +socketpair_connect (assuan_context_t *ctx, + const char *name, const char *const argv[], + int *fd_child_list, + void (*atfork) (void *opaque, int reserved), + void *atforkvalue) +{ + assuan_error_t err; + int fds[2]; + char mypidstr[50]; + + if (!ctx + || (name && (!argv || !argv[0])) + || (!name && argv)) + return _assuan_error (ASSUAN_Invalid_Value); + + fix_signals (); + + sprintf (mypidstr, "%lu", (unsigned long)getpid ()); + + if ( socketpair (AF_LOCAL, SOCK_STREAM, 0, fds) ) + { + _assuan_log_printf ("socketpair failed: %s\n", strerror (errno)); + return _assuan_error (ASSUAN_General_Error); + } + + err = _assuan_new_context (ctx); + if (err) + { + close (fds[0]); + close (fds[1]); + return err; + } + (*ctx)->pipe_mode = 1; + (*ctx)->inbound.fd = fds[0]; + (*ctx)->outbound.fd = fds[0]; + _assuan_init_uds_io (*ctx); + (*ctx)->deinit_handler = _assuan_uds_deinit; + (*ctx)->finish_handler = do_finish; + + (*ctx)->pid = fork (); + if ((*ctx)->pid < 0) + { + close (fds[0]); + close (fds[1]); + _assuan_release_context (*ctx); + *ctx = NULL; + return _assuan_error (ASSUAN_General_Error); + } + + if ((*ctx)->pid == 0) + { +#ifdef _ASSUAN_USE_DOUBLE_FORK + pid_t pid; + + if ((pid = fork ()) == 0) +#endif + { + int fd, i, n; + char errbuf[512]; + int *fdp; + + if (atfork) + atfork (atforkvalue, 0); + + /* Connect stdin and stdout to /dev/null. */ + fd = open ("/dev/null", O_RDONLY); + if (fd == -1 || dup2 (fd, STDIN_FILENO) == -1) + { + _assuan_log_printf ("dup2(dev/null) failed: %s\n", + strerror (errno)); + _exit (4); + } + fd = open ("/dev/null", O_WRONLY); + if (fd == -1 || dup2 (fd, STDOUT_FILENO) == -1) + { + _assuan_log_printf ("dup2(dev/null) failed: %s\n", + strerror (errno)); + _exit (4); + } + + /* Dup stderr to /dev/null unless it is in the list of FDs to be + passed to the child. */ + fdp = fd_child_list; + if (fdp) + { + for (; *fdp != -1 && *fdp != STDERR_FILENO; fdp++) + ; + } + if (!fdp || *fdp == -1) + { + fd = open ("/dev/null", O_WRONLY); + if (fd == -1 || dup2 (fd, STDERR_FILENO) == -1) + { + _assuan_log_printf ("dup2(dev/null) failed: %s\n", + strerror (errno)); + _exit (4); + } + } + + + /* Close all files which will not be duped, are not in the + fd_child_list and are not the connection fd. */ + n = sysconf (_SC_OPEN_MAX); + if (n < 0) + n = MAX_OPEN_FDS; + for (i=0; i < n; i++) + { + if ( i == STDIN_FILENO || i == STDOUT_FILENO + || i == STDERR_FILENO || i == fds[1]) + continue; + fdp = fd_child_list; + if (fdp) + { + while (*fdp != -1 && *fdp != i) + fdp++; + } + + if (!(fdp && *fdp != -1)) + close(i); + } + errno = 0; + + /* We store our parents pid in the environment so that the + execed assuan server is able to read the actual pid of the + client. The server can't use getppid becuase it might have + been double forked before the assuan server has been + initialized. */ + setenv ("_assuan_pipe_connect_pid", mypidstr, 1); + + /* Now set the environment variable used to convey the + connection's file descriptor. */ + sprintf (mypidstr, "%d", fds[1]); + if (setenv ("_assuan_connection_fd", mypidstr, 1)) + { + _assuan_log_printf ("setenv failed: %s\n", strerror (errno)); + _exit (4); + } + + if (!name && !argv) + { + /* No name and no args given, thus we don't do an exec + but continue the forked process. */ + _assuan_release_context (*ctx); + *ctx = NULL; + return 0; + } + + execv (name, (char *const *) argv); + /* oops - use the pipe to tell the parent about it */ + snprintf (errbuf, sizeof(errbuf)-1, + "ERR %d can't exec `%s': %.50s\n", + _assuan_error (ASSUAN_Problem_Starting_Server), + name, strerror (errno)); + errbuf[sizeof(errbuf)-1] = 0; + writen (fds[1], errbuf, strlen (errbuf)); + _exit (4); + } +#ifdef _ASSUAN_USE_DOUBLE_FORK + if (pid == -1) + _exit (1); + else + _exit (0); +#endif + } + + +#ifdef _ASSUAN_USE_DOUBLE_FORK + _assuan_waitpid ((*ctx)->pid, NULL, 0); + (*ctx)->pid = -1; +#endif + + close (fds[1]); + + return initial_handshake (ctx); +} +#endif /*!HAVE_W32_SYSTEM*/ + + + + +#ifdef _ASSUAN_IN_GPGME_BUILD_ASSUAN + +#define pipe_connect pipe_connect_gpgme + +/* From GPGME priv-io.h */ +struct spawn_fd_item_s +{ + int fd; + int dup_to; +}; + +/* W32 version of the pipe connection code. */ +static assuan_error_t +pipe_connect_gpgme (assuan_context_t *ctx, + const char *name, const char *const argv[], + int *fd_child_list, + void (*atfork) (void *opaque, int reserved), + void *atforkvalue) +{ + assuan_error_t err; + int res; + int rp[2]; + int wp[2]; + char mypidstr[50]; + struct spawn_fd_item_s child_fds[3]; /* stdin, stdout, terminating -1 */ + + if (!ctx || !name || !argv || !argv[0]) + return _assuan_error (ASSUAN_Invalid_Value); + + /* Actually, GPGME does this for us. But we plan to reuse this code + in the generic assuan. */ + fix_signals (); + + sprintf (mypidstr, "%lu", (unsigned long)getpid ()); + + /* Create the two pipes. */ + if (_gpgme_io_pipe (rp, 1)) + return _assuan_error (ASSUAN_General_Error); + + if (_gpgme_io_pipe (wp, 0)) + { + _gpgme_io_close (rp[0]); + _gpgme_io_close (rp[1]); + return _assuan_error (ASSUAN_General_Error); + } + + err = _assuan_new_context (ctx); + if (err) + { + _gpgme_io_close (rp[0]); + _gpgme_io_close (rp[1]); + _gpgme_io_close (wp[0]); + _gpgme_io_close (wp[1]); + return _assuan_error (ASSUAN_General_Error); + } + + (*ctx)->pipe_mode = 1; + (*ctx)->inbound.fd = rp[0]; /* Our inbound is read end of read pipe. */ + (*ctx)->outbound.fd = wp[1]; /* Our outbound is write end of write pipe. */ + (*ctx)->deinit_handler = do_deinit; + (*ctx)->finish_handler = do_finish; + + /* fixme: Actually we should set the "_assuan_pipe_connect_pid" env + variable to mypidstr. However this requires us to write a full + environment handler, because the strings are expected in sorted + order. The suggestion given in the MS Reference Library, to save + the old value, changeit, create proces and restore it, is not + thread safe. */ + + /* Parent list is same as client list. Note that GPGME will dup nul + to stderr even if the caller wants to inherit the handle for + it. */ + /* Server stdout is its write end of our read pipe. */ + child_fds[0].fd = rp[1]; + child_fds[0].dup_to = 1; + /* Server stdin is its read end of our write pipe. */ + child_fds[1].fd = wp[0]; + child_fds[1].dup_to = 0; + child_fds[2].fd = -1; + + /* Start the process. */ + res = _gpgme_io_spawn (name, argv, child_fds, child_fds); + if (res == -1) + { + _assuan_log_printf ("CreateProcess failed: %s\n", strerror (errno)); + _gpgme_io_close (rp[0]); + _gpgme_io_close (rp[1]); + _gpgme_io_close (wp[0]); + _gpgme_io_close (wp[1]); + return _assuan_error (ASSUAN_General_Error); + } + + (*ctx)->pid = 0; /* We don't use the PID. */ + + return initial_handshake (ctx); +} + +#else +#ifdef HAVE_W32_SYSTEM +/* Build a command line for use with W32's CreateProcess. On success + CMDLINE gets the address of a newly allocated string. */ +static int +build_w32_commandline (const char * const *argv, char **cmdline) +{ + int i, n; + const char *s; + char *buf, *p; + + *cmdline = NULL; + n = 0; + for (i=0; (s=argv[i]); i++) + { + n += strlen (s) + 1 + 2; /* (1 space, 2 quoting */ + for (; *s; s++) + if (*s == '\"') + n++; /* Need to double inner quotes. */ + } + n++; + + buf = p = xtrymalloc (n); + if (!buf) + return -1; + + for (i=0; argv[i]; i++) + { + if (i) + p = stpcpy (p, " "); + if (!*argv[i]) /* Empty string. */ + p = stpcpy (p, "\"\""); + else if (strpbrk (argv[i], " \t\n\v\f\"")) + { + p = stpcpy (p, "\""); + for (s=argv[i]; *s; s++) + { + *p++ = *s; + if (*s == '\"') + *p++ = *s; + } + *p++ = '\"'; + *p = 0; + } + else + p = stpcpy (p, argv[i]); + } + + *cmdline= buf; + return 0; +} +#endif /*HAVE_W32_SYSTEM*/ + + +#ifdef HAVE_W32_SYSTEM +/* Create pipe where one end is inheritable. */ +static int +create_inheritable_pipe (int filedes[2], int for_write) +{ + HANDLE r, w, h; + 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)) + { + _assuan_log_printf ("CreatePipe failed: %s\n", w32_strerror (-1)); + return -1; + } + + if (!DuplicateHandle (GetCurrentProcess(), for_write? r : w, + GetCurrentProcess(), &h, 0, + TRUE, DUPLICATE_SAME_ACCESS )) + { + _assuan_log_printf ("DuplicateHandle failed: %s\n", w32_strerror (-1)); + CloseHandle (r); + CloseHandle (w); + return -1; + } + if (for_write) + { + CloseHandle (r); + r = h; + } + else + { + CloseHandle (w); + w = h; + } + + _assuan_log_printf ("created pipe: read=%p%s, write=%p%s\n", + r, for_write? " (inherit)":"", + w, for_write? "":" (inherit)"); + filedes[0] = handle_to_fd (r); + filedes[1] = handle_to_fd (w); + return 0; +} +#endif /* HAVE_W32_SYSTEM */ + +#ifdef HAVE_W32_SYSTEM +#define pipe_connect pipe_connect_w32 +/* W32 version of the pipe connection code. */ +static assuan_error_t +pipe_connect_w32 (assuan_context_t *ctx, + const char *name, const char *const argv[], + int *fd_child_list, + void (*atfork) (void *opaque, int reserved), + void *atforkvalue) +{ + assuan_error_t err; + int rp[2]; + int wp[2]; + char mypidstr[50]; + char *cmdline; + SECURITY_ATTRIBUTES sec_attr; + PROCESS_INFORMATION pi = + { + NULL, /* Returns process handle. */ + 0, /* Returns primary thread handle. */ + 0, /* Returns pid. */ + 0 /* Returns tid. */ + }; + STARTUPINFO si; + int fd, *fdp; + HANDLE nullfd = INVALID_HANDLE_VALUE; + + if (!ctx || !name || !argv || !argv[0]) + return _assuan_error (ASSUAN_Invalid_Value); + + fix_signals (); + + sprintf (mypidstr, "%lu", (unsigned long)getpid ()); + + /* Build the command line. */ + if (build_w32_commandline (argv, &cmdline)) + return _assuan_error (ASSUAN_Out_Of_Core); + + /* Create thew two pipes. */ + if (create_inheritable_pipe (rp, 0)) + { + xfree (cmdline); + return _assuan_error (ASSUAN_General_Error); + } + + if (create_inheritable_pipe (wp, 1)) + { + CloseHandle (fd_to_handle (rp[0])); + CloseHandle (fd_to_handle (rp[1])); + xfree (cmdline); + return _assuan_error (ASSUAN_General_Error); + } + + + err = _assuan_new_context (ctx); + if (err) + { + CloseHandle (fd_to_handle (rp[0])); + CloseHandle (fd_to_handle (rp[1])); + CloseHandle (fd_to_handle (wp[0])); + CloseHandle (fd_to_handle (wp[1])); + xfree (cmdline); + return _assuan_error (ASSUAN_General_Error); + } + + (*ctx)->pipe_mode = 1; + (*ctx)->inbound.fd = rp[0]; /* Our inbound is read end of read pipe. */ + (*ctx)->outbound.fd = wp[1]; /* Our outbound is write end of write pipe. */ + (*ctx)->deinit_handler = do_deinit; + (*ctx)->finish_handler = do_finish; + + + /* fixme: Actually we should set the "_assuan_pipe_connect_pid" env + variable. However this requires us to write a full environment + handler, because the strings are expected in sorted order. The + suggestion given in the MS Reference Library, to save the old + value, changeit, create proces and restore it, is not thread + safe. */ + + /* Start the process. */ + memset (&sec_attr, 0, sizeof sec_attr ); + sec_attr.nLength = sizeof sec_attr; + sec_attr.bInheritHandle = FALSE; + + memset (&si, 0, sizeof si); + si.cb = sizeof (si); + si.dwFlags = STARTF_USESTDHANDLES; + si.hStdInput = fd_to_handle (wp[0]); + si.hStdOutput = fd_to_handle (rp[1]); + + /* Dup stderr to /dev/null unless it is in the list of FDs to be + passed to the child. */ + fd = fileno (stderr); + fdp = fd_child_list; + if (fdp) + { + for (; *fdp != -1 && *fdp != fd; fdp++) + ; + } + if (!fdp || *fdp == -1) + { + nullfd = CreateFile ("nul", GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, 0, NULL); + _assuan_log_printf ("created nul device, hd=%p\n", nullfd); + if (nullfd == INVALID_HANDLE_VALUE) + { + _assuan_log_printf ("can't open `nul': %s\n", w32_strerror (-1)); + CloseHandle (fd_to_handle (rp[0])); + CloseHandle (fd_to_handle (rp[1])); + CloseHandle (fd_to_handle (wp[0])); + CloseHandle (fd_to_handle (wp[1])); + xfree (cmdline); + _assuan_release_context (*ctx); + return -1; + } + si.hStdError = nullfd; + } + else + si.hStdError = fd_to_handle (_get_osfhandle (fd)); + + + /* Note: We inherit all handles flagged as inheritable. This seems + to be a security flaw but there seems to be no way of selecting + handles to inherit. */ + _assuan_log_printf ("CreateProcess, path=`%s' cmdline=`%s'\n", + name, cmdline); + _assuan_log_printf (" stdin=%p stdout=%p stderr=%p\n", + si.hStdInput, si.hStdOutput, si.hStdError); + if (!CreateProcess (name, /* Program to start. */ + cmdline, /* Command line arguments. */ + &sec_attr, /* Process security attributes. */ + &sec_attr, /* Thread security attributes. */ + TRUE, /* Inherit handles. */ + (CREATE_DEFAULT_ERROR_MODE + | DETACHED_PROCESS + | GetPriorityClass (GetCurrentProcess ()) + | CREATE_SUSPENDED), /* Creation flags. */ + NULL, /* Environment. */ + NULL, /* Use current drive/directory. */ + &si, /* Startup information. */ + &pi /* Returns process information. */ + )) + { + _assuan_log_printf ("CreateProcess failed: %s\n", w32_strerror (-1)); + CloseHandle (fd_to_handle (rp[0])); + CloseHandle (fd_to_handle (rp[1])); + CloseHandle (fd_to_handle (wp[0])); + CloseHandle (fd_to_handle (wp[1])); + if (nullfd != INVALID_HANDLE_VALUE) + CloseHandle (nullfd); + xfree (cmdline); + _assuan_release_context (*ctx); + return _assuan_error (ASSUAN_General_Error); + } + xfree (cmdline); + cmdline = NULL; + if (nullfd != INVALID_HANDLE_VALUE) + { + CloseHandle (nullfd); + nullfd = INVALID_HANDLE_VALUE; + } + + _assuan_log_printf ("closing handles %p and %p\n", + fd_to_handle (rp[1]), fd_to_handle (wp[0]) ); + CloseHandle (fd_to_handle (rp[1])); + CloseHandle (fd_to_handle (wp[0])); + + _assuan_log_printf ("CreateProcess ready: hProcess=%p hThread=%p" + " dwProcessID=%d dwThreadId=%d\n", + pi.hProcess, pi.hThread, + (int) pi.dwProcessId, (int) pi.dwThreadId); + + ResumeThread (pi.hThread); + CloseHandle (pi.hThread); + (*ctx)->pid = 0; /* We don't use the PID. */ + CloseHandle (pi.hProcess); /* We don't need to wait for the process. */ + + return initial_handshake (ctx); +} +#endif /*HAVE_W32_SYSTEM*/ +#endif /* !_ASSUAN_IN_GPGME_BUILD_ASSUAN */ + + +/* Connect to a server over a pipe, creating the assuan context and + returning it in CTX. The server filename is NAME, the argument + vector in ARGV. FD_CHILD_LIST is a -1 terminated list of file + descriptors not to close in the child. */ +assuan_error_t +assuan_pipe_connect (assuan_context_t *ctx, const char *name, + const char *const argv[], int *fd_child_list) +{ + return pipe_connect (ctx, name, argv, fd_child_list, NULL, NULL); +} + + + +assuan_error_t +assuan_pipe_connect2 (assuan_context_t *ctx, + const char *name, const char *const argv[], + int *fd_child_list, + void (*atfork) (void *opaque, int reserved), + void *atforkvalue) +{ + return pipe_connect (ctx, name, argv, fd_child_list, atfork, atforkvalue); +} + + +/* Connect to a server over a full-duplex socket (i.e. created by + socketpair), creating the assuan context and returning it in CTX. + The server filename is NAME, the argument vector in ARGV. + FD_CHILD_LIST is a -1 terminated list of file descriptors not to + close in the child. ATFORK is called in the child right after the + fork; ATFORKVALUE is passed as the first argument and 0 is passed + as the second argument. The ATFORK function should only act if the + second value is 0. + + For now FLAGS may either take the value 0 to behave like + assuan_pipe_connect2 or 1 to enable the described full-duplex + socket behaviour. + + If NAME as well as ARGV are NULL, no exec is done but the same + process is continued. However all file descriptors are closed and + some special environment variables are set. To let the caller + detect whether the child or the parent continues, the child returns + a CTX of NULL. */ +assuan_error_t +assuan_pipe_connect_ext (assuan_context_t *ctx, + const char *name, const char *const argv[], + int *fd_child_list, + void (*atfork) (void *opaque, int reserved), + void *atforkvalue, unsigned int flags) +{ + if ((flags & 1)) + { +#ifdef HAVE_W32_SYSTEM + return _assuan_error (ASSUAN_Not_Implemented); +#else + return socketpair_connect (ctx, name, argv, fd_child_list, + atfork, atforkvalue); +#endif + } + else + return pipe_connect (ctx, name, argv, fd_child_list, atfork, atforkvalue); +} + diff --git a/tags/gpgme-1.1.6/assuan/assuan-pipe-server.c b/tags/gpgme-1.1.6/assuan/assuan-pipe-server.c new file mode 100644 index 0000000..1b47def --- /dev/null +++ b/tags/gpgme-1.1.6/assuan/assuan-pipe-server.c @@ -0,0 +1,189 @@ +/* assuan-pipe-server.c - Assuan server working over a pipe + * Copyright (C) 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Assuan. + * + * Assuan is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Assuan 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include +#include +#include +#include +#include +#include +#ifdef HAVE_W32_SYSTEM +#include +#include +#endif + +#include "assuan-defs.h" + + +static void +deinit_pipe_server (assuan_context_t ctx) +{ + /* nothing to do for this simple server */ +} + +static int +accept_connection (assuan_context_t ctx) +{ + /* This is a NOP for a pipe server */ + return 0; +} + +static int +finish_connection (assuan_context_t ctx) +{ + /* This is a NOP for a pipe server */ + return 0; +} + +/* Create a new context. Note that the handlers are set up for a pipe + server/client - this way we don't need extra dummy functions */ +int +_assuan_new_context (assuan_context_t *r_ctx) +{ + static struct assuan_io io = { _assuan_simple_read, + _assuan_simple_write, + 0, 0 }; + + assuan_context_t ctx; + int rc; + + *r_ctx = NULL; + ctx = xtrycalloc (1, sizeof *ctx); + if (!ctx) + return _assuan_error (ASSUAN_Out_Of_Core); + ctx->input_fd = -1; + ctx->output_fd = -1; + + ctx->inbound.fd = -1; + ctx->outbound.fd = -1; + ctx->io = &io; + + ctx->listen_fd = -1; + /* Use the pipe server handler as a default. */ + ctx->deinit_handler = deinit_pipe_server; + ctx->accept_handler = accept_connection; + ctx->finish_handler = finish_connection; + + rc = _assuan_register_std_commands (ctx); + if (rc) + xfree (ctx); + else + *r_ctx = ctx; + return rc; +} + + +/* Returns true if atoi(S) denotes a valid socket. */ +#ifndef HAVE_W32_SYSTEM +static int +is_valid_socket (const char *s) +{ + struct stat buf; + + if ( fstat (atoi (s), &buf ) ) + return 0; + return S_ISSOCK (buf.st_mode); +} +#endif /*!HAVE_W32_SYSTEM*/ + + +int +assuan_init_pipe_server (assuan_context_t *r_ctx, int filedes[2]) +{ + int rc; + + rc = _assuan_new_context (r_ctx); + if (!rc) + { + assuan_context_t ctx = *r_ctx; + const char *s; + unsigned long ul; + + ctx->is_server = 1; +#ifdef HAVE_W32_SYSTEM + /* MS Windows has so many different types of handle that one + needs to tranlsate them at many place forth and back. Also + make sure that the fiel descriptos are in binary mode. */ + setmode (filedes[0], O_BINARY); + setmode (filedes[1], O_BINARY); + ctx->inbound.fd = _get_osfhandle (filedes[0]); + ctx->outbound.fd = _get_osfhandle (filedes[1]); +#else + s = getenv ("_assuan_connection_fd"); + if (s && *s && is_valid_socket (s) ) + { + /* Well, we are called with an bi-directional file + descriptor. Prepare for using sendmsg/recvmsg. In this + case we ignore the passed file descriptors. */ + ctx->inbound.fd = ctx->outbound.fd = atoi (s); + _assuan_init_uds_io (ctx); + ctx->deinit_handler = _assuan_uds_deinit; + } + else if (filedes && filedes[0] != -1 && filedes[1] != -1 ) + { + /* Standard pipe server. */ + ctx->inbound.fd = filedes[0]; + ctx->outbound.fd = filedes[1]; + } + else + { + _assuan_release_context (*r_ctx); + *r_ctx = NULL; + return ASSUAN_Problem_Starting_Server; + } +#endif + ctx->pipe_mode = 1; + + s = getenv ("_assuan_pipe_connect_pid"); + if (s && (ul=strtoul (s, NULL, 10)) && ul) + ctx->pid = (pid_t)ul; + else + ctx->pid = (pid_t)-1; + + } + return rc; +} + + +void +_assuan_release_context (assuan_context_t ctx) +{ + if (ctx) + { + xfree (ctx->hello_line); + xfree (ctx->okay_line); + xfree (ctx->cmdtbl); + xfree (ctx); + } +} + +void +assuan_deinit_server (assuan_context_t ctx) +{ + if (ctx) + { + /* We use this function pointer to avoid linking other server + when not needed but still allow for a generic deinit function. */ + ctx->deinit_handler (ctx); + ctx->deinit_handler = NULL; + _assuan_release_context (ctx); + } +} diff --git a/tags/gpgme-1.1.6/assuan/assuan-socket-connect.c b/tags/gpgme-1.1.6/assuan/assuan-socket-connect.c new file mode 100644 index 0000000..5953f1c --- /dev/null +++ b/tags/gpgme-1.1.6/assuan/assuan-socket-connect.c @@ -0,0 +1,184 @@ +/* assuan-socket-connect.c - Assuan socket based client + * Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + * + * This file is part of Assuan. + * + * Assuan is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Assuan 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef HAVE_W32_SYSTEM +#include +#include +#else +#include +#endif + +#include "assuan-defs.h" + +/* Hacks for Slowaris. */ +#ifndef PF_LOCAL +# ifdef PF_UNIX +# define PF_LOCAL PF_UNIX +# else +# define PF_LOCAL AF_UNIX +# endif +#endif +#ifndef AF_LOCAL +# define AF_LOCAL AF_UNIX +#endif + +#ifndef SUN_LEN +# define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \ + + strlen ((ptr)->sun_path)) +#endif + + +static int +do_finish (assuan_context_t ctx) +{ + if (ctx->inbound.fd != -1) + { + _assuan_close (ctx->inbound.fd); + } + ctx->inbound.fd = -1; + ctx->outbound.fd = -1; + return 0; +} + +static void +do_deinit (assuan_context_t ctx) +{ + do_finish (ctx); +} + + +/* Make a connection to the Unix domain socket NAME and return a new + Assuan context in CTX. SERVER_PID is currently not used but may + become handy in the future. */ +assuan_error_t +assuan_socket_connect (assuan_context_t *r_ctx, + const char *name, pid_t server_pid) +{ + return assuan_socket_connect_ext (r_ctx, name, server_pid, 0); +} + + +/* Make a connection to the Unix domain socket NAME and return a new + Assuan context in CTX. SERVER_PID is currently not used but may + become handy in the future. With flags set to 1 sendmsg and + recvmesg are used. */ +assuan_error_t +assuan_socket_connect_ext (assuan_context_t *r_ctx, + const char *name, pid_t server_pid, + unsigned int flags) +{ + static struct assuan_io io = { _assuan_simple_read, + _assuan_simple_write }; + + assuan_error_t err; + assuan_context_t ctx; + int fd; + struct sockaddr_un srvr_addr; + size_t len; + const char *s; + + if (!r_ctx || !name) + return _assuan_error (ASSUAN_Invalid_Value); + *r_ctx = NULL; + + /* We require that the name starts with a slash, so that we + eventually can reuse this function for other socket types. To + make things easier we allow an optional dirver prefix. */ + s = name; + if (*s && s[1] == ':') + s += 2; + if (*s != DIRSEP_C && *s != '/') + return _assuan_error (ASSUAN_Invalid_Value); + + if (strlen (name)+1 >= sizeof srvr_addr.sun_path) + return _assuan_error (ASSUAN_Invalid_Value); + + err = _assuan_new_context (&ctx); + if (err) + return err; + ctx->deinit_handler = ((flags&1))? _assuan_uds_deinit : do_deinit; + ctx->finish_handler = do_finish; + + fd = _assuan_sock_new (PF_LOCAL, SOCK_STREAM, 0); + if (fd == -1) + { + _assuan_log_printf ("can't create socket: %s\n", strerror (errno)); + _assuan_release_context (ctx); + return _assuan_error (ASSUAN_General_Error); + } + + memset (&srvr_addr, 0, sizeof srvr_addr); + srvr_addr.sun_family = AF_LOCAL; + strncpy (srvr_addr.sun_path, name, sizeof (srvr_addr.sun_path) - 1); + srvr_addr.sun_path[sizeof (srvr_addr.sun_path) - 1] = 0; + len = SUN_LEN (&srvr_addr); + + + if (_assuan_sock_connect (fd, (struct sockaddr *) &srvr_addr, len) == -1) + { + _assuan_log_printf ("can't connect to `%s': %s\n", + name, strerror (errno)); + _assuan_release_context (ctx); + _assuan_close (fd); + return _assuan_error (ASSUAN_Connect_Failed); + } + + ctx->inbound.fd = fd; + ctx->outbound.fd = fd; + ctx->io = &io; + if ((flags&1)) + _assuan_init_uds_io (ctx); + + /* initial handshake */ + { + int okay, off; + + err = _assuan_read_from_server (ctx, &okay, &off); + if (err) + _assuan_log_printf ("can't connect to server: %s\n", + assuan_strerror (err)); + else if (okay != 1) + { + /*LOG ("can't connect to server: `");*/ + _assuan_log_sanitized_string (ctx->inbound.line); + fprintf (assuan_get_assuan_log_stream (), "'\n"); + err = _assuan_error (ASSUAN_Connect_Failed); + } + } + + if (err) + { + assuan_disconnect (ctx); + } + else + *r_ctx = ctx; + return 0; +} + + diff --git a/tags/gpgme-1.1.6/assuan/assuan-socket-server.c b/tags/gpgme-1.1.6/assuan/assuan-socket-server.c new file mode 100644 index 0000000..5c46164 --- /dev/null +++ b/tags/gpgme-1.1.6/assuan/assuan-socket-server.c @@ -0,0 +1,193 @@ +/* assuan-socket-server.c - Assuan socket based server + * Copyright (C) 2002 Free Software Foundation, Inc. + * + * This file is part of Assuan. + * + * Assuan is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Assuan 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include +#include +#include +#include +#include +#include +#ifdef HAVE_W32_SYSTEM +# include +# if HAVE_SYS_SOCKET_H +# include +# elif HAVE_WS2TCPIP_H +# include +# endif +#else +# include +# include +#endif + + +#include "assuan-defs.h" + +static struct assuan_io io = { _assuan_simple_read, + _assuan_simple_write }; + + +static int +accept_connection_bottom (assuan_context_t ctx) +{ + int fd = ctx->connected_fd; + + ctx->peercred.valid = 0; +#ifdef HAVE_SO_PEERCRED + { + struct ucred cr; + socklen_t cl = sizeof cr; + + if ( !getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl)) + { + ctx->peercred.pid = cr.pid; + ctx->peercred.uid = cr.uid; + ctx->peercred.gid = cr.gid; + ctx->peercred.valid = 1; + + /* This overrides any already set PID if the function returns + a valid one. */ + if (cr.pid != (pid_t)-1 && cr.pid) + ctx->pid = cr.pid; + } + } +#endif + + ctx->inbound.fd = fd; + ctx->inbound.eof = 0; + ctx->inbound.linelen = 0; + ctx->inbound.attic.linelen = 0; + ctx->inbound.attic.pending = 0; + + ctx->outbound.fd = fd; + ctx->outbound.data.linelen = 0; + ctx->outbound.data.error = 0; + + ctx->confidential = 0; + + return 0; +} + + +static int +accept_connection (assuan_context_t ctx) +{ + int fd; + struct sockaddr_un clnt_addr; + socklen_t len = sizeof clnt_addr; + + fd = accept (ctx->listen_fd, (struct sockaddr*)&clnt_addr, &len ); + if (fd == -1) + { + ctx->os_errno = errno; + return _assuan_error (ASSUAN_Accept_Failed); + } + + ctx->connected_fd = fd; + return accept_connection_bottom (ctx); +} + +static int +finish_connection (assuan_context_t ctx) +{ + if (ctx->inbound.fd != -1) + { + _assuan_close (ctx->inbound.fd); + } + ctx->inbound.fd = -1; + ctx->outbound.fd = -1; + return 0; +} + + +static void +deinit_socket_server (assuan_context_t ctx) +{ + finish_connection (ctx); +} + +/* Initialize a server for the socket LISTEN_FD which has already be + put into listen mode */ +int +assuan_init_socket_server (assuan_context_t *r_ctx, int listen_fd) +{ + return assuan_init_socket_server_ext (r_ctx, listen_fd, 0); +} + +/* Initialize a server using the already accepted socket FD. This + fucntion is deprecated. */ +int +assuan_init_connected_socket_server (assuan_context_t *r_ctx, int fd) +{ + return assuan_init_socket_server_ext (r_ctx, fd, 2); +} + + +/* + Flag bits: 0 - use sendmsg/recvmsg to allow descriptor passing + 1 - FD has already been accepted. +*/ +int +assuan_init_socket_server_ext (assuan_context_t *r_ctx, int fd, + unsigned int flags) +{ + assuan_context_t ctx; + int rc; + + *r_ctx = NULL; + ctx = xtrycalloc (1, sizeof *ctx); + if (!ctx) + return _assuan_error (ASSUAN_Out_Of_Core); + ctx->is_server = 1; + if ((flags & 2)) + ctx->pipe_mode = 1; /* We want a second accept to indicate EOF. */ + ctx->input_fd = -1; + ctx->output_fd = -1; + + ctx->inbound.fd = -1; + ctx->outbound.fd = -1; + + if ((flags & 2)) + { + ctx->listen_fd = -1; + ctx->connected_fd = fd; + } + else + { + ctx->listen_fd = fd; + ctx->connected_fd = -1; + } + ctx->deinit_handler = (flags & 1)? _assuan_uds_deinit:deinit_socket_server; + ctx->accept_handler = ((flags & 2) + ? accept_connection_bottom + : accept_connection); + ctx->finish_handler = finish_connection; + + ctx->io = &io; + if ((flags & 1)) + _assuan_init_uds_io (ctx); + + rc = _assuan_register_std_commands (ctx); + if (rc) + xfree (ctx); + else + *r_ctx = ctx; + return rc; +} diff --git a/tags/gpgme-1.1.6/assuan/assuan-socket.c b/tags/gpgme-1.1.6/assuan/assuan-socket.c new file mode 100644 index 0000000..5566fde --- /dev/null +++ b/tags/gpgme-1.1.6/assuan/assuan-socket.c @@ -0,0 +1,148 @@ +/* assuan-socket.c + * Copyright (C) 2004, 2005 Free Software Foundation, Inc. + * + * This file is part of Assuan. + * + * Assuan is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Assuan 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include +#include +#ifdef HAVE_W32_SYSTEM +#include +#include +#else +#include +#include +#endif +#include "assuan-defs.h" + +/* Hacks for Slowaris. */ +#ifndef PF_LOCAL +# ifdef PF_UNIX +# define PF_LOCAL PF_UNIX +# else +# define PF_LOCAL AF_UNIX +# endif +#endif +#ifndef AF_LOCAL +# define AF_LOCAL AF_UNIX +#endif + +int +_assuan_close (int fd) +{ +#if defined (HAVE_W32_SYSTEM) && !defined(_ASSUAN_IN_GPGME_BUILD_ASSUAN) + int rc = closesocket (fd); + if (rc && WSAGetLastError () == WSAENOTSOCK) + rc = CloseHandle (fd); + return rc; +#else + return close (fd); +#endif +} + + +int +_assuan_sock_new (int domain, int type, int proto) +{ +#ifndef HAVE_W32_SYSTEM + return socket (domain, type, proto); +#else + if (domain == AF_UNIX || domain == AF_LOCAL) + domain = AF_INET; + return socket (domain, type, proto); +#endif +} + + +int +_assuan_sock_connect (int sockfd, struct sockaddr * addr, int addrlen) +{ +#ifndef HAVE_W32_SYSTEM + return connect (sockfd, addr, addrlen); +#else + struct sockaddr_in myaddr; + struct sockaddr_un * unaddr; + FILE * fp; + int port = 0; + + unaddr = (struct sockaddr_un *)addr; + fp = fopen (unaddr->sun_path, "rb"); + if (!fp) + return -1; + fscanf (fp, "%d", &port); + fclose (fp); + /* XXX: set errno in this case */ + if (port < 0 || port > 65535) + return -1; + + myaddr.sin_family = AF_INET; + myaddr.sin_port = port; + myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); + + /* we need this later. */ + unaddr->sun_family = myaddr.sin_family; + unaddr->sun_port = myaddr.sin_port; + unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr; + + return connect (sockfd, (struct sockaddr *)&myaddr, sizeof myaddr); +#endif +} + + +int +_assuan_sock_bind (int sockfd, struct sockaddr * addr, int addrlen) +{ +#ifndef HAVE_W32_SYSTEM + return bind (sockfd, addr, addrlen); +#else + if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX) + { + struct sockaddr_in myaddr; + struct sockaddr_un * unaddr; + FILE * fp; + int len = sizeof myaddr; + int rc; + + myaddr.sin_port = 0; + myaddr.sin_family = AF_INET; + myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); + + rc = bind (sockfd, (struct sockaddr *)&myaddr, len); + if (rc) + return rc; + rc = getsockname (sockfd, (struct sockaddr *)&myaddr, &len); + if (rc) + return rc; + unaddr = (struct sockaddr_un *)addr; + fp = fopen (unaddr->sun_path, "wb"); + if (!fp) + return -1; + fprintf (fp, "%d", myaddr.sin_port); + fclose (fp); + + /* we need this later. */ + unaddr->sun_family = myaddr.sin_family; + unaddr->sun_port = myaddr.sin_port; + unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr; + + return 0; + } + return bind (sockfd, addr, addrlen); +#endif +} + diff --git a/tags/gpgme-1.1.6/assuan/assuan-uds.c b/tags/gpgme-1.1.6/assuan/assuan-uds.c new file mode 100644 index 0000000..70ec8cc --- /dev/null +++ b/tags/gpgme-1.1.6/assuan/assuan-uds.c @@ -0,0 +1,313 @@ +/* assuan-uds.c - Assuan unix domain socket utilities + * Copyright (C) 2006 Free Software Foundation, Inc. + * + * This file is part of Assuan. + * + * Assuan is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Assuan 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#ifndef HAVE_W32_SYSTEM +#include +#include +#else +#include +#endif +#if HAVE_SYS_UIO_H +#include +#endif +#include +#include +#include +#include + +#include "assuan-defs.h" + +#ifdef USE_DESCRIPTOR_PASSING +/* Provide replacement for missing CMSG maccros. We assume that + size_t matches the alignment requirement. */ +#define MY_ALIGN(n) ((((n))+ sizeof(size_t)-1) & (size_t)~(sizeof(size_t)-1)) +#ifndef CMSG_SPACE +#define CMSG_SPACE(n) (MY_ALIGN(sizeof(struct cmsghdr)) + MY_ALIGN((n))) +#endif +#ifndef CMSG_LEN +#define CMSG_LEN(n) (MY_ALIGN(sizeof(struct cmsghdr)) + (n)) +#endif +#ifndef CMSG_FIRSTHDR +#define CMSG_FIRSTHDR(mhdr) \ + ((size_t)(mhdr)->msg_controllen >= sizeof (struct cmsghdr) \ + ? (struct cmsghdr*) (mhdr)->msg_control : (struct cmsghdr*)NULL) +#endif +#ifndef CMSG_DATA +#define CMSG_DATA(cmsg) ((unsigned char*)((struct cmsghdr*)(cmsg)+1)) +#endif +#endif /*USE_DESCRIPTOR_PASSING*/ + + +/* Read from a unix domain socket using sendmsg. + + FIXME: We don't need the buffering. It is a leftover from the time + when we used datagrams. */ +static ssize_t +uds_reader (assuan_context_t ctx, void *buf, size_t buflen) +{ + int len = ctx->uds.buffersize; + +#ifndef HAVE_W32_SYSTEM + if (!ctx->uds.bufferallocated) + { + ctx->uds.buffer = xtrymalloc (2048); + if (!ctx->uds.buffer) + return _assuan_error (ASSUAN_Out_Of_Core); + ctx->uds.bufferallocated = 2048; + } + + while (!len) /* No data is buffered. */ + { + struct msghdr msg; + struct iovec iovec; +#ifdef USE_DESCRIPTOR_PASSING + union { + struct cmsghdr cm; + char control[CMSG_SPACE(sizeof (int))]; + } control_u; + struct cmsghdr *cmptr; +#endif /*USE_DESCRIPTOR_PASSING*/ + + memset (&msg, 0, sizeof (msg)); + + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &iovec; + msg.msg_iovlen = 1; + iovec.iov_base = ctx->uds.buffer; + iovec.iov_len = ctx->uds.bufferallocated; +#ifdef USE_DESCRIPTOR_PASSING + msg.msg_control = control_u.control; + msg.msg_controllen = sizeof (control_u.control); +#endif + + len = _assuan_simple_recvmsg (ctx, &msg); + if (len < 0) + return -1; + if (len == 0) + return 0; + + ctx->uds.buffersize = len; + ctx->uds.bufferoffset = 0; + +#ifdef USE_DESCRIPTOR_PASSING + cmptr = CMSG_FIRSTHDR (&msg); + if (cmptr && cmptr->cmsg_len == CMSG_LEN (sizeof(int))) + { + if (cmptr->cmsg_level != SOL_SOCKET + || cmptr->cmsg_type != SCM_RIGHTS) + _assuan_log_printf ("unexpected ancillary data received\n"); + else + { + int fd = *((int*)CMSG_DATA (cmptr)); + + if (ctx->uds.pendingfdscount >= DIM (ctx->uds.pendingfds)) + { + _assuan_log_printf ("too many descriptors pending - " + "closing received descriptor %d\n", fd); + _assuan_close (fd); + } + else + ctx->uds.pendingfds[ctx->uds.pendingfdscount++] = fd; + } + } +#endif /*USE_DESCRIPTOR_PASSING*/ + } + +#else /*HAVE_W32_SYSTEM*/ + + len = recvfrom (ctx->inbound.fd, buf, buflen, 0, NULL, NULL); + +#endif /*HAVE_W32_SYSTEM*/ + + /* Return some data to the user. */ + + if (len > buflen) /* We have more than the user requested. */ + len = buflen; + + memcpy (buf, (char*)ctx->uds.buffer + ctx->uds.bufferoffset, len); + ctx->uds.buffersize -= len; + assert (ctx->uds.buffersize >= 0); + ctx->uds.bufferoffset += len; + assert (ctx->uds.bufferoffset <= ctx->uds.bufferallocated); + + return len; +} + + +/* Write to the domain server. */ +static ssize_t +uds_writer (assuan_context_t ctx, const void *buf, size_t buflen) +{ +#ifndef HAVE_W32_SYSTEM + struct msghdr msg; + struct iovec iovec; + ssize_t len; + + memset (&msg, 0, sizeof (msg)); + + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iovlen = 1; + msg.msg_iov = &iovec; + iovec.iov_base = (void*)buf; + iovec.iov_len = buflen; + + len = _assuan_simple_sendmsg (ctx, &msg); +#else /*HAVE_W32_SYSTEM*/ + int len; + + len = sendto (ctx->outbound.fd, buf, buflen, 0, + (struct sockaddr *)&ctx->serveraddr, + sizeof (struct sockaddr_in)); +#endif /*HAVE_W32_SYSTEM*/ + return len; +} + + +static assuan_error_t +uds_sendfd (assuan_context_t ctx, int fd) +{ +#ifdef USE_DESCRIPTOR_PASSING + struct msghdr msg; + struct iovec iovec; + union { + struct cmsghdr cm; + char control[CMSG_SPACE(sizeof (int))]; + } control_u; + struct cmsghdr *cmptr; + int len; + char buffer[80]; + + /* We need to send some real data so that a read won't return 0 + which will be taken as an EOF. It also helps with debugging. */ + snprintf (buffer, sizeof(buffer)-1, "# descriptor %d is in flight\n", fd); + buffer[sizeof(buffer)-1] = 0; + + memset (&msg, 0, sizeof (msg)); + + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iovlen = 1; + msg.msg_iov = &iovec; + iovec.iov_base = buffer; + iovec.iov_len = strlen (buffer); + + msg.msg_control = control_u.control; + msg.msg_controllen = sizeof (control_u.control); + cmptr = CMSG_FIRSTHDR (&msg); + cmptr->cmsg_len = CMSG_LEN(sizeof(int)); + cmptr->cmsg_level = SOL_SOCKET; + cmptr->cmsg_type = SCM_RIGHTS; + *((int*)CMSG_DATA (cmptr)) = fd; + + len = _assuan_simple_sendmsg (ctx, &msg); + if (len < 0) + { + _assuan_log_printf ("uds_sendfd: %s\n", strerror (errno)); + return _assuan_error (ASSUAN_Write_Error); + } + else + return 0; +#else + return _assuan_error (ASSUAN_Not_Implemented); +#endif +} + + +static assuan_error_t +uds_receivefd (assuan_context_t ctx, int *fd) +{ +#ifdef USE_DESCRIPTOR_PASSING + int i; + + if (!ctx->uds.pendingfdscount) + { + _assuan_log_printf ("no pending file descriptors!\n"); + return _assuan_error (ASSUAN_General_Error); + } + assert (ctx->uds.pendingfdscount <= DIM(ctx->uds.pendingfds)); + + *fd = ctx->uds.pendingfds[0]; + for (i=1; i < ctx->uds.pendingfdscount; i++) + ctx->uds.pendingfds[i-1] = ctx->uds.pendingfds[i]; + ctx->uds.pendingfdscount--; + + return 0; +#else + return _assuan_error (ASSUAN_Not_Implemented); +#endif +} + + +/* Close all pending fds. */ +void +_assuan_uds_close_fds (assuan_context_t ctx) +{ + int i; + + for (i = 0; i < ctx->uds.pendingfdscount; i++) + _assuan_close (ctx->uds.pendingfds[i]); + ctx->uds.pendingfdscount = 0; +} + +/* Deinitialize the unix domain socket I/O functions. */ +void +_assuan_uds_deinit (assuan_context_t ctx) +{ + /* First call the finish_handler which should close descriptors etc. */ + ctx->finish_handler (ctx); + + if (ctx->uds.buffer) + { + assert (ctx->uds.bufferallocated); + ctx->uds.bufferallocated = 0; + xfree (ctx->uds.buffer); + } + + _assuan_uds_close_fds (ctx); +} + + +/* Helper function to initialize a context for domain I/O. */ +void +_assuan_init_uds_io (assuan_context_t ctx) +{ + static struct assuan_io io = { uds_reader, uds_writer, + uds_sendfd, uds_receivefd }; + + ctx->io = &io; + ctx->uds.buffer = 0; + ctx->uds.bufferoffset = 0; + ctx->uds.buffersize = 0; + ctx->uds.bufferallocated = 0; + ctx->uds.pendingfdscount = 0; +} + diff --git a/tags/gpgme-1.1.6/assuan/assuan-util.c b/tags/gpgme-1.1.6/assuan/assuan-util.c new file mode 100644 index 0000000..d12277f --- /dev/null +++ b/tags/gpgme-1.1.6/assuan/assuan-util.c @@ -0,0 +1,171 @@ +/* assuan-util.c - Utility functions for Assuan + * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + * + * This file is part of Assuan. + * + * Assuan is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Assuan 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include +#include +#include +#include +#include +#include + +#include "assuan-defs.h" + +static void *(*alloc_func)(size_t n) = malloc; +static void *(*realloc_func)(void *p, size_t n) = realloc; +static void (*free_func)(void*) = free; + +void +assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n), + void *(*new_realloc_func)(void *p, size_t n), + void (*new_free_func)(void*) ) +{ + alloc_func = new_alloc_func; + realloc_func = new_realloc_func; + free_func = new_free_func; +} + +void * +_assuan_malloc (size_t n) +{ + return alloc_func (n); +} + +void * +_assuan_realloc (void *a, size_t n) +{ + return realloc_func (a, n); +} + +void * +_assuan_calloc (size_t n, size_t m) +{ + void *p; + size_t nbytes; + + nbytes = n * m; + if (m && nbytes / m != n) + { + errno = ENOMEM; + return NULL; + } + + p = _assuan_malloc (nbytes); + if (p) + memset (p, 0, nbytes); + return p; +} + +void +_assuan_free (void *p) +{ + if (p) + free_func (p); +} + + +/* Store the error in the context so that the error sending function + can take out a descriptive text. Inside the assuan code, use the + macro set_error instead of this function. */ +int +assuan_set_error (assuan_context_t ctx, int err, const char *text) +{ + ctx->err_no = err; + ctx->err_str = text; + return err; +} + +void +assuan_set_pointer (assuan_context_t ctx, void *pointer) +{ + if (ctx) + ctx->user_pointer = pointer; +} + +void * +assuan_get_pointer (assuan_context_t ctx) +{ + return ctx? ctx->user_pointer : NULL; +} + + +void +assuan_begin_confidential (assuan_context_t ctx) +{ + if (ctx) + { + ctx->confidential = 1; + } +} + +void +assuan_end_confidential (assuan_context_t ctx) +{ + if (ctx) + { + ctx->confidential = 0; + } +} + + +void +assuan_set_io_monitor (assuan_context_t ctx, + unsigned int (*monitor)(assuan_context_t ctx, + int direction, + const char *line, + size_t linelen)) +{ + if (ctx) + { + ctx->io_monitor = monitor; + } +} + + + + +/* For context CTX, set the flag FLAG to VALUE. Values for flags + are usually 1 or 0 but certain flags might allow for other values; + see the description of the type assuan_flag_t for details. */ +void +assuan_set_flag (assuan_context_t ctx, assuan_flag_t flag, int value) +{ + if (!ctx) + return; + switch (flag) + { + case ASSUAN_NO_WAITPID: ctx->flags.no_waitpid = value; break; + } +} + +/* Return the VALUE of FLAG in context CTX. */ +int +assuan_get_flag (assuan_context_t ctx, assuan_flag_t flag) +{ + if (!ctx) + return 0; + switch (flag) + { + case ASSUAN_NO_WAITPID: return ctx->flags.no_waitpid; + } + return 0; +} + + diff --git a/tags/gpgme-1.1.6/assuan/assuan.h b/tags/gpgme-1.1.6/assuan/assuan.h new file mode 100644 index 0000000..6df0166 --- /dev/null +++ b/tags/gpgme-1.1.6/assuan/assuan.h @@ -0,0 +1,580 @@ +/* assuan.h - Definitions for the Assuan IPC library + * Copyright (C) 2001, 2002, 2003, 2005, 2007 Free Software Foundation, Inc. + * + * This file is part of Assuan. + * + * Assuan is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Assuan 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#ifndef ASSUAN_H +#define ASSUAN_H + +#include +#include +#include + + +/* To use this file with libraries the following macros are useful: + + #define _ASSUAN_EXT_SYM_PREFIX _foo_ + + This prefixes all external symbols with "_foo_". + + #define _ASSUAN_ONLY_GPG_ERRORS + + If this is defined all old-style Assuan error codes are made + inactive as well as other dereacted stuff. + + The follwing macros are used internally in the implementation of + libassuan: + + #define _ASSUAN_NO_PTH + + This avoids inclusion of special GNU Pth hacks. + + #define _ASSUAN_NO_FIXED_SIGNALS + + This disables changing of certain signal handler; i.e. SIGPIPE. + + #define _ASSUAN_USE_DOUBLE_FORK + + Use a double fork approach when connecting to a server through + a pipe. + */ +/**** Begin GPGME specific modifications. ******/ +#define _ASSUAN_EXT_SYM_PREFIX _gpgme_ +#define _ASSUAN_NO_PTH +#define _ASSUAN_NO_FIXED_SIGNALS +#define _ASSUAN_USE_DOUBLE_FORK + +#ifdef _ASSUAN_IN_GPGME_BUILD_ASSUAN +#include + +int _gpgme_io_close (int fd); +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_sendmsg (int sock, const struct msghdr *msg, int flags); +int _gpgme_io_recvmsg (int sock, struct msghdr *msg, int flags); + +#define close _gpgme_io_close +#define read _gpgme_io_read +#define write _gpgme_io_write +#define waitpid _gpgme_ath_waitpid +#define select _gpgme_ath_select +#define accept _gpgme_ath_accept +#define connect _gpgme_ath_connect +#define sendmsg _gpgme_io_sendmsg +#define recvmsg _gpgme_io_recvmsg +#endif /*_ASSUAN_IN_GPGME_BUILD_ASSUAN*/ +/**** End GPGME specific modifications. ******/ + + +#ifdef _ASSUAN_EXT_SYM_PREFIX +#define _ASSUAN_PREFIX1(x,y) x ## y +#define _ASSUAN_PREFIX2(x,y) _ASSUAN_PREFIX1(x,y) +#define _ASSUAN_PREFIX(x) _ASSUAN_PREFIX2(_ASSUAN_EXT_SYM_PREFIX,x) +#define assuan_ _ASSUAN_PREFIX(assuan_) +#define assuan_register_command _ASSUAN_PREFIX(assuan_register_command) +#define assuan_register_post_cmd_notify \ + _ASSUAN_PREFIX(assuan_register_post_cmd_notify) +#define assuan_register_bye_notify _ASSUAN_PREFIX(assuan_register_bye_notify) +#define assuan_register_reset_notify \ + _ASSUAN_PREFIX(assuan_register_reset_notify) +#define assuan_register_cancel_notify \ + _ASSUAN_PREFIX(assuan_register_cancel_notify) +#define assuan_register_input_notify \ + _ASSUAN_PREFIX(assuan_register_input_notify) +#define assuan_register_output_notify \ + _ASSUAN_PREFIX(assuan_register_output_notify) +#define assuan_register_option_handler \ + _ASSUAN_PREFIX(assuan_register_option_handler) +#define assuan_process _ASSUAN_PREFIX(assuan_process) +#define assuan_process_next _ASSUAN_PREFIX(assuan_process_next) +#define assuan_get_active_fds _ASSUAN_PREFIX(assuan_get_active_fds) +#define assuan_get_data_fp _ASSUAN_PREFIX(assuan_get_data_fp) +#define assuan_set_okay_line _ASSUAN_PREFIX(assuan_set_okay_line) +#define assuan_write_status _ASSUAN_PREFIX(assuan_write_status) +#define assuan_command_parse_fd _ASSUAN_PREFIX(assuan_command_parse_fd) +#define assuan_set_hello_line _ASSUAN_PREFIX(assuan_set_hello_line) +#define assuan_accept _ASSUAN_PREFIX(assuan_accept) +#define assuan_get_input_fd _ASSUAN_PREFIX(assuan_get_input_fd) +#define assuan_get_output_fd _ASSUAN_PREFIX(assuan_get_output_fd) +#define assuan_close_input_fd _ASSUAN_PREFIX(assuan_close_input_fd) +#define assuan_close_output_fd _ASSUAN_PREFIX(assuan_close_output_fd) +#define assuan_init_pipe_server _ASSUAN_PREFIX(assuan_init_pipe_server) +#define assuan_deinit_server _ASSUAN_PREFIX(assuan_deinit_server) +#define assuan_init_socket_server _ASSUAN_PREFIX(assuan_init_socket_server) +#define assuan_init_connected_socket_server \ + _ASSUAN_PREFIX(assuan_init_connected_socket_server) +#define assuan_init_socket_server_ext \ + _ASSUAN_PREFIX(assuan_init_socket_server_ext) +#define assuan_pipe_connect _ASSUAN_PREFIX(assuan_pipe_connect) +#define assuan_pipe_connect_ext _ASSUAN_PREFIX(assuan_pipe_connect_ext) +#define assuan_socket_connect _ASSUAN_PREFIX(assuan_socket_connect) +#define assuan_socket_connect_ext _ASSUAN_PREFIX(assuan_socket_connect_ext) +#define assuan_disconnect _ASSUAN_PREFIX(assuan_disconnect) +#define assuan_get_pid _ASSUAN_PREFIX(assuan_get_pid) +#define assuan_get_peercred _ASSUAN_PREFIX(assuan_get_peercred) +#define assuan_transact _ASSUAN_PREFIX(assuan_transact) +#define assuan_inquire _ASSUAN_PREFIX(assuan_inquire) +#define assuan_read_line _ASSUAN_PREFIX(assuan_read_line) +#define assuan_pending_line _ASSUAN_PREFIX(assuan_pending_line) +#define assuan_write_line _ASSUAN_PREFIX(assuan_write_line) +#define assuan_send_data _ASSUAN_PREFIX(assuan_send_data) +#define assuan_sendfd _ASSUAN_PREFIX(assuan_sendfd) +#define assuan_receivefd _ASSUAN_PREFIX(assuan_receivefd) +#define assuan_set_malloc_hooks _ASSUAN_PREFIX(assuan_set_malloc_hooks) +#define assuan_set_assuan_log_level _ASSUAN_PREFIX(assuan_set_assuan_log_level) +#define assuan_set_log_stream _ASSUAN_PREFIX(assuan_set_log_stream) +#define assuan_set_error _ASSUAN_PREFIX(assuan_set_error) +#define assuan_set_pointer _ASSUAN_PREFIX(assuan_set_pointer) +#define assuan_get_pointer _ASSUAN_PREFIX(assuan_get_pointer) +#define assuan_set_io_monitor _ASSUAN_PREFIX(assuan_set_io_monitor) +#define assuan_begin_confidential _ASSUAN_PREFIX(assuan_begin_confidential) +#define assuan_end_confidential _ASSUAN_PREFIX(assuan_end_confidential) +#define assuan_strerror _ASSUAN_PREFIX(assuan_strerror) +#define assuan_set_assuan_err_source \ + _ASSUAN_PREFIX(assuan_set_assuan_err_source) +#define assuan_set_assuan_log_stream \ + _ASSUAN_PREFIX(assuan_set_assuan_log_stream) +#define assuan_get_assuan_log_stream \ + _ASSUAN_PREFIX(assuan_get_assuan_log_stream) +#define assuan_get_assuan_log_prefix \ + _ASSUAN_PREFIX(assuan_get_assuan_log_prefix) +#define assuan_set_flag _ASSUAN_PREFIX(assuan_set_flag) +#define assuan_get_flag _ASSUAN_PREFIX(assuan_get_flag) +#define assuan_pipe_connect2 _ASSUAN_PREFIX(assuan_pipe_connect2) +#define assuan_set_assuan_log_prefix \ + _ASSUAN_PREFIX(assuan_set_assuan_log_prefix) + +/* And now the internal functions, argh... */ +#define _assuan_read_line _ASSUAN_PREFIX(_assuan_read_line) +#define _assuan_cookie_write_data _ASSUAN_PREFIX(_assuan_cookie_write_data) +#define _assuan_cookie_write_flush _ASSUAN_PREFIX(_assuan_cookie_write_flush) +#define _assuan_read_from_server _ASSUAN_PREFIX(_assuan_read_from_server) +#define _assuan_domain_init _ASSUAN_PREFIX(_assuan_domain_init) +#define _assuan_register_std_commands \ + _ASSUAN_PREFIX(_assuan_register_std_commands) +#define _assuan_simple_read _ASSUAN_PREFIX(_assuan_simple_read) +#define _assuan_simple_write _ASSUAN_PREFIX(_assuan_simple_write) +#define _assuan_simple_read _ASSUAN_PREFIX(_assuan_simple_read) +#define _assuan_simple_write _ASSUAN_PREFIX(_assuan_simple_write) +#define _assuan_new_context _ASSUAN_PREFIX(_assuan_new_context) +#define _assuan_release_context _ASSUAN_PREFIX(_assuan_release_context) +#define _assuan_malloc _ASSUAN_PREFIX(_assuan_malloc) +#define _assuan_realloc _ASSUAN_PREFIX(_assuan_realloc) +#define _assuan_calloc _ASSUAN_PREFIX(_assuan_calloc) +#define _assuan_free _ASSUAN_PREFIX(_assuan_free) +#define _assuan_log_print_buffer _ASSUAN_PREFIX(_assuan_log_print_buffer) +#define _assuan_log_sanitized_string \ + _ASSUAN_PREFIX(_assuan_log_sanitized_string) +#define _assuan_log_printf _ASSUAN_PREFIX(_assuan_log_printf) +#define _assuan_set_default_log_stream \ + _ASSUAN_PREFIX(_assuan_set_default_log_stream) +#define _assuan_w32_strerror _ASSUAN_PREFIX(_assuan_w32_strerror) +#define _assuan_gpg_strerror_r _ASSUAN_PREFIX(_assuan_gpg_strerror_r) +#define _assuan_gpg_strsource _ASSUAN_PREFIX(_assuan_gpg_strsource) +#define _assuan_write_line _ASSUAN_PREFIX(_assuan_write_line) +#define _assuan_close _ASSUAN_PREFIX(_assuan_close) +#define _assuan_sock_new _ASSUAN_PREFIX(_assuan_sock_new) +#define _assuan_sock_bind _ASSUAN_PREFIX(_assuan_sock_bind) +#define _assuan_sock_connect _ASSUAN_PREFIX(_assuan_sock_connect) +#define _assuan_error _ASSUAN_PREFIX(_assuan_error) +#define _assuan_init_uds_io _ASSUAN_PREFIX(_assuan_init_uds_io) +#define _assuan_uds_close_fds _ASSUAN_PREFIX(_assuan_uds_close_fds) +#define _assuan_uds_deinit _ASSUAN_PREFIX(_assuan_uds_deinit) +#define _assuan_simple_recvmsg _ASSUAN_PREFIX(_assuan_simple_recvmsg) +#define _assuan_simple_sendmsg _ASSUAN_PREFIX(_assuan_simple_sendmsg) +#define _assuan_waitpid _ASSUAN_PREFIX(_assuan_waitpid) + +#define _assuan_funopen _gpgme_funopen +#endif /*_ASSUAN_EXT_SYM_PREFIX*/ + + +#ifdef __cplusplus +extern "C" +{ +#if 0 +} +#endif +#endif + + +/* Check for compiler features. */ +#if __GNUC__ +#define _ASSUAN_GCC_VERSION (__GNUC__ * 10000 \ + + __GNUC_MINOR__ * 100 \ + + __GNUC_PATCHLEVEL__) + +#if _ASSUAN_GCC_VERSION > 30100 +#define _ASSUAN_DEPRECATED __attribute__ ((__deprecated__)) +#endif +#endif +#ifndef _ASSUAN_DEPRECATED +#define _ASSUAN_DEPRECATED +#endif + + +/* Assuan error codes. These are only used by old applications or + those applications which won't make use of libgpg-error. */ +#ifndef _ASSUAN_ONLY_GPG_ERRORS +#ifndef _ASSUAN_IN_LIBASSUAN +#define ASSUAN_No_Error 0 +#endif +#define ASSUAN_General_Error 1 +#define ASSUAN_Out_Of_Core 2 +#define ASSUAN_Invalid_Value 3 +#ifndef _ASSUAN_IN_LIBASSUAN +#define ASSUAN_Timeout 4 +#endif +#define ASSUAN_Read_Error 5 +#define ASSUAN_Write_Error 6 +#define ASSUAN_Problem_Starting_Server 7 +#define ASSUAN_Not_A_Server 8 +#ifndef _ASSUAN_IN_LIBASSUAN +#define ASSUAN_Not_A_Client 9 +#endif +#define ASSUAN_Nested_Commands 10 +#define ASSUAN_Invalid_Response 11 +#define ASSUAN_No_Data_Callback 12 +#define ASSUAN_No_Inquire_Callback 13 +#define ASSUAN_Connect_Failed 14 +#define ASSUAN_Accept_Failed 15 + + /* Error codes above 99 are meant as status codes */ +#define ASSUAN_Not_Implemented 100 +#define ASSUAN_Server_Fault 101 +#ifndef _ASSUAN_IN_LIBASSUAN +#define ASSUAN_Invalid_Command 102 +#endif +#define ASSUAN_Unknown_Command 103 +#define ASSUAN_Syntax_Error 104 +#ifndef _ASSUAN_IN_LIBASSUAN +#define ASSUAN_Parameter_Error 105 +#endif +#define ASSUAN_Parameter_Conflict 106 +#define ASSUAN_Line_Too_Long 107 +#define ASSUAN_Line_Not_Terminated 108 +#ifndef _ASSUAN_IN_LIBASSUAN +#define ASSUAN_No_Input 109 +#define ASSUAN_No_Output 110 +#endif +#define ASSUAN_Canceled 111 +#ifndef _ASSUAN_IN_LIBASSUAN +#define ASSUAN_Unsupported_Algorithm 112 +#define ASSUAN_Server_Resource_Problem 113 +#define ASSUAN_Server_IO_Error 114 +#define ASSUAN_Server_Bug 115 +#define ASSUAN_No_Data_Available 116 +#define ASSUAN_Invalid_Data 117 +#endif +#define ASSUAN_Unexpected_Command 118 +#define ASSUAN_Too_Much_Data 119 +#ifndef _ASSUAN_IN_LIBASSUAN +#define ASSUAN_Inquire_Unknown 120 +#define ASSUAN_Inquire_Error 121 +#define ASSUAN_Invalid_Option 122 +#define ASSUAN_Invalid_Index 123 +#define ASSUAN_Unexpected_Status 124 +#define ASSUAN_Unexpected_Data 125 +#define ASSUAN_Invalid_Status 126 +#define ASSUAN_Locale_Problem 127 +#endif +#define ASSUAN_Not_Confirmed 128 + + /* Warning: Don't use the Error codes, below they are deprecated. */ +#ifndef _ASSUAN_IN_LIBASSUAN +#define ASSUAN_Bad_Certificate 201 +#define ASSUAN_Bad_Certificate_Chain 202 +#define ASSUAN_Missing_Certificate 203 +#define ASSUAN_Bad_Signature 204 +#define ASSUAN_No_Agent 205 +#define ASSUAN_Agent_Error 206 +#define ASSUAN_No_Public_Key 207 +#define ASSUAN_No_Secret_Key 208 +#define ASSUAN_Invalid_Name 209 + +#define ASSUAN_Cert_Revoked 301 +#define ASSUAN_No_CRL_For_Cert 302 +#define ASSUAN_CRL_Too_Old 303 +#define ASSUAN_Not_Trusted 304 + +#define ASSUAN_Card_Error 401 +#define ASSUAN_Invalid_Card 402 +#define ASSUAN_No_PKCS15_App 403 +#define ASSUAN_Card_Not_Present 404 +#define ASSUAN_Invalid_Id 405 + + /* Error codes in the range 1000 to 9999 may be used by applications + at their own discretion. */ +#define ASSUAN_USER_ERROR_FIRST 1000 +#define ASSUAN_USER_ERROR_LAST 9999 +#endif + +typedef int assuan_error_t; + +typedef assuan_error_t AssuanError _ASSUAN_DEPRECATED; + +/* This is a list of pre-registered ASSUAN commands */ +/* Note, these command IDs are now deprectated and solely exists for + compatibility reasons. */ +typedef enum +{ + ASSUAN_CMD_NOP = 0, + ASSUAN_CMD_CANCEL, /* cancel the current request */ + ASSUAN_CMD_BYE, + ASSUAN_CMD_AUTH, + ASSUAN_CMD_RESET, + ASSUAN_CMD_OPTION, + ASSUAN_CMD_DATA, + ASSUAN_CMD_END, + ASSUAN_CMD_INPUT, + ASSUAN_CMD_OUTPUT, + + ASSUAN_CMD_USER = 256 /* Other commands should be used with this offset*/ +} AssuanCommand; + + +#else /*!_ASSUAN_ONLY_GPG_ERRORS*/ + +typedef int assuan_error_t; + +#endif /*!_ASSUAN_ONLY_GPG_ERRORS*/ + + +/* Definitions of flags for assuan_set_flag(). */ +typedef enum + { + /* When using a pipe server, by default Assuan will wait for the + forked process to die in assuan_disconnect. In certain cases + this is not desirable. By setting this flag, the waitpid will + be skipped and the caller is responsible to cleanup a forked + process. */ + ASSUAN_NO_WAITPID = 1 + } +assuan_flag_t; + +#define ASSUAN_LINELENGTH 1002 /* 1000 + [CR,]LF */ + +struct assuan_context_s; +typedef struct assuan_context_s *assuan_context_t; +#ifndef _ASSUAN_ONLY_GPG_ERRORS +typedef struct assuan_context_s *ASSUAN_CONTEXT _ASSUAN_DEPRECATED; +#endif /*_ASSUAN_ONLY_GPG_ERRORS*/ + +/*-- assuan-handler.c --*/ +int assuan_register_command (assuan_context_t ctx, + const char *cmd_string, + int (*handler)(assuan_context_t, char *)); +int assuan_register_post_cmd_notify (assuan_context_t ctx, + void (*fnc)(assuan_context_t, int)); +int assuan_register_bye_notify (assuan_context_t ctx, + void (*fnc)(assuan_context_t)); +int assuan_register_reset_notify (assuan_context_t ctx, + void (*fnc)(assuan_context_t)); +int assuan_register_cancel_notify (assuan_context_t ctx, + void (*fnc)(assuan_context_t)); +int assuan_register_input_notify (assuan_context_t ctx, + void (*fnc)(assuan_context_t, const char *)); +int assuan_register_output_notify (assuan_context_t ctx, + void (*fnc)(assuan_context_t, const char *)); + +int assuan_register_option_handler (assuan_context_t ctx, + int (*fnc)(assuan_context_t, + const char*, const char*)); + +int assuan_process (assuan_context_t ctx); +int assuan_process_next (assuan_context_t ctx); +int assuan_get_active_fds (assuan_context_t ctx, int what, + int *fdarray, int fdarraysize); + + +FILE *assuan_get_data_fp (assuan_context_t ctx); +assuan_error_t assuan_set_okay_line (assuan_context_t ctx, const char *line); +assuan_error_t assuan_write_status (assuan_context_t ctx, + const char *keyword, const char *text); + +/* Negotiate a file descriptor. If LINE contains "FD=N", returns N + assuming a local file descriptor. If LINE contains "FD" reads a + file descriptor via CTX and stores it in *RDF (the CTX must be + capable of passing file descriptors). */ +assuan_error_t assuan_command_parse_fd (assuan_context_t ctx, char *line, + int *rfd); + +/*-- assuan-listen.c --*/ +assuan_error_t assuan_set_hello_line (assuan_context_t ctx, const char *line); +assuan_error_t assuan_accept (assuan_context_t ctx); +int assuan_get_input_fd (assuan_context_t ctx); +int assuan_get_output_fd (assuan_context_t ctx); +assuan_error_t assuan_close_input_fd (assuan_context_t ctx); +assuan_error_t assuan_close_output_fd (assuan_context_t ctx); + + +/*-- assuan-pipe-server.c --*/ +int assuan_init_pipe_server (assuan_context_t *r_ctx, int filedes[2]); +void assuan_deinit_server (assuan_context_t ctx); + +/*-- assuan-socket-server.c --*/ +int assuan_init_socket_server (assuan_context_t *r_ctx, int listen_fd); +int assuan_init_connected_socket_server (assuan_context_t *r_ctx, + int fd) _ASSUAN_DEPRECATED; +int assuan_init_socket_server_ext (assuan_context_t *r_ctx, int fd, + unsigned int flags); + +/*-- assuan-pipe-connect.c --*/ +assuan_error_t assuan_pipe_connect (assuan_context_t *ctx, + const char *name, + const char *const argv[], + int *fd_child_list); +assuan_error_t assuan_pipe_connect2 (assuan_context_t *ctx, + const char *name, + const char *const argv[], + int *fd_child_list, + void (*atfork) (void*, int), + void *atforkvalue) _ASSUAN_DEPRECATED; +assuan_error_t assuan_pipe_connect_ext (assuan_context_t *ctx, + const char *name, + const char *const argv[], + int *fd_child_list, + void (*atfork) (void *, int), + void *atforkvalue, + unsigned int flags); + +/*-- assuan-socket-connect.c --*/ +assuan_error_t assuan_socket_connect (assuan_context_t *ctx, + const char *name, + pid_t server_pid); +assuan_error_t assuan_socket_connect_ext (assuan_context_t *ctx, + const char *name, + pid_t server_pid, + unsigned int flags); + +/*-- assuan-connect.c --*/ +void assuan_disconnect (assuan_context_t ctx); +pid_t assuan_get_pid (assuan_context_t ctx); +#ifndef HAVE_W32_SYSTEM +assuan_error_t assuan_get_peercred (assuan_context_t ctx, + pid_t *pid, uid_t *uid, gid_t *gid); +#endif + +/*-- assuan-client.c --*/ +assuan_error_t +assuan_transact (assuan_context_t ctx, + const char *command, + int (*data_cb)(void *, const void *, size_t), + void *data_cb_arg, + int (*inquire_cb)(void*, const char *), + void *inquire_cb_arg, + int (*status_cb)(void*, const char *), + void *status_cb_arg); + + +/*-- assuan-inquire.c --*/ +assuan_error_t assuan_inquire (assuan_context_t ctx, const char *keyword, + unsigned char **r_buffer, size_t *r_length, + size_t maxlen); + +/*-- assuan-buffer.c --*/ +assuan_error_t assuan_read_line (assuan_context_t ctx, + char **line, size_t *linelen); +int assuan_pending_line (assuan_context_t ctx); +assuan_error_t assuan_write_line (assuan_context_t ctx, const char *line ); +assuan_error_t assuan_send_data (assuan_context_t ctx, + const void *buffer, size_t length); + +/* The file descriptor must be pending before assuan_receivefd is + called. This means that assuan_sendfd should be called *before* the + trigger is sent (normally via assuan_write_line ("INPUT FD")). */ +assuan_error_t assuan_sendfd (assuan_context_t ctx, int fd); +assuan_error_t assuan_receivefd (assuan_context_t ctx, int *fd); + +/*-- assuan-util.c --*/ +void assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n), + void *(*new_realloc_func)(void *p, size_t n), + void (*new_free_func)(void*) ); +void assuan_set_log_stream (assuan_context_t ctx, FILE *fp); +int assuan_set_error (assuan_context_t ctx, int err, const char *text); +void assuan_set_pointer (assuan_context_t ctx, void *pointer); +void *assuan_get_pointer (assuan_context_t ctx); + +void assuan_begin_confidential (assuan_context_t ctx); +void assuan_end_confidential (assuan_context_t ctx); + +void assuan_set_io_monitor (assuan_context_t ctx, + unsigned int (*monitor)(assuan_context_t ctx, + int direction, + const char *line, + size_t linelen)); + +/* For context CTX, set the flag FLAG to VALUE. Values for flags + are usually 1 or 0 but certain flags might allow for other values; + see the description of the type assuan_flag_t for details. */ +void assuan_set_flag (assuan_context_t ctx, assuan_flag_t flag, int value); + +/* Return the VALUE of FLAG in context CTX. */ +int assuan_get_flag (assuan_context_t ctx, assuan_flag_t flag); + + +/*-- assuan-errors.c --*/ + +#ifndef _ASSUAN_ONLY_GPG_ERRORS +/* Return a string describing the assuan error. The use of this + function is deprecated; it is better to call + assuan_set_assuan_err_source once and then make use libgpg-error. */ +const char *assuan_strerror (assuan_error_t err); +#endif /*_ASSUAN_ONLY_GPG_ERRORS*/ + +/* Enable gpg-error style error codes. ERRSOURCE is one of gpg-error + sources. Note, that this function is not thread-safe and should be + used right at startup. Switching back to the old style mode is not + supported. */ +void assuan_set_assuan_err_source (int errsource); + +/*-- assuan-logging.c --*/ + +/* Set the log level for general assuan commands. 0 is no logging at + all, 1 is the standard logging and the default. Higher leveles may + be defined in the future. Passing a level of -1 will not change + the current log level. Returns previous log level. Note, that + this function is not thread-safe and should in general be used + right at startup. */ +int assuan_set_assuan_log_level (int level); + +/* Set the stream to which assuan should log message not associated + with a context. By default, this is stderr. The default value + will be changed when the first log stream is associated with a + context. Note, that this function is not thread-safe and should + in general be used right at startup. */ +extern void assuan_set_assuan_log_stream (FILE *fp); + +/* Return the stream which is currently being using for global logging. */ +extern FILE *assuan_get_assuan_log_stream (void); + +/* Set the prefix to be used at the start of a line emitted by assuan + on the log stream. The default is the empty string. Note, that + this function is not thread-safe and should in general be used + right at startup. */ +void assuan_set_assuan_log_prefix (const char *text); + +/* Return a prefix to be used at the start of a line emitted by assuan + on the log stream. The default implementation returns the empty + string, i.e. "" */ +const char *assuan_get_assuan_log_prefix (void); + +#ifdef __cplusplus +} +#endif +#endif /* ASSUAN_H */ diff --git a/tags/gpgme-1.1.6/assuan/mkerrors b/tags/gpgme-1.1.6/assuan/mkerrors new file mode 100755 index 0000000..28451f6 --- /dev/null +++ b/tags/gpgme-1.1.6/assuan/mkerrors @@ -0,0 +1,248 @@ +#!/bin/sh +# mkerrors - Extract error strings from assuan.h +# and create C source for assuan_strerror +# Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc. +# +# This file is part of Assuan. +# +# Assuan is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Assuan 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see . +cat < +#endif + +#include +#include +#include + +#undef _ASSUAN_IN_LIBASSUAN /* undef to get all error codes. */ +#include "assuan.h" + +/* If true the modern gpg-error style error codes are used in the + API. */ +static unsigned int err_source; + +/* Enable gpg-error style error codes. ERRSOURCE is one of gpg-error + sources. Note, that this function is not thread-safe and should be + used right at startup. Switching back to the old style mode is not + supported. */ +void +assuan_set_assuan_err_source (int errsource) +{ + errsource &= 0xff; + err_source = errsource? errsource : 31 /*GPG_ERR_SOURCE_ANY*/; +} + + +/* Helper to map old style Assuan error codes to gpg-error codes. + This is used internally to keep an compatible ABI. */ +assuan_error_t +_assuan_error (int oldcode) +{ + unsigned int n; + + if (!err_source) + { + if (oldcode == -1) + return -1; + else + return (oldcode & 0x00ffffff); /* Make sure that the gpg-error + source part is cleared. */ + } + + switch (oldcode) + { + case ASSUAN_General_Error: n = 257; break; + case ASSUAN_Accept_Failed: n = 258; break; + case ASSUAN_Connect_Failed: n = 259; break; + case ASSUAN_Invalid_Response: n = 260; break; + case ASSUAN_Invalid_Value: n = 261; break; + case ASSUAN_Line_Not_Terminated: n = 262; break; + case ASSUAN_Line_Too_Long: n = 263; break; + case ASSUAN_Nested_Commands: n = 264; break; + case ASSUAN_No_Data_Callback: n = 265; break; + case ASSUAN_No_Inquire_Callback: n = 266; break; + case ASSUAN_Not_A_Server: n = 267; break; + case ASSUAN_Not_Implemented: n = 69; break; + case ASSUAN_Parameter_Conflict: n = 280; break; + case ASSUAN_Problem_Starting_Server: n = 269; break; + case ASSUAN_Server_Fault: n = 80; break; + case ASSUAN_Syntax_Error: n = 276; break; + case ASSUAN_Too_Much_Data: n = 273; break; + case ASSUAN_Unexpected_Command: n = 274; break; + case ASSUAN_Unknown_Command: n = 275; break; + case ASSUAN_Canceled: n = 277; break; + case ASSUAN_No_Secret_Key: n = 17; break; + case ASSUAN_Not_Confirmed: n = 114; break; + + case ASSUAN_Read_Error: + switch (errno) + { + case 0: n = 16381; /*GPG_ERR_MISSING_ERRNO*/ break; + case EAGAIN: + if (errno > 0 && errno < 4096) + { + n = (EAGAIN | (1 << 15)); + break; + } + default: n = 270; /*GPG_ERR_ASS_READ_ERROR*/ break; + } + break; + + case ASSUAN_Write_Error: + switch (errno) + { + case 0: n = 16381; /*GPG_ERR_MISSING_ERRNO*/ break; + case EAGAIN: + if (errno > 0 && errno < 4096) + { + n = (EAGAIN | (1 << 15)); + break; + } + default: n = 271; /*GPG_ERR_ASS_WRITE_ERROR*/ break; + } + break; + + case ASSUAN_Out_Of_Core: + switch (errno) + { + case 0: /* Should not happen but a user might have provided + an incomplete implemented malloc function. Give + him a chance to correct this fault but make sure + an error is indeed returned. */ + n = 16381; /*GPG_ERR_MISSING_ERRNO*/ + break; + case ENOMEM: + if (errno > 0 && errno < 4096) + { + n = (ENOMEM | (1 << 15)); + break; + } + default: + n = 16382; /*GPG_ERR_UNKNOWN_ERRNO*/ + break; + } + break; + + case -1: n = 16383 /*GPG_ERR_EOF*/; break; + + default: + n = 257; + break; + } + + return ((err_source << 24) | (n & 0x00ffffff)); + +} + + +/** + * assuan_strerror: + * @err: Error code + * + * This function returns a textual representaion of the given + * errorcode. If this is an unknown value, a string with the value + * is returned (Beware: it is hold in a static buffer). + * + * Return value: String with the error description. + **/ +const char * +assuan_strerror (assuan_error_t err) +{ + const char *s; + static char buf[50]; + + switch (err) + { +EOF + +awk ' +/ASSUAN_No_Error/ { okay=1 } +!okay {next} +/^#define[ ]+ASSUAN_[A-Za-z_]*/ { print_code($2) } +/ASSUAN_USER_ERROR_LAST/ { exit 0 } + + +function print_code( s ) +{ +printf " case %s: s=\"", s ; +gsub(/_/, " ", s ); +printf "%s\"; break;\n", tolower(substr(s,8)); +} +' + +cat <> 24) & 0xff); + code = (err & 0x00ffffff); + if (source) + { + /* Assume this is an libgpg-error and try to map the codes + back. */ + switch (code) + { + case 257: n = ASSUAN_General_Error ; break; + case 258: n = ASSUAN_Accept_Failed ; break; + case 259: n = ASSUAN_Connect_Failed ; break; + case 260: n = ASSUAN_Invalid_Response ; break; + case 261: n = ASSUAN_Invalid_Value ; break; + case 262: n = ASSUAN_Line_Not_Terminated ; break; + case 263: n = ASSUAN_Line_Too_Long ; break; + case 264: n = ASSUAN_Nested_Commands ; break; + case 265: n = ASSUAN_No_Data_Callback ; break; + case 266: n = ASSUAN_No_Inquire_Callback ; break; + case 267: n = ASSUAN_Not_A_Server ; break; + case 69: n = ASSUAN_Not_Implemented ; break; + case 280: n = ASSUAN_Parameter_Conflict ; break; + case 269: n = ASSUAN_Problem_Starting_Server; break; + case 270: n = ASSUAN_Read_Error ; break; + case 271: n = ASSUAN_Write_Error ; break; + case 80: n = ASSUAN_Server_Fault ; break; + case 276: n = ASSUAN_Syntax_Error ; break; + case 273: n = ASSUAN_Too_Much_Data ; break; + case 274: n = ASSUAN_Unexpected_Command ; break; + case 275: n = ASSUAN_Unknown_Command ; break; + case 277: n = ASSUAN_Canceled ; break; + case 114: n = ASSUAN_Not_Confirmed ; break; + case ((1<<15)|86): n = ASSUAN_Out_Of_Core ; break; + default: n = 0; break; + } + if (n) + s = assuan_strerror (n); + else + { + sprintf (buf, "ec=%u.%u", source, code ); + s=buf; + } + } + else + { + sprintf (buf, "ec=%d", err ); + s=buf; + } + } + break; + } + + return s; +} + +EOF diff --git a/tags/gpgme-1.1.6/autogen.sh b/tags/gpgme-1.1.6/autogen.sh new file mode 100755 index 0000000..ffe46b4 --- /dev/null +++ b/tags/gpgme-1.1.6/autogen.sh @@ -0,0 +1,162 @@ +#! /bin/sh +# Run this to generate all the initial makefiles, etc. +# +# Copyright (C) 2003 g10 Code GmbH +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +configure_ac="configure.ac" + +cvtver () { + awk 'NR==1 {split($NF,A,".");X=1000000*A[1]+1000*A[2]+A[3];print X;exit 0}' +} + +check_version () { + if [ `("$1" --version || echo "0") | cvtver` -ge "$2" ]; then + return 0 + fi + echo "**Error**: "\`$1\'" not installed or too old." >&2 + echo ' Version '$3' or newer is required.' >&2 + [ -n "$4" ] && echo ' Note that this is part of '\`$4\''.' >&2 + DIE="yes" + return 1 +} + + +DIE=no +FORCE= +if test "$1" = "--force"; then + FORCE=" --force" + shift +fi + +# Used to cross-compile for Windows. +if test "$1" = "--build-w32"; then + tmp=`dirname $0` + tsdir=`cd "$tmp"; pwd` + shift + if [ ! -f $tsdir/config.guess ]; then + echo "$tsdir/config.guess not found" >&2 + exit 1 + fi + build=`$tsdir/config.guess` + + [ -z "$w32root" ] && w32root="$HOME/w32root" + echo "Using $w32root as standard install directory" >&2 + + # See whether we have the Debian cross compiler package or the + # old mingw32/cpd system + if i586-mingw32msvc-gcc --version >/dev/null 2>&1 ; then + host=i586-mingw32msvc + crossbindir=/usr/$host/bin + else + host=i386--mingw32 + if ! mingw32 --version >/dev/null; then + echo "We need at least version 0.3 of MingW32/CPD" >&2 + exit 1 + fi + crossbindir=`mingw32 --install-dir`/bin + # Old autoconf version required us to setup the environment + # with the proper tool names. + CC=`mingw32 --get-path gcc` + CPP=`mingw32 --get-path cpp` + AR=`mingw32 --get-path ar` + RANLIB=`mingw32 --get-path ranlib` + export CC CPP AR RANLIB + fi + + if [ -f "$tsdir/config.log" ]; then + if ! head $tsdir/config.log | grep "$host" >/dev/null; then + echo "Pease run a 'make distclean' first" >&2 + exit 1 + fi + fi + + ./configure --enable-maintainer-mode --prefix=${w32root} \ + --host=i586-mingw32msvc --build=${build} \ + --with-gpg-error-prefix=${w32root} \ + --enable-shared --enable-static --enable-w32-glib \ + PKG_CONFIG_LIBDIR="$w32root/lib/pkgconfig" + + exit $? +fi + + + + + +# Grep the required versions from configure.ac +autoconf_vers=`sed -n '/^AC_PREREQ(/ { +s/^.*(\(.*\))/\1/p +q +}' ${configure_ac}` +autoconf_vers_num=`echo "$autoconf_vers" | cvtver` + +automake_vers=`sed -n '/^min_automake_version=/ { +s/^.*="\(.*\)"/\1/p +q +}' ${configure_ac}` +automake_vers_num=`echo "$automake_vers" | cvtver` + +#gettext_vers=`sed -n '/^AM_GNU_GETTEXT_VERSION(/ { +#s/^.*(\(.*\))/\1/p +#q +#}' ${configure_ac}` +#gettext_vers_num=`echo "$gettext_vers" | cvtver` + + +if [ -z "$autoconf_vers" -o -z "$automake_vers" ] +then + echo "**Error**: version information not found in "\`${configure_ac}\'"." >&2 + exit 1 +fi + +# Allow to override the default tool names +AUTOCONF=${AUTOCONF_PREFIX}${AUTOCONF:-autoconf}${AUTOCONF_SUFFIX} +AUTOHEADER=${AUTOCONF_PREFIX}${AUTOHEADER:-autoheader}${AUTOCONF_SUFFIX} + +AUTOMAKE=${AUTOMAKE_PREFIX}${AUTOMAKE:-automake}${AUTOMAKE_SUFFIX} +ACLOCAL=${AUTOMAKE_PREFIX}${ACLOCAL:-aclocal}${AUTOMAKE_SUFFIX} + +#GETTEXT=${GETTEXT_PREFIX}${GETTEXT:-gettext}${GETTEXT_SUFFIX} +#MSGMERGE=${GETTEXT_PREFIX}${MSGMERGE:-msgmerge}${GETTEXT_SUFFIX} + +DIE=no + + +if check_version $AUTOCONF $autoconf_vers_num $autoconf_vers ; then + check_version $AUTOHEADER $autoconf_vers_num $autoconf_vers autoconf +fi +if check_version $AUTOMAKE $automake_vers_num $automake_vers; then + check_version $ACLOCAL $automake_vers_num $autoconf_vers automake +fi +#if check_version $GETTEXT $gettext_vers_num $gettext_vers; then +# check_version $MSGMERGE $gettext_vers_num $gettext_vers gettext +#fi + +if test "$DIE" = "yes"; then + cat <. +# +# This program 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, or (at your option) +# any later version. +# +# This program 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. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Usage: +# compile PROGRAM [ARGS]... +# `-o FOO.o' is removed from the args passed to the actual compile. + +prog=$1 +shift + +ofile= +cfile= +args= +while test $# -gt 0; do + case "$1" in + -o) + # configure might choose to run compile as `compile cc -o foo foo.c'. + # So we do something ugly here. + ofile=$2 + shift + case "$ofile" in + *.o | *.obj) + ;; + *) + args="$args -o $ofile" + ofile= + ;; + esac + ;; + *.c) + cfile=$1 + args="$args $1" + ;; + *) + args="$args $1" + ;; + esac + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no `-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # `.c' file was seen then we are probably linking. That is also + # ok. + exec "$prog" $args +fi + +# Name of file we expect compiler to create. +cofile=`echo $cfile | sed -e 's|^.*/||' -e 's/\.c$/.o/'` + +# Create the lock directory. +# Note: use `[/.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo $cofile | sed -e 's|[/.-]|_|g'`.d +while true; do + if mkdir $lockdir > /dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir $lockdir; exit 1" 1 2 15 + +# Run the compile. +"$prog" $args +status=$? + +if test -f "$cofile"; then + mv "$cofile" "$ofile" +fi + +rmdir $lockdir +exit $status diff --git a/tags/gpgme-1.1.6/complus/ChangeLog b/tags/gpgme-1.1.6/complus/ChangeLog new file mode 100644 index 0000000..fe34a66 --- /dev/null +++ b/tags/gpgme-1.1.6/complus/ChangeLog @@ -0,0 +1,15 @@ +2001-07-30 Werner Koch + + Encryption basically works. + + + Copyright 2001 g10 Code GmbH + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + \ No newline at end of file diff --git a/tags/gpgme-1.1.6/complus/Makefile.am b/tags/gpgme-1.1.6/complus/Makefile.am new file mode 100644 index 0000000..f893d28 --- /dev/null +++ b/tags/gpgme-1.1.6/complus/Makefile.am @@ -0,0 +1,49 @@ +# Copyright (C) 2000 Werner Koch (dd9jn) +# Copyright (C) 2001 g10 Code GmbH +# +# 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 + +## Process this file with automake to produce Makefile.in + +# Because WIDL does not yet fully support generation of typelibs, we +# have to distribute a binary type library. To generate a new one, +# copy the idl file to a system with an install MIDL and run the +# command "midl /nocpp gpgcom.idl". Sorry, there is no other way yet. + +EXTRA_DIST = gpgcom.idl gpgcom.tlb gpgcom.rc vbtest.html vbtest.vbs README + +# No need to install this because we are cross-compiling anyway. +noinst_PROGRAMS = gpgcom tgpgcom + +INCLUDES = -I$(top_srcdir)/jnlib +LDADD = ../gpgme/libgpgme.la -L ../jnlib -ljnlib -lole32 -loleaut32 +gpgcom_LDADD = gpgcom_res.o $(LDADD) + +gpgcom_SOURCES = gpgcom.c main.h \ + debug.c utf8.c \ + igpgme.h igpgme.c + +tgpgcom_SOURCES = tgpgcom.c\ + debug.c \ + igpgme.h + +#regtlb_SOURCES = regtlb.c +#guidgen_SOURCES = guidgen.c + +gpgcom_res.o: gpgcom.rc + mingw32 windres $< gpgcom_res.o + diff --git a/tags/gpgme-1.1.6/complus/README b/tags/gpgme-1.1.6/complus/README new file mode 100644 index 0000000..7dc3bb1 --- /dev/null +++ b/tags/gpgme-1.1.6/complus/README @@ -0,0 +1,72 @@ + How to install and use the Gpgcom Windows Component + =================================================== + 2001-07-31 + + +Installation should be pretty easy: +----------------------------------- + + * Get and install the latest GnuPG binary for windows + (ftp://ftp.gnupg.org/gcrypt/binary/gnupg-w32-1.0.6.zip) + + * Check that you have an untampered version of this package by + comparing an MD5SUM against the one on the webpage or by checking + the signature of the package using "gpg --verify". See the + webpacge for details. + + * Because you are reading this file, you probably have already + unpacked it distribution using a unzip utility :-). You should + find these files: + + README - This file + gpgcom.exe - The Gpgcom server + vbtest.html - A Test webpage + vbtest.vbs - A VB script to be used with the cscript utility + + * If you are updating Gpgcom, run the old Gpgcom like this: + + c:\gnupg\gpgcom -UnregServer + + (Replace c:\gnupg with the actually used path) + + * Copy the file gpgcom.exe to a some location. C:\gnupg seems to be + a good choice. + + * Register the component using this command: + + c:\gnupg\gpgcom -RegServer + + * Ready + +Testing the installation: +------------------------- + + * Make sure that you have a working GnuPG (gpg.exe) and that at least + one key is installed. + + * Edit the vbtest.vbs script and replace "alice" in the line + + gpg.AddRecipient "alice" + + with a keyID or user name you have in your key ring. + + * Run the test script: + + cscript vbtest.vbs + + and you should see a valid MIME message with the encrypted text. + + +Using Gpgcom +------------ + +Gpgcom currently support only encryption but will be extended to the +full range of operations GnuPG provides. The 2 examples should goive +yopu a hint on how to use it. We suggest that you always set armor to +true, so that the returned text is a string. If you don't use armor, +the "ciphertext" property will return an array with the binary +message. + + + + diff --git a/tags/gpgme-1.1.6/complus/debug.c b/tags/gpgme-1.1.6/complus/debug.c new file mode 100644 index 0000000..d7cb0a0 --- /dev/null +++ b/tags/gpgme-1.1.6/complus/debug.c @@ -0,0 +1,40 @@ +/* debug.c - COM+ debug helpers + * Copyright (C) 2001 g10 Code GmbH + * + * 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 +#include +#include +#include + + +const char * +debugstr_guid (const GUID *id) +{ + static char str[100]; + + if (!id) + return "(null)"; + sprintf( str, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + id->Data1, id->Data2, id->Data3, + id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3], + id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7] ); + return str; +} + diff --git a/tags/gpgme-1.1.6/complus/example.c b/tags/gpgme-1.1.6/complus/example.c new file mode 100644 index 0000000..a7d838d --- /dev/null +++ b/tags/gpgme-1.1.6/complus/example.c @@ -0,0 +1,598 @@ +/* + * Copyright 1999 Marcus Meissner + */ +#include +#include +#include + +#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 (sizeszName, 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"); +} diff --git a/tags/gpgme-1.1.6/complus/gpgcom.c b/tags/gpgme-1.1.6/complus/gpgcom.c new file mode 100644 index 0000000..6670369 --- /dev/null +++ b/tags/gpgme-1.1.6/complus/gpgcom.c @@ -0,0 +1,545 @@ +/* gpgcom.c - COM+ component to access GnuPG + * Copyright (C) 2001 g10 Code GmbH + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "argparse.h" + +#include "main.h" +#include "igpgme.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 = "gpgcom"; + break; + case 13: p = VERSION; break; + /*case 17: p = PRINTABLE_OS_NAME; break;*/ + case 19: p = + _("Please report bugs to .\n"); + break; + case 1: + case 40: p = + _("Usage: gpgcom [options] (-h for help)"); + break; + case 41: p = + _("Syntax: gpgcom [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_DOSISH_SYSTEM + 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_progid ( const char *name ) +{ + HKEY hk = 0; + char buf[500]; + + /* Create a ProgID entry to point to the ClassID */ + sprintf (buf, "%.400s", name); + if (RegCreateKeyA (HKEY_CLASSES_ROOT, buf, &hk)) { + fprintf (stderr,"RegCreateKey(`%s') failed\n", buf); + exit (1); + } + sprintf (buf, "g10 Code's GnuPG made easy COMponent" ); + if (RegSetValueExA (hk, 0, 0, REG_SZ, buf, 0)) { + fprintf (stderr,"RegSetValueEx(`%s') failed\n", buf); + exit (1); + } + if (RegCloseKey (hk)) { + fprintf (stderr,"RegCloseKey() failed\n"); + exit (1); + } + sprintf (buf, "%.400s\\CLSID", name); + if (RegCreateKeyA (HKEY_CLASSES_ROOT, buf, &hk)) { + fprintf (stderr,"RegCreateKey(`%s') failed\n", buf); + exit (1); + } + sprintf (buf, "%.100s", debugstr_guid (&CLSID_Gpgme) ); + if (RegSetValueExA (hk, 0, 0, REG_SZ, buf, strlen (buf))) { + fprintf (stderr,"RegSetValueEx(`%s') failed\n", buf); + exit (1); + } + if (RegCloseKey (hk)) { + fprintf (stderr,"RegCloseKey() failed\n"); + exit (1); + } + hk = 0; +} + + +static void +register_typelib (void) +{ + ITypeLib *pTypeLib; + HRESULT hr; + char name[500]; + wchar_t *wname; + size_t n; + + if ( !GetModuleFileNameA (0, name, sizeof (name)-10) ) { + fprintf (stderr,"GetModuleFileName() failed: %d\n", + (int)GetLastError()); + exit (1); + } + n = mbstowcs (NULL, name, strlen(name)+1); + wname = xmalloc ((n+1)*sizeof *wname); + mbstowcs (wname, name, strlen (name)+1); + + hr = CoInitializeEx (NULL, COINIT_APARTMENTTHREADED); + if (hr) + fprintf (stderr, "CoInitializeEx() failed: hr=%lu\n", hr); + + hr = LoadTypeLibEx (wname, REGKIND_REGISTER, &pTypeLib); + if (hr) + fprintf (stderr, "LoadTypeLibEx() failed: hr=%lx\n", hr); + + ITypeLib_Release (pTypeLib); + CoUninitialize (); + free (wname); +} + +static void +unregister_typelib (void) +{ + UnRegisterTypeLib (&TLBID_Gpgcom, 1, 0, LANG_NEUTRAL, SYS_WIN32); +} + +static void +register_server () +{ + HKEY hk = 0; + char buf[500]; + + + register_typelib (); + + /* Create a key for the CLSID */ + sprintf (buf, "CLSID\\%.100s", debugstr_guid (&CLSID_Gpgme) ); + if (RegCreateKeyA (HKEY_CLASSES_ROOT, buf, &hk)) { + fprintf (stderr,"RegCreateKey(`%s') failed\n", buf); + exit (1); + } + /* Store our class name as default value */ + strcpy (buf, "Gpgme"); + if (RegSetValueExA (hk, 0, 0, REG_SZ, buf, strlen (buf))) { + fprintf (stderr,"RegSetValueEx(`%s') failed\n", buf); + exit (1); + } + + /* Set the application ID */ + sprintf (buf, "%.100s", debugstr_guid (&APPID_Gpgcom) ); + if (RegSetValueExA (hk, "AppID", 0, REG_SZ, buf, strlen (buf))) { + fprintf (stderr,"RegSetValueEx(`%s') failed\n", buf); + exit (1); + } + if (RegCloseKey (hk)) { + fprintf (stderr,"RegCloseKey() failed\n"); + exit (1); + } + hk = 0; + + /* Create the LocalServer32 subkey under the CLSID key */ + sprintf (buf, "CLSID\\%.100s\\LocalServer32", + debugstr_guid (&CLSID_Gpgme) ); + if (RegCreateKeyA (HKEY_CLASSES_ROOT, buf, &hk)) { + fprintf (stderr,"RegCreateKey(`%s') failed\n", buf); + exit (1); + } + /* retrieve the module name and add it under the key */ + if ( !GetModuleFileNameA (0, buf, sizeof (buf)-10) ) { + fprintf (stderr,"GetModuleFileName() failed\n"); + exit (1); + } + if (RegSetValueExA (hk, 0, 0, REG_SZ, buf, strlen (buf))) { + fprintf (stderr,"RegSetValueEx(`%s') failed\n", buf); + exit (1); + } + if (RegCloseKey (hk)) { + fprintf (stderr,"RegCloseKey() failed\n"); + exit (1); + } + hk = 0; + + /* Create the ProgID subkey under the CLSID key */ + sprintf (buf, "CLSID\\%.100s\\ProgID", + debugstr_guid (&CLSID_Gpgme) ); + if (RegCreateKeyA (HKEY_CLASSES_ROOT, buf, &hk)) { + fprintf (stderr,"RegCreateKey(`%s') failed\n", buf); + exit (1); + } + if (RegSetValueExA (hk, 0, 0, REG_SZ, "Gpgcom.Gpgme.1", 0)) { + fprintf (stderr,"RegSetValueEx(`%s') failed\n", buf); + exit (1); + } + if (RegCloseKey (hk)) { + fprintf (stderr,"RegCloseKey() failed\n"); + exit (1); + } + hk = 0; + /* Create the VersionIndependentProgID subkey under the CLSID key */ + sprintf (buf, "CLSID\\%.100s\\VersionIndependentProgID", + debugstr_guid (&CLSID_Gpgme) ); + if (RegCreateKeyA (HKEY_CLASSES_ROOT, buf, &hk)) { + fprintf (stderr,"RegCreateKey(`%s') failed\n", buf); + exit (1); + } + if (RegSetValueExA (hk, 0, 0, REG_SZ, "Gpgcom.Gpgme", 0)) { + fprintf (stderr,"RegSetValueEx(`%s') failed\n", buf); + exit (1); + } + if (RegCloseKey (hk)) { + fprintf (stderr,"RegCloseKey() failed\n"); + exit (1); + } + hk = 0; + + + /* Create a key to store AppID info */ + sprintf (buf, "AppID\\%.100s", debugstr_guid (&APPID_Gpgcom) ); + if (RegCreateKeyA (HKEY_CLASSES_ROOT, buf, &hk)) { + fprintf (stderr,"RegCreateKey(`%s') failed\n", buf); + exit (1); + } + /* Store the name as default value */ + strcpy (buf, "Gpgcom"); + if (RegSetValueExA (hk, 0, 0, REG_SZ, buf, strlen (buf))) { + fprintf (stderr,"RegSetValueEx(`%s') failed\n", buf); + exit (1); + } + if (RegCloseKey (hk)) { + fprintf (stderr,"RegCloseKey() failed\n"); + exit (1); + } + hk = 0; + + register_progid ("Gpgcom.Gpgme"); + register_progid ("Gpgcom.Gpgme.1"); + + /* Create a convenience cross reference to the AppID */ + sprintf (buf, "AppID\\gpgcom.exe"); + if (RegCreateKeyA (HKEY_CLASSES_ROOT, buf, &hk)) { + fprintf (stderr,"RegCreateKey(`%s') failed\n", buf); + exit (1); + } + sprintf (buf, "%.100s", debugstr_guid (&APPID_Gpgcom) ); + if (RegSetValueExA (hk, "AppID", 0, REG_SZ, buf, strlen (buf))) { + fprintf (stderr,"RegSetValueEx(`%s') failed\n", buf); + exit (1); + } + if (RegCloseKey (hk)) { + fprintf (stderr,"RegCloseKey() failed\n"); + exit (1); + } + hk = 0; + + fprintf (stderr,"*** Component registered\n"); +} + +static void +unregister_server () +{ + char buf[500]; + + unregister_typelib (); + sprintf (buf, "CLSID\\%.100s\\LocalServer32", + debugstr_guid (&CLSID_Gpgme) ); + if (RegDeleteKey (HKEY_CLASSES_ROOT, buf)) + fprintf (stderr,"RegDeleteKey(`%s') failed\n", buf); + + sprintf (buf, "CLSID\\%.100s\\ProgID", debugstr_guid (&CLSID_Gpgme) ); + if (RegDeleteKey (HKEY_CLASSES_ROOT, buf)) + fprintf (stderr,"RegDeleteKey(`%s') failed\n", buf); + + sprintf (buf, "CLSID\\%.100s", debugstr_guid (&CLSID_Gpgme) ); + if (RegDeleteKey (HKEY_CLASSES_ROOT, buf)) + fprintf (stderr,"RegDeleteKey(`%s') failed\n", buf); + + sprintf (buf, "Gpgcom.Gpgme.1\\CLSID"); + if (RegDeleteKey (HKEY_CLASSES_ROOT, buf)) + fprintf (stderr,"RegDeleteKey(`%s') failed\n", buf); + sprintf (buf, "Gpgcom.Gpgme.1"); + if (RegDeleteKey (HKEY_CLASSES_ROOT, buf)) + fprintf (stderr,"RegDeleteKey(`%s') failed\n", buf); + + sprintf (buf, "Gpgcom.Gpgme\\CLSID"); + if (RegDeleteKey (HKEY_CLASSES_ROOT, buf)) + fprintf (stderr,"RegDeleteKey(`%s') failed\n", buf); + sprintf (buf, "Gpgcom.Gpgme"); + if (RegDeleteKey (HKEY_CLASSES_ROOT, buf)) + fprintf (stderr,"RegDeleteKey(`%s') failed\n", buf); + + + sprintf (buf, "AppID\\%.100s", debugstr_guid (&APPID_Gpgcom) ); + if (RegDeleteKey (HKEY_CLASSES_ROOT, buf)) + fprintf (stderr,"RegDeleteKey(`%s') failed\n", buf); + + sprintf (buf, "AppID\\gpgcom.exe" ); + if (RegDeleteKey (HKEY_CLASSES_ROOT, buf)) + fprintf (stderr,"RegDeleteKey(`%s') failed\n", buf); + + fprintf (stderr,"*** component unregistered\n"); +} + + +static void +enter_complus () +{ + HANDLE running; + DWORD reg; + IClassFactory *factory; + CLSID clsid; + HRESULT hr; + + fprintf (stderr,"*** enter enter_complus()\n"); + CoInitializeEx (NULL, COINIT_MULTITHREADED); + running = CreateEvent (NULL, FALSE, FALSE, NULL ); + fprintf (stderr,"*** CoInitialize() done; event=%lx\n", (unsigned long)running ); + + igpgme_register_exit_event (running); + factory = igpgme_factory_new ( &clsid ); + fprintf (stderr,"*** igpgme_factory_new() done; got=%p\n", factory ); + hr = CoRegisterClassObject (&clsid, (IUnknown*)factory, + CLSCTX_LOCAL_SERVER, + REGCLS_SUSPENDED|REGCLS_MULTIPLEUSE, ® ); + if (hr) { + fprintf (stderr, "CoRegisterClassObject() failed: hr=%lx\n", hr); + exit (1); + } + hr = CoResumeClassObjects (); + if (hr) + fprintf (stderr, "CoRegisterClassObject() failed: hr=%lx\n", hr); + fprintf (stderr,"*** class object registered; waiting\n" ); + + WaitForSingleObject ( running, INFINITE ); + fprintf (stderr,"*** shutting down\n" ); + igpgme_register_exit_event (NULL); + CloseHandle (running); + CoRevokeClassObject ( reg ); + fprintf (stderr,"*** class object revoked\n" ); + igpgme_factory_release (factory); + fprintf (stderr,"*** factory released\n" ); + CoUninitialize (); + fprintf (stderr,"*** leave enter_complus()\n" ); +} + diff --git a/tags/gpgme-1.1.6/complus/gpgcom.idl b/tags/gpgme-1.1.6/complus/gpgcom.idl new file mode 100644 index 0000000..654eec0 --- /dev/null +++ b/tags/gpgme-1.1.6/complus/gpgcom.idl @@ -0,0 +1,62 @@ +/* ignupg.idl - Interface definition for the COM+ class GnuPG + * Copyright (C) 2001 g10 Code GmbH + * + * 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 + */ + + +import "unknwn.idl"; +import "oaidl.idl"; + + +[ object, uuid(3811fd50-7f72-11d5-8c9e-0080ad190cd5), dual] +interface IGpgme : IDispatch +{ + HRESULT GetVersion([out] BSTR *retval); + HRESULT GetEngineInfo([out] BSTR *retval); + HRESULT Cancel(void); + [propput] HRESULT Armor([in] BOOL flag); + [propget] HRESULT Armor([out, retval] BOOL *retval); + [propput] HRESULT Textmode([in] BOOL flag); + [propget] HRESULT Textmode([out, retval] BOOL *retval); + [propput] HRESULT Plaintext([in] VARIANT val); + [propget] HRESULT Plaintext([out, retval] VARIANT *retval); + [propput] HRESULT Ciphertext([in] VARIANT val); + [propget] HRESULT Ciphertext([out,retval] VARIANT *retval); + HRESULT ClearRecipients(void); + HRESULT AddRecipient([in] BSTR name, + [in, optional, defaultvalue(-1)] signed short trust); + HRESULT ResetSignKeys(void); + HRESULT AddSignKey([in] BSTR name); + HRESULT Encrypt(void); + HRESULT Sign([in,optional,defaultvalue(0)] signed short signmode); + HRESULT SignEncrypt([in,optional,defaultvalue(0)] signed short signmode); + +}; + + +[ uuid(3811fd48-7f72-11d5-8c9e-0080ad190cd5), + helpstring("g10Code.gpgcom, type library"), + version(1.0) ] +library GpgcomLib +{ + [ uuid(3811fd40-7f72-11d5-8c9e-0080ad190cd5) ] + coclass Gpgcom + { + [default] interface IGpgme; + } +}; diff --git a/tags/gpgme-1.1.6/complus/gpgcom.rc b/tags/gpgme-1.1.6/complus/gpgcom.rc new file mode 100644 index 0000000..d9ac566 --- /dev/null +++ b/tags/gpgme-1.1.6/complus/gpgcom.rc @@ -0,0 +1,22 @@ +/* gpgcom.rc - Resource file for gpgcom + * Copyright (C) 2001 g10 Code GmbH + * + * 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 + */ + +1 TYPELIB "gpgcom.tlb" + diff --git a/tags/gpgme-1.1.6/complus/gpgcom.tlb b/tags/gpgme-1.1.6/complus/gpgcom.tlb new file mode 100644 index 0000000000000000000000000000000000000000..ae3d1627d3bfd8d9902ebb95ef3afdc55c328f55 GIT binary patch literal 18596 zcmcIs4{)4Ebzl9zJDucDw&KV}kUOF_VxlCU6A`Y&G@q=KtRwn!NN1lylKSMkvvkQx zI!-4`hJcS&lX@Bhnl=QN7~*L{ac7*4OO?S4h6o77K$y7GggR4G6bQu>GdN6O0tCCi z-|n|}-^piFb;`~>efzzA``+8PZ{O~>yQhJX-bkgW5KQiB`4C-rD2x!-DOBO_Z;(rP z)axZX`S6+tu#T>mK>ie<1BgYyYk<*8Ax;8(RYEKP&H?%%^EjZnMu>U9S%6h5#FGG5 zoe*ijX+Wn-h(mxk05P`^&jQ+^$3egaK%`!X6M$vNY4r+0)z(3N5P$Gmcn{;f)$!hm zcf;|1wn4Q;*T1(>h%=7zG?}6ex;)(^#L;Vu@6B&R`yBM0cz4ow-dHM+d_Ym)x7PPR z@}rI5sd>PpS4=G^f$D-!CM`?nVLE}XC`qL0^j9bu=$i{5&@$GSP^y<09u{oUVV7Ml zBOztbH!1}>7Kt?1`zysGH{%7&eNa-%SgntyXQx?wLAqQeLht?0NNHU{$+fR-V|<-M+XE?hwdW%ZYl z?eo`(OhAYusCN)hl!3v$Drp%O9T-W!JM-oH!zCX16Cox*$i6Jfuo;nooitCE-BtRX z#X67hQ^;%l4Su&c0~ze|1wc_oF-KY^&Bu2Y8RgsI5nJE6HW{(2$S@qbXubUYdT|6Y z)?%wCuOg$It^9tkcx8<;(ug}+N0lquv7C%Q_BV+3JBoEK?*+}J$Y<#)GT6ioVnbfn zVjo`bZ?t6qcp@>Xj1T#UgE0(lQq9u&>`q zrt{_6;rCxFp6puN_^@p8ny*tvn?s()-{5Z%6WiA2yQ5c;QLY_6|0Zz^GS<=`udh*t z-@jRy-D{I!aIK3}&Q|5e;G4t}WUOUAKX?@xzB00}_qU2OK_T)O4yWO`+IQ_w5~^EB z%XaQHd&#o89TlRpY~1zx-z*;7zBa#l#9n-@mO&MKfYo@P|1HAmQ~j}ka@`JR4rrNl z-D6jgQO>WHQTr$WV#FeVe6EyYS1C79#&o5+#J7|w@B3X-AiMv?rh}gr`KLB{U%Y5D zuvXzUZ?hT`5Yn>zD|-3HDqt-|v=l=#Y3 zcz$QjgE!@99Y}{a*?qLLwiR{1NsQzYL+RwLH%HRDqtPg7T?qP#YZU(ld?y*0X1RuX zZll7H<_*jl$3Vxt0R9B%AH+B2DflsQFCb3x+3yk}jDcuj4CSF4zpumiehq_u)cz(V zT{XU8mmq5bJT34zjr=*#tssUh**qD0&q3C4$Yz}u7s>_7VxV!c9`s$L9l(oYe*$&5PCW!( z)U6foeCD9jD1h@0-B_yp=}|8@oLIS|@0^}y8h+!Xg*$g?Ie`>tKvcZ7nVE8q-kOK>bV zwxtBuC2_Zw;I>KJZ6&yFiR%PT%WV{2{^)yVli7Wtsa!IB@)BQJw?8CVtQ;inNE()BnxdfL}GG#G8fsGNrtBO zOm|PuPUST3IybVVY=1$?#G z|I6{&R6^5Li@$zfImJ@Ts$(dw!Z!)3yZ3W&i5)Vu!CsT>;>8Y7qb~c`y z&T1a(j8|J^Sum-K3i9g3=QgD?K##;Hl9OWve4}yxw)pOm)ceuQncUbEZOXkfrTgY- zTlc#{gTVscV;<^>5VNaiaK}KA-fLcaNa2Tjx`&2?nvd7~?3WdOU?{kwzenTOnco;v z_|RaaXSlbkyQd(d(F~5MvS4T=+!g8WE6Qmw-*riqbq{s-ca4m|-kN8<`OgolvabG6 z*N6ju=YECXF&G*el=#E!H*^2f3O~>_>gYF@@$Khx===v#Q-waNH6Cq__s&kmXNvt> zV>~_+-#L~As$f%(adIRcn#`o>4-Q(lvFB-J>z#Y(lk7Jy#(ur=%opOjyV9xgsmbJ2 zPU6GBdyI{VIr8XDkBvL{ctyuca|2`dPiJ=~vxBpfaB4u0ni#84-?s|+*9F%QC zca1?I?kRIk;t9+jLpxwgX<~_|PHyAj{yAXnE-d&+z46u?Q;9V7qP3%PUz#=wYz+sa z7(B26V@n5kH;KM)4JRk3b4fcQb>(tdl#@S`M~olMWXMJpC@kWIrN5-k{>B$Uua37rX^?}jPLw_nS$2##xp-+Q(=f7*@uEC+f9=py~lr@>(K2|8} z-7(m$nl5<;F|QitGXsV4on6DsYk5uPNA?uT7#+KZ2EsP)G}?Ww`Sc@&^3XuIKhzzH zbcMr1+ukktTl9DHlQjhz3||W}&q43{z>hzRwiGlXo^7lVzYEIv2ss+(Hr^XeXR_ln z@#zFYUzFzo3zEmf^b+yN0_YG0zeb zuuo&)x=%UrJqR!?YeQMBvHxfBZToVJ55!Twb;dtjzjrJfOzs(*P3LxwrDu~;hJkXg z@xeqUGnO5jr10cCWwTDb@zKxBg^5=lM*WF*8-JB6kUQGjWSrf@_F}q|oMcs$^XxOcJouT2#j;?-y@$psV;T?AQN$|bK ze7kvh`EXCK!_IX^=%LiqUaA`9dC~#Mtq***1G;v1_4jwfA`&lcZeA1X?%vhgH4DY#$Z7s0FEd~}>L!cnQJ zKOk-Nr?{&sgkH<$isEc*I#`mAne$Q!~wDYuuVH}+!!Vc0r z`#TIjsCJDS2W7=zz($Qy11{8c(Qg52tBv(tdjf7p1{djrMDUo z#M4IW%$hnhW*0m@G>CCGi1n5(^O(;)%QAa77VvKKr#-~OVMj0oB%b@rUUTI`#OqUK1WO`XMd$Z1>7(bTD4{OgiEJIhMM{iAh?{<1sAH?lvHv?VVlmzaAwW0&eS8sfVHsG~_`?~%3@ZD|y#Co&}^s-34Hzd^j%#CpM*p*>FB z0@xpLiQO8xWY{U-()=cOm;kh58zaSx+JU2J0B8+ZZW4gBm2kli!d-4hNC_6`w$2)3;;e)-B=w_1A;_aMIK-NtwS*74~V zC7$Ok9%D4Po1bvgvsr$pNqXqM&iJN_c)D>mmEj6rmK}o4yhg=uS=N_KXL?iVByuF%p$jdsR#H4-(9t8TYcf6a@nlAZ2Fd#@_Fn45^M98?U-e|O z5|_vLuM>~o!*4fk1}Lr^FVX7kxI%^!^Adjwdbq^)fX1_JdGyCdapw(%aTlD9&+;Qh zen2_L-@;e$sS(cEQCiD!iw7Y* zI!*Iy5Wg6Z^>jyrC-pqdeiNh7qMqq=&r~jpPXfu;hj`-^=7UORI!!;-F*7%m zO{AvA(l$SqHHr^CRE!78&Xn~WY}zb-_m2K)%;eZ)$tGtoiZKXxC$lWi!S9;Iu`elI zy0gi#Tw&Ki%d8cj`GVTFQTn&T_H|lAjm-u}%!Jts2j#)Pb^UMJ|zv zsL4jk!v0&6IDVglerV5jZ1TW%yf^d)Vn%&nFTX1y{h@7gKj;MTX~_2k-ct)a)>dlH zCVq*rz}(>ha#u7oxaD^6A)e=nZu2pXzm0oo#CJm9Iy1VP^jPponbq`t?=dizMU}v^qE0pt#l5IT>J|1z)O_Yz2e~+*`MG}9@OUm{H0O+V3XqA ziz$&Ms?M|653LiscV)*_kf)AM!q@A>><2ROUb!zo9_L|`W|4hN`lP+dr&~auJO>+Z z7O{y!n;8zrQd1as>}zPF!V= zceD86e>lta5`g8M(0PMseBN1(Xe3uCl=rN(-+zvz)Y3=V^aa#&iNtTR;|!D`xd)m- ze|g16E^_t?CDa&9!2d2lKaaTaYw%HQ9?fv7kUZXi9WZC!kxl0IagJZAO@9vduMyvz@5)Y2bAN(#3-Aw@xbOK0rkF`gbHuS7 zZt<=E4yR#gd+yPAk2v@D-Koq(GOG$Sex3Nsf9u8;ErNACl}X9nAeNnny}aV+kK~@N zT|)j$)#Ac0rtElj2<@v8sd;Rf%C$J_o`o$M#OLneOqUzM?%Q3-eVpG}W?;|VBYyIa z;A@xI?Zz0X6K}ewXDXiEhYt|awxUm~Mc~&Yq+IT8xx~j-X1Jkew>gG-_2RWJkw({T z72{h>&iyx!%U${oUk;w)OQ&{c#~7en#l`(#FWxLJ?dP8QW_&7PuPMJ7cyuq`H{cjy zL;lU8N`C8+j{8=d@igsv)P?Vs{m#8OzK891?uoG;_p$ioJ{QX~DCd*sP{eb8ith&` z-eY-$2XZg%=iUYJM{GLoOAya}2;xsje3iUgNj>@9!Y98^Hw&-j6<*0FhVex_zeiY~ zV}bQwm+~&{=Rp|Dxqq}-R9S|6N4sn}KAWELp7r@X!ukOlZ`pXR<%tj5cxIwPuud(*nAkPh(BlJFW}iEn(`I!Bs4{)9QvjWxlLkIo`_c5cH>=IkctWX z;TaZ4KvPkm@kyGB%V=6asrj_weA;cFLAJrh8s9F0!e3o2>$3gyZOUqcw`-aX@NWuM zNty$;4rmH!Y6>)_6u56Oepdl7@a$)W=nz*(&+eNtzYtL7OOj z+yxp-^6`}6<0;StB_H=?d|EJyb=&)--O!;(0Yo8<@5fiZyV)!If;!>^@c{jc=X$hX zrKrp^zHC9h1rbQs3rl_om`H7y`7}NPecd=*WnCwq7OYM*&8V!40F2a*SzP1q7573H zL)JwRwxKHXJmaP8c6gYki%GhsvUJcmRslfWSd|SmcoOPtaN|j+2cYG#20$ZV9l!uI z0eIHSbJ-Yx=dT2wn-X{yOW@fkf#=jbC*~P2f}A{O=D9D=LYX)Y`T#M&0^lg%Ilu)# zGYrLXe=i^pI0WE$9)zp06*aet0^7yfW=VciJ+Y8y9WM&&p|2$Ey^Jf5V_;}6e^nI})KNtkCW(mXk~c#ce- zhaF?I1+8^gSHUZJqoXR1#jdQ&n4$SQ`7qD59Qo5OJUeH81;Fnl@;?d$&(N9o0k{rk zp1S#vCq408Z!*6E;JG@c5~PY4qD>5U{bPsu2IyAeHSv7Lkati&_w0S-`s_p42iyClSM2>@;5KAML7&yhlMl3KI{| ze3h2ORp2J_`aFt|82N~+EWu$40#3D_RE!4H9m#?i3vw-#T6rM2raB7Xy#yx8YzJ%w z_`uw03oqk{ZHqk0dA7k8EdsFkl6hyWH{flw1)CPbAFjPfzZHMAeVfIDpsAGFvOoDP zMS2r|xRzhde=8_;-4h%`vBaFAl`J$B|gR}Z18A$t$zlUcsD}P7w45WNnd*z{XFQoCM5kh1B-*Eotoez+fwD%7^{$ipy&zTru?rJw(o##A01y?9P{p0Ipz^~kxa+DYDpi!jKsPC9T!i4 z5AP)@xyAW5DCseKfp)d8^1DaT7w6tSIZiRtf&O*y~7eE{CUV!p*OC-+M|;T#fQ zoP*W;4?|1*`huM!k{*I(DvhsLonaoXh+%aV!>T8S)e+|5iWpWmn2Reg7gt~|uE1Pe zfw{N>b8!Xc;)>XM0PjI@?}7V-ynn^JT7B?q?m=?zf$1_3#M>|+?>2#tXNVgmXA^8lVR^X!lJpm=UbKV)3AV<>WM z0OE>qpEz2OvDg{2S&y-p{e~=38*EQpbqTIj;%e}_vy1Y67wLQwS6jl5lA9497^78c zllf+7=bRThP}q#I=fvGCah?(!ZPW}OchcP|ao!SKr^Gds;BJ?=#u8jW;?|Ym@UsWV zFl2uqi_|9PmuAr#7|Isb&=%Gh7Dkr^ zH?iOz7FL@U`oMyVSiDQawaQ7r3xEp%z1HGg0p4dx0NCF=+hdz?9RM~a0w4|f@H-9}t@oJq^jws6K0 zRnE13F_zfXB)@0z!u?D|r)*7r<#;&9yORgU%Yvi5%c#Eq&~vO;uJ5^*%HPOdymSN& zLKP{4_fMH8Z=UHeUotlW!TmnCMalZE4|u&^iyxSyzTu2R zj5owPeL~Szh(pZCgq0wk^u=X`z~2rzpE0hSD&X3re=@F|cHj);8CT9YaFofoQYk9) z3a#fge1SV~*dqj;s|437arioS(7i?CJmQ36hQE6LE1jE6RbJM1Fq2hoj^Ns!XZbw4 z=b0|of;3cqf4OH<)zWwBLtqoKr`PrOU=Gcmr2Dm!j>!mCmIQ!)`6{ zDF!&+f#H3IQ2>)u5BB^2r=66prSm!B0(32%&z1hA^Etvb=t}2vj0NCI=W}#3aPE@6 zW!sza4dt{YntPc&AlHH%tK1ml-I-+of1knMIPmukyjQ`qqcDJX7xDo9Mu5p_NA@Ls zuH4unj3N&EPF9RBVk z2;dzSrq%7?`w9zW>X3h_!vPFFm5TEW_f8b9*cVQmEuusR{vL*lczhVj`yH(B)M3ef zclMv6Dcuu8_n=-Syx)~)IpeYNk*X3Ld>?exB{=HEG3V?rL*h!m!>AX>oRh9a;<(@9 z$s>!@CjaLKG9~TQzT_NBJS*n!d3Zm9=a$tF+6v(BiTGP5o}V%~?GeU%0^l4w?Pz=( zaK-gn`8{M4{ibQ~+Y;=XU`HMGocn0bHI#``P2Vi{BQSffqF;s|#Bi=iyos@=>02a! z?9>BKoAcX@E>p_ixi`ms#%f8w0z&=%v zeL*GGqHmYqPdSBpDz!=fXIyv205$GP +#include +#include +#include +#include +#include +#include +#include + +#include "obj_base.h" + +#include "argparse.h" + + +enum cmd_and_opt_values { aNull = 0, + oVerbose = 'v', + +aTest }; + + +static ARGPARSE_OPTS opts[] = { + + { 301, NULL, 0, "@Options:\n " }, + + { oVerbose, "verbose", 0, "verbose" }, +{0} }; + +static struct { + int verbose; +} opt; + + +static void create_guid (void); + +static const char * +my_strusage( int level ) +{ + const char *p; + switch( level ) { + case 11: p = "guidgen"; + break; + case 13: p = VERSION; break; + /*case 17: p = PRINTABLE_OS_NAME; break;*/ + case 19: p = + "Please report bugs to .\n"; + break; + case 1: + case 40: p = + "Usage: guidgen [options] (-h for help)"; + break; + case 41: p = + "Syntax: guidgen [options]\n" + "Generate GUIDs\n"; + break; + + default: p = NULL; + } + return p; +} + + +int +main (int argc, char **argv ) +{ + ARGPARSE_ARGS pargs; + + set_strusage( my_strusage ); + /*log_set_name ("gpa"); not yet implemented in logging.c */ + + pargs.argc = &argc; + pargs.argv = &argv; + pargs.flags= 0; + while( arg_parse( &pargs, opts) ) { + switch( pargs.r_opt ) { + case oVerbose: opt.verbose++; break; + + default : pargs.err = 2; break; + } + } + + if (!argc) + create_guid(); + else { + int n; + + for (n = atoi (argv[0]); n > 0; n-- ) + create_guid (); + } + + return 0; +} + + +static void +create_guid () +{ + GUID guid, *id; + id = &guid; + if ( CoCreateGuid (id) ) { + fprintf (stderr,"failed to create GUID\n"); + exit (1); + } + printf( "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n", + id->Data1, id->Data2, id->Data3, + id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3], + id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7] ); +} + + diff --git a/tags/gpgme-1.1.6/complus/igpgme.c b/tags/gpgme-1.1.6/complus/igpgme.c new file mode 100644 index 0000000..9aa64a2 --- /dev/null +++ b/tags/gpgme-1.1.6/complus/igpgme.c @@ -0,0 +1,859 @@ +/* igpgme.c - COM+ class IGpgme + * Copyright (C) 2001 g10 Code GmbH + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include "../gpgme/gpgme.h" + +/* FIXME: Put them into an extra header */ +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 INITGUID +#include "igpgme.h" + +/* + * Declare the interface implementation structures + */ +typedef struct IGpgmeImpl IGpgmeImpl; +typedef struct IClassFactoryImpl IClassFactoryImpl; + +static HANDLE my_exit_event; + +struct IGpgmeImpl { + /* IUnknown required stuff */ + ICOM_VFIELD (IGpgme); + DWORD ref; + /* Delegation to IDispatch */ + struct { + IUnknown *disp; + ITypeInfo *tinfo; + } std_disp; + /* Our stuff */ + GpgmeCtx mainctx; + GpgmeData plaintext; + int plaintext_given_as_bstr; + GpgmeData ciphertext; + int ciphertext_is_armored; + GpgmeRecipients rset; +}; + + +struct IClassFactoryImpl { + /* IUnknown fields */ + ICOM_VFIELD(IClassFactory); + DWORD ref; +}; + +/********************************************************** + ************** helper functions ************************ + *********************************************************/ +static HRESULT +map_gpgme_error (GpgmeError err) +{ + HRESULT hr; + + if (!err) + return 0; + if ( err < 0 || err > 0x1000 ) { + fprintf (stderr,"*** GpgmeError `%s' mapped to GPGME_General_Error\n", + gpgme_strerror (err) ); + err = GPGME_General_Error; + } + hr = MAKE_HRESULT (SEVERITY_ERROR, FACILITY_ITF, 0x1000 + err); + fprintf (stderr,"*** GpgmeError `%s' mapped to %lx\n", + gpgme_strerror (err), (unsigned long)hr ); + return hr; +} + + +/********************************************************** + ************** IGpgme Implementation ******************* + *********************************************************/ + +static HRESULT WINAPI +m_IGpgme_QueryInterface (IGpgme *iface, REFIID refiid, LPVOID *obj) +{ + ICOM_THIS (IGpgmeImpl,iface); + + /*fprintf (stderr,"*** m_IGpgme_QueryInterface(%p,%s)", + This, debugstr_guid(refiid));*/ + if ( IsEqualGUID (&IID_IUnknown, refiid) + || IsEqualGUID (&IID_IGpgme, refiid) ) { + *obj = This; + IGpgme_AddRef (iface); + fprintf (stderr," -> got %p\n", *obj); + return 0; + } + else if ( IsEqualGUID (&IID_IDispatch, refiid) ) { + HRESULT hr = IDispatch_QueryInterface (This->std_disp.disp, + refiid, obj); + /*fprintf (stderr," -> delegated, hr=%lx, got %p\n", + hr, hr? NULL: *obj);*/ + return hr; + } + /*fprintf (stderr," -> none\n");*/ + *obj = NULL; + return E_NOINTERFACE; +} + + +static ULONG WINAPI +m_IGpgme_AddRef (IGpgme *iface) +{ + ICOM_THIS (IGpgmeImpl,iface); + + return ++This->ref; +} + + +static ULONG WINAPI +m_IGpgme_Release (IGpgme *iface) +{ + ICOM_THIS (IGpgmeImpl,iface); + + if (--This->ref) + return This->ref; + + gpgme_release (This->mainctx); This->mainctx = NULL; + gpgme_data_release (This->plaintext); This->plaintext = NULL; + gpgme_data_release (This->ciphertext); This->ciphertext = NULL; + gpgme_recipients_release (This->rset); This->rset = NULL; + if (This->std_disp.disp) + IDispatch_Release (This->std_disp.disp); + if (This->std_disp.tinfo) + ITypeInfo_Release (This->std_disp.tinfo); + HeapFree(GetProcessHeap(),0,iface); + { + ULONG count = CoReleaseServerProcess (); + if (!count && my_exit_event) + SetEvent (my_exit_event); + } + return 0; +} + + +static HRESULT WINAPI +m_stub_IDispatch_GetTypeInfoCount (IGpgme *iface, unsigned int *pctinfo) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI +m_stub_IDispatch_GetTypeInfo (IGpgme *iface, UINT iTInfo, + LCID lcid, ITypeInfo **ppTInfo) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI +m_stub_IDispatch_GetIDsOfNames (IGpgme *iface, REFIID riid, + LPOLESTR *rgszNames, UINT cNames, + LCID lcid, DISPID *rgDispId) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI +m_stub_IDispatch_Invoke (IGpgme *iface, DISPID dispIdMember, + REFIID riid, LCID lcid, WORD wFlags, + DISPPARAMS *pDispParams, VARIANT *pVarResult, + EXCEPINFO *pExepInfo, UINT *puArgErr) +{ + return E_NOTIMPL; +} + + + +static HRESULT WINAPI +m_IGpgme_GetVersion (IGpgme *iface, BSTR *retvat) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI +m_IGpgme_GetEngineInfo (IGpgme *iface, BSTR *retval) +{ + return E_NOTIMPL; +} + + +static HRESULT WINAPI +m_IGpgme_Cancel (IGpgme *iface) +{ + return E_NOTIMPL; +} + + +static HRESULT WINAPI +m_IGpgme_SetArmor (IGpgme *iface, BOOL yes) +{ + ICOM_THIS (IGpgmeImpl,iface); + + gpgme_set_armor (This->mainctx, yes); + return 0; +} + +static HRESULT WINAPI +m_IGpgme_GetArmor (IGpgme *iface, BOOL *retval) +{ + ICOM_THIS (IGpgmeImpl,iface); + + *retval = gpgme_get_armor (This->mainctx); + return 0; +} + + +static HRESULT WINAPI +m_IGpgme_SetTextmode (IGpgme *iface, BOOL yes) +{ + ICOM_THIS (IGpgmeImpl,iface); + + gpgme_set_textmode (This->mainctx, yes); + return 0; +} + +static HRESULT WINAPI +m_IGpgme_GetTextmode (IGpgme *iface, BOOL *retval) +{ + ICOM_THIS (IGpgmeImpl,iface); + + *retval = gpgme_get_textmode (This->mainctx); + return 0; +} + + +/* + * Put the data from VAL into a a Gpgme data object, which is passed by + * reference. Valid types of the Variant are: BSTR, SAFEARRAY of BYTE and + * SAFEARRAY of VARIANTS of signed or unsigned integers. + */ +static HRESULT WINAPI +set_data_from_variant (GpgmeData *data, VARIANT val, int *given_as_bstr) +{ + GpgmeError err = 0; + HRESULT hr; + unsigned char *buf; + SAFEARRAY *array; + size_t len; + int i; + + if ( val.vt == VT_BSTR) { + len = bstrtoutf8 (val.u.bstrVal, NULL, 0); + buf = _gpgme_malloc (len); + if (!buf) + return E_OUTOFMEMORY; + + if (bstrtoutf8 (val.u.bstrVal, buf, len) < 0) { + fprintf (stderr,"problem with bstrtoutf8\n"); + _gpgme_free (buf); + return E_FAIL; + } + + #if 0 + fprintf (stderr,"Got a BSTR (utf8):"); + for (i=0; i < len; i++) + fprintf (stderr, " %0X", buf[i] ); + putc ('\n', stderr); + #endif + gpgme_data_release (*data); *data = NULL; + err = gpgme_data_new_from_mem (data, buf, len, 0 /*no need to copy*/ ); + if (!err && given_as_bstr) + *given_as_bstr = 1; + } + else if ( val.vt == (VT_ARRAY|VT_UI1)) { + array = val.u.parray; + + /*fprintf (stderr,"Got an ARRAY of bytes:");*/ + hr = SafeArrayAccessData (array, (void**)&buf); + if (hr) { + fprintf (stderr,"*** SafeArrayAccessData failed: hr=%lx\n", hr); + return hr; + } + len = array->rgsabound[0].cElements; + /*for (i=0; i < len; i++) + fprintf (stderr, " %0X", buf[i] ); + putc ('\n', stderr);*/ + + gpgme_data_release (*data); *data = NULL; + err = gpgme_data_new_from_mem (data, buf, len, 1 ); + SafeArrayUnaccessData (array); + if (given_as_bstr) + *given_as_bstr = 0; + } + else if ( val.vt == (VT_ARRAY|VT_VARIANT)) { + VARIANT *vp; + array = val.u.parray; + + /*fprintf (stderr,"Got an ARRAY of VARIANTS:");*/ + hr = SafeArrayAccessData (array, (void**)&vp); + if (hr) { + fprintf (stderr,"*** SafeArrayAccessData failed: hr=%lx\n", hr); + return hr; + } + len = array->rgsabound[0].cElements; + /* allocate the array using the gpgme allocator so that we can + * later use a new without the copy set*/ + buf = _gpgme_malloc (len); + if (!buf) { + SafeArrayUnaccessData (array); + return E_OUTOFMEMORY; + } + /* coerce all array elements into rawtext */ + for (i=0; i < len; i++) { + switch (vp[i].vt) { + case VT_I1: buf[i] = (BYTE)vp[i].u.cVal; break; + case VT_I2: buf[i] = ((UINT)vp[i].u.iVal) & 0xff; break; + case VT_I4: buf[i] = ((ULONG)vp[i].u.lVal) & 0xff; break; + case VT_INT: buf[i] = ((UINT)vp[i].u.intVal) & 0xff; break; + case VT_UI1: buf[i] = vp[i].u.bVal; break; + case VT_UI2: buf[i] = vp[i].u.uiVal & 0xff; break; + case VT_UI4: buf[i] = vp[i].u.ulVal & 0xff; break; + case VT_UINT: buf[i] = vp[i].u.uintVal & 0xff; break; + default: + fprintf (stderr, "Invalid value in array as pos %d\n", i); + _gpgme_free (buf); + SafeArrayUnaccessData (array); + return E_INVALIDARG; + } + } + + /*for (i=0; i < len; i++) + fprintf (stderr, " %0X", buf[i] ); + putc ('\n', stderr);*/ + + gpgme_data_release (*data); *data = NULL; + err = gpgme_data_new_from_mem (data, buf, len, 0); + SafeArrayUnaccessData (array); + if (given_as_bstr) + *given_as_bstr = 0; + } + else { + fprintf (stderr, "Got a variant type = %d (0x%x)\n", + (int)val.vt, (int)val.vt ); + return E_INVALIDARG; /* not a safearray of bytes */ + } + return map_gpgme_error (err); +} + + +static HRESULT WINAPI +set_data_to_variant (GpgmeData data, VARIANT *retval, int use_bstr) +{ + GpgmeError err; + HRESULT hr; + SAFEARRAY *array; + char *p; + size_t nread, len; + int i; + + /* Get some info on the data */ + err = gpgme_data_rewind (data); + if (err ) { + fprintf (stderr, "*** gpgme_data_rewind failed: %d\n", err); + return map_gpgme_error (err); + } + err = gpgme_data_read (data, NULL, 0, &nread); + if (err && err != GPGME_EOF ) { + fprintf (stderr, "*** gpgme_data_read [length] failed: %d\n", err); + return map_gpgme_error (err); + } + len = nread; /*(eof returns a length of 0)*/ + /*fprintf (stderr,"*** %d bytes are availabe\n", (int)len);*/ + + /* convert it to the target data type */ + if (use_bstr) { + BSTR bs; + unsigned char *helpbuf; + + /* It is easier to allocate some helper storage */ + helpbuf = _gpgme_malloc (len); + if (!helpbuf) + return E_OUTOFMEMORY; + err = gpgme_data_read (data, helpbuf, len, &nread); + if (err ) { + _gpgme_free (helpbuf); + fprintf (stderr, "*** gpgme_data_read [data] failed: %d\n", err); + return map_gpgme_error (err); + } + + bs = SysAllocStringLen (NULL, len+1); + if (!bs) { + _gpgme_free (helpbuf); + return E_OUTOFMEMORY; + } + + for (i=0, p=helpbuf; i < len; i++, p++) + bs[i] = *p; + bs[i] = 0; + _gpgme_free (helpbuf); + + /* Ready */ + VariantInit (retval); + retval->vt = VT_BSTR; + retval->u.bstrVal = bs; + } +#if 0 + else if (use_byte_array) { + array = SafeArrayCreateVector (VT_UI1, 0, len); + if (!array) + return E_OUTOFMEMORY; + + p = NULL; + hr = SafeArrayAccessData (array, (void**)&p); + if (hr) { + fprintf (stderr,"*** SafeArrayAccessData failed: hr=%lx\n", hr); + SafeArrayDestroyData (array); + SafeArrayDestroy (array); + return hr; + } + if (len) { + err = gpgme_data_read (data, p, len, &nread); + if (err ) { + SafeArrayUnaccessData (array); + SafeArrayDestroyData (array); + SafeArrayDestroy (array); + fprintf (stderr, "*** gpgme_data_read [data] failed: %d\n", + err); + return map_gpgme_error (err); + } + } + SafeArrayUnaccessData (array); + + /* pass the data to the caller */ + VariantInit (retval); + retval->vt = (VT_ARRAY|VT_UI1); + retval->u.parray = array; + } +#endif + else { /* Create an array of variants of bytes */ + VARIANT *v; + unsigned char *helpbuf; + + /* It is easier to allocate some helper storage */ + helpbuf = _gpgme_malloc (len); + if (!helpbuf) + return E_OUTOFMEMORY; + err = gpgme_data_read (data, helpbuf, len, &nread); + if (err ) { + _gpgme_free (helpbuf); + fprintf (stderr, "*** gpgme_data_read [data] failed: %d\n", err); + return map_gpgme_error (err); + } + + /* The create the array */ + array = SafeArrayCreateVector (VT_VARIANT, 0, len); + if (!array) { + _gpgme_free (helpbuf); + return E_OUTOFMEMORY; + } + + v = NULL; + hr = SafeArrayAccessData (array, (void**)&v); + if (hr) { + fprintf (stderr,"*** SafeArrayAccessData failed: hr=%lx\n", hr); + _gpgme_free (helpbuf); + SafeArrayDestroyData (array); + SafeArrayDestroy (array); + return hr; + } + + for (p=helpbuf; len; len--, v++) { + VariantInit (v); + v->vt = VT_UI1; + v->u.bVal = *p; + } + SafeArrayUnaccessData (array); + _gpgme_free (helpbuf); + + /* pass the data to the caller */ + VariantInit (retval); + retval->vt = (VT_ARRAY|VT_VARIANT); + retval->u.parray = array; + } + return 0; +} + + +static HRESULT WINAPI +m_IGpgme_SetPlaintext (IGpgme *iface, VARIANT val) +{ + ICOM_THIS (IGpgmeImpl,iface); + + return set_data_from_variant (&This->plaintext, val, + &This->plaintext_given_as_bstr); +} + + +static HRESULT WINAPI +m_IGpgme_GetPlaintext (IGpgme *iface, VARIANT *retval) +{ + ICOM_THIS (IGpgmeImpl,iface); + + /*fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p)\n", This );*/ + return set_data_to_variant (This->plaintext, retval, + This->plaintext_given_as_bstr); +} + +static HRESULT WINAPI +m_IGpgme_SetCiphertext (IGpgme *iface, VARIANT val) +{ + ICOM_THIS (IGpgmeImpl,iface); + + return set_data_from_variant (&This->ciphertext, val, NULL); +} + +static HRESULT WINAPI +m_IGpgme_GetCiphertext (IGpgme *iface, VARIANT *retval) +{ + ICOM_THIS (IGpgmeImpl,iface); + + return set_data_to_variant (This->ciphertext, retval, + This->ciphertext_is_armored); +} + +static HRESULT WINAPI +m_IGpgme_ClearRecipients (IGpgme *iface) +{ + ICOM_THIS (IGpgmeImpl,iface); + + gpgme_recipients_release (This->rset); This->rset = NULL; + return 0; +} + + +static HRESULT WINAPI +m_IGpgme_AddRecipient (IGpgme *iface, BSTR name, signed short int trust) +{ + GpgmeError err; + int n; + char *p; + ICOM_THIS (IGpgmeImpl,iface); + + /*fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p, %d)\n", + This, (int)trust);*/ + if (!This->rset) { + err = gpgme_recipients_new (&This->rset); + if (err) + return map_gpgme_error (err); + } + + n = bstrtoutf8 (name, NULL, 0); + p = HeapAlloc (GetProcessHeap(), 0, n ); + if (!p) { + fprintf (stderr,"HeapAlloc failed: ec=%d\n", (int)GetLastError () ); + return E_OUTOFMEMORY; + } + if (bstrtoutf8 (name, p, n) < 0) { + fprintf (stderr,"problem with bstrtoutf8\n"); + HeapFree (GetProcessHeap(), 0, p); + return E_FAIL; + } + err = gpgme_recipients_add_name (This->rset, p); + HeapFree (GetProcessHeap(), 0, p); + return map_gpgme_error (err); +} + +static HRESULT WINAPI +m_IGpgme_ResetSignKeys (IGpgme *iface) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI +m_IGpgme_AddSignKey (IGpgme *iface, BSTR name) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI +m_IGpgme_Encrypt (IGpgme *iface) +{ + GpgmeError err; + ICOM_THIS (IGpgmeImpl,iface); + + gpgme_data_release (This->ciphertext); + err = gpgme_data_new (&This->ciphertext); + if (err) + return map_gpgme_error (err); + + + This->ciphertext_is_armored = gpgme_get_armor (This->mainctx); + err = gpgme_op_encrypt (This->mainctx, This->rset, + This->plaintext, This->ciphertext); +#if 0 + if (!err ) { + char buf[100]; + size_t nread; + + err = gpgme_data_rewind ( This->ciphertext ); + if (err ) + fprintf (stderr, "*** gpgme_data_rewind failed: %d\n", err); + while ( !(err = gpgme_data_read ( This->ciphertext, + buf, 100, &nread )) ) { + fwrite ( buf, nread, 1, stderr ); + } + if (err != GPGME_EOF) + fprintf (stderr, "*** gpgme_data_read failed: %d\n", err); + err = 0; + } +#endif + + return map_gpgme_error (err); +} + +static HRESULT WINAPI +m_IGpgme_Sign (IGpgme *iface, short int signmode) +{ + ICOM_THIS (IGpgmeImpl,iface); + + fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p)\n", This ); + + return E_NOTIMPL; +} + +static HRESULT WINAPI +m_IGpgme_SignEncrypt (IGpgme *iface, short int signmode) +{ + ICOM_THIS (IGpgmeImpl,iface); + + fprintf (stderr,"*** " __PRETTY_FUNCTION__ "(%p)\n", This ); + + return E_NOTIMPL; +} + +#if 0 +static HRESULT WINAPI +m_IGpgme_GetSigStatus(GpgmeCtx c, int idx, + GpgmeSigStat *r_stat, time_t *r_created ); +{ + return 0; +} + + +static HRESULT WINAPI +m_IGpgme_GetSigKey (GpgmeCtx c, int idx, GpgmeKey *r_key); +{ + return 0; +} + +static HRESULT WINAPI +m_IGpgme_GetNotation(IGpgme *c, BSTR *retval) +{ + return 0; +} +#endif + + +static ICOM_VTABLE(IGpgme) igpgme_vtbl = +{ + /* IUnknown methods */ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + m_IGpgme_QueryInterface, + m_IGpgme_AddRef, + m_IGpgme_Release, + /* IDispatch methods */ + m_stub_IDispatch_GetTypeInfoCount, + m_stub_IDispatch_GetTypeInfo, + m_stub_IDispatch_GetIDsOfNames, + m_stub_IDispatch_Invoke, + /* Our methods */ + m_IGpgme_GetVersion, + m_IGpgme_GetEngineInfo, + m_IGpgme_Cancel, + m_IGpgme_SetArmor, + m_IGpgme_GetArmor, + m_IGpgme_SetTextmode, + m_IGpgme_GetTextmode, + m_IGpgme_SetPlaintext, + m_IGpgme_GetPlaintext, + m_IGpgme_SetCiphertext, + m_IGpgme_GetCiphertext, + m_IGpgme_ClearRecipients, + m_IGpgme_AddRecipient, + m_IGpgme_ResetSignKeys, + m_IGpgme_AddSignKey, + m_IGpgme_Encrypt, + m_IGpgme_Sign, + m_IGpgme_SignEncrypt +}; + + + +/*************************************************************** + ****************** Gpgme Factory **************************** + ***************************************************************/ + +static HRESULT WINAPI +m_GpgmeFactory_QueryInterface (IClassFactory *iface, + REFIID refiid, LPVOID *obj) +{ + ICOM_THIS (IClassFactoryImpl,iface); + + /*fprintf (stderr,"*** m_GpgmeFactory_QueryInterface(%p,%s)", + This, debugstr_guid(refiid));*/ + if ( IsEqualGUID (&IID_IUnknown, refiid) + || IsEqualGUID (&IID_IClassFactory, refiid) ) { + *obj = This; + /*fprintf (stderr," -> got %p\n", obj);*/ + return 0; + } + *obj = NULL; + /*fprintf (stderr," -> none\n");*/ + return E_NOINTERFACE; +} + +static ULONG WINAPI +m_GpgmeFactory_AddRef (IClassFactory *iface) +{ + ICOM_THIS(IClassFactoryImpl,iface); + return ++(This->ref); +} + +static ULONG WINAPI +m_GpgmeFactory_Release (IClassFactory *iface) +{ + ICOM_THIS(IClassFactoryImpl,iface); + return --(This->ref); +} + +static HRESULT WINAPI +m_GpgmeFactory_CreateInstance (IClassFactory *iface, IUnknown *outer, + REFIID refiid, LPVOID *r_obj ) +{ + /*ICOM_THIS(IClassFactoryImpl,iface);*/ + + fprintf (stderr,"*** m_GpgmeFactory_CreateInstance(%s)", + debugstr_guid(refiid) ); + if ( IsEqualGUID (&IID_IUnknown, refiid) + || IsEqualGUID (&IID_IGpgme, refiid) ) { + IGpgmeImpl *obj; + GpgmeCtx ctx; + GpgmeError err; + + + err = gpgme_new (&ctx); + if (err) { + fprintf (stderr," -> gpgme_new failed: %s\n", gpgme_strerror (err)); + return E_OUTOFMEMORY; + } + + obj = HeapAlloc (GetProcessHeap(), 0, sizeof *obj ); + if ( !obj) { + fprintf (stderr," -> out of core\n"); + gpgme_release (ctx); + return E_OUTOFMEMORY; + } + memset (obj, 0, sizeof *obj); + + ICOM_VTBL(obj) = &igpgme_vtbl; + obj->ref = 1; + obj->mainctx = ctx; + { /* Fixme: need to release some stuff on error */ + HRESULT hr; + ITypeLib *pTypeLib; + + hr = LoadRegTypeLib (&TLBID_Gpgcom, 1, 0, LANG_NEUTRAL, &pTypeLib); + if (hr) { + fprintf (stderr," -> LoadRegTypeLib failed: %lx\n", hr); + return hr; + } + hr = ITypeLib_GetTypeInfoOfGuid (pTypeLib, &IID_IGpgme, + &obj->std_disp.tinfo); + ITypeLib_Release (pTypeLib); + if (hr) { + fprintf (stderr," -> GetTypeInfoOfGuid failed: %lx\n", hr); + return hr; + } + hr = CreateStdDispatch ((IUnknown*)obj, obj, obj->std_disp.tinfo, + &obj->std_disp.disp); + if (hr) { + fprintf (stderr," -> CreateStdDispatch failed: %lx\n", hr); + return hr; + } + } + + CoAddRefServerProcess (); + *r_obj = obj; + fprintf (stderr," -> created %p\n", obj ); + return 0; + } + fprintf (stderr," -> no interface\n" ); + *r_obj = NULL; + return E_NOINTERFACE; +} + +static HRESULT WINAPI +m_GpgmeFactory_LockServer (IClassFactory *iface, BOOL dolock ) +{ + if (dolock) { + CoAddRefServerProcess (); + } + else { + ULONG count = CoReleaseServerProcess (); + if (!count && my_exit_event) + SetEvent (my_exit_event); + } + return 0; +} + +static ICOM_VTABLE(IClassFactory) igpgme_factory_vtbl = { + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + m_GpgmeFactory_QueryInterface, + m_GpgmeFactory_AddRef, + m_GpgmeFactory_Release, + m_GpgmeFactory_CreateInstance, + m_GpgmeFactory_LockServer +}; +static IClassFactoryImpl igpgme_CF = {&igpgme_factory_vtbl, 1 }; + +void +igpgme_register_exit_event (HANDLE ev) +{ + my_exit_event = ev; +} + + +IClassFactory * +igpgme_factory_new ( CLSID *r_clsid ) +{ + *r_clsid = CLSID_Gpgme; + IClassFactory_AddRef((IClassFactory*)&igpgme_CF); + return (IClassFactory*)&igpgme_CF; +} + +void +igpgme_factory_release ( IClassFactory *factory ) +{ + /* it's static - nothing to do */ +} diff --git a/tags/gpgme-1.1.6/complus/igpgme.h b/tags/gpgme-1.1.6/complus/igpgme.h new file mode 100644 index 0000000..fa96762 --- /dev/null +++ b/tags/gpgme-1.1.6/complus/igpgme.h @@ -0,0 +1,163 @@ +/* igpgme.h - COM+ class IGpgme + * Copyright (C) 2001 g10 Code GmbH + * + * 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 IGPGME_H +#define IGPGME_H 1 + +#include + +DEFINE_GUID(CLSID_Gpgme, 0x3811fd40, 0x7f72, 0x11d5, + 0x8c, 0x9e, 0x00, 0x80, 0xad, 0x19, 0x0c, 0xd5); +#if 0 +DEFINE_GUID(CLSID_GpgmeData, 0x3811fd41, 0x7f72, 0x11d5, + 0x8c, 0x9e, 0x00, 0x80, 0xad, 0x19, 0x0c, 0xd5); +DEFINE_GUID(CLSID_GpgmeKey, 0x3811fd42, 0x7f72, 0x11d5, + 0x8c, 0x9e, 0x00, 0x80, 0xad, 0x19, 0x0c, 0xd5); +DEFINE_GUID(CLSID_GpgmeRSet, 0x3811fd43, 0x7f72, 0x11d5, + 0x8c, 0x9e, 0x00, 0x80, 0xad, 0x19, 0x0c, 0xd5); +#endif + +DEFINE_GUID(TLBID_Gpgcom, 0x3811fd48, 0x7f72, 0x11d5, + 0x8c, 0x9e, 0x00, 0x80, 0xad, 0x19, 0x0c, 0xd5); +DEFINE_GUID(APPID_Gpgcom, 0x3811fd4f, 0x7f72, 0x11d5, + 0x8c, 0x9e, 0x00, 0x80, 0xad, 0x19, 0x0c, 0xd5); + + +DEFINE_GUID(IID_IGpgme, 0x3811fd50, 0x7f72, 0x11d5, + 0x8c, 0x9e, 0x00, 0x80, 0xad, 0x19, 0x0c, 0xd5); + +typedef struct IGpgme IGpgme; + +void igpgme_register_exit_event (HANDLE ev); +IClassFactory *igpgme_factory_new( CLSID *r_clsid ); +void igpgme_factory_release ( IClassFactory *factory ); + + +/******************************************** + ***** The IGpgme interface ***************** + ********************************************/ + +#define ICOM_INTERFACE IGpgme + +#define IGpgme_METHODS \ + ICOM_METHOD1(HRESULT,GetVersion, BSTR*,) \ + ICOM_METHOD1(HRESULT,GetEngineInfo, BSTR*,) \ + ICOM_METHOD(HRESULT,Cancel) \ + ICOM_METHOD1(HRESULT,SetArmor,BOOL,) \ + ICOM_METHOD1(HRESULT,GetArmor,BOOL*,) \ + ICOM_METHOD1(HRESULT,SetTextmode,BOOL,) \ + ICOM_METHOD1(HRESULT,GetTextmode,BOOL*,) \ + ICOM_METHOD1(HRESULT,SetPlaintext,VARIANT,) \ + ICOM_METHOD1(HRESULT,GetPlaintext,VARIANT*,) \ + ICOM_METHOD1(HRESULT,SetCiphertext,VARIANT,) \ + ICOM_METHOD1(HRESULT,GetCiphertext,VARIANT*,) \ + ICOM_METHOD(HRESULT,ClearRecipients) \ + ICOM_METHOD2(HRESULT,AddRecipient,BSTR,,signed short int,) \ + ICOM_METHOD(HRESULT,ResetSignKeys) \ + ICOM_METHOD1(HRESULT,AddSignKey,BSTR,) \ + ICOM_METHOD(HRESULT,Encrypt) \ + ICOM_METHOD1(HRESULT,Sign,signed short int,) \ + ICOM_METHOD1(HRESULT,SignEncrypt,signed short int,) + +#if 0 + ICOM_METHOD1(HRESULT,SetKeylistMode,) + ICOM_METHOD1(HRESULT,SetPassphraseCB,) + ICOM_METHOD1(HRESULT,SetProgressCB,) + ICOM_METHOD1(HRESULT,SignersClear,) + ICOM_METHOD1(HRESULT,SignersAdd,) + ICOM_METHOD1(HRESULT,SignersEnum,) + ICOM_METHOD1(HRESULT,GetSigStatus,) + ICOM_METHOD1(HRESULT,GetNotation,) +#endif + +#define IGpgme_IMETHODS \ + IDispatch_IMETHODS \ + IGpgme_METHODS + +ICOM_DEFINE(IGpgme,IDispatch) +#undef ICOM_INTERFACE + + +/*** IUnknown methods ***/ +#define IGpgme_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IGpgme_AddRef(p) ICOM_CALL (AddRef,p) +#define IGpgme_Release(p) ICOM_CALL (Release,p) +/*** IGpgme methods ***/ +#define IGpgme_GetVersion(p,r) ICOM_CALL1(GetVersion,p,r) +#define IGpgme_GetEngineInfo(p,r) ICOM_CALL1(GetEngineInfo,p,r) +#define IGpgme_Cancel(p,a) ICOM_CALL1(Cancel,p,a) +#define IGpgme_SetArmor(p,a) ICOM_CALL1(SetArmor,p,a) +#define IGpgme_GetArmor(p,a) ICOM_CALL1(GetArmor,p,a) +#define IGpgme_SetTextmode(p,a) ICOM_CALL1(SetTextmode,p,a) +#define IGpgme_GetTextmode(p,a) ICOM_CALL1(GetTextmode,p,a) +#define IGpgme_SetPlaintext(p,a) ICOM_CALL1(SetPlaintext,p,a) +#define IGpgme_GetPlaintext(p,a) ICOM_CALL1(GetPlaintext,p,a) +#define IGpgme_SetCiphertext(p,a) ICOM_CALL1(SetCiphertext,p,a) +#define IGpgme_GetCiphertext(p,a) ICOM_CALL1(GetCiphertext,p,a) +#define IGpgme_ClearRecipients(p) ICOM_CALL (ClearRecipients,p) +#define IGpgme_AddRecipient(p,a,b) ICOM_CALL2(AddRecipient,p,a,b) +#define IGpgme_ResetSignKeys(p) ICOM_CALL (ResetSignKeys,p) +#define IGpgme_AddSignKey(p,a) ICOM_CALL (AddSignKey,p,a) +#define IGpgme_Encrypt(p) ICOM_CALL (Encrypt,p) +#define IGpgme_Sign(p,a) ICOM_CALL (Sign,p,a) +#define IGpgme_SignEncrypt(p,a) ICOM_CALL (SignEncrypt,p,a) +#if 0 +#define IGpgme_SetKeylistMode(p,a) ICOM_CALL1(SetKeylistMode,p,a) +#define IGpgme_SetPassphraseCB(p,a) ICOM_CALL1(SetPassphraseCB,p,a) +#define IGpgme_SetProgressCB(p,a) ICOM_CALL1(SetProgressCB,p,a) +#define IGpgme_SignersClear(p,a) ICOM_CALL1(SignersClear,p,a) +#define IGpgme_SignersAdd(p,a) ICOM_CALL1(SignersAdd,p,a) +#define IGpgme_SignersEnum(p,a) ICOM_CALL1(SignersEnum,p,a) +#define IGpgme_GetSigStatus(p,a) ICOM_CALL1(GetSigStatus,p,a) +#define IGpgme_GetSigKey(p,a) ICOM_CALL1(GetSigKey,p,a) +#define IGpgme_GetNotation(p,a) ICOM_CALL1(GetNotation,p,a) +#endif + + +#if 0 +/******************************************** + ***** The IGpgmeKey interface ************** + ********************************************/ + +#define ICOM_INTERFACE IGpgmeKey + +#define IGpgmeKey_METHODS \ + ICOM_METHOD1(HRESULT,GetVersion, BSTR,) \ + ICOM_METHOD1(HRESULT,GetEngineInfo, BSTR,) + + +#define IGpgmeKey_IMETHODS \ + IUnknown_IMETHODS \ + IGpgmeKey_METHODS + +ICOM_DEFINE(IGpgmeKey,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IGpgmeKey_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IGpgmeKey_AddRef(p) ICOM_CALL (AddRef,p) +#define IGpgmeKey_Release(p) ICOM_CALL (Release,p) +/*** IGpgmeKey methods ***/ +#define IGpgmeKey_GetVersion(p,r) ICOM_CALL1(GetVersion,p,r) +#define IGpgmeKey_GetEngineInfo(p,r) ICOM_CALL1(GetEngineInfo,p,r) +#endif + +#endif /*IGPGME_H*/ + diff --git a/tags/gpgme-1.1.6/complus/main.h b/tags/gpgme-1.1.6/complus/main.h new file mode 100644 index 0000000..7e48ad4 --- /dev/null +++ b/tags/gpgme-1.1.6/complus/main.h @@ -0,0 +1,49 @@ +/* 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; + + + +#endif /* COMPLUS_MAIN_H */ + + + + + + + diff --git a/tags/gpgme-1.1.6/complus/regtlb.c b/tags/gpgme-1.1.6/complus/regtlb.c new file mode 100644 index 0000000..4ea1342 --- /dev/null +++ b/tags/gpgme-1.1.6/complus/regtlb.c @@ -0,0 +1,70 @@ +/* regtlb.c - Register a type library + * Copyright (C) 2001 g10 Code GmbH + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include "xmalloc.h" +#include "oleauto.h" + +int +main (int argc, char **argv) +{ + ITypeLib *pTypeLib; + wchar_t *fname; + HRESULT hr; + size_t n; + + if ( argc != 2 ) { + fprintf (stderr,"usage: regtlb foo.tlb\n"); + return 1; + } + + n = mbstowcs (NULL, argv[1], strlen(argv[1])+1); + fprintf (stderr, "need %d bytes\n", (int)n); + fname = xmalloc ((n+1)*sizeof *fname); + mbstowcs (fname, argv[1], strlen (argv[1])+1); + + hr = CoInitializeEx (NULL, COINIT_MULTITHREADED); + if (hr) + fprintf (stderr, "CoInitializeEx() failed: hr=%lu\n", hr); + + hr = LoadTypeLibEx (fname, REGKIND_REGISTER, &pTypeLib); + if (hr) + fprintf (stderr, "LoadTypeLibEx() failed: hr=%lx\n", hr); + + ITypeLib_Release (pTypeLib); + + CoUninitialize (); + return 0; +} + + + + + + diff --git a/tags/gpgme-1.1.6/complus/tgpgcom.c b/tags/gpgme-1.1.6/complus/tgpgcom.c new file mode 100644 index 0000000..27516b1 --- /dev/null +++ b/tags/gpgme-1.1.6/complus/tgpgcom.c @@ -0,0 +1,157 @@ +/* tgpgcom.c - Test the IGpgme classes + * Copyright (C) 2001 g10 Code GmbH + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#define INITGUID +#include "igpgme.h" + + +int +main (int argc, char **argv) +{ + IUnknown *pUnknown = NULL; + IGpgme *pGpgme; + HRESULT hr; + BSTR bs; + + hr = CoInitializeEx (NULL, COINIT_APARTMENTTHREADED); + if (hr) + fprintf (stderr, "CoInitializeEx() failed: hr=%lu\n", hr); + + fprintf (stderr, "system initialized\n"); + hr = CoCreateInstance (&CLSID_Gpgme, NULL, CLSCTX_LOCAL_SERVER, + &IID_IUnknown, (void**)&pUnknown ); + if (hr) + fprintf (stderr, "CoCreateInstance() failed: hr=%lx\n", hr); + if (!pUnknown) + exit (1); + + fprintf (stderr,"got object %p - querying %s\n", + pUnknown, debugstr_guid(&IID_IGpgme)); + hr = IGpgme_QueryInterface (pUnknown, &IID_IGpgme, (void**)&pGpgme); + if (hr) { + fprintf (stderr, "QueryInterface() failed: hr=%lx\n", hr); + goto leave; + } + fprintf (stderr, "got interface %p\n", pGpgme); + + hr = IGpgme_SetArmor (pGpgme, 1); + fprintf (stderr, "SetArmor returned %lx\n", hr); + + hr = IGpgme_SetTextmode (pGpgme, 0); + fprintf (stderr, "SetTextmode returned %lx\n", hr); + + hr = IGpgme_ClearRecipients (pGpgme); + fprintf (stderr, "ClearRecipients returned %lx\n", hr); + + bs = SysAllocString (L"alice"); + if (!bs) + fprintf (stderr, "SysAllocString failed: ec=%d\n", (int)GetLastError()); + else { + int i; + + for (i=-4; i < 12; i++ ) + fprintf (stderr," %02X", ((unsigned char*)bs)[i] ); + putc ('\n', stderr); + } + hr = IGpgme_AddRecipient (pGpgme, bs, -1); + fprintf (stderr, "AddRecipients returned %lx\n", hr); + + { + SAFEARRAY *sa; + VARIANT v; + char *p; + + sa = SafeArrayCreateVector (VT_UI1, 0, 20); + if (!sa) { + fprintf (stderr, "SafeArrayCreateVector failed\n"); + goto leave; + } + + hr = SafeArrayAccessData (sa, (void**)&p); + if (hr) { + fprintf (stderr,"SafeArrayAccessData failed: hr=%lx\n", hr); + goto leave; + } + + memcpy (p, "=> Omnis enim res <=", 20 ); + SafeArrayUnaccessData (sa); + + VariantInit (&v); + v.vt = (VT_ARRAY|VT_UI1); + v.u.parray = sa; + + hr = IGpgme_SetPlaintext (pGpgme, v ); + fprintf (stderr, "SetPlaintext returned %lx\n", hr); + SafeArrayDestroyData (sa); + SafeArrayDestroy (sa); + + VariantClear (&v); + } + + hr = IGpgme_Encrypt (pGpgme); + fprintf (stderr, "Encrypt returned %lx\n", hr); + + { + VARIANT v; + + hr = IGpgme_GetCiphertext (pGpgme, &v); + fprintf (stderr, "GetCiphertext returned %lx\n", hr); + if (!hr) { + if (v.vt != (VT_ARRAY|VT_UI1)) + fprintf (stderr, "Invalid array typed returned\n"); + else { + unsigned char *p; + + hr = SafeArrayAccessData (v.u.parray, (void**)&p); + if (hr) + fprintf (stderr,"*** SafeArrayAccessData failed: %lx\n", hr); + else { + size_t arraysize = v.u.parray->rgsabound[0].cElements; + fprintf (stderr,"*** got %d bytes\n", (int)arraysize); + for (;arraysize; arraysize--, p++ ) + putc (*p, stderr); + SafeArrayUnaccessData (v.u.parray); + } + } + } + } + IGpgme_Release (pGpgme); + + leave: + CoUninitialize (); + fprintf (stderr, "system uninitialized\n"); + return 0; +} + + + + + + diff --git a/tags/gpgme-1.1.6/complus/utf8.c b/tags/gpgme-1.1.6/complus/utf8.c new file mode 100644 index 0000000..0237a62 --- /dev/null +++ b/tags/gpgme-1.1.6/complus/utf8.c @@ -0,0 +1,236 @@ +/* + * UTF-8 support routines + * + * Copyright 2000 Alexandre Julliard + * + * Taken from WINE, so the usual WINE copyright applies: +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. + */ + +#include +#include +#include +#include + +#include + +/* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */ +static const char utf8_length[128] = +{ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */ + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */ + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */ + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */ + 3,3,3,3,3,3,3,3,4,4,4,4,5,5,0,0 /* 0xf0-0xff */ +}; + +/* first byte mask depending on UTF-8 sequence length */ +static const unsigned char utf8_mask[6] = { 0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01 }; + +/* minimum Unicode value depending on UTF-8 sequence length */ +static const unsigned int utf8_minval[6] = { 0x0, 0x80, 0x800, 0x10000, 0x200000, 0x4000000 }; + + +/* query necessary dst length for src string */ +inline static int get_length_wcs_utf8( const WCHAR *src, unsigned int srclen ) +{ + int len; + + for (len = 0; srclen; srclen--, src++, len++) + { + if (*src >= 0x80) + { + len++; + if (*src >= 0x800) len++; + } + } + return len; +} + +/* wide char to UTF-8 string conversion */ +/* return -1 on dst buffer overflow */ +int utf8_wcstombs( const WCHAR *src, int srclen, char *dst, int dstlen ) +{ + char *orig_dst = dst; + + if (!dstlen) return get_length_wcs_utf8( src, srclen ); + + for (; srclen; srclen--, src++) + { + WCHAR ch = *src; + + if (ch < 0x80) /* 0x00-0x7f: 1 byte */ + { + if (!dstlen--) return -1; /* overflow */ + *dst++ = ch; + continue; + } + + if (ch < 0x800) /* 0x80-0x7ff: 2 bytes */ + { + if ((dstlen -= 2) < 0) return -1; /* overflow */ + dst[1] = 0x80 | (ch & 0x3f); + ch >>= 6; + dst[0] = 0xc0 | ch; + dst += 2; + continue; + } + + /* 0x800-0xffff: 3 bytes */ + + if ((dstlen -= 3) < 0) return -1; /* overflow */ + dst[2] = 0x80 | (ch & 0x3f); + ch >>= 6; + dst[1] = 0x80 | (ch & 0x3f); + ch >>= 6; + dst[0] = 0xe0 | ch; + dst += 3; + } + return dst - orig_dst; +} + +/* query necessary dst length for src string */ +inline static int get_length_mbs_utf8( const unsigned char *src, int srclen ) +{ + int ret; + const unsigned char *srcend = src + srclen; + + for (ret = 0; src < srcend; ret++) + { + unsigned char ch = *src++; + if (ch < 0xc0) continue; + + switch(utf8_length[ch-0x80]) + { + case 5: + if (src >= srcend) return ret; /* ignore partial char */ + if ((ch = *src ^ 0x80) >= 0x40) continue; + src++; + case 4: + if (src >= srcend) return ret; /* ignore partial char */ + if ((ch = *src ^ 0x80) >= 0x40) continue; + src++; + case 3: + if (src >= srcend) return ret; /* ignore partial char */ + if ((ch = *src ^ 0x80) >= 0x40) continue; + src++; + case 2: + if (src >= srcend) return ret; /* ignore partial char */ + if ((ch = *src ^ 0x80) >= 0x40) continue; + src++; + case 1: + if (src >= srcend) return ret; /* ignore partial char */ + if ((ch = *src ^ 0x80) >= 0x40) continue; + src++; + } + } + return ret; +} + +/* UTF-8 to wide char string conversion */ +/* return -1 on dst buffer overflow, -2 on invalid input char */ +int utf8_mbstowcs( int flags, const char *src, int srclen, WCHAR *dst, int dstlen ) +{ + int len, count; + unsigned int res; + const char *srcend = src + srclen; + + if (!dstlen) return get_length_mbs_utf8( src, srclen ); + + for (count = dstlen; count && (src < srcend); count--, dst++) + { + unsigned char ch = *src++; + if (ch < 0x80) /* special fast case for 7-bit ASCII */ + { + *dst = ch; + continue; + } + len = utf8_length[ch-0x80]; + res = ch & utf8_mask[len]; + + switch(len) + { + case 5: + if (src >= srcend) goto done; /* ignore partial char */ + if ((ch = *src ^ 0x80) >= 0x40) goto bad; + res = (res << 6) | ch; + src++; + case 4: + if (src >= srcend) goto done; /* ignore partial char */ + if ((ch = *src ^ 0x80) >= 0x40) goto bad; + res = (res << 6) | ch; + src++; + case 3: + if (src >= srcend) goto done; /* ignore partial char */ + if ((ch = *src ^ 0x80) >= 0x40) goto bad; + res = (res << 6) | ch; + src++; + case 2: + if (src >= srcend) goto done; /* ignore partial char */ + if ((ch = *src ^ 0x80) >= 0x40) goto bad; + res = (res << 6) | ch; + src++; + case 1: + if (src >= srcend) goto done; /* ignore partial char */ + if ((ch = *src ^ 0x80) >= 0x40) goto bad; + res = (res << 6) | ch; + src++; + if (res < utf8_minval[len]) goto bad; + if (res >= 0x10000) goto bad; /* FIXME: maybe we should do surrogates here */ + *dst = res; + continue; + } + bad: + if (flags & MB_ERR_INVALID_CHARS) return -2; /* bad char */ + *dst = (WCHAR)'?'; + } + if (src < srcend) return -1; /* overflow */ +done: + return dstlen - count; +} + + +int +bstrtoutf8 ( BSTR src, char *dst, size_t dstlen ) +{ + size_t srclen, needed; + int n; + + srclen = src? SysStringLen (src): 0; + + needed = srclen? (utf8_wcstombs (src, srclen, NULL, 0) + 1) : 1; + if (!dst || !dstlen) + return needed; + if (dstlen < needed) + return -1; + if (srclen) { + n = utf8_wcstombs (src, srclen, dst, dstlen); + if (n < 0) + return -1; + } + else + n = 0; + dst[n] = 0; + return n; +} + + + diff --git a/tags/gpgme-1.1.6/complus/vbtest.html b/tags/gpgme-1.1.6/complus/vbtest.html new file mode 100644 index 0000000..03df463 --- /dev/null +++ b/tags/gpgme-1.1.6/complus/vbtest.html @@ -0,0 +1,47 @@ + +g10 code - GPGCOM test + + + + + + + +

Silly Gpgcom test page

+ +
+ +

+Encrypt for + +

+ +

+ +

+ + + + + + diff --git a/tags/gpgme-1.1.6/complus/vbtest.vbs b/tags/gpgme-1.1.6/complus/vbtest.vbs new file mode 100644 index 0000000..8246b45 --- /dev/null +++ b/tags/gpgme-1.1.6/complus/vbtest.vbs @@ -0,0 +1,39 @@ +' Demo script to generate a RFC2015 compliant message using Gpgcom +Dim gpg, body, crlf + +crlf = chr(10) & chr(13) + +' Create out Gpgcom object +set gpg = CreateObject("Gpgcom.Gpgme") +' We must use the ASCII armor and switch to textmode +gpg.armor = true +gpg.textmode = true + +' Set the secret message +gpg.plaintext = "This is the secret message." 'or: InputBox('Enter message:") + +' Set the Recipient. You may also use a keyID or an fingerprint +gpg.AddRecipient "alice" + +' And encrypt the stuff +gpg.encrypt + +' Build the MIME message +body = "Content-Type: multipart/encrypted; boundary=" +body = body & Chr(34) & "=-=-=-=" & Chr(34) & crlf & " protocol=" & Chr(34) +body = body & "application/pgp-encrypted" & Chr(34) & crlf & crlf +body = body & "--=-=-=-=" & crlf +body = body & "Content-Type: application/pgp-encrypted" & crlf & crlf +body = body & "Version: 1" & crlf & crlf +body = body & "--=-=-=-=" & crlf +body = body & "Content-Type: application/octet-stream" & crlf & crlf +body = body & gpg.ciphertext +body = body & "--=-=-=-=--" & crlf + +' And display it +Print body + +' output function for the windows scripting host +sub Print(x) + WScript.Echo x +end sub diff --git a/tags/gpgme-1.1.6/config.guess b/tags/gpgme-1.1.6/config.guess new file mode 100755 index 0000000..e8c6fc0 --- /dev/null +++ b/tags/gpgme-1.1.6/config.guess @@ -0,0 +1,1432 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + +timestamp='2004-01-05' + +# This file 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. +# +# This program 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. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit 0 ;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + macppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvmeppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pegasos:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mipseb-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sun3:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + alpha:OSF1:*:*) + if test $UNAME_RELEASE = "V4.0"; then + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + fi + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit 0 ;; + Alpha*:OpenVMS:*:*) + echo alpha-hp-vms + exit 0 ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit 0;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit 0 ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit 0 ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit 0 ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit 0 ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit 0 ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit 0 ;; + DRS?6000:UNIX_SV:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7 && exit 0 ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit 0 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit 0 ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit 0 ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit 0 ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit 0 ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit 0 ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c \ + && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && exit 0 + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit 0 ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit 0 ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 + echo rs6000-ibm-aix3.2.5 + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit 0 ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + # avoid double evaluation of $set_cc_for_build + test -n "$CC_FOR_BUILD" || eval $set_cc_for_build + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + *:UNICOS/mp:*:*) + echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + # Determine whether the default compiler uses glibc. + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #if __GLIBC__ >= 2 + LIBC=gnu + #else + LIBC= + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + # GNU/KFreeBSD systems have a "k" prefix to indicate we are using + # FreeBSD's kernel, but not the complete OS. + case ${LIBC} in gnu) kernel_only='k' ;; esac + echo ${UNAME_MACHINE}-unknown-${kernel_only}freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC} + exit 0 ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit 0 ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit 0 ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit 0 ;; + x86:Interix*:[34]*) + echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//' + exit 0 ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit 0 ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit 0 ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit 0 ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit 0 ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit 0 ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 + ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit 0 ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit 0 ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit 0 ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit 0 ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit 0 ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit 0 ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit 0 ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit 0 ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit 0 ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit 0 ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #ifdef __INTEL_COMPILER + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 + test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit 0 ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit 0 ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit 0 ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit 0 ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit 0 ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit 0 ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit 0 ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit 0 ;; + i*86:*:5:[78]*) + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit 0 ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit 0 ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit 0 ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit 0 ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit 0 ;; + M68*:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit 0 ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit 0 ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit 0 ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit 0 ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit 0 ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit 0 ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit 0 ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit 0 ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit 0 ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Darwin:*:*) + case `uname -p` in + *86) UNAME_PROCESSOR=i686 ;; + powerpc) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit 0 ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit 0 ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit 0 ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit 0 ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit 0 ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit 0 ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit 0 ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit 0 ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit 0 ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit 0 ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit 0 ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit 0 ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit 0 ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit 0 ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit 0 ;; + *:DRAGONFLY:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly${UNAME_RELEASE} + exit 0 ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0 + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/tags/gpgme-1.1.6/config.sub b/tags/gpgme-1.1.6/config.sub new file mode 100755 index 0000000..463186d --- /dev/null +++ b/tags/gpgme-1.1.6/config.sub @@ -0,0 +1,1537 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + +timestamp='2004-01-05' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file 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. +# +# This program 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. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit 0;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \ + kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | m32r | m68000 | m68k | m88k | mcore \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | msp430 \ + | ns16k | ns32k \ + | openrisc | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ + | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xscale | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* \ + | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | m32r-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | msp430-* \ + | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ + | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ + | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + crds | unos) + basic_machine=m68k-crds + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + mmix*) + basic_machine=mmix-knuth + os=-mmixware + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nv1) + basic_machine=nv1-cray + os=-unicosmp + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + or32 | or32-*) + basic_machine=or32-unknown + os=-coff + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparc | sparcv9 | sparcv9b) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -netbsd* | -openbsd* | -kfreebsd* | -freebsd* | -riscix* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-ibm) + os=-aix + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/tags/gpgme-1.1.6/configure.ac b/tags/gpgme-1.1.6/configure.ac new file mode 100644 index 0000000..2449319 --- /dev/null +++ b/tags/gpgme-1.1.6/configure.ac @@ -0,0 +1,767 @@ +# configure.ac for GPGME +# Copyright (C) 2000 Werner Koch (dd9jn) +# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 g10 Code GmbH +# +# This file is part of GPGME. +# +# GPGME is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser 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 + +# (Process this file with autoconf to produce a configure script.) +AC_PREREQ(2.59) +min_automake_version="1.9.3" + +# Version number: Remember to change it immediately *after* a release. +# Make sure to run "svn up" and "./autogen.sh --force" +# before a "make dist". See below for the LT versions. +# +# The SVN version is usually the next intended release version with +# the string "-svnNNN" appended. The reason for this is that tests for a +# specific feature can already be done under the assumption that the +# SVN version is the most recent one in a branch. To disable the SVN +# version for the real release, set the my_issvn macro to no. +m4_define(my_version, [1.1.6]) +m4_define(my_issvn, [no]) + +m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \ + || echo 'Revision: 0')|sed -n '/^Revision:/ {s/[^0-9]//gp;q;}')])) +AC_INIT([gpgme], my_version[]m4_if(my_issvn,[yes],[-svn[]svn_revision]), + [bug-gpgme@gnupg.org]) + + +# LT Version numbers, remember to change them just *before* a release. +# (Code changed: REVISION++) +# (Interfaces added/removed/changed: CURRENT++, REVISION=0) +# (Interfaces added: AGE++) +# (Interfaces removed/changed: AGE=0) +# +LIBGPGME_LT_CURRENT=17 +# Subtract 2 from this value if you want to make the LFS transition an +# ABI break. [Note to self: Remove this comment with the next regular break.] +LIBGPGME_LT_AGE=6 +LIBGPGME_LT_REVISION=4 + +# If the API is changed in an incompatible way: increment the next counter. +GPGME_CONFIG_API_VERSION=1 +############################################## + + +BUILD_REVISION=svn_revision +PACKAGE=$PACKAGE_NAME +VERSION=$PACKAGE_VERSION + +AC_CONFIG_SRCDIR(gpgme/gpgme.h) +dnl FIXME: Enable this with autoconf 2.59. +dnl AC_CONFIG_MACRO_DIR(m4) +AM_CONFIG_HEADER(config.h) +AM_INIT_AUTOMAKE($PACKAGE, $VERSION) +AM_MAINTAINER_MODE +AC_CANONICAL_HOST + +# Enable GNU extensions on systems that have them. +AC_GNU_SOURCE + +AH_VERBATIM([_REENTRANT], +[/* 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. */ +#ifndef _REENTRANT +# define _REENTRANT 1 +#endif]) + +AC_PROG_CC +AC_PROG_CXX + +AC_SUBST(LIBGPGME_LT_CURRENT) +AC_SUBST(LIBGPGME_LT_AGE) +AC_SUBST(LIBGPGME_LT_REVISION) + +AC_SUBST(PACKAGE) +AC_SUBST(VERSION) +AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of this package]) +AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version of this package]) + +# Don't default to build static libs. +AC_DISABLE_STATIC +AC_LIBTOOL_WIN32_DLL +AC_LIBTOOL_RC +AC_PROG_LIBTOOL + +# For now we hardcode the use of version scripts. It would be better +# to write a test for this or even implement this within libtool. +have_ld_version_script=no +case "${host}" in + *-*-linux*) + have_ld_version_script=yes + ;; + *-*-gnu*) + have_ld_version_script=yes + ;; +esac +AM_CONDITIONAL(HAVE_LD_VERSION_SCRIPT, test "$have_ld_version_script" = "yes") + +GPG_DEFAULT=no +GPGSM_DEFAULT=no +GPGCONF_DEFAULT=no +component_system=None +have_dosish_system=no +have_w32_system=no +build_w32_glib=no +build_w32_qt=no +case "${host}" in + *-mingw32*) + # special stuff for Windoze NT + have_dosish_system=yes + have_w32_system=yes + GPG_DEFAULT='c:\\gnupg\\gpg.exe' + GPGSM_DEFAULT='c:\\gnupg\\gpgsm.exe' + GPGCONF_DEFAULT='c:\\gnupg\\gpgconf.exe' + #component_system='COM+' + + AM_PATH_GLIB_2_0 + AC_ARG_ENABLE(w32-glib, + AC_HELP_STRING([--enable-w32-glib], [build GPGME Glib for W32]), + build_w32_glib=$enableval) + + # Check disabled, because the qt-dev packages in gpg4win do + # not provide any support for cross compilation. + # PKG_CHECK_MODULES(QT4_CORE, QtCore) + + # Use it like this: + # ./configure --enable-w32-qt QT4_CORE_CFLAGS="..." QT4_CORE_LIBS="..." + AC_SUBST(QT4_CORE_CFLAGS) + AC_SUBST(QT4_CORE_LIBS) + AC_ARG_ENABLE(w32-qt, + AC_HELP_STRING([--enable-w32-qt], [build GPGME Qt for W32]), + build_w32_qt=$enableval) + ;; + *) + AC_CHECK_PTH(1.2.0,,,no,have_pth=yes) + if test "$have_pth" = yes; then + AC_DEFINE(HAVE_PTH, ,[Define if we have Pth.]) + fi + AC_CHECK_LIB(pthread,pthread_create,have_pthread=yes) + if test "$have_pthread" = yes; then + AC_DEFINE(HAVE_PTHREAD, ,[Define if we have pthread.]) + fi + + # XXX: Probably use exec-prefix here? +# GPG_DEFAULT='/usr/bin/gpg' +# GPGSM_DEFAULT='/usr/bin/gpgsm' +# GPGCONF_DEFAULT='/usr/bin/gpgconf' + ;; +esac + +if test "$have_dosish_system" = yes; then + AC_DEFINE(HAVE_DOSISH_SYSTEM,1, + [Defined if we run on some of the PCDOS like systems + (DOS, Windoze. OS/2) with special properties like + no file modes]) +fi +AM_CONDITIONAL(HAVE_DOSISH_SYSTEM, test "$have_dosish_system" = yes) + +if test "$have_w32_system" = yes; then + AC_DEFINE(HAVE_W32_SYSTEM,1, [Defined if we run on a W32 API based system]) +fi +AM_CONDITIONAL(HAVE_W32_SYSTEM, test "$have_w32_system" = yes) +AM_CONDITIONAL(BUILD_W32_GLIB, test "$build_w32_glib" = yes) +AM_CONDITIONAL(BUILD_W32_QT, test "$build_w32_qt" = yes) + +AM_CONDITIONAL(HAVE_PTH, test "$have_pth" = "yes") +AM_CONDITIONAL(HAVE_PTHREAD, test "$have_pthread" = "yes") + + +# Checks for header files. +AC_CHECK_HEADERS(sys/select.h) + + +# Type checks. +AC_C_INLINE +AC_CHECK_SIZEOF(unsigned int) +AC_SYS_LARGEFILE +AC_TYPE_OFF_T + +# Checks for compiler features. +if test "$GCC" = yes; then + CFLAGS="$CFLAGS -Wall -Wcast-align -Wshadow -Wstrict-prototypes" + if test "$have_w32_system" = yes; then + CFLAGS="$CFLAGS -mms-bitfields" + fi +fi + +# Network library fun. +AC_CHECK_FUNC(gethostbyname, , AC_CHECK_LIB(nsl, gethostbyname, + [NETLIBS="-lnsl $NETLIBS"])) +AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt, + [NETLIBS="-lsocket $NETLIBS"])) +AC_SUBST(NETLIBS) + +# Checks for library functions. +AC_FUNC_FSEEKO + +AC_REPLACE_FUNCS(vasprintf) +if test "$ac_cv_func_vasprintf" != yes; then + GNUPG_CHECK_VA_COPY +fi + +# Try to find a thread-safe version of ttyname(). +AC_REPLACE_FUNCS(ttyname_r) +if test "$ac_cv_func_ttyname_r" != yes; then + AC_MSG_WARN([ +*** +*** ttyname() is not thread-safe and ttyname_r() does not exist +***]) +fi + +# Try to find a thread-safe version of getenv(). +have_thread_safe_getenv=no +jm_GLIBC21 +if test $GLIBC21 = yes; then + have_thread_safe_getenv=yes +fi +if test $have_thread_safe_getenv = yes; then + AC_DEFINE(HAVE_THREAD_SAFE_GETENV, [1], [Define if getenv() is thread-safe]) +fi +have_getenv_r=no +AC_CHECK_FUNCS(getenv_r, have_getenv_r=yes) +if test $have_getenv_r = no && test $have_thread_safe_getenv = no; then + AC_MSG_WARN([ +*** +*** getenv() is not thread-safe and getenv_r() does not exist +***]) +fi + +# For converting time strings to seconds since Epoch, we need the timegm +# function. +AC_CHECK_FUNCS(timegm) +if test "$ac_cv_func_timegm" != yes; then + AC_MSG_WARN([ +*** +*** timegm() not available - a non-thread-safe kludge will be used +*** and the TZ variable might be changed at runtime. +***]) +fi + +# Checking for libgpg-error. +AM_PATH_GPG_ERROR(1.4,, AC_MSG_ERROR([libgpg-error was not found])) +AC_DEFINE(GPG_ERR_SOURCE_DEFAULT, GPG_ERR_SOURCE_GPGME, + [The default error source for GPGME.]) + + + +# Checks for system services +NEED_GPG_VERSION_DEFAULT=1.3.0 +NEED_GPGSM_VERSION_DEFAULT=1.9.6 +NEED_GPGCONF_VERSION_DEFAULT=2.0.4 +NEED_GPG_VERSION="$NEED_GPG_VERSION_DEFAULT" +NEED_GPGSM_VERSION="$NEED_GPGSM_VERSION_DEFAULT" +NEED_GPGCONF_VERSION="$NEED_GPGCONF_VERSION_DEFAULT" +AC_ARG_WITH(gpg-version, + AC_HELP_STRING([--with-gpg-version=VER], [require GnuPG version VER]), + NEED_GPG_VERSION=$withval) +if test "$NEED_GPG_VERSION" = "yes"; then + NEED_GPG_VERSION="$NEED_GPG_VERSION_DEFAULT" +fi +if test "$NEED_GPG_VERSION" = "no"; then + NEED_GPG_VERSION=0.0.0 +fi +AC_ARG_WITH(gpgsm-version, + AC_HELP_STRING([--with-gpgsm-version=VER], [require GPGSM version VER]), + NEED_GPGSM_VERSION=$withval) +if test "$NEED_GPGSM_VERSION" = "yes"; then + NEED_GPGSM_VERSION="$NEED_GPGSM_VERSION_DEFAULT" +fi +if test "$NEED_GPGSM_VERSION" = "no"; then + NEED_GPGSM_VERSION=0.0.0 +fi +AC_ARG_WITH(gpgconf-version, + AC_HELP_STRING([--with-gpgconf-version=VER], [require GPGCONF version VER]), + NEED_GPGCONF_VERSION=$withval) +if test "$NEED_GPGCONF_VERSION" = "yes"; then + NEED_GPGCONF_VERSION="$NEED_GPGCONF_VERSION_DEFAULT" +fi +if test "$NEED_GPGCONF_VERSION" = "no"; then + NEED_GPGCONF_VERSION=0.0.0 +fi + +AC_DEFINE_UNQUOTED(NEED_GPG_VERSION, "$NEED_GPG_VERSION", + [Min. needed GnuPG version.]) +AC_DEFINE_UNQUOTED(NEED_GPGSM_VERSION, "$NEED_GPGSM_VERSION", + [Min. needed GPGSM version.]) +AC_DEFINE_UNQUOTED(NEED_GPGCONF_VERSION, "$NEED_GPGCONF_VERSION", + [Min. needed GPGCONF version.]) + + +NO_OVERRIDE=no +AC_ARG_WITH(gpg, + AC_HELP_STRING([--with-gpg=PATH], [use GnuPG binary at PATH]), + GPG=$withval, NO_OVERRIDE=yes) +if test "$NO_OVERRIDE" = "yes" || test "$GPG" = "yes"; then + GPG= + NO_OVERRIDE=yes + if test "$cross_compiling" != "yes"; then + AC_PATH_PROG(GPG, gpg) + fi + if test -z "$GPG"; then + GPG="$GPG_DEFAULT" + fi +fi +if test "$GPG" = no; then + if test "$NO_OVERRIDE" = "yes"; then + if test "$cross_compiling" != "yes"; then + AC_MSG_WARN([ +*** +*** Could not find GnuPG, install GnuPG or use --with-gpg=PATH to enable it +***]) + else + AC_MSG_ERROR([ +*** +*** Can not determine path to GnuPG when cross-compiling, use --with-gpg=PATH +***]) + fi + fi +else + AC_DEFINE_UNQUOTED(GPG_PATH, "$GPG", [Path to the GnuPG binary.]) + AC_SUBST(GPG) +fi +dnl Check for GnuPG version requirement. +GPG_VERSION=unknown +ok=maybe +if test -z "$GPG" -o "x$GPG" = "xno"; then + ok=no +else + if test "$cross_compiling" = "yes"; then + AC_MSG_WARN([GnuPG version can not be checked when cross compiling]) + ok=no + else + if test ! -x "$GPG"; then + AC_MSG_WARN([GnuPG not executable, version check disabled]) + ok=no + fi + fi +fi +if test "$ok" = "maybe"; then + AC_MSG_CHECKING(for GPG >= $NEED_GPG_VERSION) + req_major=`echo $NEED_GPG_VERSION | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` + req_minor=`echo $NEED_GPG_VERSION | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` + req_micro=`echo $NEED_GPG_VERSION | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` + GPG_VERSION=`$GPG --version | sed -n '1 s/[[^0-9]]*\(.*\)/\1/p'` + major=`echo $GPG_VERSION | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` + minor=`echo $GPG_VERSION | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` + micro=`echo $GPG_VERSION | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'` + + if test "$major" -gt "$req_major"; then + ok=yes + else + if test "$major" -eq "$req_major"; then + if test "$minor" -gt "$req_minor"; then + ok=yes + else + if test "$minor" -eq "$req_minor"; then + if test "$micro" -ge "$req_micro"; then + ok=yes + fi + fi + fi + fi + fi + if test "$ok" = "yes"; then + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + AC_MSG_WARN([GPG must be at least version $NEED_GPG_VERSION]) + fi +fi +run_gpg_test="$ok" +AC_ARG_ENABLE(gpg-test, + AC_HELP_STRING([--disable-gpg-test], [disable GPG run test]), + run_gpg_test=$enableval) +AM_CONDITIONAL(RUN_GPG_TESTS, test "$run_gpg_test" = "yes") +AC_SUBST(GPG_PATH) + +NO_OVERRIDE=no +AC_ARG_WITH(gpgsm, + AC_HELP_STRING([--with-gpgsm=PATH], [use GpgSM binary at PATH]), + GPGSM=$withval, NO_OVERRIDE=yes) +if test "$NO_OVERRIDE" = "yes" || test "$GPGSM" = "yes"; then + GPGSM= + NO_OVERRIDE=yes + if test "$cross_compiling" != "yes"; then + AC_PATH_PROG(GPGSM, gpgsm) + fi + if test -z "$GPGSM"; then + GPGSM="$GPGSM_DEFAULT" + fi +fi +if test "$GPGSM" = no; then + if test "$NO_OVERRIDE" = "yes"; then + if test "$cross_compiling" != "yes"; then + AC_MSG_WARN([ +*** +*** Could not find GpgSM, install GpgSM or use --with-gpgsm=PATH to enable it +***]) + else + AC_MSG_ERROR([ +*** +*** Can not determine path to GpgSM when cross-compiling, use --with-gpgsm=PATH +***]) + fi + fi +else + AC_DEFINE_UNQUOTED(GPGSM_PATH, "$GPGSM", [Path to the GPGSM binary.]) + AC_DEFINE(ENABLE_GPGSM,1,[Whether GPGSM support is enabled]) +fi +AM_CONDITIONAL(HAVE_GPGSM, test "$GPGSM" != "no") + + +dnl Check for GPGSM version requirement. +GPGSM_VERSION=unknown +ok=maybe +if test -z "$GPGSM" -o "x$GPGSM" = "xno"; then + ok=no +else + if test "$cross_compiling" = "yes"; then + AC_MSG_WARN([GPGSM version can not be checked when cross compiling]) + ok=no + else + if test ! -x "$GPGSM"; then + AC_MSG_WARN([GPGSM not executable, version check disabled]) + ok=no + fi + fi +fi +if test "$ok" = "maybe"; then + AC_MSG_CHECKING(for GPGSM >= $NEED_GPGSM_VERSION) + req_major=`echo $NEED_GPGSM_VERSION | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` + req_minor=`echo $NEED_GPGSM_VERSION | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` + req_micro=`echo $NEED_GPGSM_VERSION | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` + GPGSM_VERSION=`$GPGSM --version | sed -n '1 s/[[^0-9]]*\(.*\)/\1/p'` + major=`echo $GPGSM_VERSION | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` + minor=`echo $GPGSM_VERSION | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` + micro=`echo $GPGSM_VERSION | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'` + + if test "$major" -gt "$req_major"; then + ok=yes + else + if test "$major" -eq "$req_major"; then + if test "$minor" -gt "$req_minor"; then + ok=yes + else + if test "$minor" -eq "$req_minor"; then + if test "$micro" -ge "$req_micro"; then + ok=yes + fi + fi + fi + fi + fi + if test "$ok" = "yes"; then + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + AC_MSG_WARN([GPGSM must be at least version $NEED_GPGSM_VERSION]) + fi +fi +run_gpgsm_test="$ok" +AC_ARG_ENABLE(gpgsm-test, + AC_HELP_STRING([--disable-gpgsm-test], [disable GPGSM run test]), + run_gpgsm_test=$enableval) +AM_CONDITIONAL(RUN_GPGSM_TESTS, test "$run_gpgsm_test" = "yes") + + +NO_OVERRIDE=no +AC_ARG_WITH(gpgconf, + AC_HELP_STRING([--with-gpgconf=PATH], + [use gpgconf binary at PATH]), + GPGCONF=$withval, NO_OVERRIDE=yes) +if test "$NO_OVERRIDE" = "yes" || test "$GPGCONF" = "yes"; then + GPGCONF= + NO_OVERRIDE=yes + if test "$cross_compiling" != "yes"; then + AC_PATH_PROG(GPGCONF, gpgconf) + fi + if test -z "$GPGCONF"; then + GPGCONF="$GPGCONF_DEFAULT" + fi +fi +if test "$GPGCONF" = no; then + if test "$NO_OVERRIDE" = "yes"; then + if test "$cross_compiling" != "yes"; then + AC_MSG_WARN([ +*** +*** Could not find gpgconf, install gpgconf or use --with-gpgconf=PATH to enable it +***]) + else + AC_MSG_ERROR([ +*** +*** Can not determine path to gpgconf when cross-compiling, use --with-gpgconf=PATH +***]) + fi + fi +else + AC_DEFINE_UNQUOTED(GPGCONF_PATH, "$GPGCONF", [Path to the GPGCONF binary.]) + AC_DEFINE(ENABLE_GPGCONF,1,[Whether GPGCONF support is enabled]) +fi +AM_CONDITIONAL(HAVE_GPGCONF, test "$GPGCONF" != "no") + +dnl Check for GPGCONF version requirement. +GPGCONF_VERSION=unknown +ok=maybe +if test -z "$GPGCONF" -o "x$GPGCONF" = "xno"; then + ok=no +else + if test "$cross_compiling" = "yes"; then + AC_MSG_WARN([GPGCONF version can not be checked when cross compiling]) + ok=no + else + if test ! -x "$GPGCONF"; then + AC_MSG_WARN([GPGCONF not executable, version check disabled]) + ok=no + fi + fi +fi +if test "$ok" = "maybe"; then + AC_MSG_CHECKING(for GPGCONF >= $NEED_GPGCONF_VERSION) + req_major=`echo $NEED_GPGCONF_VERSION | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` + req_minor=`echo $NEED_GPGCONF_VERSION | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` + req_micro=`echo $NEED_GPGCONF_VERSION | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` + GPGCONF_VERSION=`$GPGCONF --version | sed -n '1 s/[[^0-9]]*\(.*\)/\1/p'` + major=`echo $GPGCONF_VERSION | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` + minor=`echo $GPGCONF_VERSION | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` + micro=`echo $GPGCONF_VERSION | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'` + + if test "$major" -gt "$req_major"; then + ok=yes + else + if test "$major" -eq "$req_major"; then + if test "$minor" -gt "$req_minor"; then + ok=yes + else + if test "$minor" -eq "$req_minor"; then + if test "$micro" -ge "$req_micro"; then + ok=yes + fi + fi + fi + fi + fi + if test "$ok" = "yes"; then + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + AC_MSG_WARN([GPGCONF must be at least version $NEED_GPGCONF_VERSION]) + fi +fi +run_gpgconf_test="$ok" +AC_ARG_ENABLE(gpgconf-test, + AC_HELP_STRING([--disable-gpgconf-test], [disable GPGCONF run test]), + run_gpgconf_test=$enableval) +AM_CONDITIONAL(RUN_GPGCONF_TESTS, test "$run_gpgconf_test" = "yes") + +# Only build if supported. +AM_CONDITIONAL(BUILD_GPGCONF, test "$GPGCONF" != "no") +if test "$GPGCONF" != "no"; then + AC_DEFINE(HAVE_GPGCONF, 1, + [Defined if we are building with gpgconf support.]) +fi + + +# FIXME: Only build if supported. +AM_CONDITIONAL(BUILD_ASSUAN, test "$GPGSM" != "no") +if test "$GPGSM" != "no"; then + AC_DEFINE(HAVE_ASSUAN_H, 1, + [Defined if we are building with assuan support.]) +fi + +# Check for funopen +AC_CHECK_FUNCS(funopen) +if test $ac_cv_func_funopen != yes; then + # No funopen but we can implement that in terms of fopencookie. + AC_CHECK_FUNCS(fopencookie) + if test $ac_cv_func_fopencookie = yes; then + AC_REPLACE_FUNCS(funopen) + else + AC_MSG_WARN([ +*** +*** No implementation of fopencookie or funopen available +***]) + fi +fi + +# More assuan replacement functions. +AC_REPLACE_FUNCS(isascii) +AC_REPLACE_FUNCS(putc_unlocked) +AC_REPLACE_FUNCS(memrchr) +AC_REPLACE_FUNCS(stpcpy) +# Check for unistd.h for setenv replacement function. +AC_CHECK_HEADERS(unistd.h) +AC_REPLACE_FUNCS(setenv) + +# More assuan checks. +AC_CHECK_HEADERS([sys/uio.h]) + +# Assuan check for descriptor passing. +AC_CHECK_MEMBER(struct cmsghdr.cmsg_len, + [supports_descriptor_passing=yes], + [supports_descriptor_passing=no + AC_MSG_WARN([ +*** +*** Data structure for sending ancillary data missing. +*** Descriptor passing won't work. +***])],[ +#include +#include +#include +#include +#include +#include +#if HAVE_SYS_UIO_H +#include +#endif +#include + ]) + +AC_ARG_ENABLE(fd-passing, + AC_HELP_STRING([--enable-fd-passing], [use FD passing if supported]), + use_descriptor_passing=$enableval) + +if test "$supports_descriptor_passing" != "yes"; then + use_descriptor_passing=no +fi + +if test "$use_descriptor_passing" = "yes"; then +AC_DEFINE(USE_DESCRIPTOR_PASSING,1, + [Defined if descriptor passing is enabled and supported]) +fi + +AM_CONDITIONAL(USE_DESCRIPTOR_PASSING, test "$use_descriptor_passing" = "yes") + +# Assuan check for the getsockopt SO_PEERCRED +AC_MSG_CHECKING(for SO_PEERCRED) +AC_CACHE_VAL(assuan_cv_sys_so_peercred, + [AC_TRY_COMPILE([#include ], + [struct ucred cr; + int cl = sizeof cr; + getsockopt (1, SOL_SOCKET, SO_PEERCRED, &cr, &cl);], + assuan_cv_sys_so_peercred=yes, + assuan_cv_sys_so_peercred=no) + ]) +AC_MSG_RESULT($assuan_cv_sys_so_peercred) +if test $assuan_cv_sys_so_peercred = yes; then + AC_DEFINE(HAVE_SO_PEERCRED, 1, + [Defined if SO_PEERCRED is supported (Linux specific)]) +fi + +if test "$have_w32_system" = yes; then + NETLIBS="-lws2_32 $NETLIBS" +fi + +# End of assuan checks. + +AM_CONDITIONAL(BUILD_COMPLUS, test "$component_system" = "COM+") + +# Make the version number in gpgme/gpgme.h the same as the one here. +# (this is easier than to have a *.in file just for one substitution) +GNUPG_FIX_HDR_VERSION(gpgme/gpgme.h, GPGME_VERSION) + +# Generate values for the DLL version info +if test "$have_w32_system" = yes; then + BUILD_TIMESTAMP=`date --iso-8601=minutes` + changequote(,)dnl + BUILD_FILEVERSION=`echo "$VERSION" | sed 's/\([0-9.]*\).*/\1./;s/\./,/g'` + changequote([,])dnl + BUILD_FILEVERSION="${BUILD_FILEVERSION}${BUILD_REVISION}" +fi +AC_SUBST(BUILD_REVISION) +AC_SUBST(BUILD_TIMESTAMP) +AC_SUBST(BUILD_FILEVERSION) + +# Add a few constants to help porting to W32 +AH_VERBATIM([SEPCONSTANTS], +[ +/* Separators as used in $PATH. */ +#ifdef HAVE_DOSISH_SYSTEM +#define PATHSEP_C ';' +#else +#define PATHSEP_C ':' +#endif +]) + +AH_BOTTOM([ +/* Definition of GCC specific attributes. */ +#if __GNUC__ > 2 +# define GPGME_GCC_A_PURE __attribute__ ((__pure__)) +#else +# define GPGME_GCC_A_PURE +#endif +]) + + +# Substitution used for gpgme-config +GPGME_CONFIG_LIBS="-lgpgme" +GPGME_CONFIG_CFLAGS="" +AC_SUBST(GPGME_CONFIG_API_VERSION) +AC_SUBST(GPGME_CONFIG_LIBS) +AC_SUBST(GPGME_CONFIG_CFLAGS) + +# Frob'da Variables +LTLIBOBJS=`echo "$LIB@&t@OBJS" | + sed 's,\.[[^.]]* ,.lo ,g;s,\.[[^.]]*$,.lo,'` +AC_SUBST(LTLIBOBJS) + +# +# Create config files + +AC_CONFIG_FILES(Makefile assuan/Makefile gpgme/Makefile + tests/Makefile tests/gpg/Makefile tests/gpgsm/Makefile + doc/Makefile complus/Makefile + gpgme/versioninfo.rc) +AC_CONFIG_FILES(gpgme/gpgme-config, chmod +x gpgme/gpgme-config) +AC_CONFIG_FILES([lang/Makefile lang/cl/Makefile lang/cl/gpgme.asd]) +AC_OUTPUT + +echo " + GPGME v${VERSION} has been configured as follows: + + GnuPG path: $GPG + GnuPG version: $GPG_VERSION, min. $NEED_GPG_VERSION + + GpgSM path: $GPGSM + GpgSM version: $GPGSM_VERSION, min. $NEED_GPGSM_VERSION + + GpgConf path: $GPGCONF + GpgConf version: $GPGCONF_VERSION, min. $NEED_GPGCONF_VERSION + + GPGME Pthread: $have_pthread + GPGME Pth: $have_pth +" diff --git a/tags/gpgme-1.1.6/depcomp b/tags/gpgme-1.1.6/depcomp new file mode 100755 index 0000000..aea3d00 --- /dev/null +++ b/tags/gpgme-1.1.6/depcomp @@ -0,0 +1,472 @@ +#! /bin/sh + +# depcomp - compile a program generating dependencies as side-effects +# Copyright 1999, 2000 Free Software Foundation, Inc. + +# This program 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, or (at your option) +# any later version. + +# This program 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. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi +# `libtool' can also be set to `yes' or `no'. + +if test -z "$depfile"; then + base=`echo "$object" | sed -e 's,^.*/,,' -e 's,\.\([^.]*\)$,.P\1,'` + dir=`echo "$object" | sed 's,/.*$,/,'` + if test "$dir" = "$object"; then + dir= + fi + # FIXME: should be _deps on DOS. + depfile="$dir.deps/$base" +fi + +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. + "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the `deleted header file' problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' ' +' < "$tmpdepfile" | +## Some versions of gcc put a space before the `:'. On the theory +## that the space means something, we add a space to the output as +## well. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like `#:fec' to the end of the + # dependency line. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> $depfile + echo >> $depfile + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> $depfile + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. This file always lives in the current directory. + # Also, the AIX compiler puts `$object:' at the start of each line; + # $object doesn't have directory information. + stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'` + tmpdepfile="$stripped.u" + outname="$stripped.o" + if test "$libtool" = yes; then + "$@" -Wc,-M + else + "$@" -M + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + + if test -f "$tmpdepfile"; then + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" + sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +icc) + # Intel's C compiler understands `-MD -MF file'. However on + # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want: + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using \ : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | + sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in `foo.d' instead, so we check for that too. + # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + tmpdepfile1="$dir.libs/$base.lo.d" + tmpdepfile2="$dir.libs/$base.d" + "$@" -Wc,-MD + else + tmpdepfile1="$dir$base.o.d" + tmpdepfile2="$dir$base.d" + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + if test -f "$tmpdepfile1"; then + tmpdepfile="$tmpdepfile1" + else + tmpdepfile="$tmpdepfile2" + fi + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a space and a tab in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the proprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for `:' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. + "$@" $dashmflag | + sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no + for arg in "$@"; do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix="`echo $object | sed 's/^.*\././'`" + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the proprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E | + sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the proprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + "$@" || exit $? + IFS=" " + for arg + do + case "$arg" in + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 diff --git a/tags/gpgme-1.1.6/doc/ChangeLog b/tags/gpgme-1.1.6/doc/ChangeLog new file mode 100644 index 0000000..24b2abe --- /dev/null +++ b/tags/gpgme-1.1.6/doc/ChangeLog @@ -0,0 +1,785 @@ +2007-09-27 Marcus Brinkmann + + * gpgme.texi (Protocols and Engines): Document GPGME_PROTOCOL_UNKNOWN. + +2007-09-11 Werner Koch + + * gpgme.texi (I/O Callback Example): Typo fix. + +2007-08-07 Werner Koch + + * gpgme.texi (Verify): Describe chain_model. + +2007-07-12 Werner Koch + + * gpgme.texi (Library Version Check): Add remark that the socket + layer will get initialized. + +2007-06-05 Marcus Brinkmann + + * gpgme.texi (Advanced Key Editing): New section. + +2007-05-21 Werner Koch + + * Makefile.am (online): New target. + +2007-05-18 Marcus Brinkmann + + * gpgme.texi (Error Strings): Fix documentation of + gpgme_strerror_r. + +2006-11-01 Moritz Schulte + + * gpgme.texi (Data Buffer I/O Operations): Fixed entry for + gpgme_data_seek: OFFSET is not a pointer; some s/whence/offset/. + +2006-09-25 Marcus Brinkmann + + * gpgme.texi (Destroying Data Buffers): Clarify that + gpgme_data_release_and_get_mem destroys DH unconditionally. + +2005-03-24 Marcus Brinkmann + + * gpgme.texi (Library Version Check): Make example code compatible + to W32 systems. + +2006-06-21 Marcus Brinkmann + + * gpgme.texi (Passphrase Callback): Fix inverted condition in + description. + +2005-12-20 Werner Koch + + * gpgme.texi (Verify): Document pka_trust. + +2005-12-06 Werner Koch + + * gpgme.texi (Key Management): Updated to match the fixes for + subkey fingerprints and theg secret flag. + +2005-10-06 Marcus Brinkmann + + * gpgme.texi (Destroying Data Buffers): Document gpgme_free. + +2005-10-02 Marcus Brinkmann + + * gpgme.texi (Key Management): Add the new member notations of + gpgme_sig_key_t. + (Key Listing Mode): Document GPGME_KEYLIST_MODE_SIG_NOTATIONS. + +2005-10-01 Marcus Brinkmann + + * gpgme.texi: Enclose all return parameters of deftypefuns in + curly brackets. + + * gpgme.texi (Signature Notation Data): New section. + (Verify): Added more about the notation data structure. + +2005-09-30 Marcus Brinkmann + + * gpgme.texi (Data Buffer I/O Operations, Data Buffer Meta-Data): + New subsections. + + * gpgme.texi: Replace plaintext_filename with file_name. + + * gpgme.texi (Key Management): Document is_qualified. + +2005-07-27 Marcus Brinkmann + + * gpgme.texi (Decrypt): Add plaintext_filename to + gpgme_decrypt_result_t. + (Verify): Likewise for gpgme_verify_result_t. + +2005-06-03 Marcus Brinkmann + + * gpgme.texi (Verify): Add information about new fields in + gpgme_signature_t. + + * gpgme.texi (Decrypt): Add gpgme_recipient_t. + +2005-05-28 Marcus Brinkmann + + * gpgme.texi (Key Listing Mode): Fix return type of + gpgme_set_keylist_mode. + Reported by "Sergio" . + +2005-04-28 Marcus Brinkmann + + * gpgme.texi (Included Certificates): Document + GPGME_INCLUDE_CERTS_DEFAULT. + +2005-01-12 Marcus Brinkmann + + * gpgme.texi (Engine Configuration): New section. + (Crypto Engine): New subsection. + +2004-12-07 Marcus Brinkmann + + * lesser.texi (Library Copying): Change from @appendixsec to + @appendix. + * gpgme.texi (Features): Change reference to GPL to one to LGPL. + + * Makefile.am: Change license to LGPL. + (gpgme_TEXINFOS): Replace gpl.texi with lesser.texi. + + * gpgme.texi: Change license to LGPL (also for documentation of + GPGME's license). + * lesser.texi: New file. + * gpl.texi: File removed. + + * gpgme.texi (Creating Contexts): Fix cut&paste error. Reported + by Noel Torres . + +2004-09-30 Marcus Brinkmann + + * Makefile.am (gpgme_TEXINFOS): Remove fdl.texi. + * gpgme.texi: Do not include fdl.texi. Change license to GPL. + * fdl.texi: File removed. + +2004-09-29 Marcus Brinkmann + + * gpgme.texi (Key Management): Change type of keylist_mode in + gpgme_key_t to gpgme_keylist_mode_t. + +2004-09-28 Marcus Brinkmann + + * gpgme.texi (Passphrase Callback): Fix last change. + +2004-09-27 Marcus Brinkmann + + * gpgme.texi (Passphrase Callback): Document + GPG_ERR_NOT_IMPLEMENTED. + + * gpgme.texi: Update copyright year for tex version. + +2004-07-29 Moritz Schulte + + * gpgme.texi (Verify): Fix gpgme_get_key example (ancient + force_update argument was still there). + +2004-06-08 Marcus Brinkmann + + * gpgme.texi (Listing Keys): Elaborate on the length restrictions + on search patterns. + + * gpgme.texi (Decrypt and Verify): Document the NO_DATA error + code. + (Verify): Document the relationship between gpgme_op_verify_result + and the decrypt and verify operations. + +2004-05-21 Marcus Brinkmann + + * gpgme.text (Verify): Document GPG_ERR_CERT_REVOKED status. + + * gpgme.texi (Decrypt): Add note about new field wrong_key_usage + of gpgme_decrypt_result_t. + + * gpgme.texi (Key Management): Add note about new field + keylist_mode of gpgme_key_t. + +2004-04-29 Marcus Brinkmann + + * gpgme.texi (Verify): Correct type of member wrong_key_usage. + +2004-03-29 Moritz Schulte + + * gpgme.texi (Verify): Fix type of gpgme_op_verify_result. + * gpgme.texi (Key Listing Mode): Typo fix. + +2004-03-23 Marcus Brinkmann + + * gpgme.texi (Library Version Check): Fix the instruction when to + set the locale. + +2004-03-03 Marcus Brinkmann + + * gpgme.texi (I/O Callback Example Qt): New section by Marc Mutz. + +2004-02-24 Marcus Brinkmann + + * gpgme.texi (cancellation): New section. + +2004-02-17 Werner Koch + + * gpgme.texi (Key Listing Mode): Doc KEYLIST_MODE_VALIDATE. + +2004-02-06 Moritz Schulte + + * gpgme.texi: A couple of small fixes regarding the Largfile + Support section. + +2004-02-01 Marcus Brinkmann + + * gpgme.texi (Largefile Support): New section. + +2004-01-13 Marcus Brinkmann + + * gpgme.texi (Key Management): Fix exportable field. + +2003-12-25 Marcus Brinkmann + + * gpgme.texi (Key Management): Rename member class in + gpgme_key_sig_t to sig_class. + (Creating a Signature): Likewise for gpgme_signature_t. + +2003-12-23 Moritz Schulte + + * gpgme.texi (Listing Keys): Minor clarification for + gpgme_get_key. + +2003-10-06 Marcus Brinkmann + + * gpgme.texi (Signal Handling): New section. + +2003-09-14 Marcus Brinkmann + + * gpgme.texi (Multi Threading): Correct documentation on memory + synchronization requirement. + + * gpgme.texi (Locale): New section. + (Multi Threading): Set locale in example. + +2003-09-13 Marcus Brinkmann + + * gpgme.texi (Error Strings): Add gpgme_strerror_r. + +2003-09-13 Marcus Brinkmann + + * gpgme.texi (Multi Threading): Update documentation. + +2003-09-03 Marcus Brinkmann + + * gpgme.texi (Header): We don't use the assuan namespace anymore. + Document new thread options. + +2003-08-14 Marcus Brinkmann + + * gpgme.texi (Creating a Signature): Change type of member class + to unsigned int. + +2003-08-04 Marcus Brinkmann + + * gpgme.texi (Verify): Get error code from SIG->status in the code + for gpgme_get_sig_status. + +2003-07-31 Marcus Brinkmann + + * gpgme.texi (Key Management): Add can_authenticate flag. + + * gpgme.texi (Listing Keys): Document GPG_ERR_AMBIGUOUS_NAME for + gpgme_get_key. + +2003-07-29 Marcus Brinkmann + + * Makefile.am (EXTRA_DIST): Remove variable. + + * gpgme.texi (Encrypting a Plaintext): Bad passphrase is only + possible with symmetric encryption, change the wording to reflect + that. + + * gpgme.texi (Creating a Signature): Document + GPG_ERR_UNUSABLE_SECKEY. + + * gpgme.texi (Encrypting a Plaintext): Mention encrypt and sign + operations in result function. + (Creating a Signature): Likewise. + +2003-07-23 Marcus Brinkmann + + * gpgme.texi (Key Listing Mode): Remove word duplication. + (Listing Keys): Remove mentioning of force argument. + (Verify): Don't mention r_stat. Fix some typos. + (Decrypt and Verify): Correct info how to get the result. Don't + mention r_stat. + (Manipulating Data Buffers): Fix documentation of return value. + (Listing Keys): Update examples. + (Decrypt): Result might also be available when operation failed. + (Verify): Result might also be available when operation failed. + All spotted by Stéphane Corthésy. + +2003-07-22 Marcus Brinkmann + + * gpgme.texi (Error Sources): Fix cut and paste error. + +2003-07-09 Marcus Brinkmann + + * gpgme.texi (Key Management): Clarify difference between can_sign + and can_certify. + (Information About Keys): Likewise for GPGME_ATTR_CAN_SIGN and + GPGME_ATTR_CAN_CERTIFY. + +2003-07-08 Marcus Brinkmann + + * gpgme.texi (Progress Meter Callback): Change return type of + gpgme_progress_cb_t to void. + +2003-06-22 Marcus Brinkmann + + * gpgme.texi: Add 2003 to copyright notice. + + * gpgme.texi (Header): Fix name space documentation on + libgpg-error. + +2003-06-22 Marcus Brinkmann + + * gpgme.texi (Multi Threading): Remove reference to + gpgme_recipients_t. + +2003-06-06 Marcus Brinkmann + + * gpgme.texi (Crypto Operations): Rename gpgme_invalid_user_id_t + to gpgme_invalid_key_t. + +2003-06-06 Marcus Brinkmann + + * gpgme.texi: Change error codes to GPG_ERR_* variants. + (Error Handling): Rewritten. + +2003-05-29 Marcus Brinkmann + + * gpgme.texi (Exporting Keys): Change and document prototypes. + Add new gpgme_op_export_ext and gpgme_op_export_ext_start + variants. + (Selecting Recipients): Section removed. + (Encrypting a Plaintext): Change prototypes and document the + changes. + +2003-05-28 Marcus Brinkmann + + * gpgme.texi (Exporting Keys): Change argument type from + gpgme_recipient_t to gpgme_user_id_t. + (Encrypting a Plaintext): Likewise. + (Selecting Recipients): Rewritten. + +2003-05-27 Marcus Brinkmann + + * gpgme.texi (Protocol Selection): Do not use @acronym in @node + because that breaks texi2dvi. + + * gpgme.texi (Passphrase Callback): Document new prototype. + +2003-05-18 Marcus Brinkmann + + * gpgme.texi (Header): Remove Gpgme as namespace prefix. Add + _GPGME to namespace prefix. + * gpgme.texi (Multi Threading): Add note about link order. + +2003-05-04 Marcus Brinkmann + + * gpgme.texi (Listing Keys): Document what happens if key is not + found. + + * gpgme.texi (Importing Keys): Fix cut and paste error. + +2003-04-30 Marcus Brinkmann + + * gpgme.texi (Encrypting a Plaintext): Remove reference to + gpgme_get_op_info. + (Detailed Results): Subsection removed. + + * gpgme.texi (Key Listing Mode): Add GPGME_KEYLIST_MODE_SIGS. + (Manipulating Keys): Add obsoleteness note. + (Key Signatures): Likewise. + (Information About Keys): Likewise. + (Key Management): Add new data types GpgmeSubkey, GpgmeKeySig, + GpgmeUserID, and all the information about GpgmeKey. + +2003-04-29 Marcus Brinkmann + + * gpgme.texi (Listing Keys): Remove force_update argument from + gpgme_get_key. + + * gpgme.texi (Trust Item Management): Add data members of + GpgmeTrustItem type. + (Information About Trust Items): Add note about obsoleteness. + (Manipulating Trust Items): Add gpgme_trust_item_ref and + gpgme_trust_item_unref. + +2003-04-28 Marcus Brinkmann + + * gpgme.texi (Verify): Rewritten to take into account new and + deprecated functions and data types. + + * gpgme.texi (Decrypt): Descript gpgme_op_decrypt_result and + GpgmeDecryptResult. + +2003-04-27 Marcus Brinkmann + + * gpgme.texi (Encrypting a Plaintext): Add info about + GpgmeEncryptResult and gpgme_op_encrypt_result. + + * gpgme.texi (Creating a Signature): Add info about + GpgmeNewSignature, GpgmeSignResult and gpgme_op_sign_result. + (Crypto Operations): Add GpgmeInvalidUserID. + (Algorithms): New chapter. + + * gpgme.texi (Deleting Keys): Document + GPGME_Ambiguous_Specification. + (Error Values): Remove GPGME_Invalid_Type and GPGME_Invalid_Mode. + Add GPGME_Unknown_Reason, GPGME_Not_Found, + GPGME_Ambiguous_Specification, GPGME_Wrong_Key_Usage, + GPGME_Key_Revoked, GPGME_Key_Expired, GPGME_No_CRL_Known, + GPGME_CRL_Too_Old, GPGME_Policy_Mismatch, GPGME_No_Secret_Key, + GPGME_Key_Not_Trusted, GPGME_Issuer_Missing, GPGME_Chain_Too_Long, + GPGME_Unsupported_Algorithm, GPGME_Sig_Expired, + GPGME_Bad_Signature, GPGME_No_Public_Key. + +2003-04-25 Marcus Brinkmann + + * gpgme.texi (Importing Keys): Change GPGME_IMPORT_PRIVATE to + GPGME_IMPORT_SECRET. + + * gpgme.texi (Importing Keys): Remove note about gpgme_get_op_info. + (Detailed Results): Remove note about import. + + * gpgme.texi (Importing Keys): Add documentation for + GpgmeImportStatus, GpgmeImportResult and gpgme_op_import_result. + + * gpgme.texi (Generating Keys): Fix documentation of public and + secret arguments. + +2003-04-24 Marcus Brinkmann + + * gpgme.texi (Generating Keys): Document changed gpgme_op_genkey + and new gpgme_op_genkey_result function. Document + GpgmeGenKeyResult data type. + + * gpgme.texi (Error Values): Rename GPGME_No_Passphrase to + GPGME_Bad_Passphrase. + * gpgme.texi (Decrypt): Likewise. + (Decrypt and Verify): Likewise. + (Creating a Signature): Likewise. + (Encrypting a Plaintext): Likewise. + + * gpgme.texi (Error Values): Rename GPGME_No_Recipients to + GPGME_No_UserID and GPGME_Invalid_Recipient to + GPGME_Invalid_UserID. + (Encrypting a Plaintext): Likewise. + + * gpgme.texi (Error Values): Remove GPGME_Busy and GPGME_No_Request. + (Listing Keys): Likewise. + (Listing Trust Items): Likewise. + +2003-02-06 Marcus Brinkmann + + * gpgme.texi (Cancelling an Operation): Removed. + (Passphrase Callback): Document new type for GpgmePassphraseCb. + +2003-01-30 Marcus Brinkmann + + * gpgme.texi (Engine Information): Rename member part to + file_name. + + * gpgme.texi (Protocols and Engines): Document + gpgme_get_protocol_name. + + * gpgme.texi (Engine Information): Rewritten. + +2003-01-29 Marcus Brinkmann + + * gpgme.texi (I/O Callback Interface): Document new even + GPGME_EVENT_START. + (Waiting For Completion): Document new possible return values. + (I/O Callback Interface): Document return type of GpgmeIOCb. + +2003-01-29 Marcus Brinkmann + + * gpgme.texi (Hooking Up Into Idle Time): Section removed. + +2002-12-24 Marcus Brinkmann + + * gpgme.texi (Verify): Drop R_STAT argument in gpgme_op_verify. + * gpgme.texi (Decrypt and Verify): Likewise for + gpgme_op_decrypt_verify. + +2002-12-23 Marcus Brinkmann + + * gpgme.texi (Information About Keys): Document that + GPGME_ATTR_IS_SECRET is not representable as a string anymore. + +2002-12-22 Marcus Brinkmann + + * gpgme.texi (Key Signatures): New section. + (Listing Keys): Add gpgme_get_key. + +2002-12-06 Marcus Brinkmann + + * gpgme.texi (Memory Based Data Buffers): New subsection. + (File Based Data Buffers): Likewise. + (Callback Based Data Buffers): Likewise. + (Manipulating Data Buffers): Update interfaces. Add + gpgme_data_seek. + * gpgme.texi (Engine Version Check): Remove gpgme_check_engine. + +2002-11-21 Marcus Brinkmann + + * gpgme.texi (Verify): Document the new interface. + +2002-11-19 Marcus Brinkmann + + * gpgme.texi (Generating Keys): Document new argument to + gpgme_op_genkey. + +2002-11-05 Marcus Brinkmann + + * gpgme.texi (Verify): Fix prototype of gpgme_get_sig_key. + Reported by Miguel Coca . + +2002-08-30 Marcus Brinkmann + + * gpgme.texi (Selecting Signers): Fix reference count. + +2002-08-21 Marcus Brinkmann + + * gpgme.texi (Header): Document name space. + +2002-08-20 Marcus Brinkmann + + * gpgme.texi (Importing Keys): Document gpgme_op_import_ext. + + * gpgme.texi (Importing Keys): Undocument EOF. + +2002-08-14 Werner Koch + + * gpgme.texi (Information About Keys): Changed GPGME_ATTR_TYPE. + +2002-07-25 Marcus Brinkmann + + * gpgme.texi (Deleting Keys): Say that secret keys might not be + deleted. + +2002-07-25 Marcus Brinkmann + + * gpgme.texi (Information About Keys): Document (badly) the new + key attributes. + + * gpgme.texi (Manipulating Data Buffers): Mention that backend + tries to detect encoding automatically. + +2002-07-03 Marcus Brinkmann + + * gpgme.texi (Run Control): Update this section. + (Waiting For Completion): Likewise for this subsection. + (Cancelling an Operation): Likewise for this subsection. + (Using External Event Loops): New subsection with several + subsubsections. + +2002-06-28 Marcus Brinkmann + + * gpgme.texi (Multi Threading): Remove item about the need to + synchronize anything against gpgme_wait (except gpgme_wait + itself). + +2002-06-27 Marcus Brinkmann + + * gpgme.texi (Information About Keys): Fix documentation for IDX. + (Information About Trust Items): Likewise. + +2002-06-26 Werner Koch + + * gpgme.texi (Importing Keys): Document the return value -1 of + gpgme_op_import. + +2002-06-20 Werner Koch + + * gpgme.texi (Verify): Explain the new whatidx variable. + +2002-06-10 Werner Koch + + * gpgme.texi (Verify): Document attribute GPGME_ATTR_ERRTOK. + +2002-06-04 Marcus Brinkmann + + * gpgme.texi (Multi Threading): Document new autodetection. + +2002-06-04 Marcus Brinkmann + + * Makefile.am (DISTCLEANFILES): New variable. + +2002-05-26 Marcus Brinkmann + + * gpgme.texi: Some typographical correctons throughout. + +2002-05-09 Marcus Brinkmann + + * gpgme.texi (Using Automake): New section. + +2002-05-09 Marcus Brinkmann + + * gpgme.texi (Multi Threading): Escape { and }. + +2002-05-09 Marcus Brinkmann + + * gpgme.texi (Overview): Replace note about thread-safeness. + (Multi Threading): New section. + +2002-05-03 Werner Koch + + * gpgme.texi (Manipulating Data Buffers): Changed some data types + to void*. + (Protocol Selection): Added gpgme_get_protocol. + (Verify): Updated to include the new attribute fucntions and + status codes. + +2002-04-27 Werner Koch + + * gpgme.texi (Manipulating Data Buffers): New type GpgmeDataEncoding. + +2002-04-23 Marcus Brinkmann + + * gpgme.texi (Passphrase Callback): Document that either return + argument can be NULL. + (Progress Meter Callback): Likewise. + +2002-04-22 Marcus Brinkmann + + * gpgme.texi (Passphrase Callback): Fix small typo. Document the + new function gpgme_get_passphrase_cb. + (Progress Meter Callback): Document the new function + gpgme_get_progress_cb. + +2002-04-16 Marcus Brinkmann + + * gpgme.texi (Creating a Signature): Fix function name. Reported + by Wichert Ackerman . + +2002-03-29 Marcus Brinkmann + + * gpgme.texi (direntry): End index entry with a full stop. + Patch submitted by Jose Carlos Garcia Sogo . + +2002-03-17 Marcus Brinkmann + + * gpgme.texi (Detailed Results): Fix syntax error in last change. + +2002-03-08 Werner Koch + + * gpgme.texi (Detailed Results): Import does also return info. + +2002-03-06 Marcus Brinkmann + + * gpgme.texi (Encrypting a Plaintext): Document symmetric + encryption. + +2002-03-06 Marcus Brinkmann + + * gpgme.texi (Error Strings): Add example. + * gpgme.texi (Listing Keys): Likewise. + +2002-03-03 Marcus Brinkmann + + * gpgme.texi (Information About Keys): Document GPGME_ATTR_EXPIRE. + +2002-03-03 Marcus Brinkmann + + * gpgme.texi (Verify): Document verification of normal and + cleartext signatures. + +2002-02-27 Marcus Brinkmann + + * gpgme.texi (Listing Keys): Document gpgme_op_keylist_ext_start. + +2002-02-27 Marcus Brinkmann + + * gpgme.texi (Encrypting a Plaintext): Document + GPGME_Invalid_Recipients. + (Error Values): Likewise. + +2002-02-26 Marcus Brinkmann + + * gpgme.texi (Encrypting a Plaintext): Document + gpgme_op_encrypt_sign and gpgme_op_encrypt_sign_start. + +2002-02-25 Marcus Brinkmann + + * gpgme.texi (Creating a Signature): Add a note about + certificates to include. + (Included Certificates): New section. + +2002-02-09 Marcus Brinkmann + + * gpgme.texi (Detailed Results): Remove literal tags. + (Generating Keys): Update documentation. + + * gpgme.texi (Generating Keys): Fix syntax error. + +2002-02-06 Marcus Brinkmann + + * gpgme.texi (Waiting For Completion): Adjust doc to changes in + the code. + +2002-02-06 Marcus Brinkmann + + * gpgme.texi (Key Listing Mode): Update documentation. + +2002-01-31 Marcus Brinkmann + + * gpgme.texi (Generating Keys): Document error at creation + failure. + +2002-01-30 Marcus Brinkmann + + * gpgme.texi (Deleting Keys): Document new error values. + +2002-01-30 Marcus Brinkmann + + * gpgme.texi (Importing Keys): Add reference to gpgme_get_op_info. + +2002-01-30 Marcus Brinkmann + + * gpgme.texi: Some spell checking. + +2002-01-30 Marcus Brinkmann + + * gpgme.texi: Add all the gpgme_op_*_start functions. + Fill the concept index with many, many entries. + +2002-01-29 Marcus Brinkmann + + * gpgme.texi (Run Control): New section. + (Verify): Docuent gpgme_get_notation. + (More Information): New section describing gpgme_get_op_info. + +2002-01-22 Marcus Brinkmann + + * gpgme.texi (Passphrase callback): Change GpgmePassphraseCb's + R_HD type from void* to void**. + +2002-01-22 Marcus Brinkmann + + * gpgme.texi (Creating data buffers): Change + gpgme_data_new_from_filepart's LENGTH type from off_t to size_t. + +2002-01-22 Marcus Brinkmann + + * gpgme.texi (Generating keys): New subsection. + (Exporting keys): Likewise. + (Importing keys): Likewise. + (Deleting keys): Likewise. + +2002-01-16 Marcus Brinkmann + + * gpgme.texi: g10Code -> g10 Code + + * gpgme.texi (Top): Complete detailmenu. + + * gpgme.texi: Convert embarassing cruft to the real thing. + +2002-01-16 Marcus Brinkmann + + * ChangeLog: New file. + * gpgme.texi: Likewise. + * gpl.texi: Likewise. + * fdl.texi: Likewise. + * Makefile.am (info_TEXINFOS): New variable. + (gpgme_TEXINFOS): Likewise. + + Copyright 2002, 2003, 2004 g10 Code GmbH + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/tags/gpgme-1.1.6/doc/Makefile.am b/tags/gpgme-1.1.6/doc/Makefile.am new file mode 100644 index 0000000..5d2d54c --- /dev/null +++ b/tags/gpgme-1.1.6/doc/Makefile.am @@ -0,0 +1,34 @@ +# doc - Automake template +# Copyright (C) 2001, 2004 g10 Code GmbH +# +# This file is part of GPGME. +# +# GPGME is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser 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 + +## Process this file with automake to produce Makefile.in + +DISTCLEANFILES = gpgme.tmp + +info_TEXINFOS = gpgme.texi +gpgme_TEXINFOS = lesser.texi + +online: gpgme.html gpgme.pdf + set -e; \ + echo "Uploading current manuals to www.gnupg.org ..."; \ + user=werner ; \ + (cd gpgme.html && rsync -vr --exclude='.svn' . \ + $${user}@cvs.gnupg.org:webspace/manuals/gpgme/ ); \ + rsync -v gpgme.pdf $${user}@cvs.gnupg.org:webspace/manuals/ + diff --git a/tags/gpgme-1.1.6/doc/gpgme.texi b/tags/gpgme-1.1.6/doc/gpgme.texi new file mode 100644 index 0000000..fe0ade2 --- /dev/null +++ b/tags/gpgme-1.1.6/doc/gpgme.texi @@ -0,0 +1,5489 @@ +()\input texinfo @c -*- Texinfo -*- +@setfilename gpgme.info +@settitle The `GnuPG Made Easy' Reference Manual + +@dircategory GNU Libraries +@direntry +* @acronym{GPGME}: (gpgme). Adding support for cryptography to your program. +@end direntry + +@include version.texi + +@c Unify some of the indices. +@syncodeindex tp fn +@syncodeindex pg fn + +@ifinfo +This file documents the @acronym{GPGME} library. + +This is Edition @value{EDITION}, last updated @value{UPDATED}, of +@cite{The `GnuPG Made Easy' Reference Manual}, for Version +@value{VERSION}. + +@c NOTE: Don't forget to update the year for the TeX version, too. +Copyright @copyright{} 2002, 2003, 2004, 2005, 2006, 2007 g10 Code GmbH. + +The GPGME reference manual is free software; you can redistribute it +and/or modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either version +2.1 of the License, or (at your option) any later version. + +The GPGME reference manual 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser 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 + +@end ifinfo + +@iftex +@shorttitlepage The `GnuPG Made Easy' Reference Manual +@end iftex +@titlepage +@center @titlefont{The `GnuPG Made Easy'} +@sp 1 +@center @titlefont{Reference Manual} +@sp 6 +@center Edition @value{EDITION} +@sp 1 +@center last updated @value{UPDATED} +@sp 1 +@center for version @value{VERSION} +@page +@vskip 0pt plus 1filll +Copyright @copyright{} 2002, 2003, 2004, 2005, 2006, 2007 g10 Code GmbH. + + +The GPGME reference manual is free software; you can redistribute it +and/or modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either version +2.1 of the License, or (at your option) any later version. + +The GPGME reference manual 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser 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 +@end titlepage +@page + +@ifnottex +@node Top +@top Main Menu +This is Edition @value{EDITION}, last updated @value{UPDATED}, of +@cite{The `GnuPG Made Easy' Reference Manual}, for Version +@value{VERSION} of the @acronym{GPGME} library. +@end ifnottex + +@menu +* Introduction:: How to use this manual. +* Preparation:: What you should do before using the library. +* Protocols and Engines:: Supported crypto protocols. +* Algorithms:: Supported algorithms. +* Error Handling:: Error numbers and their meanings. +* Exchanging Data:: Passing data to and from @acronym{GPGME}. +* Contexts:: Handling @acronym{GPGME} contexts. + +Appendices + +* Library Copying:: The GNU Lesser General Public License says + how you can copy and share `GnuPG Made Easy'. + +Indices + +* Concept Index:: Index of concepts and programs. +* Function and Data Index:: Index of functions, variables and data types. + + +@detailmenu + --- The Detailed Node Listing --- + +Introduction + +* Getting Started:: Purpose of the manual, and how to use it. +* Features:: Reasons to install and use @acronym{GPGME}. +* Overview:: Basic architecture of the @acronym{GPGME} library. + +Preparation + +* Header:: What header file you need to include. +* Building the Source:: Compiler options to be used. +* Largefile Support (LFS):: How to use @acronym{GPGME} with LFS. +* Using Automake:: Compiler options to be used the easy way. +* Using Libtool:: Avoiding compiler options entirely. +* Library Version Check:: Getting and verifying the library version. +* Signal Handling:: How @acronym{GPGME} affects signal handling. +* Multi Threading:: How @acronym{GPGME} can be used in an MT environment. + +Protocols and Engines + +* Engine Version Check:: Verifying the engine version. +* Engine Information:: Obtaining more information about the engines. +* Engine Configuration:: Changing the engine configuration. +* OpenPGP:: Support for the OpenPGP protocol. +* Cryptographic Message Syntax:: Support for the CMS. + +Algorithms + +* Public Key Algorithms:: A list of all public key algorithms. +* Hash Algorithms:: A list of all hash algorithms. + +Error Handling + +* Error Values:: The error value and what it means. +* Error Codes:: A list of important error codes. +* Error Sources:: A list of important error sources. +* Error Strings:: How to get a descriptive string from a value. + +Exchanging Data + +* Creating Data Buffers:: Creating new data buffers. +* Destroying Data Buffers:: Releasing data buffers. +* Manipulating Data Buffers:: Operations on data buffers. + +Creating Data Buffers + +* Memory Based Data Buffers:: Creating memory based data buffers. +* File Based Data Buffers:: Creating file based data buffers. +* Callback Based Data Buffers:: Creating callback based data buffers. + +Manipulating Data Buffers + +* Data Buffer I/O Operations:: I/O operations on data buffers. +* Data Buffer Meta-Data:: Meta-data manipulation of data buffers. + +Contexts + +* Creating Contexts:: Creating new @acronym{GPGME} contexts. +* Destroying Contexts:: Releasing @acronym{GPGME} contexts. +* Context Attributes:: Setting properties of a context. +* Key Management:: Managing keys with @acronym{GPGME}. +* Trust Item Management:: Managing trust items with @acronym{GPGME}. +* Crypto Operations:: Using a context for cryptography. +* Run Control:: Controlling how operations are run. + +Context Attributes + +* Protocol Selection:: Selecting the protocol used by a context. +* Crypto Engine:: Configuring the crypto engine. +* ASCII Armor:: Requesting @acronym{ASCII} armored output. +* Text Mode:: Choosing canonical text mode. +* Included Certificates:: Including a number of certificates. +* Key Listing Mode:: Selecting key listing mode. +* Passphrase Callback:: Getting the passphrase from the user. +* Progress Meter Callback:: Being informed about the progress. +* Locale:: Setting the locale of a context. + +Key Management + +* Listing Keys:: Browsing the list of available keys. +* Information About Keys:: Requesting detailed information about keys. +* Key Signatures:: Listing the signatures on a key. +* Manipulating Keys:: Operations on keys. +* Generating Keys:: Creating new key pairs. +* Exporting Keys:: Retrieving key data from the key ring. +* Importing Keys:: Adding keys to the key ring. +* Deleting Keys:: Removing keys from the key ring. +* Advanced Key Editing:: Advanced key edit operation. + +Trust Item Management + +* Listing Trust Items:: Browsing the list of available trust items. +* Information About Trust Items:: Requesting information about trust items. +* Manipulating Trust Items:: Operations on trust items. + +Crypto Operations + +* Decrypt:: Decrypting a ciphertext. +* Verify:: Verifying a signature. +* Decrypt and Verify:: Decrypting a signed ciphertext. +* Sign:: Creating a signature. +* Encrypt:: Encrypting a plaintext. + +Sign + +* Selecting Signers:: How to choose the keys to sign with. +* Creating a Signature:: How to create a signature. +* Signature Notation Data:: How to add notation data to a signature. + +Encrypt + +* Encrypting a Plaintext:: How to encrypt a plaintext. + +Run Control + +* Waiting For Completion:: Waiting until an operation is completed. +* Using External Event Loops:: Advanced control over what happens when. +* Cancellation:: How to end pending operations prematurely. + +Using External Event Loops + +* I/O Callback Interface:: How I/O callbacks are registered. +* Registering I/O Callbacks:: How to use I/O callbacks for a context. +* I/O Callback Example:: An example how to use I/O callbacks. +* I/O Callback Example GTK+:: How to integrate @acronym{GPGME} in GTK+. +* I/O Callback Example GDK:: How to integrate @acronym{GPGME} in GDK. +* I/O Callback Example Qt:: How to integrate @acronym{GPGME} in Qt. + +@end detailmenu +@end menu + +@node Introduction +@chapter Introduction + +`GnuPG Made Easy' (@acronym{GPGME}) is a C language library that +allows to add support for cryptography to a program. It is designed +to make access to public key crypto engines like GnuPG or GpgSM easier +for applications. @acronym{GPGME} provides a high-level crypto API +for encryption, decryption, signing, signature verification and key +management. + +@acronym{GPGME} uses GnuPG and GpgSM as its backends to support +OpenPGP and the Cryptographic Message Syntax (CMS). + +@menu +* Getting Started:: Purpose of the manual, and how to use it. +* Features:: Reasons to install and use @acronym{GPGME}. +* Overview:: Basic architecture of the @acronym{GPGME} library. +@end menu + + +@node Getting Started +@section Getting Started + +This manual documents the @acronym{GPGME} library programming +interface. All functions and data types provided by the library are +explained. + +The reader is assumed to possess basic knowledge about cryptography in +general, and public key cryptography in particular. The underlying +cryptographic engines that are used by the library are not explained, +but where necessary, special features or requirements by an engine are +mentioned as far as they are relevant to @acronym{GPGME} or its users. + +This manual can be used in several ways. If read from the beginning +to the end, it gives a good introduction into the library and how it +can be used in an application. Forward references are included where +necessary. Later on, the manual can be used as a reference manual to +get just the information needed about any particular interface of the +library. Experienced programmers might want to start looking at the +examples at the end of the manual, and then only read up those parts +of the interface which are unclear. + + +@node Features +@section Features + +@acronym{GPGME} has a couple of advantages over other libraries doing +a similar job, and over implementing support for GnuPG or other crypto +engines into your application directly. + +@table @asis +@item it's free software +Anybody can use, modify, and redistribute it under the terms of the GNU +Lesser General Public License (@pxref{Library Copying}). + +@item it's flexible +@acronym{GPGME} provides transparent support for several cryptographic +protocols by different engines. Currently, @acronym{GPGME} supports +the OpenPGP protocol using GnuPG as the backend, and the Cryptographic +Message Syntax using GpgSM as the backend. + +@item it's easy +@acronym{GPGME} hides the differences between the protocols and +engines from the programmer behind an easy-to-use interface. This way +the programmer can focus on the other parts of the program, and still +integrate strong cryptography in his application. Once support for +@acronym{GPGME} has been added to a program, it is easy to add support +for other crypto protocols once @acronym{GPGME} backends provide them. +@end table + + +@node Overview +@section Overview + +@acronym{GPGME} provides a data abstraction that is used to pass data +to the crypto engine, and receive returned data from it. Data can be +read from memory or from files, but it can also be provided by a +callback function. + +The actual cryptographic operations are always set within a context. +A context provides configuration parameters that define the behaviour +of all operations performed within it. Only one operation per context +is allowed at any time, but when one operation is finished, you can +run the next operation in the same context. There can be more than +one context, and all can run different operations at the same time. + +Furthermore, @acronym{GPGME} has rich key management facilities +including listing keys, querying their attributes, generating, +importing, exporting and deleting keys, and acquiring information +about the trust path. + +With some precautions, @acronym{GPGME} can be used in a multi-threaded +environment, although it is not completely thread safe and thus needs +the support of the application. + + +@node Preparation +@chapter Preparation + +To use @acronym{GPGME}, you have to perform some changes to your +sources and the build system. The necessary changes are small and +explained in the following sections. At the end of this chapter, it +is described how the library is initialized, and how the requirements +of the library are verified. + +@menu +* Header:: What header file you need to include. +* Building the Source:: Compiler options to be used. +* Largefile Support (LFS):: How to use @acronym{GPGME} with LFS. +* Using Automake:: Compiler options to be used the easy way. +* Using Libtool:: Avoiding compiler options entirely. +* Library Version Check:: Getting and verifying the library version. +* Signal Handling:: How @acronym{GPGME} affects signal handling. +* Multi Threading:: How @acronym{GPGME} can be used in an MT environment. +@end menu + + +@node Header +@section Header +@cindex header file +@cindex include file + +All interfaces (data types and functions) of the library are defined +in the header file `gpgme.h'. You must include this in all programs +using the library, either directly or through some other header file, +like this: + +@example +#include +@end example + +The name space of @acronym{GPGME} is @code{gpgme_*} for function names +and data types and @code{GPGME_*} for other symbols. Symbols internal +to @acronym{GPGME} take the form @code{_gpgme_*} and @code{_GPGME_*}. + +Because @acronym{GPGME} makes use of the GPG Error library, using +@acronym{GPGME} will also use the @code{GPG_ERR_*} name space +directly, and the @code{gpg_err*} and @code{gpg_str*} name space +indirectly. + + +@node Building the Source +@section Building the Source +@cindex compiler options +@cindex compiler flags + +If you want to compile a source file including the `gpgme.h' header +file, you must make sure that the compiler can find it in the +directory hierarchy. This is accomplished by adding the path to the +directory in which the header file is located to the compilers include +file search path (via the @option{-I} option). + +However, the path to the include file is determined at the time the +source is configured. To solve this problem, gpgme ships with a small +helper program @command{gpgme-config} that knows about the path to the +include file and other configuration options. The options that need +to be added to the compiler invocation at compile time are output by +the @option{--cflags} option to @command{gpgme-config}. The following +example shows how it can be used at the command line: + +@example +gcc -c foo.c `gpgme-config --cflags` +@end example + +Adding the output of @samp{gpgme-config --cflags} to the compiler +command line will ensure that the compiler can find the +@acronym{GPGME} header file. + +A similar problem occurs when linking the program with the library. +Again, the compiler has to find the library files. For this to work, +the path to the library files has to be added to the library search +path (via the @option{-L} option). For this, the option +@option{--libs} to @command{gpgme-config} can be used. For +convenience, this option also outputs all other options that are +required to link the program with @acronym{GPGME} (in particular, the +@samp{-lgpgme} option). The example shows how to link @file{foo.o} +with the @acronym{GPGME} library to a program @command{foo}. + +@example +gcc -o foo foo.o `gpgme-config --libs` +@end example + +Of course you can also combine both examples to a single command by +specifying both options to @command{gpgme-config}: + +@example +gcc -o foo foo.c `gpgme-config --cflags --libs` +@end example + +If you want to link to one of the thread-safe versions of +@acronym{GPGME}, you must specify the @option{--thread} option before +any other option to select the thread package you want to link with. +Supported thread packages are @option{--thread=pth} and +@option{--thread=pthread}. + + +@node Largefile Support (LFS) +@section Largefile Support (LFS) +@cindex largefile support +@cindex LFS + +@acronym{GPGME} is compiled with largefile support by default, if it +is available on the system. This means that GPGME supports files +larger than two gigabyte in size, if the underlying operating system +can. On some systems, largefile support is already the default. On +such systems, nothing special is required. However, some systems +provide only support for files up to two gigabyte in size by default. +Support for larger file sizes has to be specifically enabled. + +To make a difficult situation even more complex, such systems provide +two different types of largefile support. You can either get all +relevant functions replaced with alternatives that are largefile +capable, or you can get new functions and data types for largefile +support added. Those new functions have the same name as their +smallfile counterparts, but with a suffix of 64. + +An example: The data type @code{off_t} is 32 bit wide on GNU/Linux PC +systems. To address offsets in large files, you can either enable +largefile support add-on. Then a new data type @code{off64_t} is +provided, which is 64 bit wide. Or you can replace the existing +@code{off_t} data type with its 64 bit wide counterpart. All +occurences of @code{off_t} are then automagically replaced. + +As if matters were not complex enough, there are also two different +types of file descriptors in such systems. This is important because +if file descriptors are exchanged between programs that use a +different maximum file size, certain errors must be produced on some +file descriptors to prevent subtle overflow bugs from occuring. + +As you can see, supporting two different maximum file sizes at the +same time is not at all an easy task. However, the maximum file size +does matter for @acronym{GPGME}, because some data types it uses in +its interfaces are affected by that. For example, the @code{off_t} +data type is used in the @code{gpgme_data_seek} function, to match its +@acronym{POSIX} counterpart. This affects the call-frame of the +function, and thus the ABI of the library. Furthermore, file +descriptors can be exchanged between GPGME and the application. + +For you as the user of the library, this means that your program must +be compiled in the same file size mode as the library. Luckily, there +is absolutely no valid reason for new programs to not enable largefile +support by default and just use that. The compatibility modes (small +file sizes or dual mode) can be considered an historic artefact, only +useful to allow for a transitional period. + +@acronym{GPGME} is compiled using largefile support by default. This +means that your application must do the same, at least as far as it is +relevant for using the @file{gpgme.h} header file. All types in this +header files refer to their largefile counterparts, if they are +different from any default types on the system. + +You can enable largefile support, if it is different from the default +on the system the application is compiled on, by using the Autoconf +macro @code{AC_SYS_LARGEFILE}. If you do this, then you don't need to +worry about anything else: It will just work. In this case you might +also want to use @code{AC_FUNC_FSEEKO} to take advantage of some new +interfaces, and @code{AC_TYPE_OFF_T} (just in case). + +If you do not use Autoconf, you can define the preprocessor symbol +@code{_FILE_OFFSET_BITS} to 64 @emph{before} including any header +files, for example by specifying the option +@code{-D_FILE_OFFSET_BITS=64} on the compiler command line. You will +also want to define the preprocessor symbol @code{LARGEFILE_SOURCE} to +1 in this case, to take advantage of some new interfaces. + +If you do not want to do either of the above, you probably know enough +about the issue to invent your own solution. Just keep in mind that +the @acronym{GPGME} header file expects that largefile support is +enabled, if it is available. In particular, we do not support dual +mode (@code{_LARGEFILE64_SOURCE}). + + +@node Using Automake +@section Using Automake +@cindex automake +@cindex autoconf + +It is much easier if you use GNU Automake instead of writing your own +Makefiles. If you do that you do not have to worry about finding and +invoking the @command{gpgme-config} script at all. @acronym{GPGME} +provides an extension to Automake that does all the work for you. + +@c A simple macro for optional variables. +@macro ovar{varname} +@r{[}@var{\varname\}@r{]} +@end macro +@defmac AM_PATH_GPGME (@ovar{minimum-version}, @ovar{action-if-found}, @ovar{action-if-not-found}) +@defmacx AM_PATH_GPGME_PTH (@ovar{minimum-version}, @ovar{action-if-found}, @ovar{action-if-not-found}) +@defmacx AM_PATH_GPGME_PTHREAD (@ovar{minimum-version}, @ovar{action-if-found}, @ovar{action-if-not-found}) +Check whether @acronym{GPGME} (at least version @var{minimum-version}, +if given) exists on the host system. If it is found, execute +@var{action-if-found}, otherwise do @var{action-if-not-found}, if +given. + +Additionally, the function defines @code{GPGME_CFLAGS} to the flags +needed for compilation of the program to find the @file{gpgme.h} +header file, and @code{GPGME_LIBS} to the linker flags needed to link +the program to the @acronym{GPGME} library. + +@code{AM_PATH_GPGME_PTH} checks for the version of @acronym{GPGME} +that can be used with GNU Pth, and defines @code{GPGME_PTH_CFLAGS} and +@code{GPGME_PTH_LIBS}. + +@code{AM_PATH_GPGME_PTHREAD} checks for the version of @acronym{GPGME} +that can be used with the native pthread implementation, and defines +@code{GPGME_PTHREAD_CFLAGS} and @code{GPGME_PTHREAD_LIBS}. +@end defmac + +You can use the defined Autoconf variables like this in your +@file{Makefile.am}: + +@example +AM_CPPFLAGS = $(GPGME_CFLAGS) +LDADD = $(GPGME_LIBS) +@end example + + +@node Using Libtool +@section Using Libtool +@cindex libtool + +The easiest way is to just use GNU Libtool. If you use libtool, and +link to @code{libgpgme.la}, @code{libgpgme-pth.la} or +@code{libgpgme-pthread.la} respectively, everything will be done +automatically by Libtool. + + +@node Library Version Check +@section Library Version Check +@cindex version check, of the library + +@deftypefun {const char *} gpgme_check_version (@w{const char *@var{required_version}}) +The function @code{gpgme_check_version} has three purposes. It can be +used to retrieve the version number of the library. In addition it +can verify that the version number is higher than a certain required +version number. In either case, the function initializes some +sub-systems, and for this reason alone it must be invoked early in +your program, before you make use of the other functions in +@acronym{GPGME}. + +As a side effect for W32 based systems, the socket layer will get +initialized. + + +If @var{required_version} is @code{NULL}, the function returns a +pointer to a statically allocated string containing the version number +of the library. + +If @var{required_version} is not @code{NULL}, it should point to a +string containing a version number, and the function checks that the +version of the library is at least as high as the version number +provided. In this case, the function returns a pointer to a +statically allocated string containing the version number of the +library. If @var{REQUIRED_VERSION} is not a valid version number, or +if the version requirement is not met, the function returns +@code{NULL}. + +If you use a version of a library that is backwards compatible with +older releases, but contains additional interfaces which your program +uses, this function provides a run-time check if the necessary +features are provided by the installed version of the library. +@end deftypefun + + +After initializing @acronym{GPGME}, you should set the locale +information to the locale required for your output terminal. This +locale information is needed for example for the curses and Gtk +pinentry. Here is an example of a complete initialization: + +@example +#include +#include + +void +init_program (void) +@{ + /* Initialize the locale environment. */ + setlocale (LC_ALL, ""); + gpgme_check_version (NULL); + gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL)); +#ifdef LC_MESSAGES + gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL)); +#endif +@} +@end example + +Note that you are highly recommended to initialize the locale settings +like this. @acronym{GPGME} can not do this for you because it would +not be thread safe. The conditional on LC_MESSAGES is only necessary +for portability to W32 systems. + + +@node Signal Handling +@section Signal Handling +@cindex signals +@cindex signal handling + +The @acronym{GPGME} library communicates with child processes (the +crypto engines). If a child process dies unexpectedly, for example +due to a bug, or system problem, a @code{SIGPIPE} signal will be +delivered to the application. The default action is to abort the +program. To protect against this, @code{gpgme_check_version} sets the +@code{SIGPIPE} signal action to @code{SIG_IGN}, which means that the +signal will be ignored. + +@acronym{GPGME} will only do that if the signal action for +@code{SIGPIPE} is @code{SIG_DEF} at the time +@code{gpgme_check_version} is called. If it is something different, +@code{GPGME} will take no action. + +This means that if your application does not install any signal +handler for @code{SIGPIPE}, you don't need to take any precautions. +If you do install a signal handler for @code{SIGPIPE}, you must be +prepared to handle any @code{SIGPIPE} events that occur due to +@acronym{GPGME} writing to a defunct pipe. Furthermore, if your +application is multi-threaded, and you install a signal action for +@code{SIGPIPE}, you must make sure you do this either before +@code{gpgme_check_version} is called or afterwards. + + +@node Multi Threading +@section Multi Threading +@cindex thread-safeness +@cindex multi-threading + +The @acronym{GPGME} library is not entirely thread-safe, but it can +still be used in a multi-threaded environment if some care is taken. +If the following requirements are met, there should be no race +conditions to worry about: + +@itemize @bullet +@item +@acronym{GPGME} supports the thread libraries pthread and GNU Pth. +The support for this has to be enabled at compile time. +@acronym{GPGME} will automatically detect the location in which the +thread libraries are installed and activate the support for them at +build time. + +Support for other thread libraries is very easy to add. Please +contact us if you have the need. + +@item +If you want to use @acronym{GPGME} with threads, you must link to the +right version of the library. The name of the right library is +@code{libgpgme-} followed by the name of the thread package you use. +For example, if you use GNU Pth, the right name is +@code{libgpgme-pth}. Use the Automake macros or +@command{gpgme-config} program for simplicity. + + +@item +The function @code{gpgme_check_version} must be called before any +other function in the library, because it initializes the thread +support subsystem in @acronym{GPGME}. To achieve this in +multi-threaded programs, you must synchronize the memory with respect +to other threads that also want to use @acronym{GPGME}. For this, it +is sufficient to call @code{gpgme_check_version} before creating the +other threads using @acronym{GPGME}@footnote{At least this is true for +POSIX threads, as @code{pthread_create} is a function that +synchronizes memory with respects to other threads. There are many +functions which have this property, a complete list can be found in +POSIX, IEEE Std 1003.1-2003, Base Definitions, Issue 6, in the +definition of the term ``Memory Synchronization''. For other thread +packages other, more relaxed or more strict rules may apply.}. + +@item +Any @code{gpgme_data_t} and @code{gpgme_ctx_t} object must only be +accessed by one thread at a time. If multiple threads want to deal +with the same object, the caller has to make sure that operations on +that object are fully synchronized. + +@item +Only one thread at any time is allowed to call @code{gpgme_wait}. If +multiple threads call this function, the caller must make sure that +all invocations are fully synchronized. It is safe to start +asynchronous operations while a thread is running in gpgme_wait. + +@item +The function @code{gpgme_strerror} is not thread safe. You have to +use @code{gpgme_strerror_r} instead. +@end itemize + + +@node Protocols and Engines +@chapter Protocols and Engines +@cindex protocol +@cindex engine +@cindex crypto engine +@cindex backend +@cindex crypto backend + +@acronym{GPGME} supports several cryptographic protocols, however, it +does not implement them. Rather it uses backends (also called +engines) which implement the protocol. @acronym{GPGME} uses +inter-process communication to pass data back and forth between the +application and the backend, but the details of the communication +protocol and invocation of the backend is completely hidden by the +interface. All complexity is handled by @acronym{GPGME}. Where an +exchange of information between the application and the backend is +necessary, @acronym{GPGME} provides the necessary callback function +hooks and further interfaces. + +@deftp {Data type} {enum gpgme_protocol_t} +@tindex gpgme_protocol_t +The @code{gpgme_protocol_t} type specifies the set of possible protocol +values that are supported by @acronym{GPGME}. The following protocols +are supported: + +@table @code +@item GPGME_PROTOCOL_OpenPGP +This specifies the OpenPGP protocol. + +@item GPGME_PROTOCOL_CMS +This specifies the Cryptographic Message Syntax. + +@item GPGME_PROTOCOL_UNKNOWN +Reserved for future extension. You may use this to indicate that the +used protocol is not known to the application. Currently, +@acronym{GPGME} does not accept this value in any operation, though, +except for @code{gpgme_get_protocol_name}. +@end table +@end deftp + + +@deftypefun {const char *} gpgme_get_protocol_name (@w{gpgme_protocol_t @var{protocol}}) +The function @code{gpgme_get_protocol_name} returns a statically +allocated string describing the protocol @var{protocol}, or +@code{NULL} if the protocol number is not valid. +@end deftypefun + +@menu +* Engine Version Check:: Verifying the engine version. +* Engine Information:: Obtaining more information about the engines. +* Engine Configuration:: Changing the engine configuration. +* OpenPGP:: Support for the OpenPGP protocol. +* Cryptographic Message Syntax:: Support for the CMS. +@end menu + + +@node Engine Version Check +@section Engine Version Check +@cindex version check, of the engines + +@deftypefun gpgme_error_t gpgme_engine_check_version (@w{gpgme_protocol_t @var{protocol}}) +The function @code{gpgme_engine_check_version} verifies that the +engine implementing the protocol @var{PROTOCOL} is installed in the +expected path and meets the version requirement of @acronym{GPGME}. + +This function returns the error code @code{GPG_ERR_NO_ERROR} if the +engine is available and @code{GPG_ERR_INV_ENGINE} if it is not. +@end deftypefun + + +@node Engine Information +@section Engine Information +@cindex engine, information about + +@deftp {Data type} {gpgme_engine_info_t} +@tindex gpgme_protocol_t +The @code{gpgme_engine_info_t} type specifies a pointer to a structure +describing a crypto engine. The structure contains the following +elements: + +@table @code +@item gpgme_engine_info_t next +This is a pointer to the next engine info structure in the linked +list, or @code{NULL} if this is the last element. + +@item gpgme_protocol_t protocol +This is the protocol for which the crypto engine is used. You can +convert this to a string with @code{gpgme_get_protocol_name} for +printing. + +@item const char *file_name +This is a string holding the file name of the executable of the crypto +engine. Currently, it is never @code{NULL}, but using @code{NULL} is +reserved for future use, so always check before you use it. + +@item const char *home_dir +This is a string holding the directory name of the crypto engine's +configuration directory. If it is @code{NULL}, then the default +directory is used. + +@item const char *version +This is a string containing the version number of the crypto engine. +It might be @code{NULL} if the version number can not be determined, +for example because the executable doesn't exist or is invalid. + +@item const char *req_version +This is a string containing the minimum required version number of the +crypto engine for @acronym{GPGME} to work correctly. This is the +version number that @code{gpgme_engine_check_version} verifies +against. Currently, it is never @code{NULL}, but using @code{NULL} is +reserved for future use, so always check before you use it. +@end table +@end deftp + +@deftypefun gpgme_error_t gpgme_get_engine_info (@w{gpgme_engine_info_t *@var{info}}) +The function @code{gpgme_get_engine_info} returns a linked list of +engine info structures in @var{info}. Each info structure describes +the defaults of one configured backend. + +The memory for the info structures is allocated the first time this +function is invoked, and must not be freed by the caller. + +This function returns the error code @code{GPG_ERR_NO_ERROR} if +successful, and a system error if the memory could not be allocated. +@end deftypefun + +Here is an example how you can provide more diagnostics if you receive +an error message which indicates that the crypto engine is invalid. + +@example +gpgme_ctx_t ctx; +gpgme_error_t err; + +[...] + +if (gpgme_err_code (err) == GPG_ERR_INV_ENGINE) + @{ + gpgme_engine_info_t info; + err = gpgme_get_engine_info (&info); + if (!err) + @{ + while (info && info->protocol != gpgme_get_protocol (ctx)) + info = info->next; + if (!info) + fprintf (stderr, "GPGME compiled without support for protocol %s", + gpgme_get_protocol_name (info->protocol)); + else if (info->path && !info->version) + fprintf (stderr, "Engine %s not installed properly", + info->path); + else if (info->path && info->version && info->req_version) + fprintf (stderr, "Engine %s version %s installed, " + "but at least version %s required", info->path, + info->version, info->req_version); + else + fprintf (stderr, "Unknown problem with engine for protocol %s", + gpgme_get_protocol_name (info->protocol)); + @} + @} +@end example + + +@node Engine Configuration +@section Engine Configuration +@cindex engine, configuration of +@cindex configuration of crypto backend + +You can change the configuration of a backend engine, and thus change +the executable program and configuration directory to be used. You +can make these changes the default or set them for some contexts +individually. + +@deftypefun gpgme_error_t gpgme_set_engine_info (@w{gpgme_protocol_t @var{proto}}, @w{const char *@var{file_name}}, @w{const char *@var{home_dir}}) +The function @code{gpgme_set_engine_info} changes the default +configuration of the crypto engine implementing the protocol +@var{proto}. + +@var{file_name} is the file name of the executable program +implementing this protocol, and @var{home_dir} is the directory name +of the configuration directory for this crypto engine. If +@var{home_dir} is @code{NULL}, the engine's default will be used. + +The new defaults are not applied to already created GPGME contexts. + +This function returns the error code @code{GPG_ERR_NO_ERROR} if +successful, or an eror code on failure. +@end deftypefun + +The functions @code{gpgme_ctx_get_engine_info} and +@code{gpgme_ctx_set_engine_info} can be used to change the engine +configuration per context. @xref{Crypto Engine}. + + +@node OpenPGP +@section OpenPGP +@cindex OpenPGP +@cindex GnuPG +@cindex protocol, GnuPG +@cindex engine, GnuPG + +OpenPGP is implemented by GnuPG, the @acronym{GNU} Privacy Guard. +This is the first protocol that was supported by @acronym{GPGME}. + +The OpenPGP protocol is specified by @code{GPGME_PROTOCOL_OpenPGP}. + + +@node Cryptographic Message Syntax +@section Cryptographic Message Syntax +@cindex CMS +@cindex cryptographic message syntax +@cindex GpgSM +@cindex protocol, CMS +@cindex engine, GpgSM +@cindex S/MIME +@cindex protocol, S/MIME + +@acronym{CMS} is implemented by GpgSM, the S/MIME implementation for +GnuPG. + +The @acronym{CMS} protocol is specified by @code{GPGME_PROTOCOL_CMS}. + + +@node Algorithms +@chapter Algorithms +@cindex algorithms + +The crypto backends support a variety of algorithms used in public key +cryptography. The following sections list the identifiers used to +denote such an algorithm. + +@menu +* Public Key Algorithms:: A list of all public key algorithms. +* Hash Algorithms:: A list of all hash algorithms. +@end menu + + +@node Public Key Algorithms +@section Public Key Algorithms +@cindex algorithms, public key +@cindex public key algorithms + +Public key algorithms are used for encryption, decryption, signing and +verification of signatures. + +@deftp {Data type} {enum gpgme_pubkey_algo_t} +@tindex gpgme_pubkey_algo_t +The @code{gpgme_pubkey_algo_t} type specifies the set of all public key +algorithms that are supported by @acronym{GPGME}. Possible values +are: + +@table @code +@item GPGME_PK_RSA +This value indicates the RSA (Rivest, Shamir, Adleman) algorithm. + +@item GPGME_PK_RSA_E +Deprecated. This value indicates the RSA (Rivest, Shamir, Adleman) +algorithm for encryption and decryption only. + +@item GPGME_PK_RSA_S +Deprecated. This value indicates the RSA (Rivest, Shamir, Adleman) +algorithm for signing and verification only. + +@item GPGME_PK_DSA +This value indicates DSA, the Digital Signature Algorithm. + +@item GPGME_PK_ELG +This value indicates ElGamal. + +@item GPGME_PK_ELG_E +This value also indicates ElGamal and is used specifically in GnuPG. +@end table +@end deftp + +@deftypefun {const char *} gpgme_pubkey_algo_name (@w{gpgme_pubkey_algo_t @var{algo}}) +The function @code{gpgme_pubkey_algo_name} returns a pointer to a +statically allocated string containing a description of the public key +algorithm @var{algo}. This string can be used to output the name of +the public key algorithm to the user. + +If @var{algo} is not a valid public key algorithm, @code{NULL} is +returned. +@end deftypefun + + +@node Hash Algorithms +@section Hash Algorithms +@cindex algorithms, hash +@cindex algorithms, message digest +@cindex hash algorithms +@cindex message digest algorithms + +Hash (message digest) algorithms are used to compress a long message +to make it suitable for public key cryptography. + +@deftp {Data type} {enum gpgme_hash_algo_t} +@tindex gpgme_hash_algo_t +The @code{gpgme_hash_algo_t} type specifies the set of all hash algorithms +that are supported by @acronym{GPGME}. Possible values are: + +@table @code +@item GPGME_MD_MD5 +@item GPGME_MD_SHA1 +@item GPGME_MD_RMD160 +@item GPGME_MD_MD2 +@item GPGME_MD_TIGER +@item GPGME_MD_HAVAL +@item GPGME_MD_SHA256 +@item GPGME_MD_SHA384 +@item GPGME_MD_SHA512 +@item GPGME_MD_MD4 +@item GPGME_MD_CRC32 +@item GPGME_MD_CRC32_RFC1510 +@item GPGME_MD_CRC24_RFC2440 +@end table +@end deftp + +@deftypefun {const char *} gpgme_hash_algo_name (@w{gpgme_hash_algo_t @var{algo}}) +The function @code{gpgme_hash_algo_name} returns a pointer to a +statically allocated string containing a description of the hash +algorithm @var{algo}. This string can be used to output the name of +the hash algorithm to the user. + +If @var{algo} is not a valid hash algorithm, @code{NULL} is returned. +@end deftypefun + + +@node Error Handling +@chapter Error Handling +@cindex error handling + +Many functions in @acronym{GPGME} can return an error if they fail. +For this reason, the application should always catch the error +condition and take appropriate measures, for example by releasing the +resources and passing the error up to the caller, or by displaying a +descriptive message to the user and cancelling the operation. + +Some error values do not indicate a system error or an error in the +operation, but the result of an operation that failed properly. For +example, if you try to decrypt a tempered message, the decryption will +fail. Another error value actually means that the end of a data +buffer or list has been reached. The following descriptions explain +for many error codes what they mean usually. Some error values have +specific meanings if returned by a certain functions. Such cases are +described in the documentation of those functions. + +@acronym{GPGME} uses the @code{libgpg-error} library. This allows to +share the error codes with other components of the GnuPG system, and +thus pass error values transparently from the crypto engine, or some +helper application of the crypto engine, to the user. This way no +information is lost. As a consequence, @acronym{GPGME} does not use +its own identifiers for error codes, but uses those provided by +@code{libgpg-error}. They usually start with @code{GPG_ERR_}. + +However, @acronym{GPGME} does provide aliases for the functions +defined in libgpg-error, which might be preferred for name space +consistency. + +@menu +* Error Values:: The error value and what it means. +* Error Sources:: A list of important error sources. +* Error Codes:: A list of important error codes. +* Error Strings:: How to get a descriptive string from a value. +@end menu + + +@node Error Values +@section Error Values +@cindex error values +@cindex error codes +@cindex error sources + +@deftp {Data type} {gpgme_err_code_t} +The @code{gpgme_err_code_t} type is an alias for the @code{libgpg-error} +type @code{gpg_err_code_t}. The error code indicates the type of an +error, or the reason why an operation failed. + +A list of important error codes can be found in the next section. +@end deftp + +@deftp {Data type} {gpgme_err_source_t} +The @code{gpgme_err_source_t} type is an alias for the +@code{libgpg-error} type @code{gpg_err_source_t}. The error source +has not a precisely defined meaning. Sometimes it is the place where +the error happened, sometimes it is the place where an error was +encoded into an error value. Usually the error source will give an +indication to where to look for the problem. This is not always true, +but it is attempted to achieve this goal. + +A list of important error sources can be found in the next section. +@end deftp + +@deftp {Data type} {gpgme_error_t} +The @code{gpgme_error_t} type is an alias for the @code{libgpg-error} +type @code{gpg_error_t}. An error value like this has always two +components, an error code and an error source. Both together form the +error value. + +Thus, the error value can not be directly compared against an error +code, but the accessor functions described below must be used. +However, it is guaranteed that only 0 is used to indicate success +(@code{GPG_ERR_NO_ERROR}), and that in this case all other parts of +the error value are set to 0, too. + +Note that in @acronym{GPGME}, the error source is used purely for +diagnostical purposes. Only the error code should be checked to test +for a certain outcome of a function. The manual only documents the +error code part of an error value. The error source is left +unspecified and might be anything. +@end deftp + +@deftypefun {static inline gpgme_err_code_t} gpgme_err_code (@w{gpgme_error_t @var{err}}) +The static inline function @code{gpgme_err_code} returns the +@code{gpgme_err_code_t} component of the error value @var{err}. This +function must be used to extract the error code from an error value in +order to compare it with the @code{GPG_ERR_*} error code macros. +@end deftypefun + +@deftypefun {static inline gpgme_err_source_t} gpgme_err_source (@w{gpgme_error_t @var{err}}) +The static inline function @code{gpgme_err_source} returns the +@code{gpgme_err_source_t} component of the error value @var{err}. This +function must be used to extract the error source from an error value in +order to compare it with the @code{GPG_ERR_SOURCE_*} error source macros. +@end deftypefun + +@deftypefun {static inline gpgme_error_t} gpgme_err_make (@w{gpgme_err_source_t @var{source}}, @w{gpgme_err_code_t @var{code}}) +The static inline function @code{gpgme_err_make} returns the error +value consisting of the error source @var{source} and the error code +@var{code}. + +This function can be used in callback functions to construct an error +value to return it to the library. +@end deftypefun + +@deftypefun {static inline gpgme_error_t} gpgme_error (@w{gpgme_err_code_t @var{code}}) +The static inline function @code{gpgme_error} returns the error value +consisting of the default error source and the error code @var{code}. + +For @acronym{GPGME} applications, the default error source is +@code{GPG_ERR_SOURCE_USER_1}. You can define +@code{GPGME_ERR_SOURCE_DEFAULT} before including @file{gpgme.h} to +change this default. + +This function can be used in callback functions to construct an error +value to return it to the library. +@end deftypefun + +The @code{libgpg-error} library provides error codes for all system +error numbers it knows about. If @var{err} is an unknown error +number, the error code @code{GPG_ERR_UNKNOWN_ERRNO} is used. The +following functions can be used to construct error values from system +errnor numbers. + +@deftypefun {gpgme_error_t} gpgme_err_make_from_errno (@w{gpgme_err_source_t @var{source}}, @w{int @var{err}}) +The function @code{gpgme_err_make_from_errno} is like +@code{gpgme_err_make}, but it takes a system error like @code{errno} +instead of a @code{gpgme_err_code_t} error code. +@end deftypefun + +@deftypefun {gpgme_error_t} gpgme_error_from_errno (@w{int @var{err}}) +The function @code{gpgme_error_from_errno} is like @code{gpgme_error}, +but it takes a system error like @code{errno} instead of a +@code{gpgme_err_code_t} error code. +@end deftypefun + +Sometimes you might want to map system error numbers to error codes +directly, or map an error code representing a system error back to the +system error number. The following functions can be used to do that. + +@deftypefun {gpgme_err_code_t} gpgme_err_code_from_errno (@w{int @var{err}}) +The function @code{gpgme_err_code_from_errno} returns the error code +for the system error @var{err}. If @var{err} is not a known system +error, the function returns @code{GPG_ERR_UNKNOWN_ERRNO}. +@end deftypefun + +@deftypefun {int} gpgme_err_code_to_errno (@w{gpgme_err_code_t @var{err}}) +The function @code{gpgme_err_code_to_errno} returns the system error +for the error code @var{err}. If @var{err} is not an error code +representing a system error, or if this system error is not defined on +this system, the function returns @code{0}. +@end deftypefun + + +@node Error Sources +@section Error Sources +@cindex error codes, list of + +The library @code{libgpg-error} defines an error source for every +component of the GnuPG system. The error source part of an error +value is not well defined. As such it is mainly useful to improve the +diagnostic error message for the user. + +If the error code part of an error value is @code{0}, the whole error +value will be @code{0}. In this case the error source part is of +course @code{GPG_ERR_SOURCE_UNKNOWN}. + +The list of error sources that might occur in applications using +@acronym{GPGME} is: + +@table @code +@item GPG_ERR_SOURCE_UNKNOWN +The error source is not known. The value of this error source is +@code{0}. + +@item GPG_ERR_SOURCE_GPGME +The error source is @acronym{GPGME} itself. This is the default for +errors that occur in the @acronym{GPGME} library. + +@item GPG_ERR_SOURCE_GPG +The error source is GnuPG, which is the crypto engine used for the +OpenPGP protocol. + +@item GPG_ERR_SOURCE_GPGSM +The error source is GPGSM, which is the crypto engine used for the +CMS protocol. + +@item GPG_ERR_SOURCE_GCRYPT +The error source is @code{libgcrypt}, which is used by crypto engines +to perform cryptographic operations. + +@item GPG_ERR_SOURCE_GPGAGENT +The error source is @command{gpg-agent}, which is used by crypto +engines to perform operations with the secret key. + +@item GPG_ERR_SOURCE_PINENTRY +The error source is @command{pinentry}, which is used by +@command{gpg-agent} to query the passphrase to unlock a secret key. + +@item GPG_ERR_SOURCE_SCD +The error source is the SmartCard Daemon, which is used by +@command{gpg-agent} to delegate operations with the secret key to a +SmartCard. + +@item GPG_ERR_SOURCE_KEYBOX +The error source is @code{libkbx}, a library used by the crypto +engines to manage local keyrings. + +@item GPG_ERR_SOURCE_USER_1 +@item GPG_ERR_SOURCE_USER_2 +@item GPG_ERR_SOURCE_USER_3 +@item GPG_ERR_SOURCE_USER_4 +These error sources are not used by any GnuPG component and can be +used by other software. For example, applications using +@acronym{GPGME} can use them to mark error values coming from callback +handlers. Thus @code{GPG_ERR_SOURCE_USER_1} is the default for errors +created with @code{gpgme_error} and @code{gpgme_error_from_errno}, +unless you define @code{GPGME_ERR_SOURCE_DEFAULT} before including +@file{gpgme.h}. +@end table + + +@node Error Codes +@section Error Codes +@cindex error codes, list of + +The library @code{libgpg-error} defines many error values. Most of +them are not used by @code{GPGME} directly, but might be returned by +@acronym{GPGME} because it received them from the crypto engine. The +below list only includes such error codes that have a specific meaning +in @code{GPGME}, or which are so common that you should know about +them. + +@table @code +@item GPG_ERR_EOF +This value indicates the end of a list, buffer or file. + +@item GPG_ERR_NO_ERROR +This value indicates success. The value of this error code is +@code{0}. Also, it is guaranteed that an error value made from the +error code @code{0} will be @code{0} itself (as a whole). This means +that the error source information is lost for this error code, +however, as this error code indicates that no error occured, this is +generally not a problem. + +@item GPG_ERR_GENERAL +This value means that something went wrong, but either there is not +enough information about the problem to return a more useful error +value, or there is no separate error value for this type of problem. + +@item GPG_ERR_ENOMEM +This value means that an out-of-memory condition occurred. + +@item GPG_ERR_E... +System errors are mapped to GPG_ERR_FOO where FOO is the symbol for +the system error. + +@item GPG_ERR_INV_VALUE +This value means that some user provided data was out of range. This +can also refer to objects. For example, if an empty +@code{gpgme_data_t} object was expected, but one containing data was +provided, this error value is returned. + +@item GPG_ERR_UNUSABLE_PUBKEY +This value means that some recipients for a message were invalid. + +@item GPG_ERR_UNUSABLE_SECKEY +This value means that some signers were invalid. + +@item GPG_ERR_NO_DATA +This value means that a @code{gpgme_data_t} object which was expected +to have content was found empty. + +@item GPG_ERR_CONFLICT +This value means that a conflict of some sort occurred. + +@item GPG_ERR_NOT_IMPLEMENTED +This value indicates that the specific function (or operation) is not +implemented. This error should never happen. It can only occur if +you use certain values or configuration options which do not work, +but for which we think that they should work at some later time. + +@item GPG_ERR_DECRYPT_FAILED +This value indicates that a decryption operation was unsuccessful. + +@item GPG_ERR_BAD_PASSPHRASE +This value means that the user did not provide a correct passphrase +when requested. + +@item GPG_ERR_CANCELED +This value means that the operation was canceled. + +@item GPG_ERR_INV_ENGINE +This value means that the engine that implements the desired protocol +is currently not available. This can either be because the sources +were configured to exclude support for this engine, or because the +engine is not installed properly. + +@item GPG_ERR_AMBIGUOUS_NAME +This value indicates that a user ID or other specifier did not specify +a unique key. + +@item GPG_ERR_WRONG_KEY_USAGE +This value indicates that a key is not used appropriately. + +@item GPG_ERR_CERT_REVOKED +This value indicates that a key signature was revoced. + +@item GPG_ERR_CERT_EXPIRED +This value indicates that a key signature expired. + +@item GPG_ERR_NO_CRL_KNOWN +This value indicates that no certificate revocation list is known for +the certificate. + +@item GPG_ERR_NO_POLICY_MATCH +This value indicates that a policy issue occured. + +@item GPG_ERR_NO_SECKEY +This value indicates that no secret key for the user ID is available. + +@item GPG_ERR_MISSING_CERT +This value indicates that a key could not be imported because the +issuer certificate is missing. + +@item GPG_ERR_BAD_CERT_CHAIN +This value indicates that a key could not be imported because its +certificate chain is not good, for example it could be too long. + +@item GPG_ERR_UNSUPPORTED_ALGORITHM +This value means a verification failed because the cryptographic +algorithm is not supported by the crypto backend. + +@item GPG_ERR_BAD_SIGNATURE +This value means a verification failed because the signature is bad. + +@item GPG_ERR_NO_PUBKEY +This value means a verification failed because the public key is not +available. + +@item GPG_ERR_USER_1 +@item GPG_ERR_USER_2 +@item ... +@item GPG_ERR_USER_16 +These error codes are not used by any GnuPG component and can be +freely used by other software. Applications using @acronym{GPGME} +might use them to mark specific errors returned by callback handlers +if no suitable error codes (including the system errors) for +these errors exist already. +@end table + + +@node Error Strings +@section Error Strings +@cindex error values, printing of +@cindex error codes, printing of +@cindex error sources, printing of +@cindex error strings + +@deftypefun {const char *} gpgme_strerror (@w{gpgme_error_t @var{err}}) +The function @code{gpgme_strerror} returns a pointer to a statically +allocated string containing a description of the error code contained +in the error value @var{err}. This string can be used to output a +diagnostic message to the user. + +This function is not thread safe. Use @code{gpgme_strerror_r} in +multi-threaded programs. +@end deftypefun + + +@deftypefun {int} gpgme_strerror_r (@w{gpgme_error_t @var{err}}, @w{char *@var{buf}}, @w{size_t @var{buflen}}) +The function @code{gpgme_strerror_r} returns the error string for +@var{err} in the user-supplied buffer @var{buf} of size @var{buflen}. +This function is, in contrast to @code{gpgme_strerror}, thread-safe if +a thread-safe @code{strerror_r} function is provided by the system. +If the function succeeds, 0 is returned and @var{buf} contains the +string describing the error. If the buffer was not large enough, +ERANGE is returned and @var{buf} contains as much of the beginning of +the error string as fits into the buffer. +@end deftypefun + + +@deftypefun {const char *} gpgme_strsource (@w{gpgme_error_t @var{err}}) +The function @code{gpgme_strerror} returns a pointer to a statically +allocated string containing a description of the error source +contained in the error value @var{err}. This string can be used to +output a diagnostic message to the user. +@end deftypefun + +The following example illustrates the use of @code{gpgme_strerror}: + +@example +gpgme_ctx_t ctx; +gpgme_error_t err = gpgme_new (&ctx); +if (err) + @{ + fprintf (stderr, "%s: creating GpgME context failed: %s: %s\n", + argv[0], gpgme_strsource (err), gpgme_strerror (err)); + exit (1); + @} +@end example + + +@node Exchanging Data +@chapter Exchanging Data +@cindex data, exchanging + +A lot of data has to be exchanged between the user and the crypto +engine, like plaintext messages, ciphertext, signatures and +information about the keys. The technical details about exchanging +the data information are completely abstracted by @acronym{GPGME}. +The user provides and receives the data via @code{gpgme_data_t} objects, +regardless of the communication protocol between @acronym{GPGME} and +the crypto engine in use. + +@deftp {Data type} {gpgme_data_t} +The @code{gpgme_data_t} type is a handle for a container for generic +data, which is used by @acronym{GPGME} to exchange data with the user. +@end deftp + +@menu +* Creating Data Buffers:: Creating new data buffers. +* Destroying Data Buffers:: Releasing data buffers. +* Manipulating Data Buffers:: Operations on data buffers. +@end menu + + +@node Creating Data Buffers +@section Creating Data Buffers +@cindex data buffer, creation + +Data objects can be based on memory, files, or callback functions +provided by the user. Not all operations are supported by all +objects. + + +@menu +* Memory Based Data Buffers:: Creating memory based data buffers. +* File Based Data Buffers:: Creating file based data buffers. +* Callback Based Data Buffers:: Creating callback based data buffers. +@end menu + + +@node Memory Based Data Buffers +@subsection Memory Based Data Buffers + +Memory based data objects store all data in allocated memory. This is +convenient, but only practical for an amount of data that is a +fraction of the available physical memory. The data has to be copied +from its source and to its destination, which can often be avoided by +using one of the other data object + +@deftypefun gpgme_error_t gpgme_data_new (@w{gpgme_data_t *@var{dh}}) +The function @code{gpgme_data_new} creates a new @code{gpgme_data_t} +object and returns a handle for it in @var{dh}. The data object is +memory based and initially empty. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +data object was successfully created, @code{GPG_ERR_INV_VALUE} if +@var{dh} is not a valid pointer, and @code{GPG_ERR_ENOMEM} if not +enough memory is available. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_data_new_from_mem (@w{gpgme_data_t *@var{dh}}, @w{const char *@var{buffer}}, @w{size_t @var{size}}, @w{int @var{copy}}) +The function @code{gpgme_data_new_from_mem} creates a new +@code{gpgme_data_t} object and fills it with @var{size} bytes starting +from @var{buffer}. + +If @var{copy} is not zero, a private copy of the data is made. If +@var{copy} is zero, the data is taken from the specified buffer as +needed, and the user has to ensure that the buffer remains valid for +the whole life span of the data object. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +data object was successfully created, @code{GPG_ERR_INV_VALUE} if +@var{dh} or @var{buffer} is not a valid pointer, and +@code{GPG_ERR_ENOMEM} if not enough memory is available. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_data_new_from_file (@w{gpgme_data_t *@var{dh}}, @w{const char *@var{filename}}, @w{int @var{copy}}) +The function @code{gpgme_data_new_from_file} creates a new +@code{gpgme_data_t} object and fills it with the content of the file +@var{filename}. + +If @var{copy} is not zero, the whole file is read in at initialization +time and the file is not used anymore after that. This is the only +mode supported currently. Later, a value of zero for @var{copy} might +cause all reads to be delayed until the data is needed, but this is +not yet implemented. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +data object was successfully created, @code{GPG_ERR_INV_VALUE} if +@var{dh} or @var{filename} is not a valid pointer, +@code{GPG_ERR_NOT_IMPLEMENTED} if @var{code} is zero, and +@code{GPG_ERR_ENOMEM} if not enough memory is available. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_data_new_from_filepart (@w{gpgme_data_t *@var{dh}}, @w{const char *@var{filename}}, @w{FILE *@var{fp}}, @w{off_t @var{offset}}, @w{size_t @var{length}}) +The function @code{gpgme_data_new_from_filepart} creates a new +@code{gpgme_data_t} object and fills it with a part of the file specified +by @var{filename} or @var{fp}. + +Exactly one of @var{filename} and @var{fp} must be non-zero, the other +must be zero. The argument that is not zero specifies the file from +which @var{length} bytes are read into the data object, starting from +@var{offset}. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +data object was successfully created, @code{GPG_ERR_INV_VALUE} if +@var{dh} and exactly one of @var{filename} and @var{fp} is not a valid +pointer, and @code{GPG_ERR_ENOMEM} if not enough memory is available. +@end deftypefun + + +@node File Based Data Buffers +@subsection File Based Data Buffers + +File based data objects operate directly on file descriptors or +streams. Only a small amount of data is stored in core at any time, +so the size of the data objects is not limited by @acronym{GPGME}. + +@deftypefun gpgme_error_t gpgme_data_new_from_fd (@w{gpgme_data_t *@var{dh}}, @w{int @var{fd}}) +The function @code{gpgme_data_new_from_fd} creates a new +@code{gpgme_data_t} object and uses the file descriptor @var{fd} to read +from (if used as an input data object) and write to (if used as an +output data object). + +When using the data object as an input buffer, the function might read +a bit more from the file descriptor than is actually needed by the +crypto engine in the desired operation because of internal buffering. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +data object was successfully created, and @code{GPG_ERR_ENOMEM} if not +enough memory is available. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_data_new_from_stream (@w{gpgme_data_t *@var{dh}}, @w{FILE *@var{stream}}) +The function @code{gpgme_data_new_from_stream} creates a new +@code{gpgme_data_t} object and uses the I/O stream @var{stream} to read +from (if used as an input data object) and write to (if used as an +output data object). + +When using the data object as an input buffer, the function might read +a bit more from the stream than is actually needed by the crypto +engine in the desired operation because of internal buffering. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +data object was successfully created, and @code{GPG_ERR_ENOMEM} if not +enough memory is available. +@end deftypefun + + +@node Callback Based Data Buffers +@subsection Callback Based Data Buffers + +If neither memory nor file based data objects are a good fit for your +application, you can implement the functions a data object provides +yourself and create a data object from these callback functions. + +@deftp {Data type} {ssize_t (*gpgme_data_read_cb_t) (@w{void *@var{handle}}, @w{void @var{*buffer}}, @w{size_t @var{size}})} +@tindex gpgme_data_read_cb_t +The @code{gpgme_data_read_cb_t} type is the type of functions which +@acronym{GPGME} calls if it wants to read data from a user-implemented +data object. The function should read up to @var{size} bytes from the +current read position into the space starting at @var{buffer}. The +@var{handle} is provided by the user at data object creation time. + +The function should return the number of bytes read, 0 on EOF, and -1 +on error. If an error occurs, @var{errno} should be set to describe +the type of the error. +@end deftp + +@deftp {Data type} {ssize_t (*gpgme_data_write_cb_t) (@w{void *@var{handle}}, @w{const void @var{*buffer}}, @w{size_t @var{size}})} +@tindex gpgme_data_write_cb_t +The @code{gpgme_data_write_cb_t} type is the type of functions which +@acronym{GPGME} calls if it wants to write data to a user-implemented +data object. The function should write up to @var{size} bytes to the +current write position from the space starting at @var{buffer}. The +@var{handle} is provided by the user at data object creation time. + +The function should return the number of bytes written, and -1 on +error. If an error occurs, @var{errno} should be set to describe the +type of the error. +@end deftp + +@deftp {Data type} {off_t (*gpgme_data_seek_cb_t) (@w{void *@var{handle}}, @w{off_t @var{offset}}, @w{int @var{whence}})} +@tindex gpgme_data_seek_cb_t +The @code{gpgme_data_seek_cb_t} type is the type of functions which +@acronym{GPGME} calls if it wants to change the current read/write +position in a user-implemented data object, just like the @code{lseek} +function. + +The function should return the new read/write position, and -1 on +error. If an error occurs, @var{errno} should be set to describe the +type of the error. +@end deftp + +@deftp {Data type} {void (*gpgme_data_release_cb_t) (@w{void *@var{handle}})} +@tindex gpgme_data_release_cb_t +The @code{gpgme_data_release_cb_t} type is the type of functions which +@acronym{GPGME} calls if it wants to destroy a user-implemented data +object. The @var{handle} is provided by the user at data object +creation time. +@end deftp + +@deftp {Data type} {struct gpgme_data_cbs} +This structure is used to store the data callback interface functions +described above. It has the following members: + +@table @code +@item gpgme_data_read_cb_t read +This is the function called by @acronym{GPGME} to read data from the +data object. It is only required for input data object. + +@item gpgme_data_write_cb_t write +This is the function called by @acronym{GPGME} to write data to the +data object. It is only required for output data object. + +@item gpgme_data_seek_cb_t seek +This is the function called by @acronym{GPGME} to change the current +read/write pointer in the data object (if available). It is optional. + +@item gpgme_data_release_cb_t release +This is the function called by @acronym{GPGME} to release a data +object. It is optional. +@end table +@end deftp + +@deftypefun gpgme_error_t gpgme_data_new_from_cbs (@w{gpgme_data_t *@var{dh}}, @w{gpgme_data_cbs_t @var{cbs}}, @w{void *@var{handle}}) +The function @code{gpgme_data_new_from_cbs} creates a new +@code{gpgme_data_t} object and uses the user-provided callback functions +to operate on the data object. + +The handle @var{handle} is passed as first argument to the callback +functions. This can be used to identify this data object. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +data object was successfully created, and @code{GPG_ERR_ENOMEM} if not +enough memory is available. +@end deftypefun + +The following interface is deprecated and only provided for backward +compatibility. Don't use it. It will be removed in a future version +of @acronym{GPGME}. + +@deftypefun gpgme_error_t gpgme_data_new_with_read_cb (@w{gpgme_data_t *@var{dh}}, @w{int (*@var{readfunc})} (@w{void *@var{hook}}, @w{char *@var{buffer}}, @w{size_t @var{count}}, @w{size_t *@var{nread}}), @w{void *@var{hook_value}}) +The function @code{gpgme_data_new_with_read_cb} creates a new +@code{gpgme_data_t} object and uses the callback function @var{readfunc} +to retrieve the data on demand. As the callback function can supply +the data in any way it wants, this is the most flexible data type +@acronym{GPGME} provides. However, it can not be used to write data. + +The callback function receives @var{hook_value} as its first argument +whenever it is invoked. It should return up to @var{count} bytes in +@var{buffer}, and return the number of bytes actually read in +@var{nread}. It may return @code{0} in @var{nread} if no data is +currently available. To indicate @code{EOF} the function should +return with an error code of @code{-1} and set @var{nread} to +@code{0}. The callback function may support to reset its internal +read pointer if it is invoked with @var{buffer} and @var{nread} being +@code{NULL} and @var{count} being @code{0}. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +data object was successfully created, @code{GPG_ERR_INV_VALUE} if +@var{dh} or @var{readfunc} is not a valid pointer, and +@code{GPG_ERR_ENOMEM} if not enough memory is available. +@end deftypefun + + +@node Destroying Data Buffers +@section Destroying Data Buffers +@cindex data buffer, destruction + +@deftypefun void gpgme_data_release (@w{gpgme_data_t @var{dh}}) +The function @code{gpgme_data_release} destroys the data object with +the handle @var{dh}. It releases all associated resources that were +not provided by the user in the first place. +@end deftypefun + +@deftypefun {char *} gpgme_data_release_and_get_mem (@w{gpgme_data_t @var{dh}}, @w{size_t *@var{length}}) +The function @code{gpgme_data_release_and_get_mem} is like +@code{gpgme_data_release}, except that it returns the data buffer and +its length that was provided by the object. + +The user has to release the buffer with @code{gpgme_free}. In case +the user provided the data buffer in non-copy mode, a copy will be +made for this purpose. + +In case an error returns, or there is no suitable data buffer that can +be returned to the user, the function will return @code{NULL}. In any +case, the data object @var{dh} is destroyed. +@end deftypefun + + +@deftypefun void gpgme_free (@w{void *@var{buffer}}) +The function @code{gpgme_free} releases the memory returned by +@code{gpgme_data_release_and_get_mem}. It should be used instead of +the system libraries @code{free} function in case different allocators +are used in a single program. +@end deftypefun + + +@node Manipulating Data Buffers +@section Manipulating Data Buffers +@cindex data buffer, manipulation + +Data buffers contain data and meta-data. The following operations can +be used to manipulate both. + + +@menu +* Data Buffer I/O Operations:: I/O operations on data buffers. +* Data Buffer Meta-Data:: Meta-data manipulation of data buffers. +@end menu + + +@node Data Buffer I/O Operations +@subsection Data Buffer I/O Operations +@cindex data buffer, I/O operations +@cindex data buffer, read +@cindex data buffer, write +@cindex data buffer, seek + +@deftypefun ssize_t gpgme_data_read (@w{gpgme_data_t @var{dh}}, @w{void *@var{buffer}}, @w{size_t @var{length}}) +The function @code{gpgme_data_read} reads up to @var{length} bytes +from the data object with the handle @var{dh} into the space starting +at @var{buffer}. + +If no error occurs, the actual amount read is returned. If the end of +the data object is reached, the function returns 0. + +In all other cases, the function returns -1 and sets @var{errno}. +@end deftypefun + +@deftypefun ssize_t gpgme_data_write (@w{gpgme_data_t @var{dh}}, @w{const void *@var{buffer}}, @w{size_t @var{size}}) +The function @code{gpgme_data_write} writes up to @var{size} bytes +starting from @var{buffer} into the data object with the handle +@var{dh} at the current write position. + +The function returns the number of bytes actually written, or -1 if an +error occurs. If an error occurs, @var{errno} is set. +@end deftypefun + +@deftypefun off_t gpgme_data_seek (@w{gpgme_data_t @var{dh}}, @w{off_t @var{offset}}, @w{int @var{whence}}) +The function @code{gpgme_data_seek} changes the current read/write +position. + +The @var{whence} argument specifies how the @var{offset} should be +interpreted. It must be one of the following symbolic constants: + +@table @code +@item SEEK_SET +Specifies that @var{offset} is a count of characters from the +beginning of the data object. + +@item SEEK_CUR +Specifies that @var{offset} is a count of characters from the current +file position. This count may be positive or negative. + +@item SEEK_END +Specifies that @var{offset} is a count of characters from the end of +the data object. A negative count specifies a position within the +current extent of the data object; a positive count specifies a +position past the current end. If you set the position past the +current end, and actually write data, you will extend the data object +with zeros up to that position. +@end table + +If successful, the function returns the resulting file position, +measured in bytes from the beginning of the data object. You can use +this feature together with @code{SEEK_CUR} to read the current +read/write position. + +If the function fails, -1 is returned and @var{errno} is set. +@end deftypefun + +The following function is deprecated and should not be used. It will +be removed in a future version of @acronym{GPGME}. + +@deftypefun gpgme_error_t gpgme_data_rewind (@w{gpgme_data_t @var{dh}}) +The function @code{gpgme_data_rewind} is equivalent to: + +@example + return (gpgme_data_seek (dh, 0, SEEK_SET) == -1) + ? gpgme_error_from_errno (errno) : 0; +@end example +@end deftypefun + + + + +@node Data Buffer Meta-Data +@subsection Data Buffer Meta-Data +@cindex data buffer, meta-data +@cindex data buffer, file name +@cindex data buffer, encoding + +@deftypefun {char *} gpgme_data_get_file_name (@w{gpgme_data_t @var{dh}}) +The function @code{gpgme_data_get_file_name} returns a pointer to a +string containing the file name associated with the data object. The +file name will be stored in the output when encrypting or signing the +data and will be returned to the user when decrypting or verifying the +output data. + +If no error occurs, the string containing the file name is returned. +Otherwise, @code{NULL} will be returned. +@end deftypefun + + +@deftypefun gpgme_error_t gpgme_data_set_file_name (@w{gpgme_data_t @var{dh}}, @w{const char *@var{file_name}}) +The function @code{gpgme_data_set_file_name} sets the file name +associated with the data object. The file name will be stored in the +output when encrypting or signing the data and will be returned to the +user when decrypting or verifying the output data. + +The function returns the error code @code{GPG_ERR_INV_VALUE} if +@var{dh} is not a valid pointer and @code{GPG_ERR_ENOMEM} if not +enough memory is available. +@end deftypefun + + +@deftp {Data type} {enum gpgme_data_encoding_t} +@tindex gpgme_data_encoding_t +The @code{gpgme_data_encoding_t} type specifies the encoding of a +@code{gpgme_data_t} object. This encoding is useful to give the backend +a hint on the type of data. The following data types are available: + +@table @code +@item GPGME_DATA_ENCODING_NONE +This specifies that the encoding is not known. This is the default +for a new data object. The backend will try its best to detect the +encoding automatically. + +@item GPGME_DATA_ENCODING_BINARY +This specifies that the data is encoding in binary form; i.e. there is +no special encoding. + +@item GPGME_DATA_ENCODING_BASE64 +This specifies that the data is encoded using the Base-64 encoding +scheme as used by @acronym{MIME} and other protocols. + +@item GPGME_DATA_ENCODING_ARMOR +This specifies that the data is encoded in an armored form as used by +OpenPGP and PEM. +@end table +@end deftp + +@deftypefun gpgme_data_encoding_t gpgme_data_get_encoding (@w{gpgme_data_t @var{dh}}) +The function @code{gpgme_data_get_encoding} returns the encoding of +the data object with the handle @var{dh}. If @var{dh} is not a valid +pointer (e.g. @code{NULL}) @code{GPGME_DATA_ENCODING_NONE} is +returned. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_data_set_encoding (@w{gpgme_data_t @var{dh}, gpgme_data_encoding_t @var{enc}}) +The function @code{gpgme_data_set_encoding} changes the encoding of +the data object with the handle @var{dh} to @var{enc}. +@end deftypefun + + +@c +@c Chapter Contexts +@c +@node Contexts +@chapter Contexts +@cindex context + +All cryptographic operations in @acronym{GPGME} are performed within a +context, which contains the internal state of the operation as well as +configuration parameters. By using several contexts you can run +several cryptographic operations in parallel, with different +configuration. + +@deftp {Data type} {gpgme_ctx_t} +The @code{gpgme_ctx_t} type is a handle for a @acronym{GPGME} context, +which is used to hold the configuration, status and result of +cryptographic operations. +@end deftp + +@menu +* Creating Contexts:: Creating new @acronym{GPGME} contexts. +* Destroying Contexts:: Releasing @acronym{GPGME} contexts. +* Context Attributes:: Setting properties of a context. +* Key Management:: Managing keys with @acronym{GPGME}. +* Trust Item Management:: Managing trust items with @acronym{GPGME}. +* Crypto Operations:: Using a context for cryptography. +* Run Control:: Controlling how operations are run. +@end menu + + +@node Creating Contexts +@section Creating Contexts +@cindex context, creation + +@deftypefun gpgme_error_t gpgme_new (@w{gpgme_ctx_t *@var{ctx}}) +The function @code{gpgme_new} creates a new @code{gpgme_ctx_t} object +and returns a handle for it in @var{ctx}. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +context was successfully created, @code{GPG_ERR_INV_VALUE} if +@var{ctx} is not a valid pointer, and @code{GPG_ERR_ENOMEM} if not +enough memory is available. +@end deftypefun + + +@node Destroying Contexts +@section Destroying Contexts +@cindex context, destruction + +@deftypefun void gpgme_release (@w{gpgme_ctx_t @var{ctx}}) +The function @code{gpgme_release} destroys the context with the handle +@var{ctx} and releases all associated resources. +@end deftypefun + + +@node Context Attributes +@section Context Attributes +@cindex context, attributes + +@menu +* Protocol Selection:: Selecting the protocol used by a context. +* Crypto Engine:: Configuring the crypto engine. +* ASCII Armor:: Requesting @acronym{ASCII} armored output. +* Text Mode:: Choosing canonical text mode. +* Included Certificates:: Including a number of certificates. +* Key Listing Mode:: Selecting key listing mode. +* Passphrase Callback:: Getting the passphrase from the user. +* Progress Meter Callback:: Being informed about the progress. +* Locale:: Setting the locale of a context. +@end menu + + +@node Protocol Selection +@subsection Protocol Selection +@cindex context, selecting protocol +@cindex protocol, selecting + +@deftypefun gpgme_error_t gpgme_set_protocol (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_protocol_t @var{proto}}) +The function @code{gpgme_set_protocol} sets the protocol used within +the context @var{ctx} to @var{proto}. All crypto operations will be +performed by the crypto engine configured for that protocol. +@xref{Protocols and Engines}. + +Setting the protocol with @code{gpgme_set_protocol} does not check if +the crypto engine for that protocol is available and installed +correctly. @xref{Engine Version Check}. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +protocol could be set successfully, and @code{GPG_ERR_INV_VALUE} if +@var{protocol} is not a valid protocol. +@end deftypefun + +@deftypefun gpgme_protocol_t gpgme_get_protocol (@w{gpgme_ctx_t @var{ctx}}) +The function @code{gpgme_get_protocol} retrieves the protocol currently +use with the context @var{ctx}. +@end deftypefun + + +@node Crypto Engine +@subsection Crypto Engine +@cindex context, configuring engine +@cindex engine, configuration per context + +The following functions can be used to set and retrieve the +configuration of the crypto engines of a specific context. The +default can also be retrieved without any particular context. +@xref{Engine Information}. The default can also be changed globally. +@xref{Engine Configuration}. + +@deftypefun gpgme_engine_info_t gpgme_ctx_get_engine_info (@w{gpgme_ctx_t @var{ctx}}) +The function @code{gpgme_ctx_get_engine_info} returns a linked list of +engine info structures. Each info structure describes the +configuration of one configured backend, as used by the context +@var{ctx}. + +The result is valid until the next invocation of +@code{gpgme_ctx_set_engine_info} for this particular context. + +This function can not fail. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_ctx_set_engine_info (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_protocol_t @var{proto}}, @w{const char *@var{file_name}}, @w{const char *@var{home_dir}}) +The function @code{gpgme_ctx_set_engine_info} changes the +configuration of the crypto engine implementing the protocol +@var{proto} for the context @var{ctx}. + +@var{file_name} is the file name of the executable program +implementing this protocol, and @var{home_dir} is the directory name +of the configuration directory for this crypto engine. If +@var{home_dir} is @code{NULL}, the engine's default will be used. + +Currently this function must be used before starting the first crypto +operation. It is unspecified if and when the changes will take effect +if the function is called after starting the first operation on the +context @var{ctx}. + +This function returns the error code @code{GPG_ERR_NO_ERROR} if +successful, or an eror code on failure. +@end deftypefun + + +@c FIXME: Unfortunately, using @acronym here breaks texi2dvi. +@node ASCII Armor +@subsection @acronym{ASCII} Armor +@cindex context, armor mode +@cindex @acronym{ASCII} armor +@cindex armor mode + +@deftypefun void gpgme_set_armor (@w{gpgme_ctx_t @var{ctx}}, @w{int @var{yes}}) +The function @code{gpgme_set_armor} specifies if the output should be +@acronym{ASCII} armored. By default, output is not @acronym{ASCII} +armored. + +@acronym{ASCII} armored output is disabled if @var{yes} is zero, and +enabled otherwise. +@end deftypefun + +@deftypefun int gpgme_get_armor (@w{gpgme_ctx_t @var{ctx}}) +The function @code{gpgme_get_armor} returns 1 if the output is +@acronym{ASCII} armored, and @code{0} if it is not, or if @var{ctx} is +not a valid pointer. +@end deftypefun + + +@node Text Mode +@subsection Text Mode +@cindex context, text mode +@cindex text mode +@cindex canonical text mode + +@deftypefun void gpgme_set_textmode (@w{gpgme_ctx_t @var{ctx}}, @w{int @var{yes}}) +The function @code{gpgme_set_textmode} specifies if canonical text mode +should be used. By default, text mode is not used. + +Text mode is for example used for the RFC2015 signatures; note that +the updated RFC 3156 mandates that the mail user agent does some +preparations so that text mode is not needed anymore. + +This option is only relevant to the OpenPGP crypto engine, and ignored +by all other engines. + +Canonical text mode is disabled if @var{yes} is zero, and enabled +otherwise. +@end deftypefun + +@deftypefun int gpgme_get_textmode (@w{gpgme_ctx_t @var{ctx}}) +The function @code{gpgme_get_textmode} returns 1 if canonical text +mode is enabled, and @code{0} if it is not, or if @var{ctx} is not a +valid pointer. +@end deftypefun + + +@node Included Certificates +@subsection Included Certificates +@cindex certificates, included + +@deftypefun void gpgme_set_include_certs (@w{gpgme_ctx_t @var{ctx}}, @w{int @var{nr_of_certs}}) +The function @code{gpgme_set_include_certs} specifies how many +certificates should be included in an S/MIME signed message. By +default, only the sender's certificate is included. The possible +values of @var{nr_of_certs} are: + +@table @code +@item GPGME_INCLUDE_CERTS_DEFAULT +Fall back to the default of the crypto backend. This is the default +for GPGME. +@item -2 +Include all certificates except the root certificate. +@item -1 +Include all certificates. +@item 0 +Include no certificates. +@item 1 +Include the sender's certificate only. +@item n +Include the first n certificates of the certificates path, starting +from the sender's certificate. The number @code{n} must be positive. +@end table + +Values of @var{nr_of_certs} smaller than -2 are undefined. + +This option is only relevant to the CMS crypto engine, and ignored by +all other engines. +@end deftypefun + +@deftypefun int gpgme_get_include_certs (@w{gpgme_ctx_t @var{ctx}}) +The function @code{gpgme_get_include_certs} returns the number of +certificates to include into an S/MIME signed message. +@end deftypefun + + +@node Key Listing Mode +@subsection Key Listing Mode +@cindex key listing mode +@cindex key listing, mode of + +@deftypefun gpgme_error_t gpgme_set_keylist_mode (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_keylist_mode_t @var{mode}}) +The function @code{gpgme_set_keylist_mode} changes the default +behaviour of the key listing functions. The value in @var{mode} is a +bitwise-or combination of one or multiple of the following bit values: + +@table @code +@item GPGME_KEYLIST_MODE_LOCAL +The @code{GPGME_KEYLIST_MODE_LOCAL} symbol specifies that the local +keyring should be searched for keys in the keylisting operation. This +is the default. + +@item GPGME_KEYLIST_MODE_EXTERN +The @code{GPGME_KEYLIST_MODE_EXTERN} symbol specifies that an external +source should be searched for keys in the keylisting +operation. The type of external source is dependant on the crypto +engine used. For example, it can be a remote keyserver or LDAP +certificate server. + +@item GPGME_KEYLIST_MODE_SIGS +The @code{GPGME_KEYLIST_MODE_SIGS} symbol specifies that the key +signatures should be included in the listed keys. + +@item GPGME_KEYLIST_MODE_SIG_NOTATIONS +The @code{GPGME_KEYLIST_MODE_SIG_NOTATIONS} symbol specifies that the +signature notations on key signatures should be included in the listed +keys. This only works if @code{GPGME_KEYLIST_MODE_SIGS} is also +enabled. + +@item GPGME_KEYLIST_MODE_VALIDATE +The @code{GPGME_KEYLIST_MODE_VALIDATE} symbol specifies that the +backend should do key or certificate validation and not just get the +validity information from an internal cache. This might be an +expensive operation and is in general not useful. Currently only +implemented for the S/MIME backend and ignored for other backends. + +@end table + +At least one of @code{GPGME_KEYLIST_MODE_LOCAL} and +@code{GPGME_KEYLIST_MODE_EXTERN} must be specified. For future binary +compatibility, you should get the current mode with +@code{gpgme_get_keylist_mode} and modify it by setting or clearing the +appropriate bits, and then using that calulcated value in the +@code{gpgme_set_keylisting_mode} operation. This will leave all other +bits in the mode value intact (in particular those that are not used +in the current version of the library). + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +mode could be set correctly, and @code{GPG_ERR_INV_VALUE} if @var{ctx} +is not a valid pointer or @var{mode} is not a valid mode. +@end deftypefun + + +@deftypefun gpgme_keylist_mode_t gpgme_get_keylist_mode (@w{gpgme_ctx_t @var{ctx}}) +The function @code{gpgme_get_keylist_mode} returns the current key +listing mode of the context @var{ctx}. This value can then be +modified and used in a subsequent @code{gpgme_set_keylist_mode} +operation to only affect the desired bits (and leave all others +intact). + +The function returns 0 if @var{ctx} is not a valid pointer, and the +current mode otherwise. Note that 0 is not a valid mode value. +@end deftypefun + + +@node Passphrase Callback +@subsection Passphrase Callback +@cindex callback, passphrase +@cindex passphrase callback + +@deftp {Data type} {gpgme_error_t (*gpgme_passphrase_cb_t)(void *@var{hook}, const char *@var{uid_hint}, const char *@var{passphrase_info}, @w{int @var{prev_was_bad}}, @w{int @var{fd}})} +@tindex gpgme_passphrase_cb_t +The @code{gpgme_passphrase_cb_t} type is the type of functions usable as +passphrase callback function. + +The argument @var{uid_hint} might contain a string that gives an +indication for which user ID the passphrase is required. If this is +not available, or not applicable (in the case of symmetric encryption, +for example), @var{uid_hint} will be @code{NULL}. + +The argument @var{passphrase_info}, if not @code{NULL}, will give +further information about the context in which the passphrase is +required. This information is engine and operation specific. + +If this is the repeated attempt to get the passphrase, because +previous attempts failed, then @var{prev_was_bad} is 1, otherwise it +will be 0. + +The user must write the passphrase, followed by a newline character, +to the file descriptor @var{fd}. If the user returns 0 indicating +success, the user must at least write a newline character before +returning from the callback. + +If an error occurs, return the corresponding @code{gpgme_error_t} +value. You can use the error code @code{GPG_ERR_CANCELED} to abort +the operation. Otherwise, return @code{0}. +@end deftp + +@deftypefun void gpgme_set_passphrase_cb (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_passphrase_cb_t @var{passfunc}}, @w{void *@var{hook_value}}) +The function @code{gpgme_set_passphrase_cb} sets the function that is +used when a passphrase needs to be provided by the user to +@var{passfunc}. The function @var{passfunc} needs to implemented by +the user, and whenever it is called, it is called with its first +argument being @var{hook_value}. By default, no passphrase callback +function is set. + +Not all crypto engines require this callback to retrieve the +passphrase. It is better if the engine retrieves the passphrase from +a trusted agent (a daemon process), rather than having each user to +implement their own passphrase query. Some engines do not even +support an external passphrase callback at all, in this case the error +code @code{GPG_ERR_NOT_SUPPORTED} is returned. + +The user can disable the use of a passphrase callback function by +calling @code{gpgme_set_passphrase_cb} with @var{passfunc} being +@code{NULL}. +@end deftypefun + +@deftypefun void gpgme_get_passphrase_cb (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_passphrase_cb_t *@var{passfunc}}, @w{void **@var{hook_value}}) +The function @code{gpgme_get_passphrase_cb} returns the function that +is used when a passphrase needs to be provided by the user in +@var{*passfunc}, and the first argument for this function in +@var{*hook_value}. If no passphrase callback is set, or @var{ctx} is +not a valid pointer, @code{NULL} is returned in both variables. + +@var{passfunc} or @var{hook_value} can be @code{NULL}. In this case, +the corresponding value will not be returned. +@end deftypefun + + +@node Progress Meter Callback +@subsection Progress Meter Callback +@cindex callback, progress meter +@cindex progress meter callback + +@deftp {Data type} {void (*gpgme_progress_cb_t)(void *@var{hook}, const char *@var{what}, int @var{type}, int @var{current}, int @var{total})} +@tindex gpgme_progress_cb_t +The @code{gpgme_progress_cb_t} type is the type of functions usable as +progress callback function. + +The arguments are specific to the crypto engine. More information +about the progress information returned from the GnuPG engine can be +found in the GnuPG source code in the file @file{doc/DETAILS} in the +section PROGRESS. +@end deftp + +@deftypefun void gpgme_set_progress_cb (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_progress_cb_t @var{progfunc}}, @w{void *@var{hook_value}}) +The function @code{gpgme_set_progress_cb} sets the function that is +used when progress information about a cryptographic operation is +available. The function @var{progfunc} needs to implemented by the +user, and whenever it is called, it is called with its first argument +being @var{hook_value}. By default, no progress callback function +is set. + +Setting a callback function allows an interactive program to display +progress information about a long operation to the user. + +The user can disable the use of a progress callback function by +calling @code{gpgme_set_progress_cb} with @var{progfunc} being +@code{NULL}. +@end deftypefun + +@deftypefun void gpgme_get_progress_cb (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_progress_cb_t *@var{progfunc}}, @w{void **@var{hook_value}}) +The function @code{gpgme_get_progress_cb} returns the function that is +used to inform the user about the progress made in @var{*progfunc}, +and the first argument for this function in @var{*hook_value}. If no +progress callback is set, or @var{ctx} is not a valid pointer, +@code{NULL} is returned in both variables. + +@var{progfunc} or @var{hook_value} can be @code{NULL}. In this case, +the corresponding value will not be returned. +@end deftypefun + + +@node Locale +@subsection Locale +@cindex locale, default +@cindex locale, of a context + +A locale setting can be associated with a context. This locale is +passed to the crypto engine, and used for applications like the PIN +entry, which is displayed to the user when entering a passphrase is +required. + +The default locale is used to initialize the locale setting of all +contexts created afterwards. + +@deftypefun gpgme_error_t gpgme_set_locale (@w{gpgme_ctx_t @var{ctx}}, @w{int @var{category}}, @w{const char *@var{value}}) +The function @code{gpgme_set_locale} sets the locale of the context +@var{ctx}, or the default locale if @var{ctx} is a null pointer. + +The locale settings that should be changed are specified by +@var{category}. Supported categories are @code{LC_CTYPE}, +@code{LC_MESSAGES}, and @code{LC_ALL}, which is a wildcard you can use +if you want to change all the categories at once. + +The value to be used for the locale setting is @var{value}, which will +be copied to @acronym{GPGME}'s internal data structures. @var{value} +can be a null pointer, which disables setting the locale, and will +make PIN entry and other applications use their default setting, which +is usually not what you want. + +Note that the settings are only used if the application runs on a text +terminal, and that the settings should fit the configuration of the +output terminal. Normally, it is sufficient to initialize the default +value at startup. + +The function returns an error if not enough memory is available. +@end deftypefun + + +@node Key Management +@section Key Management +@cindex key management + +Some of the cryptographic operations require that recipients or +signers are specified. This is always done by specifying the +respective keys that should be used for the operation. The following +section describes how such keys can be selected and manipulated. + +@deftp {Data type} gpgme_sub_key_t +The @code{gpgme_sub_key_t} type is a pointer to a subkey structure. +Sub keys are one component of a @code{gpgme_key_t} object. In fact, +subkeys are those parts that contains the real information about the +individual cryptographic keys that belong to the same key object. One +@code{gpgme_key_t} can contain several subkeys. The first subkey in +the linked list is also called the primary key. + +The subkey structure has the following members: + +@table @code +@item gpgme_sub_key_t next +This is a pointer to the next subkey structure in the linked list, or +@code{NULL} if this is the last element. + +@item unsigned int revoked : 1 +This is true if the subkey is revoked. + +@item unsigned int expired : 1 +This is true if the subkey is expired. + +@item unsigned int disabled : 1 +This is true if the subkey is disabled. + +@item unsigned int invalid : 1 +This is true if the subkey is invalid. + +@item unsigned int can_encrypt : 1 +This is true if the subkey can be used for encryption. + +@item unsigned int can_sign : 1 +This is true if the subkey can be used to create data signatures. + +@item unsigned int can_certify : 1 +This is true if the subkey can be used to create key certificates. + +@item unsigned int can_authenticate : 1 +This is true if the subkey can be used for authentication. + +@item unsigned int is_qualified : 1 +This is true if the subkey can be used for qualified signatures +according to local government regulations. + +@item unsigned int secret : 1 +This is true if the subkey is a secret key. Note that it will be false +if the key is actually a stub key; i.e. a secret key operation is +currently not possible (offline-key). + +@item gpgme_pubkey_algo_t pubkey_algo +This is the public key algorithm supported by this subkey. + +@item unsigned int length +This is the length of the subkey (in bits). + +@item char *keyid +This is the key ID of the subkey in hexadecimal digits. + +@item char *fpr +This is the fingerprint of the subkey in hexadecimal digits, if +available. + +@item long int timestamp +This is the creation timestamp of the subkey. This is -1 if the +timestamp is invalid, and 0 if it is not available. + +@item long int expires +This is the expiration timestamp of the subkey, or 0 if the subkey +does not expire. +@end table +@end deftp + +@deftp {Data type} gpgme_key_sig_t +The @code{gpgme_key_sig_t} type is a pointer to a key signature structure. +Key signatures are one component of a @code{gpgme_key_t} object, and +validate user IDs on the key. + +The signatures on a key are only available if the key was retrieved +via a listing operation with the @code{GPGME_KEYLIST_MODE_SIGS} mode +enabled, because it can be expensive to retrieve all signatures of a +key. + +The signature notations on a key signature are only available if the +key was retrieved via a listing operation with the +@code{GPGME_KEYLIST_MODE_SIG_NOTATIONS} mode enabled, because it can +be expensive to retrieve all signature notations. + +The key signature structure has the following members: + +@table @code +@item gpgme_key_sig_t next +This is a pointer to the next key signature structure in the linked +list, or @code{NULL} if this is the last element. + +@item unsigned int revoked : 1 +This is true if the key signature is a revocation signature. + +@item unsigned int expired : 1 +This is true if the key signature is expired. + +@item unsigned int invalid : 1 +This is true if the key signature is invalid. + +@item unsigned int exportable : 1 +This is true if the key signature is exportable. + +@item gpgme_pubkey_algo_t pubkey_algo +This is the public key algorithm used to create the signature. + +@item char *keyid +This is the key ID of the key (in hexadecimal digits) used to create +the signature. + +@item long int timestamp +This is the creation timestamp of the key signature. This is -1 if +the timestamp is invalid, and 0 if it is not available. + +@item long int expires +This is the expiration timestamp of the key signature, or 0 if the key +signature does not expire. + +@item gpgme_error_t status +This is the status of the signature and has the same meaning as the +member of the same name in a @code{gpgme_signature_t} object. + +@item unsigned int sig_class +This specifies the signature class of the key signature. The meaning +is specific to the crypto engine. + +@item char *uid +This is the main user ID of the key used to create the signature. + +@item char *name +This is the name component of @code{uid}, if available. + +@item char *comment +This is the comment component of @code{uid}, if available. + +@item char *email +This is the email component of @code{uid}, if available. + +@item gpgme_sig_notation_t notations +This is a linked list with the notation data and policy URLs. +@end table +@end deftp + +@deftp {Data type} gpgme_user_id_t +A user ID is a component of a @code{gpgme_key_t} object. One key can +have many user IDs. The first one in the list is the main (or +primary) user ID. + +The user ID structure has the following members. + +@table @code +@item gpgme_user_id_t next +This is a pointer to the next user ID structure in the linked list, or +@code{NULL} if this is the last element. + +@item unsigned int revoked : 1 +This is true if the user ID is revoked. + +@item unsigned int invalid : 1 +This is true if the user ID is invalid. + +@item gpgme_validity_t validity +This specifies the validity of the user ID. + +@item char *uid +This is the user ID string. + +@item char *name +This is the name component of @code{uid}, if available. + +@item char *comment +This is the comment component of @code{uid}, if available. + +@item char *email +This is the email component of @code{uid}, if available. + +@item gpgme_key_sig_t signatures +This is a linked list with the signatures on this user ID. +@end table +@end deftp + +@deftp {Data type} gpgme_key_t +The @code{gpgme_key_t} type is a pointer to a key object. It has the +following members: + +@table @code +@item gpgme_keylist_mode_t keylist_mode +The keylist mode that was active when the key was retrieved. + +@item unsigned int revoked : 1 +This is true if the key is revoked. + +@item unsigned int expired : 1 +This is true if the key is expired. + +@item unsigned int disabled : 1 +This is true if the key is disabled. + +@item unsigned int invalid : 1 +This is true if the key is invalid. This might have several reasons, +for a example for the S/MIME backend, it will be set in during key +listsing if the key could not be validated due to a missing +certificates or unmatched policies. + +@item unsigned int can_encrypt : 1 +This is true if the key (ie one of its subkeys) can be used for +encryption. + +@item unsigned int can_sign : 1 +This is true if the key (ie one of its subkeys) can be used to create +data signatures. + +@item unsigned int can_certify : 1 +This is true if the key (ie one of its subkeys) can be used to create +key certificates. + +@item unsigned int can_authenticate : 1 +This is true if the key (ie one of its subkeys) can be used for +authentication. + +@item unsigned int is_qualified : 1 +This is true if the key can be used for qualified signatures according +to local government regulations. + +@item unsigned int secret : 1 +This is true if the key is a secret key. Note, that this will always be +true even if the corresponding subkey flag may be false (offline/stub +keys). + +@item gpgme_protocol_t protocol +This is the protocol supported by this key. + +@item char *issuer_serial +If @code{protocol} is @code{GPGME_PROTOCOL_CMS}, then this is the +issuer serial. + +@item char *issuer_name +If @code{protocol} is @code{GPGME_PROTOCOL_CMS}, then this is the +issuer name. + +@item char *chain_id +If @code{protocol} is @code{GPGME_PROTOCOL_CMS}, then this is the +chain ID, which can be used to built the certificate chain. + +@item gpgme_validity_t owner_trust +If @code{protocol} is @code{GPGME_PROTOCOL_OpenPGP}, then this is the +owner trust. + +@item gpgme_sub_key_t subkeys +This is a linked list with the subkeys of the key. The first subkey +in the list is the primary key and usually available. + +@item gpgme_user_id_t uids +This is a linked list with the user IDs of the key. The first user ID +in the list is the main (or primary) user ID. +@end table +@end deftp + +@menu +* Listing Keys:: Browsing the list of available keys. +* Information About Keys:: Requesting detailed information about keys. +* Key Signatures:: Listing the signatures on a key. +* Manipulating Keys:: Operations on keys. +* Generating Keys:: Creating new key pairs. +* Exporting Keys:: Retrieving key data from the key ring. +* Importing Keys:: Adding keys to the key ring. +* Deleting Keys:: Removing keys from the key ring. +* Advanced Key Editing:: Advanced key edit operation. +@end menu + + +@node Listing Keys +@subsection Listing Keys +@cindex listing keys +@cindex key listing +@cindex key listing, start +@cindex key ring, list +@cindex key ring, search + +@deftypefun gpgme_error_t gpgme_op_keylist_start (@w{gpgme_ctx_t @var{ctx}}, @w{const char *@var{pattern}}, @w{int @var{secret_only}}) +The function @code{gpgme_op_keylist_start} initiates a key listing +operation inside the context @var{ctx}. It sets everything up so that +subsequent invocations of @code{gpgme_op_keylist_next} return the keys +in the list. + +If @var{pattern} is @code{NULL}, all available keys are returned. +Otherwise, @var{pattern} contains an engine specific expression that +is used to limit the list to all keys matching the pattern. Note that +the total length of the pattern is restricted to an engine-specific +maximum (a couple of hundred characters are usually accepted). The +pattern should be used to restrict the search to a certain common name +or user, not to list many specific keys at once by listing their +fingerprints or key IDs. + +If @var{secret_only} is not @code{0}, the list is restricted to secret +keys only. + +The context will be busy until either all keys are received (and +@code{gpgme_op_keylist_next} returns @code{GPG_ERR_EOF}), or +@code{gpgme_op_keylist_end} is called to finish the operation. + +The function returns the error code @code{GPG_ERR_INV_VALUE} if +@var{ctx} is not a valid pointer, and passes through any errors that +are reported by the crypto engine support routines. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_op_keylist_ext_start (@w{gpgme_ctx_t @var{ctx}}, @w{const char *@var{pattern}[]}, @w{int @var{secret_only}}, @w{int @var{reserved}}) +The function @code{gpgme_op_keylist_ext_start} initiates an extended +key listing operation inside the context @var{ctx}. It sets +everything up so that subsequent invocations of +@code{gpgme_op_keylist_next} return the keys in the list. + +If @var{pattern} or @var{*pattern} is @code{NULL}, all available keys +are returned. Otherwise, @var{pattern} is a @code{NULL} terminated +array of strings that are used to limit the list to all keys matching +at least one of the patterns verbatim. Note that the total length of +all patterns is restricted to an engine-specific maximum (the exact +limit also depends on the number of patterns and amount of quoting +required, but a couple of hundred characters are usually accepted). +Patterns should be used to restrict the search to a certain common +name or user, not to list many specific keys at once by listing their +fingerprints or key IDs. + +If @var{secret_only} is not @code{0}, the list is restricted to secret +keys only. + +The value of @var{reserved} must be @code{0}. + +The context will be busy until either all keys are received (and +@code{gpgme_op_keylist_next} returns @code{GPG_ERR_EOF}), or +@code{gpgme_op_keylist_end} is called to finish the operation. + +The function returns the error code @code{GPG_ERR_INV_VALUE} if +@var{ctx} is not a valid pointer, and passes through any errors that +are reported by the crypto engine support routines. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_op_keylist_next (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_key_t *@var{r_key}}) +The function @code{gpgme_op_keylist_next} returns the next key in the +list created by a previous @code{gpgme_op_keylist_start} operation in +the context @var{ctx}. The key will have one reference for the user. +@xref{Manipulating Keys}. + +This is the only way to get at @code{gpgme_key_t} objects in +@acronym{GPGME}. + +If the last key in the list has already been returned, +@code{gpgme_op_keylist_next} returns @code{GPG_ERR_EOF}. + +The function returns the error code @code{GPG_ERR_INV_VALUE} if +@var{ctx} or @var{r_key} is not a valid pointer, and +@code{GPG_ERR_ENOMEM} if there is not enough memory for the operation. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_op_keylist_end (@w{gpgme_ctx_t @var{ctx}}) +The function @code{gpgme_op_keylist_next} ends a pending key list +operation in the context @var{ctx}. + +After the operation completed successfully, the result of the key +listing operation can be retrieved with +@code{gpgme_op_keylist_result}. + +The function returns the error code @code{GPG_ERR_INV_VALUE} if +@var{ctx} is not a valid pointer, and @code{GPG_ERR_ENOMEM} if at some +time during the operation there was not enough memory available. +@end deftypefun + +The following example illustrates how all keys containing a certain +string (@code{g10code}) can be listed with their key ID and the name +and e-mail address of the main user ID: + +@example +gpgme_ctx_t ctx; +gpgme_error_t err = gpgme_new (&ctx); + +if (!err) + @{ + err = gpgme_op_keylist_start (ctx, "g10code", 0); + while (!err) + @{ + err = gpgme_op_keylist_next (ctx, &key); + if (err) + break; + printf ("%s: %s <%s>\n", key->keyid, key->name, key->email); + gpgme_key_release (key); + @} + gpgme_release (ctx); + @} +if (gpg_err_code (err) != GPG_ERR_EOF) + @{ + fprintf (stderr, "%s: can not list keys: %s\n", + argv[0], gpgme_strerror (err)); + exit (1); + @} +@end example + +@deftp {Data type} {gpgme_keylist_result_t} +This is a pointer to a structure used to store the result of a +@code{gpgme_op_keylist_*} operation. After successfully ending a key +listing operation, you can retrieve the pointer to the result with +@code{gpgme_op_keylist_result}. The structure contains the following +member: + +@table @code +@item unsigned int truncated : 1 +This is true if the crypto backend had to truncate the result, and +less than the desired keys could be listed. +@end table +@end deftp + +@deftypefun gpgme_keylist_result_t gpgme_op_keylist_result (@w{gpgme_ctx_t @var{ctx}}) +The function @code{gpgme_op_keylist_result} returns a +@code{gpgme_keylist_result_t} pointer to a structure holding the +result of a @code{gpgme_op_keylist_*} operation. The pointer is only +valid if the last operation on the context was a key listing +operation, and if this operation finished successfully. The returned +pointer is only valid until the next operation is started on the +context. +@end deftypefun + +In a simple program, for which a blocking operation is acceptable, the +following function can be used to retrieve a single key. + +@deftypefun gpgme_error_t gpgme_get_key (@w{gpgme_ctx_t @var{ctx}}, @w{const char *@var{fpr}}, @w{gpgme_key_t *@var{r_key}}, @w{int @var{secret}}) +The function @code{gpgme_get_key} gets the key with the fingerprint +(or key ID) @var{fpr} from the crypto backend and return it in +@var{r_key}. If @var{secret} is true, get the secret key. The +currently active keylist mode is used to retrieve the key. The key +will have one reference for the user. + +If the key is not found in the keyring, @code{gpgme_get_key} returns +the error code @code{GPG_ERR_NO_ERROR} and *@var{r_key} will be set to +@code{NULL}. + +The function returns the error code @code{GPG_ERR_INV_VALUE} if +@var{ctx} or @var{r_key} is not a valid pointer or @var{fpr} is not a +fingerprint or key ID, @code{GPG_ERR_AMBIGUOUS_NAME} if the key ID was +not a unique specifier for a key, and @code{GPG_ERR_ENOMEM} if at some +time during the operation there was not enough memory available. +@end deftypefun + + +@node Information About Keys +@subsection Information About Keys +@cindex key, information about +@cindex key, attributes +@cindex attributes, of a key + +Please see the beginning of this section for more information about +@code{gpgme_key_t} objects. + +@deftp {Data type} gpgme_validity_t +The @code{gpgme_validity_t} type is used to specify the validity of a user ID +in a key. The following validities are defined: + +@table @code +@item GPGME_VALIDITY_UNKNOWN +The user ID is of unknown validity. The string representation of this +validity is ``?''. + +@item GPGME_VALIDITY_UNDEFINED +The validity of the user ID is undefined. The string representation of this +validity is ``q''. + +@item GPGME_VALIDITY_NEVER +The user ID is never valid. The string representation of this +validity is ``n''. + +@item GPGME_VALIDITY_MARGINAL +The user ID is marginally valid. The string representation of this +validity is ``m''. + +@item GPGME_VALIDITY_FULL +The user ID is fully valid. The string representation of this +validity is ``f''. + +@item GPGME_VALIDITY_ULTIMATE +The user ID is ultimately valid. The string representation of this +validity is ``u''. +@end table +@end deftp + + +The following interfaces are deprecated and only provided for backward +compatibility. Don't use them. They will be removed in a future +version of @acronym{GPGME}. + +@deftp {Data type} gpgme_attr_t +The @code{gpgme_attr_t} type is used to specify a key or trust item +attribute. The following attributes are defined: + +@table @code +@item GPGME_ATTR_KEYID +This is the key ID of a sub key. It is representable as a string. + +For trust items, the trust item refers to the key with this ID. + +@item GPGME_ATTR_FPR +This is the fingerprint of a sub key. It is representable as a +string. + +@item GPGME_ATTR_ALGO +This is the crypto algorithm for which the sub key can be used. It +is representable as a string and as a number. The numbers correspond +to the @code{enum gcry_pk_algos} values in the gcrypt library. + +@item GPGME_ATTR_LEN +This is the key length of a sub key. It is representable as a +number. + +@item GPGME_ATTR_CREATED +This is the timestamp at creation time of a sub key. It is +representable as a number. + +@item GPGME_ATTR_EXPIRE +This is the expiration time of a sub key. It is representable as a +number. + +@item GPGME_ATTR_OTRUST +XXX FIXME (also for trust items) + +@item GPGME_ATTR_USERID +This is a user ID. There can be more than one user IDs in a +@var{gpgme_key_t} object. The first one (with index 0) is the primary +user ID. The user ID is representable as a number. + +For trust items, this is the user ID associated with this trust item. + +@item GPGME_ATTR_NAME +This is the name belonging to a user ID. It is representable as a string. + +@item GPGME_ATTR_EMAIL +This is the email address belonging to a user ID. It is representable +as a string. + +@item GPGME_ATTR_COMMENT +This is the comment belonging to a user ID. It is representable as a +string. + +@item GPGME_ATTR_VALIDITY +This is the validity belonging to a user ID. It is representable as a +string and as a number. See below for a list of available validities. + +For trust items, this is the validity that is associated with this +trust item. + +@item GPGME_ATTR_UID_REVOKED +This specifies if a user ID is revoked. It is representable as a +number, and is @code{1} if the user ID is revoked, and @code{0} +otherwise. + +@item GPGME_ATTR_UID_INVALID +This specifies if a user ID is invalid. It is representable as a +number, and is @code{1} if the user ID is invalid, and @code{0} +otherwise. + +@item GPGME_ATTR_LEVEL +This is the trust level of a trust item. + +@item GPGME_ATTR_TYPE +This returns information about the type of key. For the string function +this will eother be "PGP" or "X.509". The integer function returns 0 +for PGP and 1 for X.509. It is also used for the type of a trust item. + +@item GPGME_ATTR_IS_SECRET +This specifies if the key is a secret key. It is representable as a +number, and is @code{1} if the key is revoked, and @code{0} otherwise. + +@item GPGME_ATTR_KEY_REVOKED +This specifies if a sub key is revoked. It is representable as a +number, and is @code{1} if the key is revoked, and @code{0} otherwise. + +@item GPGME_ATTR_KEY_INVALID +This specifies if a sub key is invalid. It is representable as a +number, and is @code{1} if the key is invalid, and @code{0} otherwise. + +@item GPGME_ATTR_KEY_EXPIRED +This specifies if a sub key is expired. It is representable as a +number, and is @code{1} if the key is expired, and @code{0} otherwise. + +@item GPGME_ATTR_KEY_DISABLED +This specifies if a sub key is disabled. It is representable as a +number, and is @code{1} if the key is disabled, and @code{0} otherwise. + +@item GPGME_ATTR_KEY_CAPS +This is a description of the capabilities of a sub key. It is +representable as a string. The string contains the letter ``e'' if +the key can be used for encryption, ``s'' if the key can be used for +signatures, and ``c'' if the key can be used for certifications. + +@item GPGME_ATTR_CAN_ENCRYPT +This specifies if a sub key can be used for encryption. It is +representable as a number, and is @code{1} if the sub key can be used +for encryption, and @code{0} otherwise. + +@item GPGME_ATTR_CAN_SIGN +This specifies if a sub key can be used to create data signatures. It +is representable as a number, and is @code{1} if the sub key can be +used for signatures, and @code{0} otherwise. + +@item GPGME_ATTR_CAN_CERTIFY +This specifies if a sub key can be used to create key certificates. +It is representable as a number, and is @code{1} if the sub key can be +used for certifications, and @code{0} otherwise. + +@item GPGME_ATTR_SERIAL +The X.509 issuer serial attribute of the key. It is representable as +a string. + +@item GPGME_ATTR_ISSUE +The X.509 issuer name attribute of the key. It is representable as a +string. + +@item GPGME_ATTR_CHAINID +The X.509 chain ID can be used to build the certification chain. It +is representable as a string. +@end table +@end deftp + +@deftypefun {const char *} gpgme_key_get_string_attr (@w{gpgme_key_t @var{key}}, @w{gpgme_attr_t @var{what}}, @w{const void *@var{reserved}}, @w{int @var{idx}}) +The function @code{gpgme_key_get_string_attr} returns the value of the +string-representable attribute @var{what} of key @var{key}. If the +attribute is an attribute of a sub key or an user ID, @var{idx} +specifies the sub key or user ID of which the attribute value is +returned. The argument @var{reserved} is reserved for later use and +should be @code{NULL}. + +The string returned is only valid as long as the key is valid. + +The function returns @code{0} if an attribute can't be returned as a +string, @var{key} is not a valid pointer, @var{idx} out of range, +or @var{reserved} not @code{NULL}. +@end deftypefun + +@deftypefun {unsigned long} gpgme_key_get_ulong_attr (@w{gpgme_key_t @var{key}}, @w{gpgme_attr_t @var{what}}, @w{const void *@var{reserved}}, @w{int @var{idx}}) +The function @code{gpgme_key_get_ulong_attr} returns the value of the +number-representable attribute @var{what} of key @var{key}. If the +attribute is an attribute of a sub key or an user ID, @var{idx} +specifies the sub key or user ID of which the attribute value is +returned. The argument @var{reserved} is reserved for later use and +should be @code{NULL}. + +The function returns @code{0} if the attribute can't be returned as a +number, @var{key} is not a valid pointer, @var{idx} out of range, or +@var{reserved} not @code{NULL}. +@end deftypefun + + +@node Key Signatures +@subsection Key Signatures +@cindex key, signatures +@cindex signatures, on a key + +The following interfaces are deprecated and only provided for backward +compatibility. Don't use them. They will be removed in a future +version of @acronym{GPGME}. + +The signatures on a key are only available if the key was retrieved +via a listing operation with the @code{GPGME_KEYLIST_MODE_SIGS} mode +enabled, because it is expensive to retrieve all signatures of a key. + +So, before using the below interfaces to retrieve the signatures on a +key, you have to make sure that the key was listed with signatures +enabled. One convenient, but blocking, way to do this is to use the +function @code{gpgme_get_key}. + +@deftp {Data type} gpgme_attr_t +The @code{gpgme_attr_t} type is used to specify a key signature +attribute. The following attributes are defined: + +@table @code +@item GPGME_ATTR_KEYID +This is the key ID of the key which was used for the signature. It is +representable as a string. + +@item GPGME_ATTR_ALGO +This is the crypto algorithm used to create the signature. It is +representable as a string and as a number. The numbers correspond to +the @code{enum gcry_pk_algos} values in the gcrypt library. + +@item GPGME_ATTR_CREATED +This is the timestamp at creation time of the signature. It is +representable as a number. + +@item GPGME_ATTR_EXPIRE +This is the expiration time of the signature. It is representable as +a number. + +@item GPGME_ATTR_USERID +This is the user ID associated with the signing key. The user ID is +representable as a number. + +@item GPGME_ATTR_NAME +This is the name belonging to a user ID. It is representable as a string. + +@item GPGME_ATTR_EMAIL +This is the email address belonging to a user ID. It is representable +as a string. + +@item GPGME_ATTR_COMMENT +This is the comment belonging to a user ID. It is representable as a +string. + +@item GPGME_ATTR_KEY_REVOKED +This specifies if a key signature is a revocation signature. It is +representable as a number, and is @code{1} if the key is revoked, and +@code{0} otherwise. + +@c @item GPGME_ATTR_KEY_EXPIRED +@c This specifies if a key signature is expired. It is representable as +@c a number, and is @code{1} if the key is revoked, and @code{0} +@c otherwise. +@c +@item GPGME_ATTR_SIG_CLASS +This specifies the signature class of a key signature. It is +representable as a number. The meaning is specific to the crypto +engine. + +@item GPGME_ATTR_SIG_CLASS +This specifies the signature class of a key signature. It is +representable as a number. The meaning is specific to the crypto +engine. + +@item GPGME_ATTR_SIG_STATUS +This is the same value as returned by @code{gpgme_get_sig_status}. +@end table +@end deftp + +@deftypefun {const char *} gpgme_key_sig_get_string_attr (@w{gpgme_key_t @var{key}}, @w{int @var{uid_idx}}, @w{gpgme_attr_t @var{what}}, @w{const void *@var{reserved}}, @w{int @var{idx}}) +The function @code{gpgme_key_sig_get_string_attr} returns the value of +the string-representable attribute @var{what} of the signature +@var{idx} on the user ID @var{uid_idx} in the key @var{key}. The +argument @var{reserved} is reserved for later use and should be +@code{NULL}. + +The string returned is only valid as long as the key is valid. + +The function returns @code{0} if an attribute can't be returned as a +string, @var{key} is not a valid pointer, @var{uid_idx} or @var{idx} +out of range, or @var{reserved} not @code{NULL}. +@end deftypefun + +@deftypefun {unsigned long} gpgme_key_sig_get_ulong_attr (@w{gpgme_key_t @var{key}}, @w{int @var{uid_idx}}, @w{gpgme_attr_t @var{what}}, @w{const void *@var{reserved}}, @w{int @var{idx}}) +The function @code{gpgme_key_sig_get_ulong_attr} returns the value of +the number-representable attribute @var{what} of the signature +@var{idx} on the user ID @var{uid_idx} in the key @var{key}. The +argument @var{reserved} is reserved for later use and should be +@code{NULL}. + +The function returns @code{0} if an attribute can't be returned as a +string, @var{key} is not a valid pointer, @var{uid_idx} or @var{idx} +out of range, or @var{reserved} not @code{NULL}. +@end deftypefun + + +@node Manipulating Keys +@subsection Manipulating Keys +@cindex key, manipulation + +@deftypefun void gpgme_key_ref (@w{gpgme_key_t @var{key}}) +The function @code{gpgme_key_ref} acquires an additional reference for +the key @var{key}. +@end deftypefun + +@deftypefun void gpgme_key_unref (@w{gpgme_key_t @var{key}}) +The function @code{gpgme_key_unref} releases a reference for the key +@var{key}. If this was the last reference, the key will be destroyed +and all resources associated to it will be released. +@end deftypefun + + +The following interface is deprecated and only provided for backward +compatibility. Don't use it. It will be removed in a future version +of @acronym{GPGME}. + +@deftypefun void gpgme_key_release (@w{gpgme_key_t @var{key}}) +The function @code{gpgme_key_release} is equivalent to +@code{gpgme_key_unref}. +@end deftypefun + + +@node Generating Keys +@subsection Generating Keys +@cindex key, creation +@cindex key ring, add + +@deftypefun gpgme_error_t gpgme_op_genkey (@w{gpgme_ctx_t @var{ctx}}, @w{const char *@var{parms}}, @w{gpgme_data_t @var{public}}, @w{gpgme_data_t @var{secret}}) +The function @code{gpgme_op_genkey} generates a new key pair in the +context @var{ctx}. The meaning of @var{public} and @var{secret} +depends on the crypto backend. + +GnuPG does not support @var{public} and @var{secret}, they should be +@code{NULL}. GnuPG will generate a key pair and add it to the +standard key ring. The fingerprint of the generated key is available +with @code{gpgme_op_genkey_result}. + +GpgSM requires @var{public} to be a writable data object. GpgSM will +generate a secret key (which will be stored by @command{gpg-agent}, +and return a certificate request in @var{public}, which then needs to +be signed by the certification authority and imported before it can be +used. GpgSM does not make the fingerprint available. + +The argument @var{parms} specifies parameters for the key in an XML +string. The details about the format of @var{parms} are specific to +the crypto engine used by @var{ctx}. Here is an example for GnuPG as +the crypto engine: + +@example + +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 + +@end example + +Here is an example for GpgSM as the crypto engine: + +@example + +Key-Type: RSA +Key-Length: 1024 +Name-DN: C=de,O=g10 code,OU=Testlab,CN=Joe 2 Tester +Name-Email: joe@@foo.bar + +@end example + +Strings should be given in UTF-8 encoding. The only format supported +for now is ``internal''. The content of the @code{GnupgKeyParms} +container is passed verbatim to the crypto backend. Control +statements are not allowed. + +After the operation completed successfully, the result can be +retrieved with @code{gpgme_op_genkey_result}. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +operation could be started successfully, @code{GPG_ERR_INV_VALUE} if +@var{parms} is not a valid XML string, @code{GPG_ERR_NOT_SUPPORTED} if +@var{public} or @var{secret} is not valid, and @code{GPG_ERR_GENERAL} +if no key was created by the backend. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_op_genkey_start (@w{gpgme_ctx_t @var{ctx}}, @w{const char *@var{parms}}, @w{gpgme_data_t @var{public}}, @w{gpgme_data_t @var{secret}}) +The function @code{gpgme_op_genkey_start} initiates a +@code{gpgme_op_genkey} operation. It can be completed by calling +@code{gpgme_wait} on the context. @xref{Waiting For Completion}. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +operation could be started successfully, @code{GPG_ERR_INV_VALUE} if +@var{parms} is not a valid XML string, and +@code{GPG_ERR_NOT_SUPPORTED} if @var{public} or @var{secret} is not +@code{NULL}. +@end deftypefun + +@deftp {Data type} {gpgme_genkey_result_t} +This is a pointer to a structure used to store the result of a +@code{gpgme_op_genkey} operation. After successfully generating a +key, you can retrieve the pointer to the result with +@code{gpgme_op_genkey_result}. The structure contains the following +members: + +@table @code +@item unsigned int primary : 1 +This is a flag that is set to 1 if a primary key was created and to 0 +if not. + +@item unsigned int sub : 1 +This is a flag that is set to 1 if a subkey was created and to 0 +if not. + +@item char *fpr +This is the fingerprint of the key that was created. If both a +primary and a sub key were generated, the fingerprint of the primary +key will be returned. If the crypto engine does not provide the +fingerprint, @code{fpr} will be a null pointer. +@end table +@end deftp + +@deftypefun gpgme_genkey_result_t gpgme_op_genkey_result (@w{gpgme_ctx_t @var{ctx}}) +The function @code{gpgme_op_genkey_result} returns a +@code{gpgme_genkey_result_t} pointer to a structure holding the result of +a @code{gpgme_op_genkey} operation. The pointer is only valid if the +last operation on the context was a @code{gpgme_op_genkey} or +@code{gpgme_op_genkey_start} operation, and if this operation finished +successfully. The returned pointer is only valid until the next +operation is started on the context. +@end deftypefun + + +@node Exporting Keys +@subsection Exporting Keys +@cindex key, export +@cindex key ring, export from + +@deftypefun gpgme_error_t gpgme_op_export (@w{gpgme_ctx_t @var{ctx}}, @w{const char *@var{pattern}}, @w{unsigned int @var{reserved}}, @w{gpgme_data_t @var{keydata}}) +The function @code{gpgme_op_export} extracts public keys and returns +them in the data buffer @var{keydata}. The output format of the key +data returned is determined by the @acronym{ASCII} armor attribute set +for the context @var{ctx}. + +If @var{pattern} is @code{NULL}, all available keys are returned. +Otherwise, @var{pattern} contains an engine specific expression that +is used to limit the list to all keys matching the pattern. + +@var{reserved} is reserved for future use and must be @code{0}. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +operation completed successfully, @code{GPG_ERR_INV_VALUE} if +@var{keydata} is not a valid empty data buffer, and passes through any +errors that are reported by the crypto engine support routines. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_op_export_start (@w{gpgme_ctx_t @var{ctx}}, @w{const char *@var{pattern}}, @w{unsigned int @var{reserved}}, @w{gpgme_data_t @var{keydata}}) +The function @code{gpgme_op_export_start} initiates a +@code{gpgme_op_export} operation. It can be completed by calling +@code{gpgme_wait} on the context. @xref{Waiting For Completion}. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +operation could be started successfully, and @code{GPG_ERR_INV_VALUE} +if @var{keydata} is not a valid empty data buffer. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_op_export_ext (@w{gpgme_ctx_t @var{ctx}}, @w{const char *@var{pattern}[]}, @w{unsigned int @var{reserved}}, @w{gpgme_data_t @var{keydata}}) +The function @code{gpgme_op_export} extracts public keys and returns +them in the data buffer @var{keydata}. The output format of the key +data returned is determined by the @acronym{ASCII} armor attribute set +for the context @var{ctx}. + +If @var{pattern} or @var{*pattern} is @code{NULL}, all available keys +are returned. Otherwise, @var{pattern} is a @code{NULL} terminated +array of strings that are used to limit the list to all keys matching +at least one of the patterns verbatim. + +@var{reserved} is reserved for future use and must be @code{0}. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +operation completed successfully, @code{GPG_ERR_INV_VALUE} if +@var{keydata} is not a valid empty data buffer, and passes through any +errors that are reported by the crypto engine support routines. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_op_export_ext_start (@w{gpgme_ctx_t @var{ctx}}, @w{const char *@var{pattern}[]}, @w{unsigned int @var{reserved}}, @w{gpgme_data_t @var{keydata}}) +The function @code{gpgme_op_export_ext_start} initiates a +@code{gpgme_op_export_ext} operation. It can be completed by calling +@code{gpgme_wait} on the context. @xref{Waiting For Completion}. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +operation could be started successfully, and @code{GPG_ERR_INV_VALUE} +if @var{keydata} is not a valid empty data buffer. +@end deftypefun + + +@node Importing Keys +@subsection Importing Keys +@cindex key, import +@cindex key ring, import to + +@deftypefun gpgme_error_t gpgme_op_import (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_data_t @var{keydata}}) +The function @code{gpgme_op_import} adds the keys in the data buffer +@var{keydata} to the key ring of the crypto engine used by @var{ctx}. +The format of @var{keydata} can be @acronym{ASCII} armored, for example, +but the details are specific to the crypto engine. + +After the operation completed successfully, the result can be +retrieved with @code{gpgme_op_import_result}. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +import was completed successfully, @code{GPG_ERR_INV_VALUE} if +@var{keydata} if @var{ctx} or @var{keydata} is not a valid pointer, +and @code{GPG_ERR_NO_DATA} if @var{keydata} is an empty data buffer. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_op_import_start (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_data_t @var{keydata}}) +The function @code{gpgme_op_import_start} initiates a +@code{gpgme_op_import} operation. It can be completed by calling +@code{gpgme_wait} on the context. @xref{Waiting For Completion}. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +import could be started successfully, @code{GPG_ERR_INV_VALUE} if +@var{keydata} if @var{ctx} or @var{keydata} is not a valid pointer, +and @code{GPG_ERR_NO_DATA} if @var{keydata} is an empty data buffer. +@end deftypefun + +@deftp {Data type} {gpgme_import_status_t} +This is a pointer to a structure used to store a part of the result of +a @code{gpgme_op_import} operation. For each considered key one +status is added that contains information about the result of the +import. The structure contains the following members: + +@table @code +@item gpgme_import_status_t next +This is a pointer to the next status structure in the linked list, or +@code{NULL} if this is the last element. + +@item char *fpr +This is the fingerprint of the key that was considered. + +@item gpgme_error_t result +If the import was not successful, this is the error value that caused +the import to fail. Otherwise the error code is +@code{GPG_ERR_NO_ERROR}. + +@item unsigned int status +This is a bit-wise OR of the following flags that give more +information about what part of the key was imported. If the key was +already known, this might be 0. + +@table @code +@item GPGME_IMPORT_NEW +The key was new. + +@item GPGME_IMPORT_UID +The key contained new user IDs. + +@item GPGME_IMPORT_SIG +The key contained new signatures. + +@item GPGME_IMPORT_SUBKEY +The key contained new sub keys. + +@item GPGME_IMPORT_SECRET +The key contained a secret key. +@end table +@end table +@end deftp + +@deftp {Data type} {gpgme_import_result_t} +This is a pointer to a structure used to store the result of a +@code{gpgme_op_import} operation. After a successful import +operation, you can retrieve the pointer to the result with +@code{gpgme_op_import_result}. The structure contains the following +members: + +@table @code +@item int considered +The total number of considered keys. + +@item int no_user_id +The number of keys without user ID. + +@item int imported +The total number of imported keys. + +@item imported_rsa +The number of imported RSA keys. + +@item unchanged +The number of unchanged keys. + +@item new_user_ids +The number of new user IDs. + +@item new_sub_keys +The number of new sub keys. + +@item new_signatures +The number of new signatures. + +@item new_revocations +The number of new revocations. + +@item secret_read +The total number of secret keys read. + +@item secret_imported +The number of imported secret keys. + +@item secret_unchanged +The number of unchanged secret keys. + +@item not_imported +The number of keys not imported. + +@item gpgme_import_status_t imports +A list of gpgme_import_status_t objects which contain more information +about the keys for which an import was attempted. +@end table +@end deftp + +@deftypefun gpgme_import_result_t gpgme_op_import_result (@w{gpgme_ctx_t @var{ctx}}) +The function @code{gpgme_op_import_result} returns a +@code{gpgme_import_result_t} pointer to a structure holding the result +of a @code{gpgme_op_import} operation. The pointer is only valid if +the last operation on the context was a @code{gpgme_op_import} or +@code{gpgme_op_import_start} operation, and if this operation finished +successfully. The returned pointer is only valid until the next +operation is started on the context. +@end deftypefun + +The following interface is deprecated and only provided for backward +compatibility. Don't use it. It will be removed in a future version +of @acronym{GPGME}. + +@deftypefun gpgme_error_t gpgme_op_import_ext (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_data_t @var{keydata}}, @w{int *@var{nr}}) +The function @code{gpgme_op_import_ext} is equivalent to: + +@example + gpgme_error_t err = gpgme_op_import (ctx, keydata); + if (!err) + @{ + gpgme_import_result_t result = gpgme_op_import_result (ctx); + *nr = result->considered; + @} +@end example +@end deftypefun + + +@node Deleting Keys +@subsection Deleting Keys +@cindex key, delete +@cindex key ring, delete from + +@deftypefun gpgme_error_t gpgme_op_delete (@w{gpgme_ctx_t @var{ctx}}, @w{const gpgme_key_t @var{key}}, @w{int @var{allow_secret}}) +The function @code{gpgme_op_delete} deletes the key @var{key} from the +key ring of the crypto engine used by @var{ctx}. If +@var{allow_secret} is @code{0}, only public keys are deleted, +otherwise secret keys are deleted as well, if that is supported. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the key +was deleted successfully, @code{GPG_ERR_INV_VALUE} if @var{ctx} or +@var{key} is not a valid pointer, @code{GPG_ERR_NO_PUBKEY} if +@var{key} could not be found in the keyring, +@code{GPG_ERR_AMBIGUOUS_NAME} if the key was not specified +unambiguously, and @code{GPG_ERR_CONFLICT} if the secret key for +@var{key} is available, but @var{allow_secret} is zero. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_op_delete_start (@w{gpgme_ctx_t @var{ctx}}, @w{const gpgme_key_t @var{key}}, @w{int @var{allow_secret}}) +The function @code{gpgme_op_delete_start} initiates a +@code{gpgme_op_delete} operation. It can be completed by calling +@code{gpgme_wait} on the context. @xref{Waiting For Completion}. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +operation was started successfully, and @code{GPG_ERR_INV_VALUE} if +@var{ctx} or @var{key} is not a valid pointer. +@end deftypefun + + +@node Advanced Key Editing +@subsection Advanced Key Editing +@cindex key, edit + +@deftp {Data type} {gpgme_error_t (*gpgme_edit_cb_t) (@w{void *@var{handle}}, @w{gpgme_status_code_t @var{status}}, @w{const char *@var{args}}, @w{int @var{fd}})} +@tindex gpgme_edit_cb_t +The @code{gpgme_edit_cb_t} type is the type of functions which +@acronym{GPGME} calls if it a key edit operation is on-going. The +status code @var{status} and the argument line @var{args} are passed +through by @acronym{GPGME} from the crypto engine. The file +descriptor @var{fd} is -1 for normal status messages. If @var{status} +indicates a command rather than a status message, the response to the +command should be written to @var{fd}. The @var{handle} is provided +by the user at start of operation. + +The function should return @code{GPG_ERR_NO_ERROR} or an error value. +@end deftp + +@deftypefun gpgme_error_t gpgme_op_edit (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_key_t @var{key}}, @w{gpgme_edit_cb_t @var{fnc}}, @w{void *@var{handle}}, @w{gpgme_data_t @var{out}}) +The function @code{gpgme_op_edit} processes the key @var{KEY} +interactively, using the edit callback function @var{FNC} with the +handle @var{HANDLE}. The callback is invoked for every status and +command request from the crypto engine. The output of the crypto +engine is written to the data object @var{out}. + +Note that the protocol between the callback function and the crypto +engine is specific to the crypto engine and no further support in +implementing this protocol correctly is provided by @acronym{GPGME}. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +edit operation completes successfully, @code{GPG_ERR_INV_VALUE} if +@var{ctx} or @var{key} is not a valid pointer, and any error returned +by the crypto engine or the edit callback handler. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_op_edit_start (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_key_t @var{key}}, @w{gpgme_edit_cb_t @var{fnc}}, @w{void *@var{handle}}, @w{gpgme_data_t @var{out}}) +The function @code{gpgme_op_edit_start} initiates a +@code{gpgme_op_edit} operation. It can be completed by calling +@code{gpgme_wait} on the context. @xref{Waiting For Completion}. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +operation was started successfully, and @code{GPG_ERR_INV_VALUE} if +@var{ctx} or @var{key} is not a valid pointer. +@end deftypefun + + +@deftypefun gpgme_error_t gpgme_op_card_edit (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_key_t @var{key}}, @w{gpgme_edit_cb_t @var{fnc}}, @w{void *@var{handle}}, @w{gpgme_data_t @var{out}}) +The function @code{gpgme_op_card_edit} is analogous to +@code{gpgme_op_edit}, but should be used to process the smart card corresponding to the key @var{key}. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_op_card_edit_start (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_key_t @var{key}}, @w{gpgme_edit_cb_t @var{fnc}}, @w{void *@var{handle}}, @w{gpgme_data_t @var{out}}) +The function @code{gpgme_op_card_edit_start} initiates a +@code{gpgme_op_card_edit} operation. It can be completed by calling +@code{gpgme_wait} on the context. @xref{Waiting For Completion}. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +operation was started successfully, and @code{GPG_ERR_INV_VALUE} if +@var{ctx} or @var{key} is not a valid pointer. +@end deftypefun + + +@node Trust Item Management +@section Trust Item Management +@cindex trust item + +@strong{Caution:} The trust items interface is experimental. + +@deftp {Data type} gpgme_trust_item_t +The @code{gpgme_trust_item_t} type is a pointer to a trust item object. +It has the following members: + +@table @code +@item char *keyid +This is a string describing the key to which this trust items belongs. + +@item int type +This is the type of the trust item. A value of 1 refers to a key, a +value of 2 refers to a user ID. + +@item int level +This is the trust level. + +@item char *owner_trust +The owner trust if @code{type} is 1. + +@item char *validity +The calculated validity. + +@item char *name +The user name if @code{type} is 2. +@end table +@end deftp + +@menu +* Listing Trust Items:: Browsing the list of available trust items. +* Information About Trust Items:: Requesting information about trust items. +* Manipulating Trust Items:: Operations on trust items. +@end menu + + +@node Listing Trust Items +@subsection Listing Trust Items +@cindex trust item list + +@deftypefun gpgme_error_t gpgme_op_trustlist_start (@w{gpgme_ctx_t @var{ctx}}, @w{const char *@var{pattern}}, @w{int @var{max_level}}) +The function @code{gpgme_op_trustlist_start} initiates a trust item +listing operation inside the context @var{ctx}. It sets everything up +so that subsequent invocations of @code{gpgme_op_trustlist_next} return +the trust items in the list. + +The string @var{pattern} contains an engine specific expression that +is used to limit the list to all trust items matching the pattern. It +can not be the empty string. + +The argument @var{max_level} is currently ignored. + +The context will be busy until either all trust items are received +(and @code{gpgme_op_trustlist_next} returns @code{GPG_ERR_EOF}), or +@code{gpgme_op_trustlist_end} is called to finish the operation. + +The function returns the error code @code{GPG_ERR_INV_VALUE} if +@var{ctx} is not a valid pointer, and passes through any errors that +are reported by the crypto engine support routines. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_op_trustlist_next (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_trust_item_t *@var{r_item}}) +The function @code{gpgme_op_trustlist_next} returns the next trust +item in the list created by a previous @code{gpgme_op_trustlist_start} +operation in the context @var{ctx}. The trust item can be destroyed +with @code{gpgme_trust_item_release}. @xref{Manipulating Trust Items}. + +This is the only way to get at @code{gpgme_trust_item_t} objects in +@acronym{GPGME}. + +If the last trust item in the list has already been returned, +@code{gpgme_op_trustlist_next} returns @code{GPG_ERR_EOF}. + +The function returns the error code @code{GPG_ERR_INV_VALUE} if @var{ctx} or +@var{r_item} is not a valid pointer, and @code{GPG_ERR_ENOMEM} if +there is not enough memory for the operation. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_op_trustlist_end (@w{gpgme_ctx_t @var{ctx}}) +The function @code{gpgme_op_trustlist_next} ends a pending key list +operation in the context @var{ctx}. + +The function returns the error code @code{GPG_ERR_INV_VALUE} if +@var{ctx} is not a valid pointer, and @code{GPG_ERR_ENOMEM} if at some +time during the operation there was not enough memory available. +@end deftypefun + + +@node Information About Trust Items +@subsection Information About Trust Items +@cindex trust item, information about +@cindex trust item, attributes +@cindex attributes, of a trust item + +The following interfaces are deprecated and only provided for backward +compatibility. Don't use them. They will be removed in a future +version of @acronym{GPGME}. + +Trust items have attributes which can be queried using the interfaces +below. The attribute identifiers are shared with those for key +attributes. @xref{Information About Keys}. + +@deftypefun {const char *} gpgme_trust_item_get_string_attr (@w{gpgme_trust_item_t @var{item}}, @w{gpgme_attr_t @var{what}}, @w{const void *@var{reserved}}, @w{int @var{idx}}) +The function @code{gpgme_trust_item_get_string_attr} returns the value +of the string-representable attribute @var{what} of trust item +@var{item}. The arguments @var{idx} and @var{reserved} are reserved +for later use and should be @code{0} and @code{NULL} respectively. + +The string returned is only valid as long as the key is valid. + +The function returns @code{0} if an attribute can't be returned as a +string, @var{key} is not a valid pointer, @var{idx} out of range, +or @var{reserved} not @code{NULL}. +@end deftypefun + +@deftypefun int gpgme_trust_item_get_int_attr (@w{gpgme_trust_item_t @var{item}}, @w{gpgme_attr_t @var{what}}, @w{const void *@var{reserved}}, @w{int @var{idx}}) +The function @code{gpgme_trust_item_get_int_attr} returns the value of +the number-representable attribute @var{what} of trust item +@var{item}. If the attribute occurs more than once in the trust item, +the index is specified by @var{idx}. However, currently no such +attribute exists, so @var{idx} should be @code{0}. The argument +@var{reserved} is reserved for later use and should be @code{NULL}. + +The function returns @code{0} if the attribute can't be returned as a +number, @var{key} is not a valid pointer, @var{idx} out of range, +or @var{reserved} not @code{NULL}. +@end deftypefun + + +@node Manipulating Trust Items +@subsection Manipulating Trust Items +@cindex trust item, manipulation + +@deftypefun void gpgme_trust_item_ref (@w{gpgme_trust_item_t @var{item}}) +The function @code{gpgme_trust_item_ref} acquires an additional +reference for the trust item @var{item}. +@end deftypefun + +@deftypefun void gpgme_trust_item_unref (@w{gpgme_trust_item_t @var{item}}) +The function @code{gpgme_trust_item_unref} releases a reference for +the trust item @var{item}. If this was the last reference, the trust +item will be destroyed and all resources associated to it will be +released. +@end deftypefun + + +The following interface is deprecated and only provided for backward +compatibility. Don't use it. It will be removed in a future version +of @acronym{GPGME}. + +@deftypefun void gpgme_trust_item_release (@w{gpgme_trust_item_t @var{item}}) +The function @code{gpgme_trust_item_release} is an alias for +@code{gpgme_trust_item_unref}. +@end deftypefun + + +@node Crypto Operations +@section Crypto Operations +@cindex cryptographic operation + +Sometimes, the result of a crypto operation returns a list of invalid +keys encountered in processing the request. The following structure +is used to hold information about such a key. + +@deftp {Data type} {gpgme_invalid_key_t} +This is a pointer to a structure used to store a part of the result of +a crypto operation which takes user IDs as one input parameter. The +structure contains the following members: + +@table @code +@item gpgme_invalid_key_t next +This is a pointer to the next invalid key structure in the linked +list, or @code{NULL} if this is the last element. + +@item char *fpr +The fingerprint or key ID of the invalid key encountered. + +@item gpgme_error_t reason +An error code describing the reason why the key was found invalid. +@end table +@end deftp + + +@menu +* Decrypt:: Decrypting a ciphertext. +* Verify:: Verifying a signature. +* Decrypt and Verify:: Decrypting a signed ciphertext. +* Sign:: Creating a signature. +* Encrypt:: Encrypting a plaintext. +@end menu + + +@node Decrypt +@subsection Decrypt +@cindex decryption +@cindex cryptographic operation, decryption + +@deftypefun gpgme_error_t gpgme_op_decrypt (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_data_t @var{cipher}}, @w{gpgme_data_t @var{plain}}) +The function @code{gpgme_op_decrypt} decrypts the ciphertext in the +data object @var{cipher} and stores it into the data object +@var{plain}. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +ciphertext could be decrypted successfully, @code{GPG_ERR_INV_VALUE} +if @var{ctx}, @var{cipher} or @var{plain} is not a valid pointer, +@code{GPG_ERR_NO_DATA} if @var{cipher} does not contain any data to +decrypt, @code{GPG_ERR_DECRYPT_FAILED} if @var{cipher} is not a valid +cipher text, @code{GPG_ERR_BAD_PASSPHRASE} if the passphrase for the +secret key could not be retrieved, and passes through any errors that +are reported by the crypto engine support routines. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_op_decrypt_start (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_data_t @var{cipher}}, @w{gpgme_data_t @var{plain}}) +The function @code{gpgme_op_decrypt_start} initiates a +@code{gpgme_op_decrypt} operation. It can be completed by calling +@code{gpgme_wait} on the context. @xref{Waiting For Completion}. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +operation could be started successfully, and @code{GPG_ERR_INV_VALUE} +if @var{cipher} or @var{plain} is not a valid pointer. +@end deftypefun + +@deftp {Data type} {gpgme_recipient_t} +This is a pointer to a structure used to store information about the +recipient of an encrypted text which is decrypted in a +@code{gpgme_op_decrypt} operation. This information (except for the +status field) is even available before the operation finished +successfully, for example in a passphrase callback. The structure +contains the following members: + +@table @code +@item gpgme_recipient_t next +This is a pointer to the next recipient structure in the linked list, +or @code{NULL} if this is the last element. + +@item gpgme_pubkey_algo_t +The public key algorithm used in the encryption. + +@item unsigned int wrong_key_usage : 1 +This is true if the key was not used according to its policy. + +@item char *keyid +This is the key ID of the key (in hexadecimal digits) used as +recipient. + +@item gpgme_error_t status +This is an error number with the error code GPG_ERR_NO_SECKEY if the +secret key for this recipient is not available, and 0 otherwise. +@end table +@end deftp + +@deftp {Data type} {gpgme_decrypt_result_t} +This is a pointer to a structure used to store the result of a +@code{gpgme_op_decrypt} operation. After successfully decrypting +data, you can retrieve the pointer to the result with +@code{gpgme_op_decrypt_result}. The structure contains the following +members: + +@table @code +@item char *unsupported_algorithm +If an unsupported algorithm was encountered, this string describes the +algorithm that is not supported. + +@item unsigned int wrong_key_usage : 1 +This is true if the key was not used according to its policy. + +@item gpgme_recipient_t recipient +This is a linked list of recipients to which this message was encrypted. + +@item char *file_name +This is the filename of the original plaintext message file if it is +known, otherwise this is a null pointer. +@end table +@end deftp + +@deftypefun gpgme_decrypt_result_t gpgme_op_decrypt_result (@w{gpgme_ctx_t @var{ctx}}) +The function @code{gpgme_op_decrypt_result} returns a +@code{gpgme_decrypt_result_t} pointer to a structure holding the +result of a @code{gpgme_op_decrypt} operation. The pointer is only +valid if the last operation on the context was a +@code{gpgme_op_decrypt} or @code{gpgme_op_decrypt_start} operation. +If the operation failed this might be a @code{NULL} pointer. The +returned pointer is only valid until the next operation is started on +the context. +@end deftypefun + + +@node Verify +@subsection Verify +@cindex verification +@cindex signature, verification +@cindex cryptographic operation, verification +@cindex cryptographic operation, signature check +@cindex signature notation data +@cindex notation data + +@deftypefun gpgme_error_t gpgme_op_verify (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_data_t @var{sig}}, @w{gpgme_data_t @var{signed_text}}, @w{gpgme_data_t @var{plain}}) +The function @code{gpgme_op_verify} verifies that the signature in the +data object @var{sig} is a valid signature. If @var{sig} is a +detached signature, then the signed text should be provided in +@var{signed_text} and @var{plain} should be a null pointer. +Otherwise, if @var{sig} is a normal (or cleartext) signature, +@var{signed_text} should be a null pointer and @var{plain} should be a +writable data object that will contain the plaintext after successful +verification. + +The results of the individual signature verifications can be retrieved +with @code{gpgme_op_verify_result}. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +operation could be completed successfully, @code{GPG_ERR_INV_VALUE} if +@var{ctx}, @var{sig} or @var{plain} is not a valid pointer, +@code{GPG_ERR_NO_DATA} if @var{sig} does not contain any data to +verify, and passes through any errors that are reported by the crypto +engine support routines. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_op_verify_start (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_data_t @var{sig}}, @w{gpgme_data_t @var{signed_text}}, @w{gpgme_data_t @var{plain}}) +The function @code{gpgme_op_verify_start} initiates a +@code{gpgme_op_verify} operation. It can be completed by calling +@code{gpgme_wait} on the context. @xref{Waiting For Completion}. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +operation could be started successfully, @code{GPG_ERR_INV_VALUE} if +@var{ctx}, @var{sig} or @var{plain} is not a valid pointer, and +@code{GPG_ERR_NO_DATA} if @var{sig} or @var{plain} does not contain +any data to verify. +@end deftypefun + +@deftp {Data type} {gpgme_sig_notation_t} +This is a pointer to a structure used to store a part of the result of +a @code{gpgme_op_verify} operation. The structure contains the +following members: + +@table @code +@item gpgme_sig_notation_t next +This is a pointer to the next new signature notation structure in the +linked list, or @code{NULL} if this is the last element. + +@item char *name +The name of the notation field. If this is @code{NULL}, then the +member @code{value} will contain a policy URL. + +@item int name_len +The length of the @code{name} field. For strings the length is +counted without the trailing binary zero. + +@item char *value +The value of the notation field. If @code{name} is @code{NULL}, then +this is a policy URL. + +@item int value_len +The length of the @code{value} field. For strings the length is +counted without the trailing binary zero. + +@item gpgme_sig_notation_flags_t flags +The accumulated flags field. This field contains the flags associated +with the notation data in an accumulated form which can be used as an +argument to the function @code{gpgme_sig_notation_add}. The value +@code{flags} is a bitwise-or combination of one or multiple of the +following bit values: + +@table @code +@item GPGME_SIG_NOTATION_HUMAN_READABLE +The @code{GPGME_SIG_NOTATION_HUMAN_READABLE} symbol specifies that the +notation data is in human readable form + +@item GPGME_SIG_NOTATION_CRITICAL +The @code{GPGME_SIG_NOTATION_CRITICAL} symbol specifies that the +notation data is critical. + +@end table + +@item unsigned int human_readable : 1 +This is true if the @code{GPGME_SIG_NOTATION_HUMAN_READABLE} flag is +set and false otherwise. This flag is only valid for notation data, +not for policy URLs. + +@item unsigned int critical : 1 +This is true if the @code{GPGME_SIG_NOTATION_CRITICAL} flag is set and +false otherwise. This flag is valid for notation data and policy URLs. + +@end table +@end deftp + +@deftp {Data type} {gpgme_signature_t} +This is a pointer to a structure used to store a part of the result of +a @code{gpgme_op_verify} operation. The structure contains the +following members: + +@table @code +@item gpgme_signature_t next +This is a pointer to the next new signature structure in the linked +list, or @code{NULL} if this is the last element. + +@item gpgme_sigsum_t summary +This is a bit vector giving a summary of the signature status. It +provides an easy interface to a defined semantic of the signature +status. Checking just one bit is sufficient to see whether a +signature is valid without any restrictions. + +The defined bits are: + @table @code + @item GPGME_SIGSUM_VALID + The signature is fully valid. + + @item GPGME_SIGSUM_GREEN + The signature is good but one might want to display some extra + information. Check the other bits. + + @item GPGME_SIGSUM_RED + The signature is bad. It might be useful to check other bits and + display more information, i.e. a revoked certificate might not render a + signature invalid when the message was received prior to the cause for + the revocation. + + @item GPGME_SIGSUM_KEY_REVOKED + The key or at least one certificate has been revoked. + + @item GPGME_SIGSUM_KEY_EXPIRED + The key or one of the certificates has expired. It is probably a good + idea to display the date of the expiration. + + @item GPGME_SIGSUM_SIG_EXPIRED + The signature has expired. + + @item GPGME_SIGSUM_KEY_MISSING + Can't verify due to a missing key or certificate. + + @item GPGME_SIGSUM_CRL_MISSING + The CRL (or an equivalent mechanism) is not available. + + @item GPGME_SIGSUM_CRL_TOO_OLD + Available CRL is too old. + + @item GPGME_SIGSUM_BAD_POLICY + A policy requirement was not met. + + @item GPGME_SIGSUM_SYS_ERROR + A system error occured. + @end table + +@item char *fpr +This is the fingerprint or key ID of the signature. + +@item gpgme_error_t status +This is the status of the signature. In particular, the following +status codes are of interest: + + @table @code + @item GPG_ERR_NO_ERROR + This status indicates that the signature is valid. For the combined + result this status means that all signatures are valid. + + @item GPG_ERR_SIG_EXPIRED + This status indicates that the signature is valid but expired. For + the combined result this status means that all signatures are valid + and expired. + + @item GPG_ERR_KEY_EXPIRED + This status indicates that the signature is valid but the key used to + verify the signature has expired. For the combined result this status + means that all signatures are valid and all keys are expired. + + @item GPG_ERR_CERT_REVOKED + This status indicates that the signature is valid but the key used + to verify the signature has been revoked. For the combined result + this status means that all signatures are valid and all keys are + revoked. + + @item GPG_ERR_BAD_SIGNATURE + This status indicates that the signature is invalid. For the combined + result this status means that all signatures are invalid. + + @item GPG_ERR_NO_PUBKEY + This status indicates that the signature could not be verified due to + a missing key. For the combined result this status means that all + signatures could not be checked due to missing keys. + + @item GPG_ERR_GENERAL + This status indicates that there was some other error which prevented + the signature verification. + @end table + +@item gpgme_sig_notation_t notations +This is a linked list with the notation data and policy URLs. + +@item unsigned long timestamp +The creation timestamp of this signature. + +@item unsigned long exp_timestamp +The expiration timestamp of this signature, or 0 if the signature does +not expire. + +@item unsigned int wrong_key_usage : 1 +This is true if the key was not used according to its policy. + +@item unsigned int pka_trust : 2 +This is set to the trust information gained by means of the PKA system. +Values are: + @table @code + @item 0 + No PKA information available or verification not possible. + @item 1 + PKA verification failed. + @item 2 + PKA verification succeeded. + @item 3 + Reserved for future use. + @end table +Depending on the configuration of the engine, this metric may also be +reflected by the validity of the signature. + +@item unsigned int chain_model : 1 +This is true if the validity of the signature has been checked using the +chain model. In the chain model the time the signature has been created +must be within the validity period of the certificate and the time the +certificate itself has been created must be within the validity period +of the issuing certificate. In contrast the default validation model +checks the validity of signature as well at the entire certificate chain +at the current time. + + +@item gpgme_validity_t validity +The validity of the signature. + +@item gpgme_error_t validity_reason +If a signature is not valid, this provides a reason why. + +@item gpgme_pubkey_algo_t +The public key algorithm used to create this signature. + +@item gpgme_hash_algo_t +The hash algorithm used to create this signature. +@end table +@end deftp + +@deftp {Data type} {gpgme_verify_result_t} +This is a pointer to a structure used to store the result of a +@code{gpgme_op_verify} operation. After verifying a signature, you +can retrieve the pointer to the result with +@code{gpgme_op_verify_result}. If the operation failed this might be +a @code{NULL} pointer. The structure contains the following member: + +@table @code +@item gpgme_signature_t signatures +A linked list with information about all signatures for which a +verification was attempted. + +@item char *file_name +This is the filename of the original plaintext message file if it is +known, otherwise this is a null pointer. +@end table +@end deftp + +@deftypefun gpgme_verify_result_t gpgme_op_verify_result (@w{gpgme_ctx_t @var{ctx}}) +The function @code{gpgme_op_verify_result} returns a +@code{gpgme_verify_result_t} pointer to a structure holding the result +of a @code{gpgme_op_verify} operation. The pointer is only valid if +the last operation on the context was a @code{gpgme_op_verify}, +@code{gpgme_op_verify_start}, @code{gpgme_op_decrypt_verify} or +@code{gpgme_op_decrypt_verify_start} operation, and if this operation +finished successfully (for @code{gpgme_op_decrypt_verify} and +@code{gpgme_op_decrypt_verify_start}, the error code +@code{GPG_ERR_NO_DATA} counts as successful in this context). The +returned pointer is only valid until the next operation is started on +the context. +@end deftypefun + + +The following interfaces are deprecated and only provided for backward +compatibility. Don't use them. They will be removed in a future +version of @acronym{GPGME}. + +@deftp {Data type} {enum gpgme_sig_stat_t} +@tindex gpgme_sig_stat_t +The @code{gpgme_sig_stat_t} type holds the result of a signature check, or +the combined result of all signatures. The following results are +possible: + +@table @code +@item GPGME_SIG_STAT_NONE +This status should not occur in normal operation. + +@item GPGME_SIG_STAT_GOOD +This status indicates that the signature is valid. For the combined +result this status means that all signatures are valid. + +@item GPGME_SIG_STAT_GOOD_EXP +This status indicates that the signature is valid but expired. For +the combined result this status means that all signatures are valid +and expired. + +@item GPGME_SIG_STAT_GOOD_EXPKEY +This status indicates that the signature is valid but the key used to +verify the signature has expired. For the combined result this status +means that all signatures are valid and all keys are expired. + +@item GPGME_SIG_STAT_BAD +This status indicates that the signature is invalid. For the combined +result this status means that all signatures are invalid. + +@item GPGME_SIG_STAT_NOKEY +This status indicates that the signature could not be verified due to +a missing key. For the combined result this status means that all +signatures could not be checked due to missing keys. + +@item GPGME_SIG_STAT_NOSIG +This status indicates that the signature data provided was not a real +signature. + +@item GPGME_SIG_STAT_ERROR +This status indicates that there was some other error which prevented +the signature verification. + +@item GPGME_SIG_STAT_DIFF +For the combined result this status means that at least two signatures +have a different status. You can get each key's status with +@code{gpgme_get_sig_status}. +@end table +@end deftp + +@deftypefun {const char *} gpgme_get_sig_status (@w{gpgme_ctx_t @var{ctx}}, @w{int @var{idx}}, @w{gpgme_sig_stat_t *@var{r_stat}}, @w{time_t *@var{r_created}}) +The function @code{gpgme_get_sig_status} is equivalent to: + +@example + gpgme_verify_result_t result; + gpgme_signature_t sig; + + result = gpgme_op_verify_result (ctx); + sig = result->signatures; + + while (sig && idx) + @{ + sig = sig->next; + idx--; + @} + if (!sig || idx) + return NULL; + + if (r_stat) + @{ + switch (gpg_err_code (sig->status)) + @{ + case GPG_ERR_NO_ERROR: + *r_stat = GPGME_SIG_STAT_GOOD; + break; + + case GPG_ERR_BAD_SIGNATURE: + *r_stat = GPGME_SIG_STAT_BAD; + break; + + case GPG_ERR_NO_PUBKEY: + *r_stat = GPGME_SIG_STAT_NOKEY; + break; + + case GPG_ERR_NO_DATA: + *r_stat = GPGME_SIG_STAT_NOSIG; + break; + + case GPG_ERR_SIG_EXPIRED: + *r_stat = GPGME_SIG_STAT_GOOD_EXP; + break; + + case GPG_ERR_KEY_EXPIRED: + *r_stat = GPGME_SIG_STAT_GOOD_EXPKEY; + break; + + default: + *r_stat = GPGME_SIG_STAT_ERROR; + break; + @} + @} + if (r_created) + *r_created = sig->timestamp; + return sig->fpr; +@end example +@end deftypefun + +@deftypefun {const char *} gpgme_get_sig_string_attr (@w{gpgme_ctx_t @var{ctx}}, @w{int @var{idx}}, @w{gpgme_attr_t @var{what}}, @w{int @var{whatidx}}) +The function @code{gpgme_get_sig_string_attr} is equivalent to: + +@example + gpgme_verify_result_t result; + gpgme_signature_t sig; + + result = gpgme_op_verify_result (ctx); + sig = result->signatures; + + while (sig && idx) + @{ + sig = sig->next; + idx--; + @} + if (!sig || idx) + return NULL; + + switch (what) + @{ + case GPGME_ATTR_FPR: + return sig->fpr; + + case GPGME_ATTR_ERRTOK: + if (whatidx == 1) + return sig->wrong_key_usage ? "Wrong_Key_Usage" : ""; + else + return ""; + default: + break; + @} + + return NULL; +@end example +@end deftypefun + +@deftypefun {const char *} gpgme_get_sig_ulong_attr (@w{gpgme_ctx_t @var{ctx}}, @w{int @var{idx}}, @w{gpgme_attr_t @var{waht}}, @w{int @var{whatidx}}) +The function @code{gpgme_get_sig_ulong_attr} is equivalent to: + +@example + gpgme_verify_result_t result; + gpgme_signature_t sig; + + result = gpgme_op_verify_result (ctx); + sig = result->signatures; + + while (sig && idx) + @{ + sig = sig->next; + idx--; + @} + if (!sig || idx) + return 0; + + switch (what) + @{ + case GPGME_ATTR_CREATED: + return sig->timestamp; + + case GPGME_ATTR_EXPIRE: + return sig->exp_timestamp; + + case GPGME_ATTR_VALIDITY: + return (unsigned long) sig->validity; + + case GPGME_ATTR_SIG_STATUS: + switch (sig->status) + @{ + case GPG_ERR_NO_ERROR: + return GPGME_SIG_STAT_GOOD; + + case GPG_ERR_BAD_SIGNATURE: + return GPGME_SIG_STAT_BAD; + + case GPG_ERR_NO_PUBKEY: + return GPGME_SIG_STAT_NOKEY; + + case GPG_ERR_NO_DATA: + return GPGME_SIG_STAT_NOSIG; + + case GPG_ERR_SIG_EXPIRED: + return GPGME_SIG_STAT_GOOD_EXP; + + case GPG_ERR_KEY_EXPIRED: + return GPGME_SIG_STAT_GOOD_EXPKEY; + + default: + return GPGME_SIG_STAT_ERROR; + @} + + case GPGME_ATTR_SIG_SUMMARY: + return sig->summary; + + default: + break; + @} + return 0; +@end example +@end deftypefun + +@deftypefun {const char *} gpgme_get_sig_key (@w{gpgme_ctx_t @var{ctx}}, @w{int @var{idx}}, @w{gpgme_key_t *@var{r_key}}) +The function @code{gpgme_get_sig_key} is equivalent to: + +@example + gpgme_verify_result_t result; + gpgme_signature_t sig; + + result = gpgme_op_verify_result (ctx); + sig = result->signatures; + + while (sig && idx) + @{ + sig = sig->next; + idx--; + @} + if (!sig || idx) + return gpg_error (GPG_ERR_EOF); + + return gpgme_get_key (ctx, sig->fpr, r_key, 0); +@end example +@end deftypefun + + +@node Decrypt and Verify +@subsection Decrypt and Verify +@cindex decryption and verification +@cindex verification and decryption +@cindex signature check +@cindex cryptographic operation, decryption and verification + +@deftypefun gpgme_error_t gpgme_op_decrypt_verify (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_data_t @var{cipher}}, @w{gpgme_data_t @var{plain}}) +The function @code{gpgme_op_decrypt_verify} decrypts the ciphertext in +the data object @var{cipher} and stores it into the data object +@var{plain}. If @var{cipher} contains signatures, they will be +verified. + +After the operation completed, @code{gpgme_op_decrypt_result} and +@code{gpgme_op_verify_result} can be used to retrieve more information +about the signatures. + +If the error code @code{GPG_ERR_NO_DATA} is returned, @var{cipher} +does not contain any data to decrypt. However, it might still be +signed. The information about detected signatures is available with +@code{gpgme_op_verify_result} in this case. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +ciphertext could be decrypted successfully, @code{GPG_ERR_INV_VALUE} +if @var{ctx}, @var{cipher} or @var{plain} is not a valid pointer, +@code{GPG_ERR_NO_DATA} if @var{cipher} does not contain any data to +decrypt, @code{GPG_ERR_DECRYPT_FAILED} if @var{cipher} is not a valid +cipher text, @code{GPG_ERR_BAD_PASSPHRASE} if the passphrase for the +secret key could not be retrieved, and passes through any errors that +are reported by the crypto engine support routines. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_op_decrypt_verify (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_data_t @var{cipher}}, @w{gpgme_data_t @var{plain}}) +The function @code{gpgme_op_decrypt_verify_start} initiates a +@code{gpgme_op_decrypt_verify} operation. It can be completed by +calling @code{gpgme_wait} on the context. @xref{Waiting For +Completion}. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +operation could be started successfully, @code{GPG_ERR_INV_VALUE} if +@var{ctx}, @var{cipher}, @var{plain} or @var{r_stat} is not a valid +pointer, and @code{GPG_ERR_NO_DATA} if @var{cipher} does not contain +any data to decrypt. +@end deftypefun + + +@node Sign +@subsection Sign +@cindex signature, creation +@cindex sign +@cindex cryptographic operation, signing + +A signature can contain signatures by one or more keys. The set of +keys used to create a signatures is contained in a context, and is +applied to all following signing operations in this context (until the +set is changed). + +@menu +* Selecting Signers:: How to choose the keys to sign with. +* Creating a Signature:: How to create a signature. +* Signature Notation Data:: How to add notation data to a signature. +@end menu + + +@node Selecting Signers +@subsubsection Selecting Signers +@cindex signature, selecting signers +@cindex signers, selecting + +@deftypefun void gpgme_signers_clear (@w{gpgme_ctx_t @var{ctx}}) +The function @code{gpgme_signers_clear} releases a reference for each +key on the signers list and removes the list of signers from the +context @var{ctx}. + +Every context starts with an empty list. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_signers_add (@w{gpgme_ctx_t @var{ctx}}, @w{const gpgme_key_t @var{key}}) +The function @code{gpgme_signers_add} adds the key @var{key} to the +list of signers in the context @var{ctx}. + +Calling this function acquires an additional reference for the key. +@end deftypefun + +@deftypefun gpgme_key_t gpgme_signers_enum (@w{const gpgme_ctx_t @var{ctx}}, @w{int @var{seq}}) +The function @code{gpgme_signers_enum} returns the @var{seq}th key in +the list of signers in the context @var{ctx}. An additional reference +is acquired for the user. + +If @var{seq} is out of range, @code{NULL} is returned. +@end deftypefun + + +@node Creating a Signature +@subsubsection Creating a Signature + +@deftp {Data type} {enum gpgme_sig_mode_t} +@tindex gpgme_sig_mode_t +The @code{gpgme_sig_mode_t} type is used to specify the desired type of a +signature. The following modes are available: + +@table @code +@item GPGME_SIG_MODE_NORMAL +A normal signature is made, the output includes the plaintext and the +signature. + +@item GPGME_SIG_MODE_DETACH +A detached signature is made. + +@item GPGME_SIG_MODE_CLEAR +A clear text signature is made. The @acronym{ASCII} armor and text +mode settings of the context are ignored. +@end table +@end deftp + +@deftypefun gpgme_error_t gpgme_op_sign (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_data_t @var{plain}}, @w{gpgme_data_t @var{sig}}, @w{gpgme_sig_mode_t @var{mode}}) +The function @code{gpgme_op_sign} creates a signature for the text in +the data object @var{plain} and returns it in the data object +@var{sig}. The type of the signature created is determined by the +@acronym{ASCII} armor and text mode attributes set for the context +@var{ctx} and the requested signature mode @var{mode}. + +After the operation completed successfully, the result can be +retrieved with @code{gpgme_op_sign_result}. + +If an S/MIME signed message is created using the CMS crypto engine, +the number of certificates to include in the message can be specified +with @code{gpgme_set_include_certs}. @xref{Included Certificates}. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +signature could be created successfully, @code{GPG_ERR_INV_VALUE} if +@var{ctx}, @var{plain} or @var{sig} is not a valid pointer, +@code{GPG_ERR_NO_DATA} if the signature could not be created, +@code{GPG_ERR_BAD_PASSPHRASE} if the passphrase for the secret key +could not be retrieved, @code{GPG_ERR_UNUSABLE_SECKEY} if there are +invalid signers, and passes through any errors that are reported by the +crypto engine support routines. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_op_sign_start (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_data_t @var{plain}}, @w{gpgme_data_t @var{sig}}, @w{gpgme_sig_mode_t @var{mode}}) +The function @code{gpgme_op_sign_start} initiates a +@code{gpgme_op_sign} operation. It can be completed by calling +@code{gpgme_wait} on the context. @xref{Waiting For Completion}. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the operation could be +started successfully, and @code{GPG_ERR_INV_VALUE} if @var{ctx}, +@var{plain} or @var{sig} is not a valid pointer. +@end deftypefun + +@deftp {Data type} {gpgme_new_signature_t} +This is a pointer to a structure used to store a part of the result of +a @code{gpgme_op_sign} operation. The structure contains the +following members: + +@table @code +@item gpgme_new_signature_t next +This is a pointer to the next new signature structure in the linked +list, or @code{NULL} if this is the last element. + +@item gpgme_sig_mode_t type +The type of this signature. + +@item gpgme_pubkey_algo_t +The public key algorithm used to create this signature. + +@item gpgme_hash_algo_t +The hash algorithm used to create this signature. + +@item unsigned int sig_class +The signature class of this signature. + +@item long int timestamp +The creation timestamp of this signature. + +@item char *fpr +The fingerprint of the key which was used to create this signature. +@end table +@end deftp + +@deftp {Data type} {gpgme_sign_result_t} +This is a pointer to a structure used to store the result of a +@code{gpgme_op_sign} operation. After successfully generating a +signature, you can retrieve the pointer to the result with +@code{gpgme_op_sign_result}. The structure contains the following +members: + +@table @code +@item gpgme_invalid_key_t invalid_signers +A linked list with information about all invalid keys for which a +signature could not be created. + +@item gpgme_new_signature_t signatures +A linked list with information about all signatures created. +@end table +@end deftp + +@deftypefun gpgme_sign_result_t gpgme_op_sign_result (@w{gpgme_ctx_t @var{ctx}}) +The function @code{gpgme_op_sign_result} returns a +@code{gpgme_sign_result_t} pointer to a structure holding the result +of a @code{gpgme_op_sign} operation. The pointer is only valid if the +last operation on the context was a @code{gpgme_op_sign}, +@code{gpgme_op_sign_start}, @code{gpgme_op_encrypt_sign} or +@code{gpgme_op_encrypt_sign_start} operation. If that operation +failed, the function might return a @code{NULL} pointer, The returned +pointer is only valid until the next operation is started on the +context. +@end deftypefun + + +@node Signature Notation Data +@subsubsection Signature Notation Data +@cindex notation data +@cindex signature notation data +@cindex policy URL + +Using the following functions, you can attach arbitrary notation data +to a signature. This information is then available to the user when +the signature is verified. + +@deftypefun void gpgme_sig_notation_clear (@w{gpgme_ctx_t @var{ctx}}) +The function @code{gpgme_sig_notation_clear} removes the notation data +from the context @var{ctx}. Subsequent signing operations from this +context will not include any notation data. + +Every context starts with an empty notation data list. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_sig_notation_add (@w{gpgme_ctx_t @var{ctx}}, @w{const char *@var{name}}, @w{const char *@var{value}}, @w{gpgme_sig_notation_flags_t @var{flags}}) +The function @code{gpgme_sig_notation_add} adds the notation data with +the name @var{name} and the value @var{value} to the context +@var{ctx}. + +Subsequent signing operations will include this notation data, as well +as any other notation data that was added since the creation of the +context or the last @code{gpgme_sig_notation_clear} operation. + +The arguments @var{name} and @var{value} must be @code{NUL}-terminated +strings in human-readable form. The flag +@code{GPGME_SIG_NOTATION_HUMAN_READABLE} is implied +(non-human-readable notation data is currently not supported). The +strings must be in UTF-8 encoding. + +If @var{name} is @code{NULL}, then @var{value} should be a policy URL. + +The function @code{gpgme_sig_notation_add} returns the error code +@code{GPG_ERR_NO_ERROR} if the notation data could be added +successfully, @code{GPG_ERR_INV_VALUE} if @var{ctx} is not a valid +pointer, or if @var{name}, @var{value} and @var{flags} are an invalid +combination. The function also passes through any errors that are +reported by the crypto engine support routines. +@end deftypefun + +@deftypefun gpgme_sig_notation_t gpgme_sig_notation_get (@w{const gpgme_ctx_t @var{ctx}}) +The function @code{gpgme_sig_notation_get} returns the linked list of +notation data structures that are contained in the context @var{ctx}. + +If @var{ctx} is not a valid pointer, or there is no notation data +added for this context, @code{NULL} is returned. +@end deftypefun + + +@node Encrypt +@subsection Encrypt +@cindex encryption +@cindex cryptographic operation, encryption + +One plaintext can be encrypted for several recipients at the same +time. The list of recipients is created independently of any context, +and then passed to the encryption operation. + +@menu +* Encrypting a Plaintext:: How to encrypt a plaintext. +@end menu + + +@node Encrypting a Plaintext +@subsubsection Encrypting a Plaintext + +@deftypefun gpgme_error_t gpgme_op_encrypt (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_key_t @var{recp}[]}, @w{gpgme_encrypt_flags_t @var{flags}}, @w{gpgme_data_t @var{plain}}, @w{gpgme_data_t @var{cipher}}) +The function @code{gpgme_op_encrypt} encrypts the plaintext in the data +object @var{plain} for the recipients @var{recp} and stores the +ciphertext in the data object @var{cipher}. The type of the +ciphertext created is determined by the @acronym{ASCII} armor and text +mode attributes set for the context @var{ctx}. + +@var{key} must be a @code{NULL}-terminated array of keys. The user +must keep references for all keys during the whole duration of the +call (but see @code{gpgme_op_encrypt_start} for the requirements with +the asynchronous variant). + +The value in @var{flags} is a bitwise-or combination of one or +multiple of the following bit values: + +@table @code +@item GPGME_ENCRYPT_ALWAYS_TRUST +The @code{GPGME_ENCRYPT_ALWAYS_TRUST} symbol specifies that all the +recipients in @var{recp} should be trusted, even if the keys do not +have a high enough validity in the keyring. This flag should be used +with care; in general it is not a good idea to use any untrusted keys. +@end table + +If @code{GPG_ERR_UNUSABLE_PUBKEY} is returned, some recipients in +@var{recp} are invalid, but not all. In this case the plaintext might +be encrypted for all valid recipients and returned in @var{cipher} (if +this happens depends on the crypto engine). More information about +the invalid recipients is available with +@code{gpgme_op_encrypt_result}. + +If @var{recp} is @code{NULL}, symmetric rather than public key +encryption is performed. Symmetrically encrypted cipher text can be +deciphered with @code{gpgme_op_decrypt}. Note that in this case the +crypto backend needs to retrieve a passphrase from the user. +Symmetric encryption is currently only supported for the OpenPGP +crypto backend. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +ciphertext could be created successfully, @code{GPG_ERR_INV_VALUE} if +@var{ctx}, @var{recp}, @var{plain} or @var{cipher} is not a valid +pointer, @code{GPG_ERR_UNUSABLE_PUBKEY} if @var{recp} contains some +invalid recipients, @code{GPG_ERR_BAD_PASSPHRASE} if the passphrase +for the symmetric key could not be retrieved, and passes through any +errors that are reported by the crypto engine support routines. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_op_encrypt_start (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_key_t @var{recp}[]}, @w{gpgme_encrypt_flags_t @var{flags}}, @w{gpgme_data_t @var{plain}}, @w{gpgme_data_t @var{cipher}}) +The function @code{gpgme_op_encrypt_start} initiates a +@code{gpgme_op_encrypt} operation. It can be completed by calling +@code{gpgme_wait} on the context. @xref{Waiting For Completion}. + +References to the keys only need to be held for the duration of this +call. The user can release its references to the keys after this +function returns, even if the operation is not yet finished. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +operation could be started successfully, @code{GPG_ERR_INV_VALUE} if +@var{ctx}, @var{rset}, @var{plain} or @var{cipher} is not a valid +pointer, and @code{GPG_ERR_UNUSABLE_PUBKEY} if @var{rset} does not +contain any valid recipients. +@end deftypefun + +@deftp {Data type} {gpgme_encrypt_result_t} +This is a pointer to a structure used to store the result of a +@code{gpgme_op_encrypt} operation. After successfully encrypting +data, you can retrieve the pointer to the result with +@code{gpgme_op_encrypt_result}. The structure contains the following +members: + +@table @code +@item gpgme_invalid_key_t invalid_recipients +A linked list with information about all invalid keys for which +the data could not be encrypted. +@end table +@end deftp + +@deftypefun gpgme_encrypt_result_t gpgme_op_encrypt_result (@w{gpgme_ctx_t @var{ctx}}) +The function @code{gpgme_op_encrypt_result} returns a +@code{gpgme_encrypt_result_t} pointer to a structure holding the +result of a @code{gpgme_op_encrypt} operation. The pointer is only +valid if the last operation on the context was a +@code{gpgme_op_encrypt}, @code{gpgme_op_encrypt_start}, +@code{gpgme_op_sign} or @code{gpgme_op_sign_start} operation. If this +operation failed, this might be a @code{NULL} pointer. The returned +pointer is only valid until the next operation is started on the +context. +@end deftypefun + + +@deftypefun gpgme_error_t gpgme_op_encrypt_sign (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_key_t @var{recp}[]}, @w{gpgme_encrypt_flags_t @var{flags}}, @w{gpgme_data_t @var{plain}}, @w{gpgme_data_t @var{cipher}}) +The function @code{gpgme_op_encrypt_sign} does a combined encrypt and +sign operation. It is used like @code{gpgme_op_encrypt}, but the +ciphertext also contains signatures for the signers listed in +@var{ctx}. + +The combined encrypt and sign operation is currently only available +for the OpenPGP crypto engine. +@end deftypefun + +@deftypefun gpgme_error_t gpgme_op_encrypt_sign_start (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_key_t @var{recp}}, @w{gpgme_encrypt_flags_t @var{flags}}, @w{gpgme_data_t @var{plain}}, @w{gpgme_data_t @var{cipher}}) +The function @code{gpgme_op_encrypt_sign_start} initiates a +@code{gpgme_op_encrypt_sign} operation. It can be completed by +calling @code{gpgme_wait} on the context. @xref{Waiting For +Completion}. + +The function returns the error code @code{GPG_ERR_NO_ERROR} if the +operation could be started successfully, and @code{GPG_ERR_INV_VALUE} +if @var{ctx}, @var{rset}, @var{plain} or @var{cipher} is not a valid +pointer. +@end deftypefun + + +@node Run Control +@section Run Control +@cindex run control +@cindex cryptographic operation, running + +@acronym{GPGME} supports running operations synchronously and +asynchronously. You can use asynchronous operation to set up a +context up to initiating the desired operation, but delay performing +it to a later point. + +Furthermore, you can use an external event loop to control exactly +when @acronym{GPGME} runs. This ensures that @acronym{GPGME} only +runs when necessary and also prevents it from blocking for a long +time. + +@menu +* Waiting For Completion:: Waiting until an operation is completed. +* Using External Event Loops:: Advanced control over what happens when. +* Cancellation:: How to end pending operations prematurely. +@end menu + + +@node Waiting For Completion +@subsection Waiting For Completion +@cindex cryptographic operation, wait for +@cindex wait for completion + +@deftypefun gpgme_ctx_t gpgme_wait (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_error_t *@var{status}}, @w{int @var{hang}}) +The function @code{gpgme_wait} continues the pending operation within +the context @var{ctx}. In particular, it ensures the data exchange +between @acronym{GPGME} and the crypto backend and watches over the +run time status of the backend process. + +If @var{hang} is true, the function does not return until the +operation is completed or cancelled. Otherwise the function will not +block for a long time. + +The error status of the finished operation is returned in @var{status} +if @code{gpgme_wait} does not return @code{NULL}. + +The @var{ctx} argument can be @code{NULL}. In that case, +@code{gpgme_wait} waits for any context to complete its operation. + +@code{gpgme_wait} can be used only in conjunction with any context +that has a pending operation initiated with one of the +@code{gpgme_op_*_start} functions except @code{gpgme_op_keylist_start} +and @code{gpgme_op_trustlist_start} (for which you should use the +corresponding @code{gpgme_op_*_next} functions). If @var{ctx} is +@code{NULL}, all of such contexts are waited upon and possibly +returned. Synchronous operations running in parallel, as well as key +and trust item list operations, do not affect @code{gpgme_wait}. + +In a multi-threaded environment, only one thread should ever call +@code{gpgme_wait} at any time, irregardless if @var{ctx} is specified +or not. This means that all calls to this function should be fully +synchronized by locking primitives. It is safe to start asynchronous +operations while a thread is running in @code{gpgme_wait}. + +The function returns the @var{ctx} of the context which has finished +the operation. If @var{hang} is false, and the timeout expires, +@code{NULL} is returned and @code{*status} will be set to 0. If an +error occurs, @code{NULL} is returned and the error is returned in +@code{*status}. +@end deftypefun + + +@node Using External Event Loops +@subsection Using External Event Loops +@cindex event loop, external + +@acronym{GPGME} hides the complexity of the communication between the +library and the crypto engine. The price of this convenience is that +the calling thread can block arbitrary long waiting for the data +returned by the crypto engine. In single-threaded programs, in +particular if they are interactive, this is an unwanted side-effect. +OTOH, if @code{gpgme_wait} is used without the @var{hang} option being +enabled, it might be called unnecessarily often, wasting CPU time that +could be used otherwise. + +The I/O callback interface described in this section lets the user +take control over what happens when. @acronym{GPGME} will provide the +user with the file descriptors that should be monitored, and the +callback functions that should be invoked when a file descriptor is +ready for reading or writing. It is then the user's responsibility to +decide when to check the file descriptors and when to invoke the +callback functions. Usually this is done in an event loop, that also +checks for events in other parts of the program. If the callback +functions are only called when the file descriptors are ready, +@acronym{GPGME} will never block. This gives the user more control +over the program flow, and allows to perform other tasks when +@acronym{GPGME} would block otherwise. + +By using this advanced mechanism, @acronym{GPGME} can be integrated +smoothly into GUI toolkits like GTK+ even for single-threaded +programs. + +@menu +* I/O Callback Interface:: How I/O callbacks are registered. +* Registering I/O Callbacks:: How to use I/O callbacks for a context. +* I/O Callback Example:: An example how to use I/O callbacks. +* I/O Callback Example GTK+:: How to use @acronym{GPGME} with GTK+. +* I/O Callback Example GDK:: How to use @acronym{GPGME} with GDK. +* I/O Callback Example Qt:: How to use @acronym{GPGME} with Qt. +@end menu + + +@node I/O Callback Interface +@subsubsection I/O Callback Interface + +@deftp {Data type} {gpgme_error_t (*gpgme_io_cb_t) (@w{void *@var{data}}, @w{int @var{fd}})} +@tindex gpgme_io_cb_t +The @code{gpgme_io_cb_t} type is the type of functions which +@acronym{GPGME} wants to register as I/O callback handlers using the +@code{gpgme_register_io_cb_t} functions provided by the user. + +@var{data} and @var{fd} are provided by @acronym{GPGME} when the I/O +callback handler is registered, and should be passed through to the +handler when it is invoked by the user because it noticed activity on +the file descriptor @var{fd}. + +The callback handler always returns @code{0}, but you should consider +the return value to be reserved for later use. +@end deftp + +@deftp {Data type} {gpgme_error_t (*gpgme_register_io_cb_t) (@w{void *@var{data}}, @w{int @var{fd}}, @w{int @var{dir}}, @w{gpgme_io_cb_t @var{fnc}}, @w{void *@var{fnc_data}}, @w{void **@var{tag}})} +@tindex gpgme_register_io_cb_t +The @code{gpgme_register_io_cb_t} type is the type of functions which can +be called by @acronym{GPGME} to register an I/O callback function +@var{fnc} for the file descriptor @var{fd} with the user. +@var{fnc_data} should be passed as the first argument to @var{fnc} +when the handler is invoked (the second argument should be @var{fd}). +If @var{dir} is 0, @var{fnc} should be called by the user when +@var{fd} is ready for writing. If @var{dir} is 1, @var{fnc} should be +called when @var{fd} is ready for reading. + +@var{data} was provided by the user when registering the +@code{gpgme_register_io_cb_t} function with @acronym{GPGME} and will always +be passed as the first argument when registering a callback function. +For example, the user can use this to determine the event loop to +which the file descriptor should be added. + +@acronym{GPGME} will call this function when a crypto operation is +initiated in a context for which the user has registered I/O callback +handler functions with @code{gpgme_set_io_cbs}. It can also call this +function when it is in an I/O callback handler for a file descriptor +associated to this context. + +The user should return a unique handle in @var{tag} identifying this +I/O callback registration, which will be passed to the +@code{gpgme_register_io_cb_t} function without interpretation when the file +descriptor should not be monitored anymore. +@end deftp + +@deftp {Data type} {void (*gpgme_remove_io_cb_t) (@w{void *@var{tag}})} +The @code{gpgme_remove_io_cb_t} type is the type of functions which can be +called by @acronym{GPGME} to remove an I/O callback handler that was +registered before. @var{tag} is the handle that was returned by the +@code{gpgme_register_io_cb_t} for this I/O callback. + +@acronym{GPGME} can call this function when a crypto operation is in +an I/O callback. It will also call this function when the context is +destroyed while an operation is pending. +@end deftp + +@deftp {Data type} {enum gpgme_event_io_t} +@tindex gpgme_event_io_t +The @code{gpgme_event_io_t} type specifies the type of an event that is +reported to the user by @acronym{GPGME} as a consequence of an I/O +operation. The following events are defined: + +@table @code +@item GPGME_EVENT_START +The operation is fully initialized now, and you can start to run the +registered I/O callback handlers now. Note that registered I/O +callback handlers must not be run before this event is signalled. +@var{type_data} is @code{NULL} and reserved for later use. + +@item GPGME_EVENT_DONE +The operation is finished, the last I/O callback for this operation +was removed. The accompanying @var{type_data} points to a +@code{gpgme_error_t} variable that contains the status of the operation +that finished. This event is signalled after the last I/O callback +has been removed. + +@item GPGME_EVENT_NEXT_KEY +In a @code{gpgme_op_keylist_start} operation, the next key was +received from the crypto engine. The accompanying @var{type_data} is +a @code{gpgme_key_t} variable that contains the key with one reference +for the user. + +@item GPGME_EVENT_NEXT_TRUSTITEM +In a @code{gpgme_op_trustlist_start} operation, the next trust item +was received from the crypto engine. The accompanying @var{type_data} +is a @code{gpgme_trust_item_t} variable that contains the trust item with +one reference for the user. +@end table +@end deftp + +@deftp {Data type} {void (*gpgme_event_io_cb_t) (@w{void *@var{data}}, @w{gpgme_event_io_t @var{type}}, @w{void *@var{type_data}})} +The @code{gpgme_event_io_cb_t} type is the type of functions which can be +called by @acronym{GPGME} to signal an event for an operation running +in a context which has I/O callback functions registered by the user. + +@var{data} was provided by the user when registering the +@code{gpgme_event_io_cb_t} function with @acronym{GPGME} and will always be +passed as the first argument when registering a callback function. +For example, the user can use this to determine the context in which +this event has occured. + +@var{type} will specify the type of event that has occured. +@var{type_data} specifies the event further, as described in the above +list of possible @code{gpgme_event_io_t} types. + +@acronym{GPGME} can call this function in an I/O callback handler. +@end deftp + + +@node Registering I/O Callbacks +@subsubsection Registering I/O Callbacks + +@deftp {Data type} {struct gpgme_io_cb_ts} +@tindex gpgme_event_io_t +This structure is used to store the I/O callback interface functions +described in the previous section. It has the following members: + +@table @code +@item gpgme_register_io_cb_t add +This is the function called by @acronym{GPGME} to register an I/O +callback handler. It must be specified. + +@item void *add_data +This is passed as the first argument to the @code{add} function when +it is called by @acronym{GPGME}. For example, it can be used to +determine the event loop to which the file descriptor should be added. + +@item gpgme_remove_io_cb_t remove +This is the function called by @acronym{GPGME} to remove an I/O +callback handler. It must be specified. + +@item gpgme_event_io_cb_t event +This is the function called by @acronym{GPGME} to signal an event for +an operation. It must be specified, because at least the start event +must be processed. + +@item void *event_data +This is passed as the first argument to the @code{event} function when +it is called by @acronym{GPGME}. For example, it can be used to +determine the context in which the event has occured. +@end table +@end deftp + +@deftypefun void gpgme_set_io_cbs (@w{gpgme_ctx_t @var{ctx}}, @w{struct gpgme_io_cb_ts *@var{io_cbs}}) +The function @code{gpgme_set_io_cbs} enables the I/O callback +interface for the context @var{ctx}. The I/O callback functions are +specified by @var{io_cbs}. + +If @var{io_cbs}->@code{add} is @code{NULL}, the I/O callback interface +is disabled for the context, and normal operation is restored. +@end deftypefun + +@deftypefun void gpgme_get_io_cbs (@w{gpgme_ctx_t @var{ctx}}, @w{struct gpgme_io_cb_ts *@var{io_cbs}}) +The function @code{gpgme_get_io_cbs} returns the I/O callback +functions set with @code{gpgme_set_io_cbs} in @var{io_cbs}. +@end deftypefun + + +@node I/O Callback Example +@subsubsection I/O Callback Example + +To actually use an external event loop, you have to implement the I/O +callback functions that are used by @acronym{GPGME} to register and +unregister file descriptors. Furthermore, you have to actually +monitor these file descriptors for activity and call the appropriate +I/O callbacks. + +The following example illustrates how to do that. The example uses +locking to show in which way the callbacks and the event loop can +run concurrently. For the event loop, we use a fixed array. For a +real-world implementation, you should use a dynamically sized +structure because the number of file descriptors needed for a crypto +operation in @acronym{GPGME} is not predictable. + +@example +#include +#include +#include + +/* The following structure holds the result of a crypto operation. */ +struct op_result +@{ + int done; + gpgme_error_t err; +@}; + +/* The following structure holds the data associated with one I/O +callback. */ +struct one_fd +@{ + int fd; + int dir; + gpgme_io_cb_t fnc; + void *fnc_data; +@}; + +struct event_loop +@{ + pthread_mutex_t lock; +#define MAX_FDS 32 + /* Unused slots are marked with FD being -1. */ + struct one_fd fds[MAX_FDS]; +@}; +@end example + +The following functions implement the I/O callback interface. + +@example +gpgme_error_t +add_io_cb (void *data, int fd, int dir, gpgme_io_cb_t fnc, void *fnc_data, + void **r_tag) +@{ + struct event_loop *loop = data; + struct one_fd *fds = loop->fds; + int i; + + pthread_mutex_lock (&loop->lock); + for (i = 0; i < MAX_FDS; i++) + @{ + if (fds[i].fd == -1) + @{ + fds[i].fd = fd; + fds[i].dir = dir; + fds[i].fnc = fnc; + fds[i].fnc_data = fnc_data; + break; + @} + @} + pthread_mutex_unlock (&loop->lock); + if (i == MAX_FDS) + return gpg_error (GPG_ERR_GENERAL); + *r_tag = &fds[i]; + return 0; +@} + +void +remove_io_cb (void *tag) +@{ + struct one_fd *fd = tag; + + pthread_mutex_lock (&loop->lock); + fd->fd = -1; + pthread_mutex_unlock (&loop->lock); +@} + +void +event_io_cb (void *data, gpgme_event_io_t type, void *type_data) +@{ + struct op_result *result = data; + + /* We don't support list operations here. */ + if (type == GPGME_EVENT_DONE) + @{ + result->done = 1; + result->err = *type_data; + @} +@} +@end example + +The final missing piece is the event loop, which will be presented +next. We only support waiting for the success of a single operation. + +@example +int +do_select (struct event_loop *loop) +@{ + fd_set rfds; + fd_set wfds; + int i, n; + int any = 0; + + pthread_mutex_lock (&loop->lock); + FD_ZERO (&rfds); + FD_ZERO (&wfds); + for (i = 0; i < FDLIST_MAX; i++) + if (fdlist[i].fd != -1) + FD_SET (fdlist[i].fd, fdlist[i].dir ? &rfds : &wfds); + pthread_mutex_unlock (&loop->unlock); + + do + @{ + n = select (FD_SETSIZE, &rfds, &wfds, NULL, 0); + @} + while (n < 0 && errno == EINTR); + + if (n < 0) + return n; /* Error or timeout. */ + + pthread_mutex_lock (&loop->lock); + for (i = 0; i < FDLIST_MAX && n; i++) + @{ + if (fdlist[i].fd != -1) + @{ + if (FD_ISSET (fdlist[i].fd, fdlist[i].dir ? &rfds : &wfds)) + @{ + assert (n); + n--; + any = 1; + /* The I/O callback handler can register/remove callbacks, + so we have to unlock the file descriptor list. */ + pthread_mutex_unlock (&loop->lock); + (*fdlist[i].fnc) (fdlist[i].fnc_data, fdlist[i].fd); + pthread_mutex_lock (&loop->lock); + @} + @} + @} + pthread_mutex_unlock (&loop->lock); + return any; +@} + +void +wait_for_op (struct event_loop *loop, struct op_result *result) +@{ + int ret; + + do + @{ + ret = do_select (loop); + @} + while (ret >= 0 && !result->done); + return ret; +@} +@end example + +The main function shows how to put it all together. + +@example +int +main (int argc, char *argv[]) +@{ + struct event_loop loop; + struct op_result result; + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_data_t sig, text; + gpgme_sig_stat_t status; + int i; + struct gpgme_io_cb_ts io_cbs = + @{ + add_io_cb, + &loop, + remove_io_cb, + event_io_cb, + &result + @}; + + /* Initialize the loop structure. */ + loop.lock = PTHREAD_MUTEX_INITIALIZER; + for (i = 0; i < MAX_FDS; i++) + loop->fds[i].fd = -1; + + /* Initialize the result structure. */ + result.done = 0; + + err = gpgme_data_new_from_file (&sig, "signature", 1); + if (!err) + err = gpgme_data_new_from_file (&text, "text", 1); + if (!err) + err = gpgme_new (&ctx); + if (!err) + @{ + gpgme_set_io_cbs (ctx, &io_cbs); + err = gpgme_op_verify_start (ctx, sig, text, &status); + @} + if (err) + @{ + fprintf (stderr, "gpgme error: %s: %s\n", + gpgme_strsource (err), gpgme_strerror (err)); + exit (1); + @} + + wait_for_op (&loop, &result); + if (!result.done) + @{ + fprintf (stderr, "select error\n"); + exit (1); + @} + if (!result.err) + @{ + fprintf (stderr, "verification failed: %s: %s\n", + gpgme_strsource (result.err), gpgme_strerror (result.err)); + exit (1); + @} + /* Evaluate STATUS. */ + @dots{} + return 0; +@} +@end example + + +@node I/O Callback Example GTK+ +@subsubsection I/O Callback Example GTK+ +@cindex GTK+, using @acronym{GPGME} with + +The I/O callback interface can be used to integrate @acronym{GPGME} +with the GTK+ event loop. The following code snippets shows how this +can be done using the appropriate register and remove I/O callback +functions. In this example, the private data of the register I/O +callback function is unused. The event notifications is missing +because it does not require any GTK+ specific setup. + +@example +#include + +struct my_gpgme_io_cb +@{ + gpgme_io_cb_t fnc; + void *fnc_data; + guint input_handler_id +@}; + +void +my_gpgme_io_cb (gpointer data, gint source, GdkInputCondition condition) +@{ + struct my_gpgme_io_cb *iocb = data; + (*(iocb->fnc)) (iocb->data, source); +@} + +void +my_gpgme_remove_io_cb (void *data) +@{ + struct my_gpgme_io_cb *iocb = data; + gtk_input_remove (data->input_handler_id); +@} + +void +my_gpgme_register_io_callback (void *data, int fd, int dir, gpgme_io_cb_t fnc, + void *fnc_data, void **tag) +@{ + struct my_gpgme_io_cb *iocb = g_malloc (sizeof (struct my_gpgme_io_cb)); + iocb->fnc = fnc; + iocb->data = fnc_data; + iocb->input_handler_id = gtk_input_add_full (fd, dir + ? GDK_INPUT_READ + : GDK_INPUT_WRITE, + my_gpgme_io_callback, + 0, iocb, NULL); + *tag = iocb; + return 0; +@} +@end example + + +@node I/O Callback Example GDK +@subsubsection I/O Callback Example GDK +@cindex GDK, using @acronym{GPGME} with + +The I/O callback interface can also be used to integrate +@acronym{GPGME} with the GDK event loop. The following code snippets +shows how this can be done using the appropriate register and remove +I/O callback functions. In this example, the private data of the +register I/O callback function is unused. The event notifications is +missing because it does not require any GDK specific setup. + +It is very similar to the GTK+ example in the previous section. + +@example +#include + +struct my_gpgme_io_cb +@{ + gpgme_io_cb_t fnc; + void *fnc_data; + gint tag; +@}; + +void +my_gpgme_io_cb (gpointer data, gint source, GdkInputCondition condition) +@{ + struct my_gpgme_io_cb *iocb = data; + (*(iocb->fnc)) (iocb->data, source); +@} + +void +my_gpgme_remove_io_cb (void *data) +@{ + struct my_gpgme_io_cb *iocb = data; + gdk_input_remove (data->tag); +@} + +void +my_gpgme_register_io_callback (void *data, int fd, int dir, gpgme_io_cb_t fnc, + void *fnc_data, void **tag) +@{ + struct my_gpgme_io_cb *iocb = g_malloc (sizeof (struct my_gpgme_io_cb)); + iocb->fnc = fnc; + iocb->data = fnc_data; + iocb->tag = gtk_input_add_full (fd, dir ? GDK_INPUT_READ : GDK_INPUT_WRITE, + my_gpgme_io_callback, iocb, NULL); + *tag = iocb; + return 0; +@} +@end example + + +@node I/O Callback Example Qt +@subsubsection I/O Callback Example Qt +@cindex Qt, using @acronym{GPGME} with + +The I/O callback interface can also be used to integrate +@acronym{GPGME} with the Qt event loop. The following code snippets +show how this can be done using the appropriate register and remove +I/O callback functions. In this example, the private data of the +register I/O callback function is unused. The event notifications is +missing because it does not require any Qt specific setup. + +@example +#include +#include + +struct IOCB @{ + IOCB( GpgmeIOCb f, void * d, QSocketNotifier * n ) + : func( f ), data( d ), notifier( n ) @{@} + GpgmeIOCb func; + void * data; + QSocketNotifier * notifier; +@} + +class MyApp : public QApplication @{ + + // ... + + static void registerGpgmeIOCallback( void * data, int fd, int dir, + GpgmeIOCb func, void * func_data, + void ** tag ) @{ + QSocketNotifier * n = + new QSocketNotifier( fd, dir ? QSocketNotifier::Read + : QSocketNotifier::Write ); + connect( n, SIGNAL(activated(int)), + qApp, SLOT(slotGpgmeIOCallback(int)) ); + qApp->mIOCBs.push_back( IOCB( func, func_data, n ) ); + *tag = (void*)n; + @} + + static void removeGpgmeIOCallback( void * tag ) @{ + if ( !tag ) return; + QSocketNotifier * n = static_cast( tag ); + for ( QValueList::iterator it = qApp->mIOCBs.begin() ; + it != qApp->mIOCBs.end() ; ++it ) + if ( it->notifier == n ) @{ + delete it->notifier; + qApp->mIOCBs.erase( it ); + return; + @} + @} + +public slots: + void slotGpgmeIOCallback( int fd ) @{ + for ( QValueList::const_iterator it = mIOCBs.begin() ; + it != mIOCBs.end() ; ++it ) + if ( it->notifier && it->notifier->socket() == fd ) + (*(it->func)) ( it->func_data, fd ); + @} + + // ... + +private: + QValueList mIOCBs; + // ... +@}; +@end example + + +@node Cancellation +@subsection Cancellation +@cindex cryptographic operation, aborting +@cindex cryptographic operation, cancelling +@cindex aborting operations +@cindex cancelling operations + +Sometimes you do not want to wait for an operation to finish. If you +use external I/O callbacks, you can cancel a pending operation. +However, you must ensure that no other thread is currently using the +context in which the operation you want to cancel runs. This includes +callback handlers. So your external event loop must either be halted +or otherwise it must be guaranteed that no installed I/O callbacks are +run for this context. + +@deftypefun gpgme_ctx_t gpgme_cancel (@w{gpgme_ctx_t @var{ctx}}) +The function @code{gpgme_cancel} attempts to cancel a pending +operation in the context @var{ctx}. This only works if you use the +global event loop or your own event loop. + +If you use the global event loop, you must not call @code{gpgme_wait} +or @code{gpgme_wait} during cancellation. After successful +cancellation, you can call @code{gpgme_wait} (optionally waiting on +@var{ctx}), and the context @var{ctx} will appear as if it had +finished with the error code @code{GPG_ERR_CANCEL}. + +If you use your an external event loop, you must ensure that no I/O +callbacks are invoked for this context (for example by halting the +event loop). On successful cancellation, all registered I/O callbacks +for this context will be unregistered, and a @code{GPGME_EVENT_DONE} +event with the error code @code{GPG_ERR_CANCEL} will be signaled. + +The function returns an error code if the cancellation failed (in this +case the state of @var{ctx} is not modified). +@end deftypefun + + +@include lesser.texi + + +@node Concept Index +@unnumbered Concept Index + +@printindex cp + + +@node Function and Data Index +@unnumbered Function and Data Index + +@printindex fn + + +@summarycontents +@contents +@bye diff --git a/tags/gpgme-1.1.6/doc/lesser.texi b/tags/gpgme-1.1.6/doc/lesser.texi new file mode 100644 index 0000000..ce83628 --- /dev/null +++ b/tags/gpgme-1.1.6/doc/lesser.texi @@ -0,0 +1,565 @@ +@node Library Copying +@appendix GNU LESSER GENERAL PUBLIC LICENSE + +@cindex LGPL, Lesser General Public License +@center Version 2.1, February 1999 + +@display +Copyright @copyright{} 1991, 1999 Free Software Foundation, Inc. +59 Temple Place -- Suite 330, Boston, MA 02111-1307, USA + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts +as the successor of the GNU Library Public License, version 2, hence the +version number 2.1.] +@end display + +@appendixsubsec Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software---to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software---typically libraries---of the Free +Software Foundation and other authors who decide to use it. You can use +it too, but we suggest you first think carefully about whether this +license or the ordinary General Public License is the better strategy to +use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of it +in new free programs; and that you are informed that you can do these +things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the @dfn{Lesser} General Public License because it +does @emph{Less} to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +``work based on the library'' and a ``work that uses the library''. The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + +@iftex +@appendixsubsec TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION +@end iftex +@ifinfo +@center GNU LESSER GENERAL PUBLIC LICENSE +@center TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION +@end ifinfo + +@enumerate 0 +@item +This License Agreement applies to any software library or other program +which contains a notice placed by the copyright holder or other +authorized party saying it may be distributed under the terms of this +Lesser General Public License (also called ``this License''). Each +licensee is addressed as ``you''. + + A ``library'' means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The ``Library'', below, refers to any such software library or work +which has been distributed under these terms. A ``work based on the +Library'' means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term ``modification''.) + + ``Source code'' for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + +@item +You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + +@item +You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + +@enumerate a +@item +The modified work must itself be a software library. + +@item +You must cause the files modified to carry prominent notices +stating that you changed the files and the date of any change. + +@item +You must cause the whole of the work to be licensed at no +charge to all third parties under the terms of this License. + +@item +If a facility in the modified Library refers to a function or a +table of data to be supplied by an application program that uses +the facility, other than as an argument passed when the facility +is invoked, then you must make a good faith effort to ensure that, +in the event an application does not supply such function or +table, the facility still operates, and performs whatever part of +its purpose remains meaningful. + +(For example, a function in a library to compute square roots has +a purpose that is entirely well-defined independent of the +application. Therefore, Subsection 2d requires that any +application-supplied function or table used by this function must +be optional: if the application does not supply it, the square +root function must still compute square roots.) +@end enumerate + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + +@item +You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + +@item +You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + +@item +A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a ``work that uses the Library''. Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a ``work that uses the Library'' with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a ``work that uses the +library''. The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a ``work that uses the Library'' uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + +@item +As an exception to the Sections above, you may also combine or +link a ``work that uses the Library'' with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + +@enumerate a +@item +Accompany the work with the complete corresponding +machine-readable source code for the Library including whatever +changes were used in the work (which must be distributed under +Sections 1 and 2 above); and, if the work is an executable linked +with the Library, with the complete machine-readable ``work that +uses the Library'', as object code and/or source code, so that the +user can modify the Library and then relink to produce a modified +executable containing the modified Library. (It is understood +that the user who changes the contents of definitions files in the +Library will not necessarily be able to recompile the application +to use the modified definitions.) + +@item +Use a suitable shared library mechanism for linking with the Library. A +suitable mechanism is one that (1) uses at run time a copy of the +library already present on the user's computer system, rather than +copying library functions into the executable, and (2) will operate +properly with a modified version of the library, if the user installs +one, as long as the modified version is interface-compatible with the +version that the work was made with. + +@item +Accompany the work with a written offer, valid for at +least three years, to give the same user the materials +specified in Subsection 6a, above, for a charge no more +than the cost of performing this distribution. + +@item +If distribution of the work is made by offering access to copy +from a designated place, offer equivalent access to copy the above +specified materials from the same place. + +@item +Verify that the user has already received a copy of these +materials or that you have already sent this user a copy. +@end enumerate + + For an executable, the required form of the ``work that uses the +Library'' must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies the +executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + +@item +You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + +@enumerate a +@item +Accompany the combined library with a copy of the same work +based on the Library, uncombined with any other library +facilities. This must be distributed under the terms of the +Sections above. + +@item +Give prominent notice with the combined library of the fact +that part of it is a work based on the Library, and explaining +where to find the accompanying uncombined form of the same work. +@end enumerate + +@item +You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + +@item +You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + +@item +Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + +@item +If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + +@item +If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + +@item +The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +``any later version'', you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + +@item +If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + +@iftex +@heading NO WARRANTY +@end iftex +@ifinfo +@center NO WARRANTY +@end ifinfo + +@item +BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY ``AS IS'' WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +@item +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. +@end enumerate + +@iftex +@heading END OF TERMS AND CONDITIONS +@end iftex +@ifinfo +@center END OF TERMS AND CONDITIONS +@end ifinfo + +@page +@appendixsubsec How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +``copyright'' line and a pointer to where the full notice is found. + +@smallexample +@var{one line to give the library's name and an idea of what it does.} +Copyright (C) @var{year} @var{name of author} + +This library is free software; you can redistribute it and/or modify it +under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or (at +your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, +USA. +@end smallexample + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a ``copyright disclaimer'' for the library, if +necessary. Here is a sample; alter the names: + +@smallexample +Yoyodyne, Inc., hereby disclaims all copyright interest in the library +`Frob' (a library for tweaking knobs) written by James Random Hacker. + +@var{signature of Ty Coon}, 1 April 1990 +Ty Coon, President of Vice +@end smallexample + +That's all there is to it! diff --git a/tags/gpgme-1.1.6/doc/mdate-sh b/tags/gpgme-1.1.6/doc/mdate-sh new file mode 100755 index 0000000..b610b47 --- /dev/null +++ b/tags/gpgme-1.1.6/doc/mdate-sh @@ -0,0 +1,133 @@ +#!/bin/sh +# Get modification time of a file or directory and pretty-print it. +# Copyright (C) 1995, 1996, 1997, 2003 Free Software Foundation, Inc. +# written by Ulrich Drepper , June 1995 +# +# This program 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, or (at your option) +# any later version. +# +# This program 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. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Prevent date giving response in another language. +LANG=C +export LANG +LC_ALL=C +export LC_ALL +LC_TIME=C +export LC_TIME + +save_arg1="$1" + +# Find out how to get the extended ls output of a file or directory. +if ls -L /dev/null 1>/dev/null 2>&1; then + ls_command='ls -L -l -d' +else + ls_command='ls -l -d' +fi + +# A `ls -l' line looks as follows on OS/2. +# drwxrwx--- 0 Aug 11 2001 foo +# This differs from Unix, which adds ownership information. +# drwxrwx--- 2 root root 4096 Aug 11 2001 foo +# +# To find the date, we split the line on spaces and iterate on words +# until we find a month. This cannot work with files whose owner is a +# user named `Jan', or `Feb', etc. However, it's unlikely that `/' +# will be owned by a user whose name is a month. So we first look at +# the extended ls output of the root directory to decide how many +# words should be skipped to get the date. + +# On HPUX /bin/sh, "set" interprets "-rw-r--r--" as options, so the "x" below. +set - x`$ls_command /` + +# Find which argument is the month. +month= +command= +until test $month +do + shift + # Add another shift to the command. + command="$command shift;" + case $1 in + Jan) month=January; nummonth=1;; + Feb) month=February; nummonth=2;; + Mar) month=March; nummonth=3;; + Apr) month=April; nummonth=4;; + May) month=May; nummonth=5;; + Jun) month=June; nummonth=6;; + Jul) month=July; nummonth=7;; + Aug) month=August; nummonth=8;; + Sep) month=September; nummonth=9;; + Oct) month=October; nummonth=10;; + Nov) month=November; nummonth=11;; + Dec) month=December; nummonth=12;; + esac +done + +# Get the extended ls output of the file or directory. +set - x`eval "$ls_command \"\$save_arg1\""` + +# Remove all preceding arguments +eval $command + +# Get the month. Next argument is day, followed by the year or time. +case $1 in + Jan) month=January; nummonth=1;; + Feb) month=February; nummonth=2;; + Mar) month=March; nummonth=3;; + Apr) month=April; nummonth=4;; + May) month=May; nummonth=5;; + Jun) month=June; nummonth=6;; + Jul) month=July; nummonth=7;; + Aug) month=August; nummonth=8;; + Sep) month=September; nummonth=9;; + Oct) month=October; nummonth=10;; + Nov) month=November; nummonth=11;; + Dec) month=December; nummonth=12;; +esac + +day=$2 + +# Here we have to deal with the problem that the ls output gives either +# the time of day or the year. +case $3 in + *:*) set `date`; eval year=\$$# + case $2 in + Jan) nummonthtod=1;; + Feb) nummonthtod=2;; + Mar) nummonthtod=3;; + Apr) nummonthtod=4;; + May) nummonthtod=5;; + Jun) nummonthtod=6;; + Jul) nummonthtod=7;; + Aug) nummonthtod=8;; + Sep) nummonthtod=9;; + Oct) nummonthtod=10;; + Nov) nummonthtod=11;; + Dec) nummonthtod=12;; + esac + # For the first six month of the year the time notation can also + # be used for files modified in the last year. + if (expr $nummonth \> $nummonthtod) > /dev/null; + then + year=`expr $year - 1` + fi;; + *) year=$3;; +esac + +# The result. +echo $day $month $year diff --git a/tags/gpgme-1.1.6/doc/texinfo.tex b/tags/gpgme-1.1.6/doc/texinfo.tex new file mode 100644 index 0000000..e9293f3 --- /dev/null +++ b/tags/gpgme-1.1.6/doc/texinfo.tex @@ -0,0 +1,6773 @@ +% texinfo.tex -- TeX macros to handle Texinfo files. +% +% Load plain if necessary, i.e., if running under initex. +\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi +% +\def\texinfoversion{2003-05-04.08} +% +% Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995, +% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +% +% This texinfo.tex file 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, or (at +% your option) any later version. +% +% This texinfo.tex file 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 texinfo.tex file; see the file COPYING. If not, write +% to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +% Boston, MA 02111-1307, USA. +% +% In other words, you are welcome to use, share and improve this program. +% You are forbidden to forbid anyone else to use, share and improve +% what you give them. Help stamp out software-hoarding! +% +% Please try the latest version of texinfo.tex before submitting bug +% reports; you can get the latest version from: +% ftp://ftp.gnu.org/gnu/texinfo/texinfo.tex +% (and all GNU mirrors, see http://www.gnu.org/order/ftp.html) +% ftp://tug.org/tex/texinfo.tex +% (and all CTAN mirrors, see http://www.ctan.org), +% and /home/gd/gnu/doc/texinfo.tex on the GNU machines. +% +% The GNU Texinfo home page is http://www.gnu.org/software/texinfo. +% +% The texinfo.tex in any given Texinfo distribution could well be out +% of date, so if that's what you're using, please check. +% +% Send bug reports to bug-texinfo@gnu.org. Please include including a +% complete document in each bug report with which we can reproduce the +% problem. Patches are, of course, greatly appreciated. +% +% To process a Texinfo manual with TeX, it's most reliable to use the +% texi2dvi shell script that comes with the distribution. For a simple +% manual foo.texi, however, you can get away with this: +% tex foo.texi +% texindex foo.?? +% tex foo.texi +% tex foo.texi +% dvips foo.dvi -o # or whatever; this makes foo.ps. +% The extra TeX runs get the cross-reference information correct. +% Sometimes one run after texindex suffices, and sometimes you need more +% than two; texi2dvi does it as many times as necessary. +% +% It is possible to adapt texinfo.tex for other languages, to some +% extent. You can get the existing language-specific files from the +% full Texinfo distribution. + +\message{Loading texinfo [version \texinfoversion]:} + +% If in a .fmt file, print the version number +% and turn on active characters that we couldn't do earlier because +% they might have appeared in the input file name. +\everyjob{\message{[Texinfo version \texinfoversion]}% + \catcode`+=\active \catcode`\_=\active} + +\message{Basics,} +\chardef\other=12 + +% We never want plain's \outer definition of \+ in Texinfo. +% For @tex, we can use \tabalign. +\let\+ = \relax + +% Save some plain tex macros whose names we will redefine. +\let\ptexb=\b +\let\ptexbullet=\bullet +\let\ptexc=\c +\let\ptexcomma=\, +\let\ptexdot=\. +\let\ptexdots=\dots +\let\ptexend=\end +\let\ptexequiv=\equiv +\let\ptexexclam=\! +\let\ptexgtr=> +\let\ptexhat=^ +\let\ptexi=\i +\let\ptexindent=\indent +\let\ptexlbrace=\{ +\let\ptexless=< +\let\ptexplus=+ +\let\ptexrbrace=\} +\let\ptexslash=\/ +\let\ptexstar=\* +\let\ptext=\t + +% If this character appears in an error message or help string, it +% starts a new line in the output. +\newlinechar = `^^J + +% Set up fixed words for English if not already set. +\ifx\putwordAppendix\undefined \gdef\putwordAppendix{Appendix}\fi +\ifx\putwordChapter\undefined \gdef\putwordChapter{Chapter}\fi +\ifx\putwordfile\undefined \gdef\putwordfile{file}\fi +\ifx\putwordin\undefined \gdef\putwordin{in}\fi +\ifx\putwordIndexIsEmpty\undefined \gdef\putwordIndexIsEmpty{(Index is empty)}\fi +\ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi +\ifx\putwordInfo\undefined \gdef\putwordInfo{Info}\fi +\ifx\putwordInstanceVariableof\undefined \gdef\putwordInstanceVariableof{Instance Variable of}\fi +\ifx\putwordMethodon\undefined \gdef\putwordMethodon{Method on}\fi +\ifx\putwordNoTitle\undefined \gdef\putwordNoTitle{No Title}\fi +\ifx\putwordof\undefined \gdef\putwordof{of}\fi +\ifx\putwordon\undefined \gdef\putwordon{on}\fi +\ifx\putwordpage\undefined \gdef\putwordpage{page}\fi +\ifx\putwordsection\undefined \gdef\putwordsection{section}\fi +\ifx\putwordSection\undefined \gdef\putwordSection{Section}\fi +\ifx\putwordsee\undefined \gdef\putwordsee{see}\fi +\ifx\putwordSee\undefined \gdef\putwordSee{See}\fi +\ifx\putwordShortTOC\undefined \gdef\putwordShortTOC{Short Contents}\fi +\ifx\putwordTOC\undefined \gdef\putwordTOC{Table of Contents}\fi +% +\ifx\putwordMJan\undefined \gdef\putwordMJan{January}\fi +\ifx\putwordMFeb\undefined \gdef\putwordMFeb{February}\fi +\ifx\putwordMMar\undefined \gdef\putwordMMar{March}\fi +\ifx\putwordMApr\undefined \gdef\putwordMApr{April}\fi +\ifx\putwordMMay\undefined \gdef\putwordMMay{May}\fi +\ifx\putwordMJun\undefined \gdef\putwordMJun{June}\fi +\ifx\putwordMJul\undefined \gdef\putwordMJul{July}\fi +\ifx\putwordMAug\undefined \gdef\putwordMAug{August}\fi +\ifx\putwordMSep\undefined \gdef\putwordMSep{September}\fi +\ifx\putwordMOct\undefined \gdef\putwordMOct{October}\fi +\ifx\putwordMNov\undefined \gdef\putwordMNov{November}\fi +\ifx\putwordMDec\undefined \gdef\putwordMDec{December}\fi +% +\ifx\putwordDefmac\undefined \gdef\putwordDefmac{Macro}\fi +\ifx\putwordDefspec\undefined \gdef\putwordDefspec{Special Form}\fi +\ifx\putwordDefvar\undefined \gdef\putwordDefvar{Variable}\fi +\ifx\putwordDefopt\undefined \gdef\putwordDefopt{User Option}\fi +\ifx\putwordDeftypevar\undefined\gdef\putwordDeftypevar{Variable}\fi +\ifx\putwordDeffunc\undefined \gdef\putwordDeffunc{Function}\fi +\ifx\putwordDeftypefun\undefined\gdef\putwordDeftypefun{Function}\fi + +% In some macros, we cannot use the `\? notation---the left quote is +% in some cases the escape char. +\chardef\colonChar = `\: +\chardef\commaChar = `\, +\chardef\dotChar = `\. +\chardef\equalChar = `\= +\chardef\exclamChar= `\! +\chardef\questChar = `\? +\chardef\semiChar = `\; +\chardef\spaceChar = `\ % +\chardef\underChar = `\_ + +% Ignore a token. +% +\def\gobble#1{} + +% True if #1 is the empty string, i.e., called like `\ifempty{}'. +% +\def\ifempty#1{\ifemptyx #1\emptymarkA\emptymarkB}% +\def\ifemptyx#1#2\emptymarkB{\ifx #1\emptymarkA}% + +% Hyphenation fixes. +\hyphenation{ap-pen-dix} +\hyphenation{eshell} +\hyphenation{mini-buf-fer mini-buf-fers} +\hyphenation{time-stamp} +\hyphenation{white-space} + +% Margin to add to right of even pages, to left of odd pages. +\newdimen\bindingoffset +\newdimen\normaloffset +\newdimen\pagewidth \newdimen\pageheight + +% Sometimes it is convenient to have everything in the transcript file +% and nothing on the terminal. We don't just call \tracingall here, +% since that produces some useless output on the terminal. We also make +% some effort to order the tracing commands to reduce output in the log +% file; cf. trace.sty in LaTeX. +% +\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}% +\def\loggingall{% + \tracingstats2 + \tracingpages1 + \tracinglostchars2 % 2 gives us more in etex + \tracingparagraphs1 + \tracingoutput1 + \tracingmacros2 + \tracingrestores1 + \showboxbreadth\maxdimen \showboxdepth\maxdimen + \ifx\eTeXversion\undefined\else % etex gives us more logging + \tracingscantokens1 + \tracingifs1 + \tracinggroups1 + \tracingnesting2 + \tracingassigns1 + \fi + \tracingcommands3 % 3 gives us more in etex + \errorcontextlines\maxdimen +}% + +% add check for \lastpenalty to plain's definitions. If the last thing +% we did was a \nobreak, we don't want to insert more space. +% +\def\smallbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\smallskipamount + \removelastskip\penalty-50\smallskip\fi\fi} +\def\medbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\medskipamount + \removelastskip\penalty-100\medskip\fi\fi} +\def\bigbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\bigskipamount + \removelastskip\penalty-200\bigskip\fi\fi} + +% For @cropmarks command. +% Do @cropmarks to get crop marks. +% +\newif\ifcropmarks +\let\cropmarks = \cropmarkstrue +% +% Dimensions to add cropmarks at corners. +% Added by P. A. MacKay, 12 Nov. 1986 +% +\newdimen\outerhsize \newdimen\outervsize % set by the paper size routines +\newdimen\cornerlong \cornerlong=1pc +\newdimen\cornerthick \cornerthick=.3pt +\newdimen\topandbottommargin \topandbottommargin=.75in + +% Main output routine. +\chardef\PAGE = 255 +\output = {\onepageout{\pagecontents\PAGE}} + +\newbox\headlinebox +\newbox\footlinebox + +% \onepageout takes a vbox as an argument. Note that \pagecontents +% does insertions, but you have to call it yourself. +\def\onepageout#1{% + \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi + % + \ifodd\pageno \advance\hoffset by \bindingoffset + \else \advance\hoffset by -\bindingoffset\fi + % + % Do this outside of the \shipout so @code etc. will be expanded in + % the headline as they should be, not taken literally (outputting ''code). + \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}% + \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}% + % + {% + % Have to do this stuff outside the \shipout because we want it to + % take effect in \write's, yet the group defined by the \vbox ends + % before the \shipout runs. + % + \escapechar = `\\ % use backslash in output files. + \indexdummies % don't expand commands in the output. + \normalturnoffactive % \ in index entries must not stay \, e.g., if + % the page break happens to be in the middle of an example. + \shipout\vbox{% + % Do this early so pdf references go to the beginning of the page. + \ifpdfmakepagedest \pdfmkdest{\the\pageno} \fi + % + \ifcropmarks \vbox to \outervsize\bgroup + \hsize = \outerhsize + \vskip-\topandbottommargin + \vtop to0pt{% + \line{\ewtop\hfil\ewtop}% + \nointerlineskip + \line{% + \vbox{\moveleft\cornerthick\nstop}% + \hfill + \vbox{\moveright\cornerthick\nstop}% + }% + \vss}% + \vskip\topandbottommargin + \line\bgroup + \hfil % center the page within the outer (page) hsize. + \ifodd\pageno\hskip\bindingoffset\fi + \vbox\bgroup + \fi + % + \unvbox\headlinebox + \pagebody{#1}% + \ifdim\ht\footlinebox > 0pt + % Only leave this space if the footline is nonempty. + % (We lessened \vsize for it in \oddfootingxxx.) + % The \baselineskip=24pt in plain's \makefootline has no effect. + \vskip 2\baselineskip + \unvbox\footlinebox + \fi + % + \ifcropmarks + \egroup % end of \vbox\bgroup + \hfil\egroup % end of (centering) \line\bgroup + \vskip\topandbottommargin plus1fill minus1fill + \boxmaxdepth = \cornerthick + \vbox to0pt{\vss + \line{% + \vbox{\moveleft\cornerthick\nsbot}% + \hfill + \vbox{\moveright\cornerthick\nsbot}% + }% + \nointerlineskip + \line{\ewbot\hfil\ewbot}% + }% + \egroup % \vbox from first cropmarks clause + \fi + }% end of \shipout\vbox + }% end of group with \normalturnoffactive + \advancepageno + \ifnum\outputpenalty>-20000 \else\dosupereject\fi +} + +\newinsert\margin \dimen\margin=\maxdimen + +\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}} +{\catcode`\@ =11 +\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi +% marginal hacks, juha@viisa.uucp (Juha Takala) +\ifvoid\margin\else % marginal info is present + \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi +\dimen@=\dp#1 \unvbox#1 +\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi +\ifr@ggedbottom \kern-\dimen@ \vfil \fi} +} + +% Here are the rules for the cropmarks. Note that they are +% offset so that the space between them is truly \outerhsize or \outervsize +% (P. A. MacKay, 12 November, 1986) +% +\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong} +\def\nstop{\vbox + {\hrule height\cornerthick depth\cornerlong width\cornerthick}} +\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong} +\def\nsbot{\vbox + {\hrule height\cornerlong depth\cornerthick width\cornerthick}} + +% Parse an argument, then pass it to #1. The argument is the rest of +% the input line (except we remove a trailing comment). #1 should be a +% macro which expects an ordinary undelimited TeX argument. +% +\def\parsearg#1{% + \let\next = #1% + \begingroup + \obeylines + \futurelet\temp\parseargx +} + +% If the next token is an obeyed space (from an @example environment or +% the like), remove it and recurse. Otherwise, we're done. +\def\parseargx{% + % \obeyedspace is defined far below, after the definition of \sepspaces. + \ifx\obeyedspace\temp + \expandafter\parseargdiscardspace + \else + \expandafter\parseargline + \fi +} + +% Remove a single space (as the delimiter token to the macro call). +{\obeyspaces % + \gdef\parseargdiscardspace {\futurelet\temp\parseargx}} + +{\obeylines % + \gdef\parseargline#1^^M{% + \endgroup % End of the group started in \parsearg. + % + % First remove any @c comment, then any @comment. + % Result of each macro is put in \toks0. + \argremovec #1\c\relax % + \expandafter\argremovecomment \the\toks0 \comment\relax % + % + % Call the caller's macro, saved as \next in \parsearg. + \expandafter\next\expandafter{\the\toks0}% + }% +} + +% Since all \c{,omment} does is throw away the argument, we can let TeX +% do that for us. The \relax here is matched by the \relax in the call +% in \parseargline; it could be more or less anything, its purpose is +% just to delimit the argument to the \c. +\def\argremovec#1\c#2\relax{\toks0 = {#1}} +\def\argremovecomment#1\comment#2\relax{\toks0 = {#1}} + +% \argremovec{,omment} might leave us with trailing spaces, though; e.g., +% @end itemize @c foo +% will have two active spaces as part of the argument with the +% `itemize'. Here we remove all active spaces from #1, and assign the +% result to \toks0. +% +% This loses if there are any *other* active characters besides spaces +% in the argument -- _ ^ +, for example -- since they get expanded. +% Fortunately, Texinfo does not define any such commands. (If it ever +% does, the catcode of the characters in questionwill have to be changed +% here.) But this means we cannot call \removeactivespaces as part of +% \argremovec{,omment}, since @c uses \parsearg, and thus the argument +% that \parsearg gets might well have any character at all in it. +% +\def\removeactivespaces#1{% + \begingroup + \ignoreactivespaces + \edef\temp{#1}% + \global\toks0 = \expandafter{\temp}% + \endgroup +} + +% Change the active space to expand to nothing. +% +\begingroup + \obeyspaces + \gdef\ignoreactivespaces{\obeyspaces\let =\empty} +\endgroup + + +\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} + +%% These are used to keep @begin/@end levels from running away +%% Call \inENV within environments (after a \begingroup) +\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi} +\def\ENVcheck{% +\ifENV\errmessage{Still within an environment; press RETURN to continue} +\endgroup\fi} % This is not perfect, but it should reduce lossage + +% @begin foo is the same as @foo, for now. +\newhelp\EMsimple{Press RETURN to continue.} + +\outer\def\begin{\parsearg\beginxxx} + +\def\beginxxx #1{% +\expandafter\ifx\csname #1\endcsname\relax +{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else +\csname #1\endcsname\fi} + +% @end foo executes the definition of \Efoo. +% +\def\end{\parsearg\endxxx} +\def\endxxx #1{% + \removeactivespaces{#1}% + \edef\endthing{\the\toks0}% + % + \expandafter\ifx\csname E\endthing\endcsname\relax + \expandafter\ifx\csname \endthing\endcsname\relax + % There's no \foo, i.e., no ``environment'' foo. + \errhelp = \EMsimple + \errmessage{Undefined command `@end \endthing'}% + \else + \unmatchedenderror\endthing + \fi + \else + % Everything's ok; the right environment has been started. + \csname E\endthing\endcsname + \fi +} + +% There is an environment #1, but it hasn't been started. Give an error. +% +\def\unmatchedenderror#1{% + \errhelp = \EMsimple + \errmessage{This `@end #1' doesn't have a matching `@#1'}% +} + +% Define the control sequence \E#1 to give an unmatched @end error. +% +\def\defineunmatchedend#1{% + \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}% +} + + +%% Simple single-character @ commands + +% @@ prints an @ +% Kludge this until the fonts are right (grr). +\def\@{{\tt\char64}} + +% This is turned off because it was never documented +% and you can use @w{...} around a quote to suppress ligatures. +%% Define @` and @' to be the same as ` and ' +%% but suppressing ligatures. +%\def\`{{`}} +%\def\'{{'}} + +% Used to generate quoted braces. +\def\mylbrace {{\tt\char123}} +\def\myrbrace {{\tt\char125}} +\let\{=\mylbrace +\let\}=\myrbrace +\begingroup + % Definitions to produce \{ and \} commands for indices, + % and @{ and @} for the aux file. + \catcode`\{ = \other \catcode`\} = \other + \catcode`\[ = 1 \catcode`\] = 2 + \catcode`\! = 0 \catcode`\\ = \other + !gdef!lbracecmd[\{]% + !gdef!rbracecmd[\}]% + !gdef!lbraceatcmd[@{]% + !gdef!rbraceatcmd[@}]% +!endgroup + +% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent +% Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H. +\let\, = \c +\let\dotaccent = \. +\def\ringaccent#1{{\accent23 #1}} +\let\tieaccent = \t +\let\ubaraccent = \b +\let\udotaccent = \d + +% Other special characters: @questiondown @exclamdown +% Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss. +\def\questiondown{?`} +\def\exclamdown{!`} + +% Dotless i and dotless j, used for accents. +\def\imacro{i} +\def\jmacro{j} +\def\dotless#1{% + \def\temp{#1}% + \ifx\temp\imacro \ptexi + \else\ifx\temp\jmacro \j + \else \errmessage{@dotless can be used only with i or j}% + \fi\fi +} + +% Be sure we're in horizontal mode when doing a tie, since we make space +% equivalent to this in @example-like environments. Otherwise, a space +% at the beginning of a line will start with \penalty -- and +% since \penalty is valid in vertical mode, we'd end up putting the +% penalty on the vertical list instead of in the new paragraph. +{\catcode`@ = 11 + % Avoid using \@M directly, because that causes trouble + % if the definition is written into an index file. + \global\let\tiepenalty = \@M + \gdef\tie{\leavevmode\penalty\tiepenalty\ } +} + +% @: forces normal size whitespace following. +\def\:{\spacefactor=1000 } + +% @* forces a line break. +\def\*{\hfil\break\hbox{}\ignorespaces} + +% @/ allows a line break. +\let\/=\allowbreak + +% @. is an end-of-sentence period. +\def\.{.\spacefactor=3000 } + +% @! is an end-of-sentence bang. +\def\!{!\spacefactor=3000 } + +% @? is an end-of-sentence query. +\def\?{?\spacefactor=3000 } + +% @w prevents a word break. Without the \leavevmode, @w at the +% beginning of a paragraph, when TeX is still in vertical mode, would +% produce a whole line of output instead of starting the paragraph. +\def\w#1{\leavevmode\hbox{#1}} + +% @group ... @end group forces ... to be all on one page, by enclosing +% it in a TeX vbox. We use \vtop instead of \vbox to construct the box +% to keep its height that of a normal line. According to the rules for +% \topskip (p.114 of the TeXbook), the glue inserted is +% max (\topskip - \ht (first item), 0). If that height is large, +% therefore, no glue is inserted, and the space between the headline and +% the text is small, which looks bad. +% +% Another complication is that the group might be very large. This can +% cause the glue on the previous page to be unduly stretched, because it +% does not have much material. In this case, it's better to add an +% explicit \vfill so that the extra space is at the bottom. The +% threshold for doing this is if the group is more than \vfilllimit +% percent of a page (\vfilllimit can be changed inside of @tex). +% +\newbox\groupbox +\def\vfilllimit{0.7} +% +\def\group{\begingroup + \ifnum\catcode13=\active \else + \errhelp = \groupinvalidhelp + \errmessage{@group invalid in context where filling is enabled}% + \fi + % + % The \vtop we start below produces a box with normal height and large + % depth; thus, TeX puts \baselineskip glue before it, and (when the + % next line of text is done) \lineskip glue after it. (See p.82 of + % the TeXbook.) Thus, space below is not quite equal to space + % above. But it's pretty close. + \def\Egroup{% + \egroup % End the \vtop. + % \dimen0 is the vertical size of the group's box. + \dimen0 = \ht\groupbox \advance\dimen0 by \dp\groupbox + % \dimen2 is how much space is left on the page (more or less). + \dimen2 = \pageheight \advance\dimen2 by -\pagetotal + % if the group doesn't fit on the current page, and it's a big big + % group, force a page break. + \ifdim \dimen0 > \dimen2 + \ifdim \pagetotal < \vfilllimit\pageheight + \page + \fi + \fi + \copy\groupbox + \endgroup % End the \group. + }% + % + \setbox\groupbox = \vtop\bgroup + % We have to put a strut on the last line in case the @group is in + % the midst of an example, rather than completely enclosing it. + % Otherwise, the interline space between the last line of the group + % and the first line afterwards is too small. But we can't put the + % strut in \Egroup, since there it would be on a line by itself. + % Hence this just inserts a strut at the beginning of each line. + \everypar = {\strut}% + % + % Since we have a strut on every line, we don't need any of TeX's + % normal interline spacing. + \offinterlineskip + % + % OK, but now we have to do something about blank + % lines in the input in @example-like environments, which normally + % just turn into \lisppar, which will insert no space now that we've + % turned off the interline space. Simplest is to make them be an + % empty paragraph. + \ifx\par\lisppar + \edef\par{\leavevmode \par}% + % + % Reset ^^M's definition to new definition of \par. + \obeylines + \fi + % + % Do @comment since we are called inside an environment such as + % @example, where each end-of-line in the input causes an + % end-of-line in the output. We don't want the end-of-line after + % the `@group' to put extra space in the output. Since @group + % should appear on a line by itself (according to the Texinfo + % manual), we don't worry about eating any user text. + \comment +} +% +% TeX puts in an \escapechar (i.e., `@') at the beginning of the help +% message, so this ends up printing `@group can only ...'. +% +\newhelp\groupinvalidhelp{% +group can only be used in environments such as @example,^^J% +where each line of input produces a line of output.} + +% @need space-in-mils +% forces a page break if there is not space-in-mils remaining. + +\newdimen\mil \mil=0.001in + +\def\need{\parsearg\needx} + +% Old definition--didn't work. +%\def\needx #1{\par % +%% This method tries to make TeX break the page naturally +%% if the depth of the box does not fit. +%{\baselineskip=0pt% +%\vtop to #1\mil{\vfil}\kern -#1\mil\nobreak +%\prevdepth=-1000pt +%}} + +\def\needx#1{% + % Ensure vertical mode, so we don't make a big box in the middle of a + % paragraph. + \par + % + % If the @need value is less than one line space, it's useless. + \dimen0 = #1\mil + \dimen2 = \ht\strutbox + \advance\dimen2 by \dp\strutbox + \ifdim\dimen0 > \dimen2 + % + % Do a \strut just to make the height of this box be normal, so the + % normal leading is inserted relative to the preceding line. + % And a page break here is fine. + \vtop to #1\mil{\strut\vfil}% + % + % TeX does not even consider page breaks if a penalty added to the + % main vertical list is 10000 or more. But in order to see if the + % empty box we just added fits on the page, we must make it consider + % page breaks. On the other hand, we don't want to actually break the + % page after the empty box. So we use a penalty of 9999. + % + % There is an extremely small chance that TeX will actually break the + % page at this \penalty, if there are no other feasible breakpoints in + % sight. (If the user is using lots of big @group commands, which + % almost-but-not-quite fill up a page, TeX will have a hard time doing + % good page breaking, for example.) However, I could not construct an + % example where a page broke at this \penalty; if it happens in a real + % document, then we can reconsider our strategy. + \penalty9999 + % + % Back up by the size of the box, whether we did a page break or not. + \kern -#1\mil + % + % Do not allow a page break right after this kern. + \nobreak + \fi +} + +% @br forces paragraph break + +\let\br = \par + +% @dots{} output an ellipsis using the current font. +% We do .5em per period so that it has the same spacing in a typewriter +% font as three actual period characters. +% +\def\dots{% + \leavevmode + \hbox to 1.5em{% + \hskip 0pt plus 0.25fil minus 0.25fil + .\hss.\hss.% + \hskip 0pt plus 0.5fil minus 0.5fil + }% +} + +% @enddots{} is an end-of-sentence ellipsis. +% +\def\enddots{% + \leavevmode + \hbox to 2em{% + \hskip 0pt plus 0.25fil minus 0.25fil + .\hss.\hss.\hss.% + \hskip 0pt plus 0.5fil minus 0.5fil + }% + \spacefactor=3000 +} + +% @page forces the start of a new page. +% +\def\page{\par\vfill\supereject} + +% @exdent text.... +% outputs text on separate line in roman font, starting at standard page margin + +% This records the amount of indent in the innermost environment. +% That's how much \exdent should take out. +\newskip\exdentamount + +% This defn is used inside fill environments such as @defun. +\def\exdent{\parsearg\exdentyyy} +\def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}} + +% This defn is used inside nofill environments such as @example. +\def\nofillexdent{\parsearg\nofillexdentyyy} +\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount +\leftline{\hskip\leftskip{\rm#1}}}} + +% @inmargin{WHICH}{TEXT} puts TEXT in the WHICH margin next to the current +% paragraph. For more general purposes, use the \margin insertion +% class. WHICH is `l' or `r'. +% +\newskip\inmarginspacing \inmarginspacing=1cm +\def\strutdepth{\dp\strutbox} +% +\def\doinmargin#1#2{\strut\vadjust{% + \nobreak + \kern-\strutdepth + \vtop to \strutdepth{% + \baselineskip=\strutdepth + \vss + % if you have multiple lines of stuff to put here, you'll need to + % make the vbox yourself of the appropriate size. + \ifx#1l% + \llap{\ignorespaces #2\hskip\inmarginspacing}% + \else + \rlap{\hskip\hsize \hskip\inmarginspacing \ignorespaces #2}% + \fi + \null + }% +}} +\def\inleftmargin{\doinmargin l} +\def\inrightmargin{\doinmargin r} +% +% @inmargin{TEXT [, RIGHT-TEXT]} +% (if RIGHT-TEXT is given, use TEXT for left page, RIGHT-TEXT for right; +% else use TEXT for both). +% +\def\inmargin#1{\parseinmargin #1,,\finish} +\def\parseinmargin#1,#2,#3\finish{% not perfect, but better than nothing. + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0 > 0pt + \def\lefttext{#1}% have both texts + \def\righttext{#2}% + \else + \def\lefttext{#1}% have only one text + \def\righttext{#1}% + \fi + % + \ifodd\pageno + \def\temp{\inrightmargin\righttext}% odd page -> outside is right margin + \else + \def\temp{\inleftmargin\lefttext}% + \fi + \temp +} + +% @include file insert text of that file as input. +% Allow normal characters that we make active in the argument (a file name). +\def\include{\begingroup + \catcode`\\=\other + \catcode`~=\other + \catcode`^=\other + \catcode`_=\other + \catcode`|=\other + \catcode`<=\other + \catcode`>=\other + \catcode`+=\other + \parsearg\includezzz} +% Restore active chars for included file. +\def\includezzz#1{\endgroup\begingroup + % Read the included file in a group so nested @include's work. + \def\thisfile{#1}% + \let\value=\expandablevalue + \input\thisfile +\endgroup} + +\def\thisfile{} + +% @center line +% outputs that line, centered. +% +\def\center{\parsearg\docenter} +\def\docenter#1{{% + \ifhmode \hfil\break \fi + \advance\hsize by -\leftskip + \advance\hsize by -\rightskip + \line{\hfil \ignorespaces#1\unskip \hfil}% + \ifhmode \break \fi +}} + +% @sp n outputs n lines of vertical space + +\def\sp{\parsearg\spxxx} +\def\spxxx #1{\vskip #1\baselineskip} + +% @comment ...line which is ignored... +% @c is the same as @comment +% @ignore ... @end ignore is another way to write a comment + +\def\comment{\begingroup \catcode`\^^M=\other% +\catcode`\@=\other \catcode`\{=\other \catcode`\}=\other% +\commentxxx} +{\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}} + +\let\c=\comment + +% @paragraphindent NCHARS +% We'll use ems for NCHARS, close enough. +% NCHARS can also be the word `asis' or `none'. +% We cannot feasibly implement @paragraphindent asis, though. +% +\def\asisword{asis} % no translation, these are keywords +\def\noneword{none} +% +\def\paragraphindent{\parsearg\doparagraphindent} +\def\doparagraphindent#1{% + \def\temp{#1}% + \ifx\temp\asisword + \else + \ifx\temp\noneword + \defaultparindent = 0pt + \else + \defaultparindent = #1em + \fi + \fi + \parindent = \defaultparindent +} + +% @exampleindent NCHARS +% We'll use ems for NCHARS like @paragraphindent. +% It seems @exampleindent asis isn't necessary, but +% I preserve it to make it similar to @paragraphindent. +\def\exampleindent{\parsearg\doexampleindent} +\def\doexampleindent#1{% + \def\temp{#1}% + \ifx\temp\asisword + \else + \ifx\temp\noneword + \lispnarrowing = 0pt + \else + \lispnarrowing = #1em + \fi + \fi +} + +% @firstparagraphindent WORD +% If WORD is `none', then suppress indentation of the first paragraph +% after a section heading. If WORD is `insert', then do indentat such +% paragraphs. +% +% The paragraph indentation is suppressed or not by calling +% \suppressfirstparagraphindent, which the sectioning commands do. We +% switch the definition of this back and forth according to WORD. By +% default, we suppress indentation. +% +\def\suppressfirstparagraphindent{\dosuppressfirstparagraphindent} +\newdimen\currentparindent +% +\def\insertword{insert} +% +\def\firstparagraphindent{\parsearg\dofirstparagraphindent} +\def\dofirstparagraphindent#1{% + \def\temp{#1}% + \ifx\temp\noneword + \let\suppressfirstparagraphindent = \dosuppressfirstparagraphindent + \else\ifx\temp\insertword + \let\suppressfirstparagraphindent = \relax + \else + \errhelp = \EMsimple + \errmessage{Unknown @firstparagraphindent option `\temp'}% + \fi\fi +} + +% Here is how we actually suppress indentation. Redefine \everypar to +% \kern backwards by \parindent, and then reset itself to empty. +% +% We also make \indent itself not actually do anything until the next +% paragraph. +% +\gdef\dosuppressfirstparagraphindent{% + \gdef\indent{% + \global\let\indent=\ptexindent + \global\everypar = {}% + }% + \global\everypar = {% + \kern-\parindent + \global\let\indent=\ptexindent + \global\everypar = {}% + }% +}% + + +% @asis just yields its argument. Used with @table, for example. +% +\def\asis#1{#1} + +% @math outputs its argument in math mode. +% We don't use $'s directly in the definition of \math because we need +% to set catcodes according to plain TeX first, to allow for subscripts, +% superscripts, special math chars, etc. +% +\let\implicitmath = $%$ font-lock fix +% +% One complication: _ usually means subscripts, but it could also mean +% an actual _ character, as in @math{@var{some_variable} + 1}. So make +% _ within @math be active (mathcode "8000), and distinguish by seeing +% if the current family is \slfam, which is what @var uses. +% +{\catcode\underChar = \active +\gdef\mathunderscore{% + \catcode\underChar=\active + \def_{\ifnum\fam=\slfam \_\else\sb\fi}% +}} +% +% Another complication: we want \\ (and @\) to output a \ character. +% FYI, plain.tex uses \\ as a temporary control sequence (why?), but +% this is not advertised and we don't care. Texinfo does not +% otherwise define @\. +% +% The \mathchar is class=0=ordinary, family=7=ttfam, position=5C=\. +\def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi} +% +\def\math{% + \tex + \mathcode`\_="8000 \mathunderscore + \let\\ = \mathbackslash + \mathactive + \implicitmath\finishmath} +\def\finishmath#1{#1\implicitmath\Etex} + +% Some active characters (such as <) are spaced differently in math. +% We have to reset their definitions in case the @math was an +% argument to a command which set the catcodes (such as @item or @section). +% +{ + \catcode`^ = \active + \catcode`< = \active + \catcode`> = \active + \catcode`+ = \active + \gdef\mathactive{% + \let^ = \ptexhat + \let< = \ptexless + \let> = \ptexgtr + \let+ = \ptexplus + } +} + +% @bullet and @minus need the same treatment as @math, just above. +\def\bullet{\implicitmath\ptexbullet\implicitmath} +\def\minus{\implicitmath-\implicitmath} + +% @refill is a no-op. +\let\refill=\relax + +% If working on a large document in chapters, it is convenient to +% be able to disable indexing, cross-referencing, and contents, for test runs. +% This is done with @novalidate (before @setfilename). +% +\newif\iflinks \linkstrue % by default we want the aux files. +\let\novalidate = \linksfalse + +% @setfilename is done at the beginning of every texinfo file. +% So open here the files we need to have open while reading the input. +% This makes it possible to make a .fmt file for texinfo. +\def\setfilename{% + \iflinks + \readauxfile + \fi % \openindices needs to do some work in any case. + \openindices + \fixbackslash % Turn off hack to swallow `\input texinfo'. + \global\let\setfilename=\comment % Ignore extra @setfilename cmds. + % + % If texinfo.cnf is present on the system, read it. + % Useful for site-wide @afourpaper, etc. + % Just to be on the safe side, close the input stream before the \input. + \openin 1 texinfo.cnf + \ifeof1 \let\temp=\relax \else \def\temp{\input texinfo.cnf }\fi + \closein1 + \temp + % + \comment % Ignore the actual filename. +} + +% Called from \setfilename. +% +\def\openindices{% + \newindex{cp}% + \newcodeindex{fn}% + \newcodeindex{vr}% + \newcodeindex{tp}% + \newcodeindex{ky}% + \newcodeindex{pg}% +} + +% @bye. +\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} + + +\message{pdf,} +% adobe `portable' document format +\newcount\tempnum +\newcount\lnkcount +\newtoks\filename +\newcount\filenamelength +\newcount\pgn +\newtoks\toksA +\newtoks\toksB +\newtoks\toksC +\newtoks\toksD +\newbox\boxA +\newcount\countA +\newif\ifpdf +\newif\ifpdfmakepagedest + +\ifx\pdfoutput\undefined + \pdffalse + \let\pdfmkdest = \gobble + \let\pdfurl = \gobble + \let\endlink = \relax + \let\linkcolor = \relax + \let\pdfmakeoutlines = \relax +\else + \pdftrue + \pdfoutput = 1 + \input pdfcolor + \def\dopdfimage#1#2#3{% + \def\imagewidth{#2}% + \def\imageheight{#3}% + % without \immediate, pdftex seg faults when the same image is + % included twice. (Version 3.14159-pre-1.0-unofficial-20010704.) + \ifnum\pdftexversion < 14 + \immediate\pdfimage + \else + \immediate\pdfximage + \fi + \ifx\empty\imagewidth\else width \imagewidth \fi + \ifx\empty\imageheight\else height \imageheight \fi + \ifnum\pdftexversion<13 + #1.pdf% + \else + {#1.pdf}% + \fi + \ifnum\pdftexversion < 14 \else + \pdfrefximage \pdflastximage + \fi} + \def\pdfmkdest#1{{\normalturnoffactive \pdfdest name{#1} xyz}} + \def\pdfmkpgn#1{#1} + \let\linkcolor = \Blue % was Cyan, but that seems light? + \def\endlink{\Black\pdfendlink} + % Adding outlines to PDF; macros for calculating structure of outlines + % come from Petr Olsak + \def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0% + \else \csname#1\endcsname \fi} + \def\advancenumber#1{\tempnum=\expnumber{#1}\relax + \advance\tempnum by1 + \expandafter\xdef\csname#1\endcsname{\the\tempnum}} + \def\pdfmakeoutlines{{% + \openin 1 \jobname.toc + \ifeof 1\else\begingroup + \closein 1 + % Thanh's hack / proper braces in bookmarks + \edef\mylbrace{\iftrue \string{\else}\fi}\let\{=\mylbrace + \edef\myrbrace{\iffalse{\else\string}\fi}\let\}=\myrbrace + % + \def\chapentry ##1##2##3{} + \def\secentry ##1##2##3##4{\advancenumber{chap##2}} + \def\subsecentry ##1##2##3##4##5{\advancenumber{sec##2.##3}} + \def\subsubsecentry ##1##2##3##4##5##6{\advancenumber{subsec##2.##3.##4}} + \let\appendixentry = \chapentry + \let\unnumbchapentry = \chapentry + \let\unnumbsecentry = \secentry + \let\unnumbsubsecentry = \subsecentry + \let\unnumbsubsubsecentry = \subsubsecentry + \input \jobname.toc + \def\chapentry ##1##2##3{% + \pdfoutline goto name{\pdfmkpgn{##3}}count-\expnumber{chap##2}{##1}} + \def\secentry ##1##2##3##4{% + \pdfoutline goto name{\pdfmkpgn{##4}}count-\expnumber{sec##2.##3}{##1}} + \def\subsecentry ##1##2##3##4##5{% + \pdfoutline goto name{\pdfmkpgn{##5}}count-\expnumber{subsec##2.##3.##4}{##1}} + \def\subsubsecentry ##1##2##3##4##5##6{% + \pdfoutline goto name{\pdfmkpgn{##6}}{##1}} + \let\appendixentry = \chapentry + \let\unnumbchapentry = \chapentry + \let\unnumbsecentry = \secentry + \let\unnumbsubsecentry = \subsecentry + \let\unnumbsubsubsecentry = \subsubsecentry + % + % Make special characters normal for writing to the pdf file. + % + \indexnofonts + \let\tt=\relax + \turnoffactive + \input \jobname.toc + \endgroup\fi + }} + \def\makelinks #1,{% + \def\params{#1}\def\E{END}% + \ifx\params\E + \let\nextmakelinks=\relax + \else + \let\nextmakelinks=\makelinks + \ifnum\lnkcount>0,\fi + \picknum{#1}% + \startlink attr{/Border [0 0 0]} + goto name{\pdfmkpgn{\the\pgn}}% + \linkcolor #1% + \advance\lnkcount by 1% + \endlink + \fi + \nextmakelinks + } + \def\picknum#1{\expandafter\pn#1} + \def\pn#1{% + \def\p{#1}% + \ifx\p\lbrace + \let\nextpn=\ppn + \else + \let\nextpn=\ppnn + \def\first{#1} + \fi + \nextpn + } + \def\ppn#1{\pgn=#1\gobble} + \def\ppnn{\pgn=\first} + \def\pdfmklnk#1{\lnkcount=0\makelinks #1,END,} + \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} + \def\skipspaces#1{\def\PP{#1}\def\D{|}% + \ifx\PP\D\let\nextsp\relax + \else\let\nextsp\skipspaces + \ifx\p\space\else\addtokens{\filename}{\PP}% + \advance\filenamelength by 1 + \fi + \fi + \nextsp} + \def\getfilename#1{\filenamelength=0\expandafter\skipspaces#1|\relax} + \ifnum\pdftexversion < 14 + \let \startlink \pdfannotlink + \else + \let \startlink \pdfstartlink + \fi + \def\pdfurl#1{% + \begingroup + \normalturnoffactive\def\@{@}% + \let\value=\expandablevalue + \leavevmode\Red + \startlink attr{/Border [0 0 0]}% + user{/Subtype /Link /A << /S /URI /URI (#1) >>}% + % #1 + \endgroup} + \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}} + \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} + \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks} + \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}} + \def\maketoks{% + \expandafter\poptoks\the\toksA|ENDTOKS| + \ifx\first0\adn0 + \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3 + \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6 + \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9 + \else + \ifnum0=\countA\else\makelink\fi + \ifx\first.\let\next=\done\else + \let\next=\maketoks + \addtokens{\toksB}{\the\toksD} + \ifx\first,\addtokens{\toksB}{\space}\fi + \fi + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi + \next} + \def\makelink{\addtokens{\toksB}% + {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0} + \def\pdflink#1{% + \startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}} + \linkcolor #1\endlink} + \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st} +\fi % \ifx\pdfoutput + + +\message{fonts,} +% Font-change commands. + +% Texinfo sort of supports the sans serif font style, which plain TeX does not. +% So we set up a \sf analogous to plain's \rm, etc. +\newfam\sffam +\def\sf{\fam=\sffam \tensf} +\let\li = \sf % Sometimes we call it \li, not \sf. + +% We don't need math for this one. +\def\ttsl{\tenttsl} + +% Default leading. +\newdimen\textleading \textleading = 13.2pt + +% Set the baselineskip to #1, and the lineskip and strut size +% correspondingly. There is no deep meaning behind these magic numbers +% used as factors; they just match (closely enough) what Knuth defined. +% +\def\lineskipfactor{.08333} +\def\strutheightpercent{.70833} +\def\strutdepthpercent {.29167} +% +\def\setleading#1{% + \normalbaselineskip = #1\relax + \normallineskip = \lineskipfactor\normalbaselineskip + \normalbaselines + \setbox\strutbox =\hbox{% + \vrule width0pt height\strutheightpercent\baselineskip + depth \strutdepthpercent \baselineskip + }% +} + +% Set the font macro #1 to the font named #2, adding on the +% specified font prefix (normally `cm'). +% #3 is the font's design size, #4 is a scale factor +\def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4} + +% Use cm as the default font prefix. +% To specify the font prefix, you must define \fontprefix +% before you read in texinfo.tex. +\ifx\fontprefix\undefined +\def\fontprefix{cm} +\fi +% Support font families that don't use the same naming scheme as CM. +\def\rmshape{r} +\def\rmbshape{bx} %where the normal face is bold +\def\bfshape{b} +\def\bxshape{bx} +\def\ttshape{tt} +\def\ttbshape{tt} +\def\ttslshape{sltt} +\def\itshape{ti} +\def\itbshape{bxti} +\def\slshape{sl} +\def\slbshape{bxsl} +\def\sfshape{ss} +\def\sfbshape{ss} +\def\scshape{csc} +\def\scbshape{csc} + +\newcount\mainmagstep +\ifx\bigger\relax + % not really supported. + \mainmagstep=\magstep1 + \setfont\textrm\rmshape{12}{1000} + \setfont\texttt\ttshape{12}{1000} +\else + \mainmagstep=\magstephalf + \setfont\textrm\rmshape{10}{\mainmagstep} + \setfont\texttt\ttshape{10}{\mainmagstep} +\fi +% Instead of cmb10, you may want to use cmbx10. +% cmbx10 is a prettier font on its own, but cmb10 +% looks better when embedded in a line with cmr10 +% (in Bob's opinion). +\setfont\textbf\bfshape{10}{\mainmagstep} +\setfont\textit\itshape{10}{\mainmagstep} +\setfont\textsl\slshape{10}{\mainmagstep} +\setfont\textsf\sfshape{10}{\mainmagstep} +\setfont\textsc\scshape{10}{\mainmagstep} +\setfont\textttsl\ttslshape{10}{\mainmagstep} +\font\texti=cmmi10 scaled \mainmagstep +\font\textsy=cmsy10 scaled \mainmagstep + +% A few fonts for @defun, etc. +\setfont\defbf\bxshape{10}{\magstep1} %was 1314 +\setfont\deftt\ttshape{10}{\magstep1} +\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf} + +% Fonts for indices, footnotes, small examples (9pt). +\setfont\smallrm\rmshape{9}{1000} +\setfont\smalltt\ttshape{9}{1000} +\setfont\smallbf\bfshape{10}{900} +\setfont\smallit\itshape{9}{1000} +\setfont\smallsl\slshape{9}{1000} +\setfont\smallsf\sfshape{9}{1000} +\setfont\smallsc\scshape{10}{900} +\setfont\smallttsl\ttslshape{10}{900} +\font\smalli=cmmi9 +\font\smallsy=cmsy9 + +% Fonts for small examples (8pt). +\setfont\smallerrm\rmshape{8}{1000} +\setfont\smallertt\ttshape{8}{1000} +\setfont\smallerbf\bfshape{10}{800} +\setfont\smallerit\itshape{8}{1000} +\setfont\smallersl\slshape{8}{1000} +\setfont\smallersf\sfshape{8}{1000} +\setfont\smallersc\scshape{10}{800} +\setfont\smallerttsl\ttslshape{10}{800} +\font\smalleri=cmmi8 +\font\smallersy=cmsy8 + +% Fonts for title page: +\setfont\titlerm\rmbshape{12}{\magstep3} +\setfont\titleit\itbshape{10}{\magstep4} +\setfont\titlesl\slbshape{10}{\magstep4} +\setfont\titlett\ttbshape{12}{\magstep3} +\setfont\titlettsl\ttslshape{10}{\magstep4} +\setfont\titlesf\sfbshape{17}{\magstep1} +\let\titlebf=\titlerm +\setfont\titlesc\scbshape{10}{\magstep4} +\font\titlei=cmmi12 scaled \magstep3 +\font\titlesy=cmsy10 scaled \magstep4 +\def\authorrm{\secrm} +\def\authortt{\sectt} + +% Chapter (and unnumbered) fonts (17.28pt). +\setfont\chaprm\rmbshape{12}{\magstep2} +\setfont\chapit\itbshape{10}{\magstep3} +\setfont\chapsl\slbshape{10}{\magstep3} +\setfont\chaptt\ttbshape{12}{\magstep2} +\setfont\chapttsl\ttslshape{10}{\magstep3} +\setfont\chapsf\sfbshape{17}{1000} +\let\chapbf=\chaprm +\setfont\chapsc\scbshape{10}{\magstep3} +\font\chapi=cmmi12 scaled \magstep2 +\font\chapsy=cmsy10 scaled \magstep3 + +% Section fonts (14.4pt). +\setfont\secrm\rmbshape{12}{\magstep1} +\setfont\secit\itbshape{10}{\magstep2} +\setfont\secsl\slbshape{10}{\magstep2} +\setfont\sectt\ttbshape{12}{\magstep1} +\setfont\secttsl\ttslshape{10}{\magstep2} +\setfont\secsf\sfbshape{12}{\magstep1} +\let\secbf\secrm +\setfont\secsc\scbshape{10}{\magstep2} +\font\seci=cmmi12 scaled \magstep1 +\font\secsy=cmsy10 scaled \magstep2 + +% Subsection fonts (13.15pt). +\setfont\ssecrm\rmbshape{12}{\magstephalf} +\setfont\ssecit\itbshape{10}{1315} +\setfont\ssecsl\slbshape{10}{1315} +\setfont\ssectt\ttbshape{12}{\magstephalf} +\setfont\ssecttsl\ttslshape{10}{1315} +\setfont\ssecsf\sfbshape{12}{\magstephalf} +\let\ssecbf\ssecrm +\setfont\ssecsc\scbshape{10}{\magstep1} +\font\sseci=cmmi12 scaled \magstephalf +\font\ssecsy=cmsy10 scaled 1315 +% The smallcaps and symbol fonts should actually be scaled \magstep1.5, +% but that is not a standard magnification. + +% In order for the font changes to affect most math symbols and letters, +% we have to define the \textfont of the standard families. Since +% texinfo doesn't allow for producing subscripts and superscripts except +% in the main text, we don't bother to reset \scriptfont and +% \scriptscriptfont (which would also require loading a lot more fonts). +% +\def\resetmathfonts{% + \textfont0=\tenrm \textfont1=\teni \textfont2=\tensy + \textfont\itfam=\tenit \textfont\slfam=\tensl \textfont\bffam=\tenbf + \textfont\ttfam=\tentt \textfont\sffam=\tensf +} + +% The font-changing commands redefine the meanings of \tenSTYLE, instead +% of just \STYLE. We do this so that font changes will continue to work +% in math mode, where it is the current \fam that is relevant in most +% cases, not the current font. Plain TeX does \def\bf{\fam=\bffam +% \tenbf}, for example. By redefining \tenbf, we obviate the need to +% redefine \bf itself. +\def\textfonts{% + \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl + \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc + \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy \let\tenttsl=\textttsl + \resetmathfonts \setleading{\textleading}} +\def\titlefonts{% + \let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl + \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc + \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy + \let\tenttsl=\titlettsl + \resetmathfonts \setleading{25pt}} +\def\titlefont#1{{\titlefonts\rm #1}} +\def\chapfonts{% + \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl + \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc + \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy \let\tenttsl=\chapttsl + \resetmathfonts \setleading{19pt}} +\def\secfonts{% + \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl + \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc + \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy \let\tenttsl=\secttsl + \resetmathfonts \setleading{16pt}} +\def\subsecfonts{% + \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl + \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc + \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy \let\tenttsl=\ssecttsl + \resetmathfonts \setleading{15pt}} +\let\subsubsecfonts = \subsecfonts % Maybe make sssec fonts scaled magstephalf? +\def\smallfonts{% + \let\tenrm=\smallrm \let\tenit=\smallit \let\tensl=\smallsl + \let\tenbf=\smallbf \let\tentt=\smalltt \let\smallcaps=\smallsc + \let\tensf=\smallsf \let\teni=\smalli \let\tensy=\smallsy + \let\tenttsl=\smallttsl + \resetmathfonts \setleading{10.5pt}} +\def\smallerfonts{% + \let\tenrm=\smallerrm \let\tenit=\smallerit \let\tensl=\smallersl + \let\tenbf=\smallerbf \let\tentt=\smallertt \let\smallcaps=\smallersc + \let\tensf=\smallersf \let\teni=\smalleri \let\tensy=\smallersy + \let\tenttsl=\smallerttsl + \resetmathfonts \setleading{9.5pt}} + +% Set the fonts to use with the @small... environments. +\let\smallexamplefonts = \smallfonts + +% About \smallexamplefonts. If we use \smallfonts (9pt), @smallexample +% can fit this many characters: +% 8.5x11=86 smallbook=72 a4=90 a5=69 +% If we use \smallerfonts (8pt), then we can fit this many characters: +% 8.5x11=90+ smallbook=80 a4=90+ a5=77 +% For me, subjectively, the few extra characters that fit aren't worth +% the additional smallness of 8pt. So I'm making the default 9pt. +% +% By the way, for comparison, here's what fits with @example (10pt): +% 8.5x11=71 smallbook=60 a4=75 a5=58 +% +% I wish we used A4 paper on this side of the Atlantic. +% +% --karl, 24jan03. + + +% Set up the default fonts, so we can use them for creating boxes. +% +\textfonts + +% Define these so they can be easily changed for other fonts. +\def\angleleft{$\langle$} +\def\angleright{$\rangle$} + +% Count depth in font-changes, for error checks +\newcount\fontdepth \fontdepth=0 + +% Fonts for short table of contents. +\setfont\shortcontrm\rmshape{12}{1000} +\setfont\shortcontbf\bxshape{12}{1000} +\setfont\shortcontsl\slshape{12}{1000} +\setfont\shortconttt\ttshape{12}{1000} + +%% Add scribe-like font environments, plus @l for inline lisp (usually sans +%% serif) and @ii for TeX italic + +% \smartitalic{ARG} outputs arg in italics, followed by an italic correction +% unless the following character is such as not to need one. +\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else + \ptexslash\fi\fi\fi} +\def\smartslanted#1{{\ifusingtt\ttsl\sl #1}\futurelet\next\smartitalicx} +\def\smartitalic#1{{\ifusingtt\ttsl\it #1}\futurelet\next\smartitalicx} + +\let\i=\smartitalic +\let\var=\smartslanted +\let\dfn=\smartslanted +\let\emph=\smartitalic +\let\cite=\smartslanted + +\def\b#1{{\bf #1}} +\let\strong=\b + +% We can't just use \exhyphenpenalty, because that only has effect at +% the end of a paragraph. Restore normal hyphenation at the end of the +% group within which \nohyphenation is presumably called. +% +\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation} +\def\restorehyphenation{\hyphenchar\font = `- } + +% Set sfcode to normal for the chars that usually have another value. +% Can't use plain's \frenchspacing because it uses the `\x notation, and +% sometimes \x has an active definition that messes things up. +% +\catcode`@=11 + \def\frenchspacing{% + \sfcode\dotChar =\@m \sfcode\questChar=\@m \sfcode\exclamChar=\@m + \sfcode\colonChar=\@m \sfcode\semiChar =\@m \sfcode\commaChar =\@m + } +\catcode`@=\other + +\def\t#1{% + {\tt \rawbackslash \frenchspacing #1}% + \null +} +\let\ttfont=\t +\def\samp#1{`\tclose{#1}'\null} +\setfont\keyrm\rmshape{8}{1000} +\font\keysy=cmsy9 +\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{% + \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{% + \vbox{\hrule\kern-0.4pt + \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}% + \kern-0.4pt\hrule}% + \kern-.06em\raise0.4pt\hbox{\angleright}}}} +% The old definition, with no lozenge: +%\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null} +\def\ctrl #1{{\tt \rawbackslash \hat}#1} + +% @file, @option are the same as @samp. +\let\file=\samp +\let\option=\samp + +% @code is a modification of @t, +% which makes spaces the same size as normal in the surrounding text. +\def\tclose#1{% + {% + % Change normal interword space to be same as for the current font. + \spaceskip = \fontdimen2\font + % + % Switch to typewriter. + \tt + % + % But `\ ' produces the large typewriter interword space. + \def\ {{\spaceskip = 0pt{} }}% + % + % Turn off hyphenation. + \nohyphenation + % + \rawbackslash + \frenchspacing + #1% + }% + \null +} + +% We *must* turn on hyphenation at `-' and `_' in \code. +% Otherwise, it is too hard to avoid overfull hboxes +% in the Emacs manual, the Library manual, etc. + +% Unfortunately, TeX uses one parameter (\hyphenchar) to control +% both hyphenation at - and hyphenation within words. +% We must therefore turn them both off (\tclose does that) +% and arrange explicitly to hyphenate at a dash. +% -- rms. +{ + \catcode`\-=\active + \catcode`\_=\active + % + \global\def\code{\begingroup + \catcode`\-=\active \let-\codedash + \catcode`\_=\active \let_\codeunder + \codex + } + % + % If we end up with any active - characters when handling the index, + % just treat them as a normal -. + \global\def\indexbreaks{\catcode`\-=\active \let-\realdash} +} + +\def\realdash{-} +\def\codedash{-\discretionary{}{}{}} +\def\codeunder{% + % this is all so @math{@code{var_name}+1} can work. In math mode, _ + % is "active" (mathcode"8000) and \normalunderscore (or \char95, etc.) + % will therefore expand the active definition of _, which is us + % (inside @code that is), therefore an endless loop. + \ifusingtt{\ifmmode + \mathchar"075F % class 0=ordinary, family 7=ttfam, pos 0x5F=_. + \else\normalunderscore \fi + \discretionary{}{}{}}% + {\_}% +} +\def\codex #1{\tclose{#1}\endgroup} + +% @kbd is like @code, except that if the argument is just one @key command, +% then @kbd has no effect. + +% @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always), +% `example' (@kbd uses ttsl only inside of @example and friends), +% or `code' (@kbd uses normal tty font always). +\def\kbdinputstyle{\parsearg\kbdinputstylexxx} +\def\kbdinputstylexxx#1{% + \def\arg{#1}% + \ifx\arg\worddistinct + \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}% + \else\ifx\arg\wordexample + \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}% + \else\ifx\arg\wordcode + \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}% + \else + \errhelp = \EMsimple + \errmessage{Unknown @kbdinputstyle option `\arg'}% + \fi\fi\fi +} +\def\worddistinct{distinct} +\def\wordexample{example} +\def\wordcode{code} + +% Default is `distinct.' +\kbdinputstyle distinct + +\def\xkey{\key} +\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}% +\ifx\one\xkey\ifx\threex\three \key{#2}% +\else{\tclose{\kbdfont\look}}\fi +\else{\tclose{\kbdfont\look}}\fi} + +% For @url, @env, @command quotes seem unnecessary, so use \code. +\let\url=\code +\let\env=\code +\let\command=\code + +% @uref (abbreviation for `urlref') takes an optional (comma-separated) +% second argument specifying the text to display and an optional third +% arg as text to display instead of (rather than in addition to) the url +% itself. First (mandatory) arg is the url. Perhaps eventually put in +% a hypertex \special here. +% +\def\uref#1{\douref #1,,,\finish} +\def\douref#1,#2,#3,#4\finish{\begingroup + \unsepspaces + \pdfurl{#1}% + \setbox0 = \hbox{\ignorespaces #3}% + \ifdim\wd0 > 0pt + \unhbox0 % third arg given, show only that + \else + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0 > 0pt + \ifpdf + \unhbox0 % PDF: 2nd arg given, show only it + \else + \unhbox0\ (\code{#1})% DVI: 2nd arg given, show both it and url + \fi + \else + \code{#1}% only url given, so show it + \fi + \fi + \endlink +\endgroup} + +% rms does not like angle brackets --karl, 17may97. +% So now @email is just like @uref, unless we are pdf. +% +%\def\email#1{\angleleft{\tt #1}\angleright} +\ifpdf + \def\email#1{\doemail#1,,\finish} + \def\doemail#1,#2,#3\finish{\begingroup + \unsepspaces + \pdfurl{mailto:#1}% + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0>0pt\unhbox0\else\code{#1}\fi + \endlink + \endgroup} +\else + \let\email=\uref +\fi + +% Check if we are currently using a typewriter font. Since all the +% Computer Modern typewriter fonts have zero interword stretch (and +% shrink), and it is reasonable to expect all typewriter fonts to have +% this property, we can check that font parameter. +% +\def\ifmonospace{\ifdim\fontdimen3\font=0pt } + +% Typeset a dimension, e.g., `in' or `pt'. The only reason for the +% argument is to make the input look right: @dmn{pt} instead of @dmn{}pt. +% +\def\dmn#1{\thinspace #1} + +\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par} + +% @l was never documented to mean ``switch to the Lisp font'', +% and it is not used as such in any manual I can find. We need it for +% Polish suppressed-l. --karl, 22sep96. +%\def\l#1{{\li #1}\null} + +% Explicit font changes: @r, @sc, undocumented @ii. +\def\r#1{{\rm #1}} % roman font +\def\sc#1{{\smallcaps#1}} % smallcaps font +\def\ii#1{{\it #1}} % italic font + +% @acronym downcases the argument and prints in smallcaps. +\def\acronym#1{{\smallcaps \lowercase{#1}}} + +% @pounds{} is a sterling sign. +\def\pounds{{\it\$}} + +% @registeredsymbol - R in a circle. For now, only works in text size; +% we'd have to redo the font mechanism to change the \scriptstyle and +% \scriptscriptstyle font sizes to make it look right in headings. +% Adapted from the plain.tex definition of \copyright. +% +\def\registeredsymbol{% + $^{{\ooalign{\hfil\raise.07ex\hbox{$\scriptstyle\rm R$}\hfil\crcr\Orb}}% + }$% +} + + +\message{page headings,} + +\newskip\titlepagetopglue \titlepagetopglue = 1.5in +\newskip\titlepagebottomglue \titlepagebottomglue = 2pc + +% First the title page. Must do @settitle before @titlepage. +\newif\ifseenauthor +\newif\iffinishedtitlepage + +% Do an implicit @contents or @shortcontents after @end titlepage if the +% user says @setcontentsaftertitlepage or @setshortcontentsaftertitlepage. +% +\newif\ifsetcontentsaftertitlepage + \let\setcontentsaftertitlepage = \setcontentsaftertitlepagetrue +\newif\ifsetshortcontentsaftertitlepage + \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue + +\def\shorttitlepage{\parsearg\shorttitlepagezzz} +\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}% + \endgroup\page\hbox{}\page} + +\def\titlepage{\begingroup \parindent=0pt \textfonts + \let\subtitlerm=\tenrm + \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}% + % + \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines + \let\tt=\authortt}% + % + % Leave some space at the very top of the page. + \vglue\titlepagetopglue + % + % Now you can print the title using @title. + \def\title{\parsearg\titlezzz}% + \def\titlezzz##1{\leftline{\titlefonts\rm ##1} + % print a rule at the page bottom also. + \finishedtitlepagefalse + \vskip4pt \hrule height 4pt width \hsize \vskip4pt}% + % No rule at page bottom unless we print one at the top with @title. + \finishedtitlepagetrue + % + % Now you can put text using @subtitle. + \def\subtitle{\parsearg\subtitlezzz}% + \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}% + % + % @author should come last, but may come many times. + \def\author{\parsearg\authorzzz}% + \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi + {\authorfont \leftline{##1}}}% + % + % Most title ``pages'' are actually two pages long, with space + % at the top of the second. We don't want the ragged left on the second. + \let\oldpage = \page + \def\page{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + \oldpage + \let\page = \oldpage + \hbox{}}% +% \def\page{\oldpage \hbox{}} +} + +\def\Etitlepage{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + % It is important to do the page break before ending the group, + % because the headline and footline are only empty inside the group. + % If we use the new definition of \page, we always get a blank page + % after the title page, which we certainly don't want. + \oldpage + \endgroup + % + % Need this before the \...aftertitlepage checks so that if they are + % in effect the toc pages will come out with page numbers. + \HEADINGSon + % + % If they want short, they certainly want long too. + \ifsetshortcontentsaftertitlepage + \shortcontents + \contents + \global\let\shortcontents = \relax + \global\let\contents = \relax + \fi + % + \ifsetcontentsaftertitlepage + \contents + \global\let\contents = \relax + \global\let\shortcontents = \relax + \fi +} + +\def\finishtitlepage{% + \vskip4pt \hrule height 2pt width \hsize + \vskip\titlepagebottomglue + \finishedtitlepagetrue +} + +%%% Set up page headings and footings. + +\let\thispage=\folio + +\newtoks\evenheadline % headline on even pages +\newtoks\oddheadline % headline on odd pages +\newtoks\evenfootline % footline on even pages +\newtoks\oddfootline % footline on odd pages + +% Now make Tex use those variables +\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline + \else \the\evenheadline \fi}} +\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline + \else \the\evenfootline \fi}\HEADINGShook} +\let\HEADINGShook=\relax + +% Commands to set those variables. +% For example, this is what @headings on does +% @evenheading @thistitle|@thispage|@thischapter +% @oddheading @thischapter|@thispage|@thistitle +% @evenfooting @thisfile|| +% @oddfooting ||@thisfile + +\def\evenheading{\parsearg\evenheadingxxx} +\def\oddheading{\parsearg\oddheadingxxx} +\def\everyheading{\parsearg\everyheadingxxx} + +\def\evenfooting{\parsearg\evenfootingxxx} +\def\oddfooting{\parsearg\oddfootingxxx} +\def\everyfooting{\parsearg\everyfootingxxx} + +{\catcode`\@=0 % + +\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish} +\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{% +\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish} +\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{% +\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\everyheadingxxx#1{\oddheadingxxx{#1}\evenheadingxxx{#1}}% + +\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish} +\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{% +\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish} +\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{% + \global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}% + % + % Leave some space for the footline. Hopefully ok to assume + % @evenfooting will not be used by itself. + \global\advance\pageheight by -\baselineskip + \global\advance\vsize by -\baselineskip +} + +\gdef\everyfootingxxx#1{\oddfootingxxx{#1}\evenfootingxxx{#1}} +% +}% unbind the catcode of @. + +% @headings double turns headings on for double-sided printing. +% @headings single turns headings on for single-sided printing. +% @headings off turns them off. +% @headings on same as @headings double, retained for compatibility. +% @headings after turns on double-sided headings after this page. +% @headings doubleafter turns on double-sided headings after this page. +% @headings singleafter turns on single-sided headings after this page. +% By default, they are off at the start of a document, +% and turned `on' after @end titlepage. + +\def\headings #1 {\csname HEADINGS#1\endcsname} + +\def\HEADINGSoff{ +\global\evenheadline={\hfil} \global\evenfootline={\hfil} +\global\oddheadline={\hfil} \global\oddfootline={\hfil}} +\HEADINGSoff +% When we turn headings on, set the page number to 1. +% For double-sided printing, put current file name in lower left corner, +% chapter name on inside top of right hand pages, document +% title on inside top of left hand pages, and page numbers on outside top +% edge of all pages. +\def\HEADINGSdouble{ +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chapoddpage +} +\let\contentsalignmacro = \chappager + +% For single-sided printing, chapter title goes across top left of page, +% page number on top right. +\def\HEADINGSsingle{ +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chappager +} +\def\HEADINGSon{\HEADINGSdouble} + +\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex} +\let\HEADINGSdoubleafter=\HEADINGSafter +\def\HEADINGSdoublex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chapoddpage +} + +\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex} +\def\HEADINGSsinglex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chappager +} + +% Subroutines used in generating headings +% This produces Day Month Year style of output. +% Only define if not already defined, in case a txi-??.tex file has set +% up a different format (e.g., txi-cs.tex does this). +\ifx\today\undefined +\def\today{% + \number\day\space + \ifcase\month + \or\putwordMJan\or\putwordMFeb\or\putwordMMar\or\putwordMApr + \or\putwordMMay\or\putwordMJun\or\putwordMJul\or\putwordMAug + \or\putwordMSep\or\putwordMOct\or\putwordMNov\or\putwordMDec + \fi + \space\number\year} +\fi + +% @settitle line... specifies the title of the document, for headings. +% It generates no output of its own. +\def\thistitle{\putwordNoTitle} +\def\settitle{\parsearg\settitlezzz} +\def\settitlezzz #1{\gdef\thistitle{#1}} + + +\message{tables,} +% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(x). + +% default indentation of table text +\newdimen\tableindent \tableindent=.8in +% default indentation of @itemize and @enumerate text +\newdimen\itemindent \itemindent=.3in +% margin between end of table item and start of table text. +\newdimen\itemmargin \itemmargin=.1in + +% used internally for \itemindent minus \itemmargin +\newdimen\itemmax + +% Note @table, @vtable, and @vtable define @item, @itemx, etc., with +% these defs. +% They also define \itemindex +% to index the item name in whatever manner is desired (perhaps none). + +\newif\ifitemxneedsnegativevskip + +\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi} + +\def\internalBitem{\smallbreak \parsearg\itemzzz} +\def\internalBitemx{\itemxpar \parsearg\itemzzz} + +\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz} +\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \itemxpar \parsearg\xitemzzz} + +\def\internalBkitem{\smallbreak \parsearg\kitemzzz} +\def\internalBkitemx{\itemxpar \parsearg\kitemzzz} + +\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}% + \itemzzz {#1}} + +\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}% + \itemzzz {#1}} + +\def\itemzzz #1{\begingroup % + \advance\hsize by -\rightskip + \advance\hsize by -\tableindent + \setbox0=\hbox{\itemfont{#1}}% + \itemindex{#1}% + \nobreak % This prevents a break before @itemx. + % + % If the item text does not fit in the space we have, put it on a line + % by itself, and do not allow a page break either before or after that + % line. We do not start a paragraph here because then if the next + % command is, e.g., @kindex, the whatsit would get put into the + % horizontal list on a line by itself, resulting in extra blank space. + \ifdim \wd0>\itemmax + % + % Make this a paragraph so we get the \parskip glue and wrapping, + % but leave it ragged-right. + \begingroup + \advance\leftskip by-\tableindent + \advance\hsize by\tableindent + \advance\rightskip by0pt plus1fil + \leavevmode\unhbox0\par + \endgroup + % + % We're going to be starting a paragraph, but we don't want the + % \parskip glue -- logically it's part of the @item we just started. + \nobreak \vskip-\parskip + % + % Stop a page break at the \parskip glue coming up. (Unfortunately + % we can't prevent a possible page break at the following + % \baselineskip glue.) However, if what follows is an environment + % such as @example, there will be no \parskip glue; then + % the negative vskip we just would cause the example and the item to + % crash together. So we use this bizarre value of 10001 as a signal + % to \aboveenvbreak to insert \parskip glue after all. + % (Possibly there are other commands that could be followed by + % @example which need the same treatment, but not section titles; or + % maybe section titles are the only special case and they should be + % penalty 10001...) + \penalty 10001 + \endgroup + \itemxneedsnegativevskipfalse + \else + % The item text fits into the space. Start a paragraph, so that the + % following text (if any) will end up on the same line. + \noindent + % Do this with kerns and \unhbox so that if there is a footnote in + % the item text, it can migrate to the main vertical list and + % eventually be printed. + \nobreak\kern-\tableindent + \dimen0 = \itemmax \advance\dimen0 by \itemmargin \advance\dimen0 by -\wd0 + \unhbox0 + \nobreak\kern\dimen0 + \endgroup + \itemxneedsnegativevskiptrue + \fi +} + +\def\item{\errmessage{@item while not in a table}} +\def\itemx{\errmessage{@itemx while not in a table}} +\def\kitem{\errmessage{@kitem while not in a table}} +\def\kitemx{\errmessage{@kitemx while not in a table}} +\def\xitem{\errmessage{@xitem while not in a table}} +\def\xitemx{\errmessage{@xitemx while not in a table}} + +% Contains a kludge to get @end[description] to work. +\def\description{\tablez{\dontindex}{1}{}{}{}{}} + +% @table, @ftable, @vtable. +\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex} +{\obeylines\obeyspaces% +\gdef\tablex #1^^M{% +\tabley\dontindex#1 \endtabley}} + +\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex} +{\obeylines\obeyspaces% +\gdef\ftablex #1^^M{% +\tabley\fnitemindex#1 \endtabley +\def\Eftable{\endgraf\afterenvbreak\endgroup}% +\let\Etable=\relax}} + +\def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex} +{\obeylines\obeyspaces% +\gdef\vtablex #1^^M{% +\tabley\vritemindex#1 \endtabley +\def\Evtable{\endgraf\afterenvbreak\endgroup}% +\let\Etable=\relax}} + +\def\dontindex #1{} +\def\fnitemindex #1{\doind {fn}{\code{#1}}}% +\def\vritemindex #1{\doind {vr}{\code{#1}}}% + +{\obeyspaces % +\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup% +\tablez{#1}{#2}{#3}{#4}{#5}{#6}}} + +\def\tablez #1#2#3#4#5#6{% +\aboveenvbreak % +\begingroup % +\def\Edescription{\Etable}% Necessary kludge. +\let\itemindex=#1% +\ifnum 0#3>0 \advance \leftskip by #3\mil \fi % +\ifnum 0#4>0 \tableindent=#4\mil \fi % +\ifnum 0#5>0 \advance \rightskip by #5\mil \fi % +\def\itemfont{#2}% +\itemmax=\tableindent % +\advance \itemmax by -\itemmargin % +\advance \leftskip by \tableindent % +\exdentamount=\tableindent +\parindent = 0pt +\parskip = \smallskipamount +\ifdim \parskip=0pt \parskip=2pt \fi% +\def\Etable{\endgraf\afterenvbreak\endgroup}% +\let\item = \internalBitem % +\let\itemx = \internalBitemx % +\let\kitem = \internalBkitem % +\let\kitemx = \internalBkitemx % +\let\xitem = \internalBxitem % +\let\xitemx = \internalBxitemx % +} + +% This is the counter used by @enumerate, which is really @itemize + +\newcount \itemno + +\def\itemize{\parsearg\itemizezzz} + +\def\itemizezzz #1{% + \begingroup % ended by the @end itemize + \itemizey {#1}{\Eitemize} +} + +\def\itemizey#1#2{% + \aboveenvbreak + \itemmax=\itemindent + \advance\itemmax by -\itemmargin + \advance\leftskip by \itemindent + \exdentamount=\itemindent + \parindent=0pt + \parskip=\smallskipamount + \ifdim\parskip=0pt \parskip=2pt \fi + \def#2{\endgraf\afterenvbreak\endgroup}% + \def\itemcontents{#1}% + % @itemize with no arg is equivalent to @itemize @bullet. + \ifx\itemcontents\empty\def\itemcontents{\bullet}\fi + \let\item=\itemizeitem +} + +% \splitoff TOKENS\endmark defines \first to be the first token in +% TOKENS, and \rest to be the remainder. +% +\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}% + +% Allow an optional argument of an uppercase letter, lowercase letter, +% or number, to specify the first label in the enumerated list. No +% argument is the same as `1'. +% +\def\enumerate{\parsearg\enumeratezzz} +\def\enumeratezzz #1{\enumeratey #1 \endenumeratey} +\def\enumeratey #1 #2\endenumeratey{% + \begingroup % ended by the @end enumerate + % + % If we were given no argument, pretend we were given `1'. + \def\thearg{#1}% + \ifx\thearg\empty \def\thearg{1}\fi + % + % Detect if the argument is a single token. If so, it might be a + % letter. Otherwise, the only valid thing it can be is a number. + % (We will always have one token, because of the test we just made. + % This is a good thing, since \splitoff doesn't work given nothing at + % all -- the first parameter is undelimited.) + \expandafter\splitoff\thearg\endmark + \ifx\rest\empty + % Only one token in the argument. It could still be anything. + % A ``lowercase letter'' is one whose \lccode is nonzero. + % An ``uppercase letter'' is one whose \lccode is both nonzero, and + % not equal to itself. + % Otherwise, we assume it's a number. + % + % We need the \relax at the end of the \ifnum lines to stop TeX from + % continuing to look for a . + % + \ifnum\lccode\expandafter`\thearg=0\relax + \numericenumerate % a number (we hope) + \else + % It's a letter. + \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax + \lowercaseenumerate % lowercase letter + \else + \uppercaseenumerate % uppercase letter + \fi + \fi + \else + % Multiple tokens in the argument. We hope it's a number. + \numericenumerate + \fi +} + +% An @enumerate whose labels are integers. The starting integer is +% given in \thearg. +% +\def\numericenumerate{% + \itemno = \thearg + \startenumeration{\the\itemno}% +} + +% The starting (lowercase) letter is in \thearg. +\def\lowercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more lowercase letters in @enumerate; get a bigger + alphabet}% + \fi + \char\lccode\itemno + }% +} + +% The starting (uppercase) letter is in \thearg. +\def\uppercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more uppercase letters in @enumerate; get a bigger + alphabet} + \fi + \char\uccode\itemno + }% +} + +% Call itemizey, adding a period to the first argument and supplying the +% common last two arguments. Also subtract one from the initial value in +% \itemno, since @item increments \itemno. +% +\def\startenumeration#1{% + \advance\itemno by -1 + \itemizey{#1.}\Eenumerate\flushcr +} + +% @alphaenumerate and @capsenumerate are abbreviations for giving an arg +% to @enumerate. +% +\def\alphaenumerate{\enumerate{a}} +\def\capsenumerate{\enumerate{A}} +\def\Ealphaenumerate{\Eenumerate} +\def\Ecapsenumerate{\Eenumerate} + +% Definition of @item while inside @itemize. + +\def\itemizeitem{% +\advance\itemno by 1 +{\let\par=\endgraf \smallbreak}% +\ifhmode \errmessage{In hmode at itemizeitem}\fi +{\parskip=0in \hskip 0pt +\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}% +\vadjust{\penalty 1200}}% +\flushcr} + +% @multitable macros +% Amy Hendrickson, 8/18/94, 3/6/96 +% +% @multitable ... @end multitable will make as many columns as desired. +% Contents of each column will wrap at width given in preamble. Width +% can be specified either with sample text given in a template line, +% or in percent of \hsize, the current width of text on page. + +% Table can continue over pages but will only break between lines. + +% To make preamble: +% +% Either define widths of columns in terms of percent of \hsize: +% @multitable @columnfractions .25 .3 .45 +% @item ... +% +% Numbers following @columnfractions are the percent of the total +% current hsize to be used for each column. You may use as many +% columns as desired. + + +% Or use a template: +% @multitable {Column 1 template} {Column 2 template} {Column 3 template} +% @item ... +% using the widest term desired in each column. +% +% For those who want to use more than one line's worth of words in +% the preamble, break the line within one argument and it +% will parse correctly, i.e., +% +% @multitable {Column 1 template} {Column 2 template} {Column 3 +% template} +% Not: +% @multitable {Column 1 template} {Column 2 template} +% {Column 3 template} + +% Each new table line starts with @item, each subsequent new column +% starts with @tab. Empty columns may be produced by supplying @tab's +% with nothing between them for as many times as empty columns are needed, +% ie, @tab@tab@tab will produce two empty columns. + +% @item, @tab, @multitable or @end multitable do not need to be on their +% own lines, but it will not hurt if they are. + +% Sample multitable: + +% @multitable {Column 1 template} {Column 2 template} {Column 3 template} +% @item first col stuff @tab second col stuff @tab third col +% @item +% first col stuff +% @tab +% second col stuff +% @tab +% third col +% @item first col stuff @tab second col stuff +% @tab Many paragraphs of text may be used in any column. +% +% They will wrap at the width determined by the template. +% @item@tab@tab This will be in third column. +% @end multitable + +% Default dimensions may be reset by user. +% @multitableparskip is vertical space between paragraphs in table. +% @multitableparindent is paragraph indent in table. +% @multitablecolmargin is horizontal space to be left between columns. +% @multitablelinespace is space to leave between table items, baseline +% to baseline. +% 0pt means it depends on current normal line spacing. +% +\newskip\multitableparskip +\newskip\multitableparindent +\newdimen\multitablecolspace +\newskip\multitablelinespace +\multitableparskip=0pt +\multitableparindent=6pt +\multitablecolspace=12pt +\multitablelinespace=0pt + +% Macros used to set up halign preamble: +% +\let\endsetuptable\relax +\def\xendsetuptable{\endsetuptable} +\let\columnfractions\relax +\def\xcolumnfractions{\columnfractions} +\newif\ifsetpercent + +% #1 is the part of the @columnfraction before the decimal point, which +% is presumably either 0 or the empty string (but we don't check, we +% just throw it away). #2 is the decimal part, which we use as the +% percent of \hsize for this column. +\def\pickupwholefraction#1.#2 {% + \global\advance\colcount by 1 + \expandafter\xdef\csname col\the\colcount\endcsname{.#2\hsize}% + \setuptable +} + +\newcount\colcount +\def\setuptable#1{% + \def\firstarg{#1}% + \ifx\firstarg\xendsetuptable + \let\go = \relax + \else + \ifx\firstarg\xcolumnfractions + \global\setpercenttrue + \else + \ifsetpercent + \let\go\pickupwholefraction + \else + \global\advance\colcount by 1 + \setbox0=\hbox{#1\unskip\space}% Add a normal word space as a + % separator; typically that is always in the input, anyway. + \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}% + \fi + \fi + \ifx\go\pickupwholefraction + % Put the argument back for the \pickupwholefraction call, so + % we'll always have a period there to be parsed. + \def\go{\pickupwholefraction#1}% + \else + \let\go = \setuptable + \fi% + \fi + \go +} + +% @multitable ... @end multitable definitions: +% +\def\multitable{\parsearg\dotable} +\def\dotable#1{\bgroup + \vskip\parskip + \let\item=\crcrwithfootnotes + % A \tab used to include \hskip1sp. But then the space in a template + % line is not enough. That is bad. So let's go back to just & until + % we encounter the problem it was intended to solve again. --karl, + % nathan@acm.org, 20apr99. + \let\tab=&% + \let\startfootins=\startsavedfootnote + \tolerance=9500 + \hbadness=9500 + \setmultitablespacing + \parskip=\multitableparskip + \parindent=\multitableparindent + \overfullrule=0pt + \global\colcount=0 + \def\Emultitable{% + \global\setpercentfalse + \crcrwithfootnotes\crcr + \egroup\egroup + }% + % + % To parse everything between @multitable and @item: + \setuptable#1 \endsetuptable + % + % \everycr will reset column counter, \colcount, at the end of + % each line. Every column entry will cause \colcount to advance by one. + % The table preamble + % looks at the current \colcount to find the correct column width. + \everycr{\noalign{% + % + % \filbreak%% keeps underfull box messages off when table breaks over pages. + % Maybe so, but it also creates really weird page breaks when the table + % breaks over pages. Wouldn't \vfil be better? Wait until the problem + % manifests itself, so it can be fixed for real --karl. + \global\colcount=0\relax}}% + % + % This preamble sets up a generic column definition, which will + % be used as many times as user calls for columns. + % \vtop will set a single line and will also let text wrap and + % continue for many paragraphs if desired. + \halign\bgroup&\global\advance\colcount by 1\relax + \multistrut\vtop{\hsize=\expandafter\csname col\the\colcount\endcsname + % + % In order to keep entries from bumping into each other + % we will add a \leftskip of \multitablecolspace to all columns after + % the first one. + % + % If a template has been used, we will add \multitablecolspace + % to the width of each template entry. + % + % If the user has set preamble in terms of percent of \hsize we will + % use that dimension as the width of the column, and the \leftskip + % will keep entries from bumping into each other. Table will start at + % left margin and final column will justify at right margin. + % + % Make sure we don't inherit \rightskip from the outer environment. + \rightskip=0pt + \ifnum\colcount=1 + % The first column will be indented with the surrounding text. + \advance\hsize by\leftskip + \else + \ifsetpercent \else + % If user has not set preamble in terms of percent of \hsize + % we will advance \hsize by \multitablecolspace. + \advance\hsize by \multitablecolspace + \fi + % In either case we will make \leftskip=\multitablecolspace: + \leftskip=\multitablecolspace + \fi + % Ignoring space at the beginning and end avoids an occasional spurious + % blank line, when TeX decides to break the line at the space before the + % box from the multistrut, so the strut ends up on a line by itself. + % For example: + % @multitable @columnfractions .11 .89 + % @item @code{#} + % @tab Legal holiday which is valid in major parts of the whole country. + % Is automatically provided with highlighting sequences respectively marking + % characters. + \noindent\ignorespaces##\unskip\multistrut}\cr +} + +\def\setmultitablespacing{% test to see if user has set \multitablelinespace. +% If so, do nothing. If not, give it an appropriate dimension based on +% current baselineskip. +\ifdim\multitablelinespace=0pt +\setbox0=\vbox{X}\global\multitablelinespace=\the\baselineskip +\global\advance\multitablelinespace by-\ht0 +%% strut to put in table in case some entry doesn't have descenders, +%% to keep lines equally spaced +\let\multistrut = \strut +\else +%% FIXME: what is \box0 supposed to be? +\gdef\multistrut{\vrule height\multitablelinespace depth\dp0 +width0pt\relax} \fi +%% Test to see if parskip is larger than space between lines of +%% table. If not, do nothing. +%% If so, set to same dimension as multitablelinespace. +\ifdim\multitableparskip>\multitablelinespace +\global\multitableparskip=\multitablelinespace +\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller + %% than skip between lines in the table. +\fi% +\ifdim\multitableparskip=0pt +\global\multitableparskip=\multitablelinespace +\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller + %% than skip between lines in the table. +\fi} + +% In case a @footnote appears inside an alignment, save the footnote +% text to a box and make the \insert when a row of the table is +% finished. Otherwise, the insertion is lost, it never migrates to the +% main vertical list. --kasal, 22jan03. +% +\newbox\savedfootnotes +% +% \dotable \let's \startfootins to this, so that \dofootnote will call +% it instead of starting the insertion right away. +\def\startsavedfootnote{% + \global\setbox\savedfootnotes = \vbox\bgroup + \unvbox\savedfootnotes +} +\def\crcrwithfootnotes{% + \crcr + \ifvoid\savedfootnotes \else + \noalign{\insert\footins{\box\savedfootnotes}}% + \fi +} + +\message{conditionals,} +% Prevent errors for section commands. +% Used in @ignore and in failing conditionals. +\def\ignoresections{% + \let\chapter=\relax + \let\unnumbered=\relax + \let\top=\relax + \let\unnumberedsec=\relax + \let\unnumberedsection=\relax + \let\unnumberedsubsec=\relax + \let\unnumberedsubsection=\relax + \let\unnumberedsubsubsec=\relax + \let\unnumberedsubsubsection=\relax + \let\section=\relax + \let\subsec=\relax + \let\subsubsec=\relax + \let\subsection=\relax + \let\subsubsection=\relax + \let\appendix=\relax + \let\appendixsec=\relax + \let\appendixsection=\relax + \let\appendixsubsec=\relax + \let\appendixsubsection=\relax + \let\appendixsubsubsec=\relax + \let\appendixsubsubsection=\relax + \let\contents=\relax + \let\smallbook=\relax + \let\titlepage=\relax +} + +% Used in nested conditionals, where we have to parse the Texinfo source +% and so want to turn off most commands, in case they are used +% incorrectly. +% +% We use \empty instead of \relax for the @def... commands, so that \end +% doesn't throw an error. For instance: +% @ignore +% @deffn ... +% @end deffn +% @end ignore +% +% The @end deffn is going to get expanded, because we're trying to allow +% nested conditionals. But we don't want to expand the actual @deffn, +% since it might be syntactically correct and intended to be ignored. +% Since \end checks for \relax, using \empty does not cause an error. +% +\def\ignoremorecommands{% + \let\defcodeindex = \relax + \let\defcv = \empty + \let\defcvx = \empty + \let\Edefcv = \empty + \let\deffn = \empty + \let\deffnx = \empty + \let\Edeffn = \empty + \let\defindex = \relax + \let\defivar = \empty + \let\defivarx = \empty + \let\Edefivar = \empty + \let\defmac = \empty + \let\defmacx = \empty + \let\Edefmac = \empty + \let\defmethod = \empty + \let\defmethodx = \empty + \let\Edefmethod = \empty + \let\defop = \empty + \let\defopx = \empty + \let\Edefop = \empty + \let\defopt = \empty + \let\defoptx = \empty + \let\Edefopt = \empty + \let\defspec = \empty + \let\defspecx = \empty + \let\Edefspec = \empty + \let\deftp = \empty + \let\deftpx = \empty + \let\Edeftp = \empty + \let\deftypefn = \empty + \let\deftypefnx = \empty + \let\Edeftypefn = \empty + \let\deftypefun = \empty + \let\deftypefunx = \empty + \let\Edeftypefun = \empty + \let\deftypeivar = \empty + \let\deftypeivarx = \empty + \let\Edeftypeivar = \empty + \let\deftypemethod = \empty + \let\deftypemethodx = \empty + \let\Edeftypemethod = \empty + \let\deftypeop = \empty + \let\deftypeopx = \empty + \let\Edeftypeop = \empty + \let\deftypevar = \empty + \let\deftypevarx = \empty + \let\Edeftypevar = \empty + \let\deftypevr = \empty + \let\deftypevrx = \empty + \let\Edeftypevr = \empty + \let\defun = \empty + \let\defunx = \empty + \let\Edefun = \empty + \let\defvar = \empty + \let\defvarx = \empty + \let\Edefvar = \empty + \let\defvr = \empty + \let\defvrx = \empty + \let\Edefvr = \empty + \let\clear = \relax + \let\down = \relax + \let\evenfooting = \relax + \let\evenheading = \relax + \let\everyfooting = \relax + \let\everyheading = \relax + \let\headings = \relax + \let\include = \relax + \let\item = \relax + \let\lowersections = \relax + \let\oddfooting = \relax + \let\oddheading = \relax + \let\printindex = \relax + \let\pxref = \relax + \let\raisesections = \relax + \let\ref = \relax + \let\set = \relax + \let\setchapternewpage = \relax + \let\setchapterstyle = \relax + \let\settitle = \relax + \let\up = \relax + \let\verbatiminclude = \relax + \let\xref = \relax +} + +% Ignore @ignore, @ifhtml, @ifinfo, and the like. +% +\def\direntry{\doignore{direntry}} +\def\documentdescriptionword{documentdescription} +\def\documentdescription{\doignore{documentdescription}} +\def\html{\doignore{html}} +\def\ifhtml{\doignore{ifhtml}} +\def\ifinfo{\doignore{ifinfo}} +\def\ifnottex{\doignore{ifnottex}} +\def\ifplaintext{\doignore{ifplaintext}} +\def\ifxml{\doignore{ifxml}} +\def\ignore{\doignore{ignore}} +\def\menu{\doignore{menu}} +\def\xml{\doignore{xml}} + +% @dircategory CATEGORY -- specify a category of the dir file +% which this file should belong to. Ignore this in TeX. +\let\dircategory = \comment + +% Ignore text until a line `@end #1'. +% +\def\doignore#1{\begingroup + % Don't complain about control sequences we have declared \outer. + \ignoresections + % + % Define a command to swallow text until we reach `@end #1'. + % This @ is a catcode 12 token (that is the normal catcode of @ in + % this texinfo.tex file). We change the catcode of @ below to match. + \long\def\doignoretext##1@end #1{\enddoignore}% + % + % Make sure that spaces turn into tokens that match what \doignoretext wants. + \catcode\spaceChar = 10 + % + % Ignore braces, too, so mismatched braces don't cause trouble. + \catcode`\{ = 9 + \catcode`\} = 9 + % + % We must not have @c interpreted as a control sequence. + \catcode`\@ = 12 + % + \def\ignoreword{#1}% + \ifx\ignoreword\documentdescriptionword + % The c kludge breaks documentdescription, since + % `documentdescription' contains a `c'. Means not everything will + % be ignored inside @documentdescription, but oh well... + \else + % Make the letter c a comment character so that the rest of the line + % will be ignored. This way, the document can have (for example) + % @c @end ifinfo + % and the @end ifinfo will be properly ignored. + % (We've just changed @ to catcode 12.) + \catcode`\c = 14 + \fi + % + % And now expand the command defined above. + \doignoretext +} + +% What we do to finish off ignored text. +% +\def\enddoignore{\endgroup\ignorespaces}% + +\newif\ifwarnedobs\warnedobsfalse +\def\obstexwarn{% + \ifwarnedobs\relax\else + % We need to warn folks that they may have trouble with TeX 3.0. + % This uses \immediate\write16 rather than \message to get newlines. + \immediate\write16{} + \immediate\write16{WARNING: for users of Unix TeX 3.0!} + \immediate\write16{This manual trips a bug in TeX version 3.0 (tex hangs).} + \immediate\write16{If you are running another version of TeX, relax.} + \immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.} + \immediate\write16{ Then upgrade your TeX installation if you can.} + \immediate\write16{ (See ftp://ftp.gnu.org/non-gnu/TeX.README.)} + \immediate\write16{If you are stuck with version 3.0, run the} + \immediate\write16{ script ``tex3patch'' from the Texinfo distribution} + \immediate\write16{ to use a workaround.} + \immediate\write16{} + \global\warnedobstrue + \fi +} + +% **In TeX 3.0, setting text in \nullfont hangs tex. For a +% workaround (which requires the file ``dummy.tfm'' to be installed), +% uncomment the following line: +%%%%%\font\nullfont=dummy\let\obstexwarn=\relax + +% Ignore text, except that we keep track of conditional commands for +% purposes of nesting, up to an `@end #1' command. +% +\def\nestedignore#1{% + \obstexwarn + % We must actually expand the ignored text to look for the @end + % command, so that nested ignore constructs work. Thus, we put the + % text into a \vbox and then do nothing with the result. To minimize + % the chance of memory overflow, we follow the approach outlined on + % page 401 of the TeXbook. + % + \setbox0 = \vbox\bgroup + % Don't complain about control sequences we have declared \outer. + \ignoresections + % + % Define `@end #1' to end the box, which will in turn undefine the + % @end command again. + \expandafter\def\csname E#1\endcsname{\egroup\ignorespaces}% + % + % We are going to be parsing Texinfo commands. Most cause no + % trouble when they are used incorrectly, but some commands do + % complicated argument parsing or otherwise get confused, so we + % undefine them. + % + % We can't do anything about stray @-signs, unfortunately; + % they'll produce `undefined control sequence' errors. + \ignoremorecommands + % + % Set the current font to be \nullfont, a TeX primitive, and define + % all the font commands to also use \nullfont. We don't use + % dummy.tfm, as suggested in the TeXbook, because some sites + % might not have that installed. Therefore, math mode will still + % produce output, but that should be an extremely small amount of + % stuff compared to the main input. + % + \nullfont + \let\tenrm=\nullfont \let\tenit=\nullfont \let\tensl=\nullfont + \let\tenbf=\nullfont \let\tentt=\nullfont \let\smallcaps=\nullfont + \let\tensf=\nullfont + % Similarly for index fonts. + \let\smallrm=\nullfont \let\smallit=\nullfont \let\smallsl=\nullfont + \let\smallbf=\nullfont \let\smalltt=\nullfont \let\smallsc=\nullfont + \let\smallsf=\nullfont + % Similarly for smallexample fonts. + \let\smallerrm=\nullfont \let\smallerit=\nullfont \let\smallersl=\nullfont + \let\smallerbf=\nullfont \let\smallertt=\nullfont \let\smallersc=\nullfont + \let\smallersf=\nullfont + % + % Don't complain when characters are missing from the fonts. + \tracinglostchars = 0 + % + % Don't bother to do space factor calculations. + \frenchspacing + % + % Don't report underfull hboxes. + \hbadness = 10000 + % + % Do minimal line-breaking. + \pretolerance = 10000 + % + % Do not execute instructions in @tex. + \def\tex{\doignore{tex}}% + % Do not execute macro definitions. + % `c' is a comment character, so the word `macro' will get cut off. + \def\macro{\doignore{ma}}% +} + +% @set VAR sets the variable VAR to an empty value. +% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE. +% +% Since we want to separate VAR from REST-OF-LINE (which might be +% empty), we can't just use \parsearg; we have to insert a space of our +% own to delimit the rest of the line, and then take it out again if we +% didn't need it. Make sure the catcode of space is correct to avoid +% losing inside @example, for instance. +% +\def\set{\begingroup\catcode` =10 + \catcode`\-=12 \catcode`\_=12 % Allow - and _ in VAR. + \parsearg\setxxx} +\def\setxxx#1{\setyyy#1 \endsetyyy} +\def\setyyy#1 #2\endsetyyy{% + \def\temp{#2}% + \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty + \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted. + \fi + \endgroup +} +% Can't use \xdef to pre-expand #2 and save some time, since \temp or +% \next or other control sequences that we've defined might get us into +% an infinite loop. Consider `@set foo @cite{bar}'. +\def\setzzz#1#2 \endsetzzz{\expandafter\gdef\csname SET#1\endcsname{#2}} + +% @clear VAR clears (i.e., unsets) the variable VAR. +% +\def\clear{\parsearg\clearxxx} +\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax} + +% @value{foo} gets the text saved in variable foo. +{ + \catcode`\_ = \active + % + % We might end up with active _ or - characters in the argument if + % we're called from @code, as @code{@value{foo-bar_}}. So \let any + % such active characters to their normal equivalents. + \gdef\value{\begingroup + \catcode`\-=\other \catcode`\_=\other + \indexbreaks \let_\normalunderscore + \valuexxx} +} +\def\valuexxx#1{\expandablevalue{#1}\endgroup} + +% We have this subroutine so that we can handle at least some @value's +% properly in indexes (we \let\value to this in \indexdummies). Ones +% whose names contain - or _ still won't work, but we can't do anything +% about that. The command has to be fully expandable (if the variable +% is set), since the result winds up in the index file. This means that +% if the variable's value contains other Texinfo commands, it's almost +% certain it will fail (although perhaps we could fix that with +% sufficient work to do a one-level expansion on the result, instead of +% complete). +% +\def\expandablevalue#1{% + \expandafter\ifx\csname SET#1\endcsname\relax + {[No value for ``#1'']}% + \message{Variable `#1', used in @value, is not set.}% + \else + \csname SET#1\endcsname + \fi +} + +% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined +% with @set. +% +\def\ifset{\parsearg\doifset} +\def\doifset#1{% + \expandafter\ifx\csname SET#1\endcsname\relax + \let\next=\ifsetfail + \else + \let\next=\ifsetsucceed + \fi + \next +} +\def\ifsetsucceed{\conditionalsucceed{ifset}} +\def\ifsetfail{\nestedignore{ifset}} +\defineunmatchedend{ifset} + +% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been +% defined with @set, or has been undefined with @clear. +% +\def\ifclear{\parsearg\doifclear} +\def\doifclear#1{% + \expandafter\ifx\csname SET#1\endcsname\relax + \let\next=\ifclearsucceed + \else + \let\next=\ifclearfail + \fi + \next +} +\def\ifclearsucceed{\conditionalsucceed{ifclear}} +\def\ifclearfail{\nestedignore{ifclear}} +\defineunmatchedend{ifclear} + +% @iftex, @ifnothtml, @ifnotinfo, @ifnotplaintext always succeed; we +% read the text following, through the first @end iftex (etc.). Make +% `@end iftex' (etc.) valid only after an @iftex. +% +\def\iftex{\conditionalsucceed{iftex}} +\def\ifnothtml{\conditionalsucceed{ifnothtml}} +\def\ifnotinfo{\conditionalsucceed{ifnotinfo}} +\def\ifnotplaintext{\conditionalsucceed{ifnotplaintext}} +\defineunmatchedend{iftex} +\defineunmatchedend{ifnothtml} +\defineunmatchedend{ifnotinfo} +\defineunmatchedend{ifnotplaintext} + +% True conditional. Since \set globally defines its variables, we can +% just start and end a group (to keep the @end definition undefined at +% the outer level). +% +\def\conditionalsucceed#1{\begingroup + \expandafter\def\csname E#1\endcsname{\endgroup}% +} + +% @defininfoenclose. +\let\definfoenclose=\comment + + +\message{indexing,} +% Index generation facilities + +% Define \newwrite to be identical to plain tex's \newwrite +% except not \outer, so it can be used within \newindex. +{\catcode`\@=11 +\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}} + +% \newindex {foo} defines an index named foo. +% It automatically defines \fooindex such that +% \fooindex ...rest of line... puts an entry in the index foo. +% It also defines \fooindfile to be the number of the output channel for +% the file that accumulates this index. The file's extension is foo. +% The name of an index should be no more than 2 characters long +% for the sake of vms. +% +\def\newindex#1{% + \iflinks + \expandafter\newwrite \csname#1indfile\endcsname + \openout \csname#1indfile\endcsname \jobname.#1 % Open the file + \fi + \expandafter\xdef\csname#1index\endcsname{% % Define @#1index + \noexpand\doindex{#1}} +} + +% @defindex foo == \newindex{foo} +% +\def\defindex{\parsearg\newindex} + +% Define @defcodeindex, like @defindex except put all entries in @code. +% +\def\defcodeindex{\parsearg\newcodeindex} +% +\def\newcodeindex#1{% + \iflinks + \expandafter\newwrite \csname#1indfile\endcsname + \openout \csname#1indfile\endcsname \jobname.#1 + \fi + \expandafter\xdef\csname#1index\endcsname{% + \noexpand\docodeindex{#1}}% +} + + +% @synindex foo bar makes index foo feed into index bar. +% Do this instead of @defindex foo if you don't want it as a separate index. +% +% @syncodeindex foo bar similar, but put all entries made for index foo +% inside @code. +% +\def\synindex#1 #2 {\dosynindex\doindex{#1}{#2}} +\def\syncodeindex#1 #2 {\dosynindex\docodeindex{#1}{#2}} + +% #1 is \doindex or \docodeindex, #2 the index getting redefined (foo), +% #3 the target index (bar). +\def\dosynindex#1#2#3{% + % Only do \closeout if we haven't already done it, else we'll end up + % closing the target index. + \expandafter \ifx\csname donesynindex#2\endcsname \undefined + % The \closeout helps reduce unnecessary open files; the limit on the + % Acorn RISC OS is a mere 16 files. + \expandafter\closeout\csname#2indfile\endcsname + \expandafter\let\csname\donesynindex#2\endcsname = 1 + \fi + % redefine \fooindfile: + \expandafter\let\expandafter\temp\expandafter=\csname#3indfile\endcsname + \expandafter\let\csname#2indfile\endcsname=\temp + % redefine \fooindex: + \expandafter\xdef\csname#2index\endcsname{\noexpand#1{#3}}% +} + +% Define \doindex, the driver for all \fooindex macros. +% Argument #1 is generated by the calling \fooindex macro, +% and it is "foo", the name of the index. + +% \doindex just uses \parsearg; it calls \doind for the actual work. +% This is because \doind is more useful to call from other macros. + +% There is also \dosubind {index}{topic}{subtopic} +% which makes an entry in a two-level index such as the operation index. + +\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer} +\def\singleindexer #1{\doind{\indexname}{#1}} + +% like the previous two, but they put @code around the argument. +\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer} +\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}} + +% Take care of Texinfo commands that can appear in an index entry. +% Since there are some commands we want to expand, and others we don't, +% we have to laboriously prevent expansion for those that we don't. +% +\def\indexdummies{% + \def\@{@}% change to @@ when we switch to @ as escape char in index files. + \def\ {\realbackslash\space }% + % Need these in case \tex is in effect and \{ is a \delimiter again. + % But can't use \lbracecmd and \rbracecmd because texindex assumes + % braces and backslashes are used only as delimiters. + \let\{ = \mylbrace + \let\} = \myrbrace + % + % \definedummyword defines \#1 as \realbackslash #1\space, thus + % effectively preventing its expansion. This is used only for control + % words, not control letters, because the \space would be incorrect + % for control characters, but is needed to separate the control word + % from whatever follows. + % + % For control letters, we have \definedummyletter, which omits the + % space. + % + % These can be used both for control words that take an argument and + % those that do not. If it is followed by {arg} in the input, then + % that will dutifully get written to the index (or wherever). + % + \def\definedummyword##1{% + \expandafter\def\csname ##1\endcsname{\realbackslash ##1\space}% + }% + \def\definedummyletter##1{% + \expandafter\def\csname ##1\endcsname{\realbackslash ##1}% + }% + % + % Do the redefinitions. + \commondummies +} + +% For the aux file, @ is the escape character. So we want to redefine +% everything using @ instead of \realbackslash. When everything uses +% @, this will be simpler. +% +\def\atdummies{% + \def\@{@@}% + \def\ {@ }% + \let\{ = \lbraceatcmd + \let\} = \rbraceatcmd + % + % (See comments in \indexdummies.) + \def\definedummyword##1{% + \expandafter\def\csname ##1\endcsname{@##1\space}% + }% + \def\definedummyletter##1{% + \expandafter\def\csname ##1\endcsname{@##1}% + }% + % + % Do the redefinitions. + \commondummies +} + +% Called from \indexdummies and \atdummies. \definedummyword and +% \definedummyletter must be defined first. +% +\def\commondummies{% + % + \normalturnoffactive + % + % Control letters and accents. + \definedummyletter{_}% + \definedummyletter{,}% + \definedummyletter{"}% + \definedummyletter{`}% + \definedummyletter{'}% + \definedummyletter{^}% + \definedummyletter{~}% + \definedummyletter{=}% + \definedummyword{u}% + \definedummyword{v}% + \definedummyword{H}% + \definedummyword{dotaccent}% + \definedummyword{ringaccent}% + \definedummyword{tieaccent}% + \definedummyword{ubaraccent}% + \definedummyword{udotaccent}% + \definedummyword{dotless}% + % + % Other non-English letters. + \definedummyword{AA}% + \definedummyword{AE}% + \definedummyword{L}% + \definedummyword{OE}% + \definedummyword{O}% + \definedummyword{aa}% + \definedummyword{ae}% + \definedummyword{l}% + \definedummyword{oe}% + \definedummyword{o}% + \definedummyword{ss}% + % + % Although these internal commands shouldn't show up, sometimes they do. + \definedummyword{bf}% + \definedummyword{gtr}% + \definedummyword{hat}% + \definedummyword{less}% + \definedummyword{sf}% + \definedummyword{sl}% + \definedummyword{tclose}% + \definedummyword{tt}% + % + % Texinfo font commands. + \definedummyword{b}% + \definedummyword{i}% + \definedummyword{r}% + \definedummyword{sc}% + \definedummyword{t}% + % + \definedummyword{TeX}% + \definedummyword{acronym}% + \definedummyword{cite}% + \definedummyword{code}% + \definedummyword{command}% + \definedummyword{dfn}% + \definedummyword{dots}% + \definedummyword{emph}% + \definedummyword{env}% + \definedummyword{file}% + \definedummyword{kbd}% + \definedummyword{key}% + \definedummyword{math}% + \definedummyword{option}% + \definedummyword{samp}% + \definedummyword{strong}% + \definedummyword{uref}% + \definedummyword{url}% + \definedummyword{var}% + \definedummyword{w}% + % + % Assorted special characters. + \definedummyword{bullet}% + \definedummyword{copyright}% + \definedummyword{dots}% + \definedummyword{enddots}% + \definedummyword{equiv}% + \definedummyword{error}% + \definedummyword{expansion}% + \definedummyword{minus}% + \definedummyword{pounds}% + \definedummyword{point}% + \definedummyword{print}% + \definedummyword{result}% + % + % Handle some cases of @value -- where the variable name does not + % contain - or _, and the value does not contain any + % (non-fully-expandable) commands. + \let\value = \expandablevalue + % + % Normal spaces, not active ones. + \unsepspaces + % + % No macro expansion. + \turnoffmacros +} + +% If an index command is used in an @example environment, any spaces +% therein should become regular spaces in the raw index file, not the +% expansion of \tie (\leavevmode \penalty \@M \ ). +{\obeyspaces + \gdef\unsepspaces{\obeyspaces\let =\space}} + + +% \indexnofonts is used when outputting the strings to sort the index +% by, and when constructing control sequence names. It eliminates all +% control sequences and just writes whatever the best ASCII sort string +% would be for a given command (usually its argument). +% +\def\indexdummytex{TeX} +\def\indexdummydots{...} +% +\def\indexnofonts{% + \def\ { }% + \def\@{@}% + % how to handle braces? + \def\_{\normalunderscore}% + % + \let\,=\asis + \let\"=\asis + \let\`=\asis + \let\'=\asis + \let\^=\asis + \let\~=\asis + \let\==\asis + \let\u=\asis + \let\v=\asis + \let\H=\asis + \let\dotaccent=\asis + \let\ringaccent=\asis + \let\tieaccent=\asis + \let\ubaraccent=\asis + \let\udotaccent=\asis + \let\dotless=\asis + % + % Other non-English letters. + \def\AA{AA}% + \def\AE{AE}% + \def\L{L}% + \def\OE{OE}% + \def\O{O}% + \def\aa{aa}% + \def\ae{ae}% + \def\l{l}% + \def\oe{oe}% + \def\o{o}% + \def\ss{ss}% + \def\exclamdown{!}% + \def\questiondown{?}% + % + % Don't no-op \tt, since it isn't a user-level command + % and is used in the definitions of the active chars like <, >, |, etc. + % Likewise with the other plain tex font commands. + %\let\tt=\asis + % + % Texinfo font commands. + \let\b=\asis + \let\i=\asis + \let\r=\asis + \let\sc=\asis + \let\t=\asis + % + \let\TeX=\indexdummytex + \let\acronym=\asis + \let\cite=\asis + \let\code=\asis + \let\command=\asis + \let\dfn=\asis + \let\dots=\indexdummydots + \let\emph=\asis + \let\env=\asis + \let\file=\asis + \let\kbd=\asis + \let\key=\asis + \let\math=\asis + \let\option=\asis + \let\samp=\asis + \let\strong=\asis + \let\uref=\asis + \let\url=\asis + \let\var=\asis + \let\w=\asis +} + +\let\indexbackslash=0 %overridden during \printindex. +\let\SETmarginindex=\relax % put index entries in margin (undocumented)? + +% For \ifx comparisons. +\def\emptymacro{\empty} + +% Most index entries go through here, but \dosubind is the general case. +% +\def\doind#1#2{\dosubind{#1}{#2}\empty} + +% Workhorse for all \fooindexes. +% #1 is name of index, #2 is stuff to put there, #3 is subentry -- +% \empty if called from \doind, as we usually are. The main exception +% is with defuns, which call us directly. +% +\def\dosubind#1#2#3{% + % Put the index entry in the margin if desired. + \ifx\SETmarginindex\relax\else + \insert\margin{\hbox{\vrule height8pt depth3pt width0pt #2}}% + \fi + {% + \count255=\lastpenalty + {% + \indexdummies % Must do this here, since \bf, etc expand at this stage + \escapechar=`\\ + {% + \let\folio = 0% We will expand all macros now EXCEPT \folio. + \def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now + % so it will be output as is; and it will print as backslash. + % + % The main index entry text. + \toks0 = {#2}% + % + % If third arg is present, precede it with space in sort key. + \def\thirdarg{#3}% + \ifx\thirdarg\emptymacro \else + % If the third (subentry) arg is present, add it to the index + % line to write. + \toks0 = \expandafter{\the\toks0 \space #3}% + \fi + % + % Process the index entry with all font commands turned off, to + % get the string to sort by. + {\indexnofonts + \edef\temp{\the\toks0}% need full expansion + \xdef\indexsorttmp{\temp}% + }% + % + % Set up the complete index entry, with both the sort key and + % the original text, including any font commands. We write + % three arguments to \entry to the .?? file (four in the + % subentry case), texindex reduces to two when writing the .??s + % sorted result. + \edef\temp{% + \write\csname#1indfile\endcsname{% + \realbackslash entry{\indexsorttmp}{\folio}{\the\toks0}}% + }% + % + % If a skip is the last thing on the list now, preserve it + % by backing up by \lastskip, doing the \write, then inserting + % the skip again. Otherwise, the whatsit generated by the + % \write will make \lastskip zero. The result is that sequences + % like this: + % @end defun + % @tindex whatever + % @defun ... + % will have extra space inserted, because the \medbreak in the + % start of the @defun won't see the skip inserted by the @end of + % the previous defun. + % + % But don't do any of this if we're not in vertical mode. We + % don't want to do a \vskip and prematurely end a paragraph. + % + % Avoid page breaks due to these extra skips, too. + % + \iflinks + \ifvmode + \skip0 = \lastskip + \ifdim\lastskip = 0pt \else \nobreak\vskip-\skip0 \fi + \fi + % + \temp % do the write + % + \ifvmode \ifdim\skip0 = 0pt \else \nobreak\vskip\skip0 \fi \fi + \fi + }% + }% + \penalty\count255 + }% +} + +% The index entry written in the file actually looks like +% \entry {sortstring}{page}{topic} +% or +% \entry {sortstring}{page}{topic}{subtopic} +% The texindex program reads in these files and writes files +% containing these kinds of lines: +% \initial {c} +% before the first topic whose initial is c +% \entry {topic}{pagelist} +% for a topic that is used without subtopics +% \primary {topic} +% for the beginning of a topic that is used with subtopics +% \secondary {subtopic}{pagelist} +% for each subtopic. + +% Define the user-accessible indexing commands +% @findex, @vindex, @kindex, @cindex. + +\def\findex {\fnindex} +\def\kindex {\kyindex} +\def\cindex {\cpindex} +\def\vindex {\vrindex} +\def\tindex {\tpindex} +\def\pindex {\pgindex} + +\def\cindexsub {\begingroup\obeylines\cindexsub} +{\obeylines % +\gdef\cindexsub "#1" #2^^M{\endgroup % +\dosubind{cp}{#2}{#1}}} + +% Define the macros used in formatting output of the sorted index material. + +% @printindex causes a particular index (the ??s file) to get printed. +% It does not print any chapter heading (usually an @unnumbered). +% +\def\printindex{\parsearg\doprintindex} +\def\doprintindex#1{\begingroup + \dobreak \chapheadingskip{10000}% + % + \smallfonts \rm + \tolerance = 9500 + \everypar = {}% don't want the \kern\-parindent from indentation suppression. + \indexbreaks + % + % See if the index file exists and is nonempty. + % Change catcode of @ here so that if the index file contains + % \initial {@} + % as its first line, TeX doesn't complain about mismatched braces + % (because it thinks @} is a control sequence). + \catcode`\@ = 11 + \openin 1 \jobname.#1s + \ifeof 1 + % \enddoublecolumns gets confused if there is no text in the index, + % and it loses the chapter title and the aux file entries for the + % index. The easiest way to prevent this problem is to make sure + % there is some text. + \putwordIndexNonexistent + \else + % + % If the index file exists but is empty, then \openin leaves \ifeof + % false. We have to make TeX try to read something from the file, so + % it can discover if there is anything in it. + \read 1 to \temp + \ifeof 1 + \putwordIndexIsEmpty + \else + % Index files are almost Texinfo source, but we use \ as the escape + % character. It would be better to use @, but that's too big a change + % to make right now. + \def\indexbackslash{\rawbackslashxx}% + \catcode`\\ = 0 + \escapechar = `\\ + \begindoublecolumns + \input \jobname.#1s + \enddoublecolumns + \fi + \fi + \closein 1 +\endgroup} + +% These macros are used by the sorted index file itself. +% Change them to control the appearance of the index. + +\def\initial#1{{% + % Some minor font changes for the special characters. + \let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt + % + % Remove any glue we may have, we'll be inserting our own. + \removelastskip + % + % We like breaks before the index initials, so insert a bonus. + \penalty -300 + % + % Typeset the initial. Making this add up to a whole number of + % baselineskips increases the chance of the dots lining up from column + % to column. It still won't often be perfect, because of the stretch + % we need before each entry, but it's better. + % + % No shrink because it confuses \balancecolumns. + \vskip 1.67\baselineskip plus .5\baselineskip + \leftline{\secbf #1}% + \vskip .33\baselineskip plus .1\baselineskip + % + % Do our best not to break after the initial. + \nobreak +}} + +% This typesets a paragraph consisting of #1, dot leaders, and then #2 +% flush to the right margin. It is used for index and table of contents +% entries. The paragraph is indented by \leftskip. +% +\def\entry#1#2{\begingroup + % + % Start a new paragraph if necessary, so our assignments below can't + % affect previous text. + \par + % + % Do not fill out the last line with white space. + \parfillskip = 0in + % + % No extra space above this paragraph. + \parskip = 0in + % + % Do not prefer a separate line ending with a hyphen to fewer lines. + \finalhyphendemerits = 0 + % + % \hangindent is only relevant when the entry text and page number + % don't both fit on one line. In that case, bob suggests starting the + % dots pretty far over on the line. Unfortunately, a large + % indentation looks wrong when the entry text itself is broken across + % lines. So we use a small indentation and put up with long leaders. + % + % \hangafter is reset to 1 (which is the value we want) at the start + % of each paragraph, so we need not do anything with that. + \hangindent = 2em + % + % When the entry text needs to be broken, just fill out the first line + % with blank space. + \rightskip = 0pt plus1fil + % + % A bit of stretch before each entry for the benefit of balancing columns. + \vskip 0pt plus1pt + % + % Start a ``paragraph'' for the index entry so the line breaking + % parameters we've set above will have an effect. + \noindent + % + % Insert the text of the index entry. TeX will do line-breaking on it. + #1% + % The following is kludged to not output a line of dots in the index if + % there are no page numbers. The next person who breaks this will be + % cursed by a Unix daemon. + \def\tempa{{\rm }}% + \def\tempb{#2}% + \edef\tempc{\tempa}% + \edef\tempd{\tempb}% + \ifx\tempc\tempd\ \else% + % + % If we must, put the page number on a line of its own, and fill out + % this line with blank space. (The \hfil is overwhelmed with the + % fill leaders glue in \indexdotfill if the page number does fit.) + \hfil\penalty50 + \null\nobreak\indexdotfill % Have leaders before the page number. + % + % The `\ ' here is removed by the implicit \unskip that TeX does as + % part of (the primitive) \par. Without it, a spurious underfull + % \hbox ensues. + \ifpdf + \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph. + \else + \ #2% The page number ends the paragraph. + \fi + \fi% + \par +\endgroup} + +% Like \dotfill except takes at least 1 em. +\def\indexdotfill{\cleaders + \hbox{$\mathsurround=0pt \mkern1.5mu ${\it .}$ \mkern1.5mu$}\hskip 1em plus 1fill} + +\def\primary #1{\line{#1\hfil}} + +\newskip\secondaryindent \secondaryindent=0.5cm +\def\secondary#1#2{{% + \parfillskip=0in + \parskip=0in + \hangindent=1in + \hangafter=1 + \noindent\hskip\secondaryindent\hbox{#1}\indexdotfill + \ifpdf + \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph. + \else + #2 + \fi + \par +}} + +% Define two-column mode, which we use to typeset indexes. +% Adapted from the TeXbook, page 416, which is to say, +% the manmac.tex format used to print the TeXbook itself. +\catcode`\@=11 + +\newbox\partialpage +\newdimen\doublecolumnhsize + +\def\begindoublecolumns{\begingroup % ended by \enddoublecolumns + % Grab any single-column material above us. + \output = {% + % + % Here is a possibility not foreseen in manmac: if we accumulate a + % whole lot of material, we might end up calling this \output + % routine twice in a row (see the doublecol-lose test, which is + % essentially a couple of indexes with @setchapternewpage off). In + % that case we just ship out what is in \partialpage with the normal + % output routine. Generally, \partialpage will be empty when this + % runs and this will be a no-op. See the indexspread.tex test case. + \ifvoid\partialpage \else + \onepageout{\pagecontents\partialpage}% + \fi + % + \global\setbox\partialpage = \vbox{% + % Unvbox the main output page. + \unvbox\PAGE + \kern-\topskip \kern\baselineskip + }% + }% + \eject % run that output routine to set \partialpage + % + % Use the double-column output routine for subsequent pages. + \output = {\doublecolumnout}% + % + % Change the page size parameters. We could do this once outside this + % routine, in each of @smallbook, @afourpaper, and the default 8.5x11 + % format, but then we repeat the same computation. Repeating a couple + % of assignments once per index is clearly meaningless for the + % execution time, so we may as well do it in one place. + % + % First we halve the line length, less a little for the gutter between + % the columns. We compute the gutter based on the line length, so it + % changes automatically with the paper format. The magic constant + % below is chosen so that the gutter has the same value (well, +-<1pt) + % as it did when we hard-coded it. + % + % We put the result in a separate register, \doublecolumhsize, so we + % can restore it in \pagesofar, after \hsize itself has (potentially) + % been clobbered. + % + \doublecolumnhsize = \hsize + \advance\doublecolumnhsize by -.04154\hsize + \divide\doublecolumnhsize by 2 + \hsize = \doublecolumnhsize + % + % Double the \vsize as well. (We don't need a separate register here, + % since nobody clobbers \vsize.) + \vsize = 2\vsize +} + +% The double-column output routine for all double-column pages except +% the last. +% +\def\doublecolumnout{% + \splittopskip=\topskip \splitmaxdepth=\maxdepth + % Get the available space for the double columns -- the normal + % (undoubled) page height minus any material left over from the + % previous page. + \dimen@ = \vsize + \divide\dimen@ by 2 + \advance\dimen@ by -\ht\partialpage + % + % box0 will be the left-hand column, box2 the right. + \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@ + \onepageout\pagesofar + \unvbox255 + \penalty\outputpenalty +} +% +% Re-output the contents of the output page -- any previous material, +% followed by the two boxes we just split, in box0 and box2. +\def\pagesofar{% + \unvbox\partialpage + % + \hsize = \doublecolumnhsize + \wd0=\hsize \wd2=\hsize + \hbox to\pagewidth{\box0\hfil\box2}% +} +% +% All done with double columns. +\def\enddoublecolumns{% + \output = {% + % Split the last of the double-column material. Leave it on the + % current page, no automatic page break. + \balancecolumns + % + % If we end up splitting too much material for the current page, + % though, there will be another page break right after this \output + % invocation ends. Having called \balancecolumns once, we do not + % want to call it again. Therefore, reset \output to its normal + % definition right away. (We hope \balancecolumns will never be + % called on to balance too much material, but if it is, this makes + % the output somewhat more palatable.) + \global\output = {\onepageout{\pagecontents\PAGE}}% + }% + \eject + \endgroup % started in \begindoublecolumns + % + % \pagegoal was set to the doubled \vsize above, since we restarted + % the current page. We're now back to normal single-column + % typesetting, so reset \pagegoal to the normal \vsize (after the + % \endgroup where \vsize got restored). + \pagegoal = \vsize +} +% +% Called at the end of the double column material. +\def\balancecolumns{% + \setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120. + \dimen@ = \ht0 + \advance\dimen@ by \topskip + \advance\dimen@ by-\baselineskip + \divide\dimen@ by 2 % target to split to + %debug\message{final 2-column material height=\the\ht0, target=\the\dimen@.}% + \splittopskip = \topskip + % Loop until we get a decent breakpoint. + {% + \vbadness = 10000 + \loop + \global\setbox3 = \copy0 + \global\setbox1 = \vsplit3 to \dimen@ + \ifdim\ht3>\dimen@ + \global\advance\dimen@ by 1pt + \repeat + }% + %debug\message{split to \the\dimen@, column heights: \the\ht1, \the\ht3.}% + \setbox0=\vbox to\dimen@{\unvbox1}% + \setbox2=\vbox to\dimen@{\unvbox3}% + % + \pagesofar +} +\catcode`\@ = \other + + +\message{sectioning,} +% Chapters, sections, etc. + +\newcount\chapno +\newcount\secno \secno=0 +\newcount\subsecno \subsecno=0 +\newcount\subsubsecno \subsubsecno=0 + +% This counter is funny since it counts through charcodes of letters A, B, ... +\newcount\appendixno \appendixno = `\@ +% \def\appendixletter{\char\the\appendixno} +% We do the following for the sake of pdftex, which needs the actual +% letter in the expansion, not just typeset. +\def\appendixletter{% + \ifnum\appendixno=`A A% + \else\ifnum\appendixno=`B B% + \else\ifnum\appendixno=`C C% + \else\ifnum\appendixno=`D D% + \else\ifnum\appendixno=`E E% + \else\ifnum\appendixno=`F F% + \else\ifnum\appendixno=`G G% + \else\ifnum\appendixno=`H H% + \else\ifnum\appendixno=`I I% + \else\ifnum\appendixno=`J J% + \else\ifnum\appendixno=`K K% + \else\ifnum\appendixno=`L L% + \else\ifnum\appendixno=`M M% + \else\ifnum\appendixno=`N N% + \else\ifnum\appendixno=`O O% + \else\ifnum\appendixno=`P P% + \else\ifnum\appendixno=`Q Q% + \else\ifnum\appendixno=`R R% + \else\ifnum\appendixno=`S S% + \else\ifnum\appendixno=`T T% + \else\ifnum\appendixno=`U U% + \else\ifnum\appendixno=`V V% + \else\ifnum\appendixno=`W W% + \else\ifnum\appendixno=`X X% + \else\ifnum\appendixno=`Y Y% + \else\ifnum\appendixno=`Z Z% + % The \the is necessary, despite appearances, because \appendixletter is + % expanded while writing the .toc file. \char\appendixno is not + % expandable, thus it is written literally, thus all appendixes come out + % with the same letter (or @) in the toc without it. + \else\char\the\appendixno + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi} + +% Each @chapter defines this as the name of the chapter. +% page headings and footings can use it. @section does likewise. +\def\thischapter{} +\def\thissection{} + +\newcount\absseclevel % used to calculate proper heading level +\newcount\secbase\secbase=0 % @raise/lowersections modify this count + +% @raisesections: treat @section as chapter, @subsection as section, etc. +\def\raisesections{\global\advance\secbase by -1} +\let\up=\raisesections % original BFox name + +% @lowersections: treat @chapter as section, @section as subsection, etc. +\def\lowersections{\global\advance\secbase by 1} +\let\down=\lowersections % original BFox name + +% Choose a numbered-heading macro +% #1 is heading level if unmodified by @raisesections or @lowersections +% #2 is text for heading +\def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \chapterzzz{#2} +\or + \seczzz{#2} +\or + \numberedsubseczzz{#2} +\or + \numberedsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \chapterzzz{#2} + \else + \numberedsubsubseczzz{#2} + \fi +\fi +\suppressfirstparagraphindent +} + +% like \numhead, but chooses appendix heading levels +\def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \appendixzzz{#2} +\or + \appendixsectionzzz{#2} +\or + \appendixsubseczzz{#2} +\or + \appendixsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \appendixzzz{#2} + \else + \appendixsubsubseczzz{#2} + \fi +\fi +\suppressfirstparagraphindent +} + +% like \numhead, but chooses numberless heading levels +\def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \unnumberedzzz{#2} +\or + \unnumberedseczzz{#2} +\or + \unnumberedsubseczzz{#2} +\or + \unnumberedsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \unnumberedzzz{#2} + \else + \unnumberedsubsubseczzz{#2} + \fi +\fi +\suppressfirstparagraphindent +} + +% @chapter, @appendix, @unnumbered. +\def\thischaptername{No Chapter Title} +\outer\def\chapter{\parsearg\chapteryyy} +\def\chapteryyy #1{\numhead0{#1}} % normally numhead0 calls chapterzzz +\def\chapterzzz #1{% + \secno=0 \subsecno=0 \subsubsecno=0 + \global\advance \chapno by 1 \message{\putwordChapter\space \the\chapno}% + \chapmacro {#1}{\the\chapno}% + \gdef\thissection{#1}% + \gdef\thischaptername{#1}% + % We don't substitute the actual chapter name into \thischapter + % because we don't want its macros evaluated now. + \xdef\thischapter{\putwordChapter{} \the\chapno: \noexpand\thischaptername}% + \writetocentry{chap}{#1}{{\the\chapno}} + \donoderef + \global\let\section = \numberedsec + \global\let\subsection = \numberedsubsec + \global\let\subsubsection = \numberedsubsubsec +} + +% we use \chapno to avoid indenting back +\def\appendixbox#1{% + \setbox0 = \hbox{\putwordAppendix{} \the\chapno}% + \hbox to \wd0{#1\hss}} + +\outer\def\appendix{\parsearg\appendixyyy} +\def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz +\def\appendixzzz #1{% + \secno=0 \subsecno=0 \subsubsecno=0 + \global\advance \appendixno by 1 + \message{\putwordAppendix\space \appendixletter}% + \chapmacro {#1}{\appendixbox{\putwordAppendix{} \appendixletter}}% + \gdef\thissection{#1}% + \gdef\thischaptername{#1}% + \xdef\thischapter{\putwordAppendix{} \appendixletter: \noexpand\thischaptername}% + \writetocentry{appendix}{#1}{{\appendixletter}} + \appendixnoderef + \global\let\section = \appendixsec + \global\let\subsection = \appendixsubsec + \global\let\subsubsection = \appendixsubsubsec +} + +% @centerchap is like @unnumbered, but the heading is centered. +\outer\def\centerchap{\parsearg\centerchapyyy} +\def\centerchapyyy #1{{\let\unnumbchapmacro=\centerchapmacro \unnumberedyyy{#1}}} + +% @top is like @unnumbered. +\outer\def\top{\parsearg\unnumberedyyy} + +\outer\def\unnumbered{\parsearg\unnumberedyyy} +\def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz +\def\unnumberedzzz #1{% + \secno=0 \subsecno=0 \subsubsecno=0 + % + % This used to be simply \message{#1}, but TeX fully expands the + % argument to \message. Therefore, if #1 contained @-commands, TeX + % expanded them. For example, in `@unnumbered The @cite{Book}', TeX + % expanded @cite (which turns out to cause errors because \cite is meant + % to be executed, not expanded). + % + % Anyway, we don't want the fully-expanded definition of @cite to appear + % as a result of the \message, we just want `@cite' itself. We use + % \the to achieve this: TeX expands \the only once, + % simply yielding the contents of . (We also do this for + % the toc entries.) + \toks0 = {#1}\message{(\the\toks0)}% + % + \unnumbchapmacro {#1}% + \gdef\thischapter{#1}\gdef\thissection{#1}% + \writetocentry{unnumbchap}{#1}{{\the\chapno}} + \unnumbnoderef + \global\let\section = \unnumberedsec + \global\let\subsection = \unnumberedsubsec + \global\let\subsubsection = \unnumberedsubsubsec +} + +% Sections. +\outer\def\numberedsec{\parsearg\secyyy} +\def\secyyy #1{\numhead1{#1}} % normally calls seczzz +\def\seczzz #1{% + \subsecno=0 \subsubsecno=0 \global\advance \secno by 1 % + \gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}% + \writetocentry{sec}{#1}{{\the\chapno}{\the\secno}} + \donoderef + \nobreak +} + +\outer\def\appendixsection{\parsearg\appendixsecyyy} +\outer\def\appendixsec{\parsearg\appendixsecyyy} +\def\appendixsecyyy #1{\apphead1{#1}} % normally calls appendixsectionzzz +\def\appendixsectionzzz #1{% + \subsecno=0 \subsubsecno=0 \global\advance \secno by 1 % + \gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}% + \writetocentry{sec}{#1}{{\appendixletter}{\the\secno}} + \appendixnoderef + \nobreak +} + +\outer\def\unnumberedsec{\parsearg\unnumberedsecyyy} +\def\unnumberedsecyyy #1{\unnmhead1{#1}} % normally calls unnumberedseczzz +\def\unnumberedseczzz #1{% + \plainsecheading {#1}\gdef\thissection{#1}% + \writetocentry{unnumbsec}{#1}{{\the\chapno}{\the\secno}} + \unnumbnoderef + \nobreak +} + +% Subsections. +\outer\def\numberedsubsec{\parsearg\numberedsubsecyyy} +\def\numberedsubsecyyy #1{\numhead2{#1}} % normally calls numberedsubseczzz +\def\numberedsubseczzz #1{% + \gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 % + \subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}% + \writetocentry{subsec}{#1}{{\the\chapno}{\the\secno}{\the\subsecno}} + \donoderef + \nobreak +} + +\outer\def\appendixsubsec{\parsearg\appendixsubsecyyy} +\def\appendixsubsecyyy #1{\apphead2{#1}} % normally calls appendixsubseczzz +\def\appendixsubseczzz #1{% + \gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 % + \subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}% + \writetocentry{subsec}{#1}{{\appendixletter}{\the\secno}{\the\subsecno}} + \appendixnoderef + \nobreak +} + +\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy} +\def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz +\def\unnumberedsubseczzz #1{% + \plainsubsecheading {#1}\gdef\thissection{#1}% + \writetocentry{unnumbsubsec}{#1}{{\the\chapno}{\the\secno}{\the\subsecno}} + \unnumbnoderef + \nobreak +} + +% Subsubsections. +\outer\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy} +\def\numberedsubsubsecyyy #1{\numhead3{#1}} % normally numberedsubsubseczzz +\def\numberedsubsubseczzz #1{% + \gdef\thissection{#1}\global\advance \subsubsecno by 1 % + \subsubsecheading {#1} + {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}% + \writetocentry{subsubsec}{#1}{{\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}} + \donoderef + \nobreak +} + +\outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy} +\def\appendixsubsubsecyyy #1{\apphead3{#1}} % normally appendixsubsubseczzz +\def\appendixsubsubseczzz #1{% + \gdef\thissection{#1}\global\advance \subsubsecno by 1 % + \subsubsecheading {#1} + {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}% + \writetocentry{subsubsec}{#1}{{\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}} + \appendixnoderef + \nobreak +} + +\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy} +\def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz +\def\unnumberedsubsubseczzz #1{% + \plainsubsubsecheading {#1}\gdef\thissection{#1}% + \writetocentry{unnumbsubsubsec}{#1}{{\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}} + \unnumbnoderef + \nobreak +} + +% These are variants which are not "outer", so they can appear in @ifinfo. +% Actually, they should now be obsolete; ordinary section commands should work. +\def\infotop{\parsearg\unnumberedzzz} +\def\infounnumbered{\parsearg\unnumberedzzz} +\def\infounnumberedsec{\parsearg\unnumberedseczzz} +\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz} +\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz} + +\def\infoappendix{\parsearg\appendixzzz} +\def\infoappendixsec{\parsearg\appendixseczzz} +\def\infoappendixsubsec{\parsearg\appendixsubseczzz} +\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz} + +\def\infochapter{\parsearg\chapterzzz} +\def\infosection{\parsearg\sectionzzz} +\def\infosubsection{\parsearg\subsectionzzz} +\def\infosubsubsection{\parsearg\subsubsectionzzz} + +% These macros control what the section commands do, according +% to what kind of chapter we are in (ordinary, appendix, or unnumbered). +% Define them by default for a numbered chapter. +\global\let\section = \numberedsec +\global\let\subsection = \numberedsubsec +\global\let\subsubsection = \numberedsubsubsec + +% Define @majorheading, @heading and @subheading + +% NOTE on use of \vbox for chapter headings, section headings, and such: +% 1) We use \vbox rather than the earlier \line to permit +% overlong headings to fold. +% 2) \hyphenpenalty is set to 10000 because hyphenation in a +% heading is obnoxious; this forbids it. +% 3) Likewise, headings look best if no \parindent is used, and +% if justification is not attempted. Hence \raggedright. + + +\def\majorheading{\parsearg\majorheadingzzz} +\def\majorheadingzzz #1{% + {\advance\chapheadingskip by 10pt \chapbreak }% + {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 200} + +\def\chapheading{\parsearg\chapheadingzzz} +\def\chapheadingzzz #1{\chapbreak % + {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 200} + +% @heading, @subheading, @subsubheading. +\def\heading{\parsearg\plainsecheading} +\def\subheading{\parsearg\plainsubsecheading} +\def\subsubheading{\parsearg\plainsubsubsecheading} + +% These macros generate a chapter, section, etc. heading only +% (including whitespace, linebreaking, etc. around it), +% given all the information in convenient, parsed form. + +%%% Args are the skip and penalty (usually negative) +\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi} + +\def\setchapterstyle #1 {\csname CHAPF#1\endcsname} + +%%% Define plain chapter starts, and page on/off switching for it +% Parameter controlling skip before chapter headings (if needed) + +\newskip\chapheadingskip + +\def\chapbreak{\dobreak \chapheadingskip {-4000}} +\def\chappager{\par\vfill\supereject} +\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi} + +\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname} + +\def\CHAPPAGoff{% +\global\let\contentsalignmacro = \chappager +\global\let\pchapsepmacro=\chapbreak +\global\let\pagealignmacro=\chappager} + +\def\CHAPPAGon{% +\global\let\contentsalignmacro = \chappager +\global\let\pchapsepmacro=\chappager +\global\let\pagealignmacro=\chappager +\global\def\HEADINGSon{\HEADINGSsingle}} + +\def\CHAPPAGodd{ +\global\let\contentsalignmacro = \chapoddpage +\global\let\pchapsepmacro=\chapoddpage +\global\let\pagealignmacro=\chapoddpage +\global\def\HEADINGSon{\HEADINGSdouble}} + +\CHAPPAGon + +\def\CHAPFplain{ +\global\let\chapmacro=\chfplain +\global\let\unnumbchapmacro=\unnchfplain +\global\let\centerchapmacro=\centerchfplain} + +% Plain chapter opening. +% #1 is the text, #2 the chapter number or empty if unnumbered. +\def\chfplain#1#2{% + \pchapsepmacro + {% + \chapfonts \rm + \def\chapnum{#2}% + \setbox0 = \hbox{#2\ifx\chapnum\empty\else\enspace\fi}% + \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright + \hangindent = \wd0 \centerparametersmaybe + \unhbox0 #1\par}% + }% + \nobreak\bigskip % no page break after a chapter title + \nobreak +} + +% Plain opening for unnumbered. +\def\unnchfplain#1{\chfplain{#1}{}} + +% @centerchap -- centered and unnumbered. +\let\centerparametersmaybe = \relax +\def\centerchfplain#1{{% + \def\centerparametersmaybe{% + \advance\rightskip by 3\rightskip + \leftskip = \rightskip + \parfillskip = 0pt + }% + \chfplain{#1}{}% +}} + +\CHAPFplain % The default + +\def\unnchfopen #1{% +\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\nobreak +} + +\def\chfopen #1#2{\chapoddpage {\chapfonts +\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}% +\par\penalty 5000 % +} + +\def\centerchfopen #1{% +\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt + \hfill {\rm #1}\hfill}}\bigskip \par\nobreak +} + +\def\CHAPFopen{ +\global\let\chapmacro=\chfopen +\global\let\unnumbchapmacro=\unnchfopen +\global\let\centerchapmacro=\centerchfopen} + + +% Section titles. +\newskip\secheadingskip +\def\secheadingbreak{\dobreak \secheadingskip {-1000}} +\def\secheading#1#2#3{\sectionheading{sec}{#2.#3}{#1}} +\def\plainsecheading#1{\sectionheading{sec}{}{#1}} + +% Subsection titles. +\newskip \subsecheadingskip +\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}} +\def\subsecheading#1#2#3#4{\sectionheading{subsec}{#2.#3.#4}{#1}} +\def\plainsubsecheading#1{\sectionheading{subsec}{}{#1}} + +% Subsubsection titles. +\let\subsubsecheadingskip = \subsecheadingskip +\let\subsubsecheadingbreak = \subsecheadingbreak +\def\subsubsecheading#1#2#3#4#5{\sectionheading{subsubsec}{#2.#3.#4.#5}{#1}} +\def\plainsubsubsecheading#1{\sectionheading{subsubsec}{}{#1}} + + +% Print any size section title. +% +% #1 is the section type (sec/subsec/subsubsec), #2 is the section +% number (maybe empty), #3 the text. +\def\sectionheading#1#2#3{% + {% + \expandafter\advance\csname #1headingskip\endcsname by \parskip + \csname #1headingbreak\endcsname + }% + {% + % Switch to the right set of fonts. + \csname #1fonts\endcsname \rm + % + % Only insert the separating space if we have a section number. + \def\secnum{#2}% + \setbox0 = \hbox{#2\ifx\secnum\empty\else\enspace\fi}% + % + \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright + \hangindent = \wd0 % zero if no section number + \unhbox0 #3}% + }% + % Add extra space after the heading -- either a line space or a + % paragraph space, whichever is more. (Some people like to set + % \parskip to large values for some reason.) Don't allow stretch, though. + \nobreak + \ifdim\parskip>\normalbaselineskip + \kern\parskip + \else + \kern\normalbaselineskip + \fi + \nobreak +} + + +\message{toc,} +% Table of contents. +\newwrite\tocfile + +% Write an entry to the toc file, opening it if necessary. +% Called from @chapter, etc. We supply {\folio} at the end of the +% argument, which will end up as the last argument to the \...entry macro. +% +% Usage: \writetocentry{chap}{The Name of The Game}{{\the\chapno}} +% We open the .toc file for writing here instead of at @setfilename (or +% any other fixed time) so that @contents can be anywhere in the document. +% +\newif\iftocfileopened +\def\writetocentry#1#2#3{% + \iftocfileopened\else + \immediate\openout\tocfile = \jobname.toc + \global\tocfileopenedtrue + \fi + % + \iflinks + \toks0 = {#2}% + \edef\temp{\write\tocfile{\realbackslash #1entry{\the\toks0}#3{\folio}}}% + \temp + \fi + % + % Tell \shipout to create a page destination if we're doing pdf, which + % will be the target of the links in the table of contents. We can't + % just do it on every page because the title pages are numbered 1 and + % 2 (the page numbers aren't printed), and so are the first two pages + % of the document. Thus, we'd have two destinations named `1', and + % two named `2'. + \ifpdf \pdfmakepagedesttrue \fi +} + +\newskip\contentsrightmargin \contentsrightmargin=1in +\newcount\savepageno +\newcount\lastnegativepageno \lastnegativepageno = -1 + +% Finish up the main text and prepare to read what we've written +% to \tocfile. +% +\def\startcontents#1{% + % If @setchapternewpage on, and @headings double, the contents should + % start on an odd page, unlike chapters. Thus, we maintain + % \contentsalignmacro in parallel with \pagealignmacro. + % From: Torbjorn Granlund + \contentsalignmacro + \immediate\closeout\tocfile + % + % Don't need to put `Contents' or `Short Contents' in the headline. + % It is abundantly clear what they are. + \unnumbchapmacro{#1}\def\thischapter{}% + \savepageno = \pageno + \begingroup % Set up to handle contents files properly. + \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11 + % We can't do this, because then an actual ^ in a section + % title fails, e.g., @chapter ^ -- exponentiation. --karl, 9jul97. + %\catcode`\^=7 % to see ^^e4 as \"a etc. juha@piuha.ydi.vtt.fi + \raggedbottom % Worry more about breakpoints than the bottom. + \advance\hsize by -\contentsrightmargin % Don't use the full line length. + % + % Roman numerals for page numbers. + \ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi +} + + +% Normal (long) toc. +\def\contents{% + \startcontents{\putwordTOC}% + \openin 1 \jobname.toc + \ifeof 1 \else + \closein 1 + \input \jobname.toc + \fi + \vfill \eject + \contentsalignmacro % in case @setchapternewpage odd is in effect + \pdfmakeoutlines + \endgroup + \lastnegativepageno = \pageno + \global\pageno = \savepageno +} + +% And just the chapters. +\def\summarycontents{% + \startcontents{\putwordShortTOC}% + % + \let\chapentry = \shortchapentry + \let\appendixentry = \shortappendixentry + \let\unnumbchapentry = \shortunnumberedentry + % We want a true roman here for the page numbers. + \secfonts + \let\rm=\shortcontrm \let\bf=\shortcontbf + \let\sl=\shortcontsl \let\tt=\shortconttt + \rm + \hyphenpenalty = 10000 + \advance\baselineskip by 1pt % Open it up a little. + \def\secentry ##1##2##3##4{} + \def\subsecentry ##1##2##3##4##5{} + \def\subsubsecentry ##1##2##3##4##5##6{} + \let\unnumbsecentry = \secentry + \let\unnumbsubsecentry = \subsecentry + \let\unnumbsubsubsecentry = \subsubsecentry + \openin 1 \jobname.toc + \ifeof 1 \else + \closein 1 + \input \jobname.toc + \fi + \vfill \eject + \contentsalignmacro % in case @setchapternewpage odd is in effect + \endgroup + \lastnegativepageno = \pageno + \global\pageno = \savepageno +} +\let\shortcontents = \summarycontents + +\ifpdf + \pdfcatalog{/PageMode /UseOutlines}% +\fi + +% These macros generate individual entries in the table of contents. +% The first argument is the chapter or section name. +% The last argument is the page number. +% The arguments in between are the chapter number, section number, ... + +% Chapters, in the main contents. +\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}} +% +% Chapters, in the short toc. +% See comments in \dochapentry re vbox and related settings. +\def\shortchapentry#1#2#3{% + \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno\bgroup#3\egroup}% +} + +% Appendices, in the main contents. +\def\appendixentry#1#2#3{% + \dochapentry{\appendixbox{\putwordAppendix{} #2}\labelspace#1}{#3}} +% +% Appendices, in the short toc. +\let\shortappendixentry = \shortchapentry + +% Typeset the label for a chapter or appendix for the short contents. +% The arg is, e.g., `Appendix A' for an appendix, or `3' for a chapter. +% We could simplify the code here by writing out an \appendixentry +% command in the toc file for appendices, instead of using \chapentry +% for both, but it doesn't seem worth it. +% +\newdimen\shortappendixwidth +% +\def\shortchaplabel#1{% + % This space should be enough, since a single number is .5em, and the + % widest letter (M) is 1em, at least in the Computer Modern fonts. + % But use \hss just in case. + % (This space doesn't include the extra space that gets added after + % the label; that gets put in by \shortchapentry above.) + \dimen0 = 1em + \hbox to \dimen0{#1\hss}% +} + +% Unnumbered chapters. +\def\unnumbchapentry#1#2#3{\dochapentry{#1}{#3}} +\def\shortunnumberedentry#1#2#3{\tocentry{#1}{\doshortpageno\bgroup#3\egroup}} + +% Sections. +\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}} +\def\unnumbsecentry#1#2#3#4{\dosecentry{#1}{#4}} + +% Subsections. +\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}} +\def\unnumbsubsecentry#1#2#3#4#5{\dosubsecentry{#1}{#5}} + +% And subsubsections. +\def\subsubsecentry#1#2#3#4#5#6{% + \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}} +\def\unnumbsubsubsecentry#1#2#3#4#5#6{\dosubsubsecentry{#1}{#6}} + +% This parameter controls the indentation of the various levels. +\newdimen\tocindent \tocindent = 3pc + +% Now for the actual typesetting. In all these, #1 is the text and #2 is the +% page number. +% +% If the toc has to be broken over pages, we want it to be at chapters +% if at all possible; hence the \penalty. +\def\dochapentry#1#2{% + \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip + \begingroup + \chapentryfonts + \tocentry{#1}{\dopageno\bgroup#2\egroup}% + \endgroup + \nobreak\vskip .25\baselineskip plus.1\baselineskip +} + +\def\dosecentry#1#2{\begingroup + \secentryfonts \leftskip=\tocindent + \tocentry{#1}{\dopageno\bgroup#2\egroup}% +\endgroup} + +\def\dosubsecentry#1#2{\begingroup + \subsecentryfonts \leftskip=2\tocindent + \tocentry{#1}{\dopageno\bgroup#2\egroup}% +\endgroup} + +\def\dosubsubsecentry#1#2{\begingroup + \subsubsecentryfonts \leftskip=3\tocindent + \tocentry{#1}{\dopageno\bgroup#2\egroup}% +\endgroup} + +% Final typesetting of a toc entry; we use the same \entry macro as for +% the index entries, but we want to suppress hyphenation here. (We +% can't do that in the \entry macro, since index entries might consist +% of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.) +\def\tocentry#1#2{\begingroup + \vskip 0pt plus1pt % allow a little stretch for the sake of nice page breaks + % Do not use \turnoffactive in these arguments. Since the toc is + % typeset in cmr, characters such as _ would come out wrong; we + % have to do the usual translation tricks. + \entry{#1}{#2}% +\endgroup} + +% Space between chapter (or whatever) number and the title. +\def\labelspace{\hskip1em \relax} + +\def\dopageno#1{{\rm #1}} +\def\doshortpageno#1{{\rm #1}} + +\def\chapentryfonts{\secfonts \rm} +\def\secentryfonts{\textfonts} +\let\subsecentryfonts = \textfonts +\let\subsubsecentryfonts = \textfonts + + +\message{environments,} +% @foo ... @end foo. + +% @point{}, @result{}, @expansion{}, @print{}, @equiv{}. +% +% Since these characters are used in examples, it should be an even number of +% \tt widths. Each \tt character is 1en, so two makes it 1em. +% +\def\point{$\star$} +\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}} +\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}} +\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}} +\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}} + +% The @error{} command. +% Adapted from the TeXbook's \boxit. +% +\newbox\errorbox +% +{\tentt \global\dimen0 = 3em}% Width of the box. +\dimen2 = .55pt % Thickness of rules +% The text. (`r' is open on the right, `e' somewhat less so on the left.) +\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt} +% +\global\setbox\errorbox=\hbox to \dimen0{\hfil + \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right. + \advance\hsize by -2\dimen2 % Rules. + \vbox{ + \hrule height\dimen2 + \hbox{\vrule width\dimen2 \kern3pt % Space to left of text. + \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below. + \kern3pt\vrule width\dimen2}% Space to right. + \hrule height\dimen2} + \hfil} +% +\def\error{\leavevmode\lower.7ex\copy\errorbox} + +% @tex ... @end tex escapes into raw Tex temporarily. +% One exception: @ is still an escape character, so that @end tex works. +% But \@ or @@ will get a plain tex @ character. + +\def\tex{\begingroup + \catcode `\\=0 \catcode `\{=1 \catcode `\}=2 + \catcode `\$=3 \catcode `\&=4 \catcode `\#=6 + \catcode `\^=7 \catcode `\_=8 \catcode `\~=\active \let~=\tie + \catcode `\%=14 + \catcode `\+=\other + \catcode `\"=\other + \catcode `\==\other + \catcode `\|=\other + \catcode `\<=\other + \catcode `\>=\other + \escapechar=`\\ + % + \let\b=\ptexb + \let\bullet=\ptexbullet + \let\c=\ptexc + \let\,=\ptexcomma + \let\.=\ptexdot + \let\dots=\ptexdots + \let\equiv=\ptexequiv + \let\!=\ptexexclam + \let\i=\ptexi + \let\indent=\ptexindent + \let\{=\ptexlbrace + \let\+=\tabalign + \let\}=\ptexrbrace + \let\/=\ptexslash + \let\*=\ptexstar + \let\t=\ptext + % + \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}% + \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}% + \def\@{@}% +\let\Etex=\endgroup} + +% Define @lisp ... @end lisp. +% @lisp does a \begingroup so it can rebind things, +% including the definition of @end lisp (which normally is erroneous). + +% Amount to narrow the margins by for @lisp. +\newskip\lispnarrowing \lispnarrowing=0.4in + +% This is the definition that ^^M gets inside @lisp, @example, and other +% such environments. \null is better than a space, since it doesn't +% have any width. +\def\lisppar{\null\endgraf} + +% Make each space character in the input produce a normal interword +% space in the output. Don't allow a line break at this space, as this +% is used only in environments like @example, where each line of input +% should produce a line of output anyway. +% +{\obeyspaces % +\gdef\sepspaces{\obeyspaces\let =\tie}} + +% Define \obeyedspace to be our active space, whatever it is. This is +% for use in \parsearg. +{\sepspaces% +\global\let\obeyedspace= } + +% This space is always present above and below environments. +\newskip\envskipamount \envskipamount = 0pt + +% Make spacing and below environment symmetrical. We use \parskip here +% to help in doing that, since in @example-like environments \parskip +% is reset to zero; thus the \afterenvbreak inserts no space -- but the +% start of the next paragraph will insert \parskip. +% +\def\aboveenvbreak{{% + % =10000 instead of <10000 because of a special case in \itemzzz, q.v. + \ifnum \lastpenalty=10000 \else + \advance\envskipamount by \parskip + \endgraf + \ifdim\lastskip<\envskipamount + \removelastskip + % it's not a good place to break if the last penalty was \nobreak + % or better ... + \ifnum\lastpenalty>10000 \else \penalty-50 \fi + \vskip\envskipamount + \fi + \fi +}} + +\let\afterenvbreak = \aboveenvbreak + +% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins. +\let\nonarrowing=\relax + +% @cartouche ... @end cartouche: draw rectangle w/rounded corners around +% environment contents. +\font\circle=lcircle10 +\newdimen\circthick +\newdimen\cartouter\newdimen\cartinner +\newskip\normbskip\newskip\normpskip\newskip\normlskip +\circthick=\fontdimen8\circle +% +\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth +\def\ctr{{\hskip 6pt\circle\char'010}} +\def\cbl{{\circle\char'012\hskip -6pt}} +\def\cbr{{\hskip 6pt\circle\char'011}} +\def\carttop{\hbox to \cartouter{\hskip\lskip + \ctl\leaders\hrule height\circthick\hfil\ctr + \hskip\rskip}} +\def\cartbot{\hbox to \cartouter{\hskip\lskip + \cbl\leaders\hrule height\circthick\hfil\cbr + \hskip\rskip}} +% +\newskip\lskip\newskip\rskip + +\def\cartouche{% +\par % can't be in the midst of a paragraph. +\begingroup + \lskip=\leftskip \rskip=\rightskip + \leftskip=0pt\rightskip=0pt %we want these *outside*. + \cartinner=\hsize \advance\cartinner by-\lskip + \advance\cartinner by-\rskip + \cartouter=\hsize + \advance\cartouter by 18.4pt % allow for 3pt kerns on either +% side, and for 6pt waste from +% each corner char, and rule thickness + \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip + % Flag to tell @lisp, etc., not to narrow margin. + \let\nonarrowing=\comment + \vbox\bgroup + \baselineskip=0pt\parskip=0pt\lineskip=0pt + \carttop + \hbox\bgroup + \hskip\lskip + \vrule\kern3pt + \vbox\bgroup + \hsize=\cartinner + \kern3pt + \begingroup + \baselineskip=\normbskip + \lineskip=\normlskip + \parskip=\normpskip + \vskip -\parskip +\def\Ecartouche{% + \endgroup + \kern3pt + \egroup + \kern3pt\vrule + \hskip\rskip + \egroup + \cartbot + \egroup +\endgroup +}} + + +% This macro is called at the beginning of all the @example variants, +% inside a group. +\def\nonfillstart{% + \aboveenvbreak + \inENV % This group ends at the end of the body + \hfuzz = 12pt % Don't be fussy + \sepspaces % Make spaces be word-separators rather than space tokens. + \let\par = \lisppar % don't ignore blank lines + \obeylines % each line of input is a line of output + \parskip = 0pt + \parindent = 0pt + \emergencystretch = 0pt % don't try to avoid overfull boxes + % @cartouche defines \nonarrowing to inhibit narrowing + % at next level down. + \ifx\nonarrowing\relax + \advance \leftskip by \lispnarrowing + \exdentamount=\lispnarrowing + \let\exdent=\nofillexdent + \let\nonarrowing=\relax + \fi +} + +% Define the \E... control sequence only if we are inside the particular +% environment, so the error checking in \end will work. +% +% To end an @example-like environment, we first end the paragraph (via +% \afterenvbreak's vertical glue), and then the group. That way we keep +% the zero \parskip that the environments set -- \parskip glue will be +% inserted at the beginning of the next paragraph in the document, after +% the environment. +% +\def\nonfillfinish{\afterenvbreak\endgroup} + +% @lisp: indented, narrowed, typewriter font. +\def\lisp{\begingroup + \nonfillstart + \let\Elisp = \nonfillfinish + \tt + \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special. + \gobble % eat return +} + +% @example: Same as @lisp. +\def\example{\begingroup \def\Eexample{\nonfillfinish\endgroup}\lisp} + +% @smallexample and @smalllisp: use smaller fonts. +% Originally contributed by Pavel@xerox. +\def\smalllisp{\begingroup + \def\Esmalllisp{\nonfillfinish\endgroup}% + \def\Esmallexample{\nonfillfinish\endgroup}% + \smallexamplefonts + \lisp +} +\let\smallexample = \smalllisp + + +% @display: same as @lisp except keep current font. +% +\def\display{\begingroup + \nonfillstart + \let\Edisplay = \nonfillfinish + \gobble +} +% +% @smalldisplay: @display plus smaller fonts. +% +\def\smalldisplay{\begingroup + \def\Esmalldisplay{\nonfillfinish\endgroup}% + \smallexamplefonts \rm + \display +} + +% @format: same as @display except don't narrow margins. +% +\def\format{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eformat = \nonfillfinish + \gobble +} +% +% @smallformat: @format plus smaller fonts. +% +\def\smallformat{\begingroup + \def\Esmallformat{\nonfillfinish\endgroup}% + \smallexamplefonts \rm + \format +} + +% @flushleft (same as @format). +% +\def\flushleft{\begingroup \def\Eflushleft{\nonfillfinish\endgroup}\format} + +% @flushright. +% +\def\flushright{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eflushright = \nonfillfinish + \advance\leftskip by 0pt plus 1fill + \gobble +} + + +% @quotation does normal linebreaking (hence we can't use \nonfillstart) +% and narrows the margins. +% +\def\quotation{% + \begingroup\inENV %This group ends at the end of the @quotation body + {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip + \parindent=0pt + % We have retained a nonzero parskip for the environment, since we're + % doing normal filling. So to avoid extra space below the environment... + \def\Equotation{\parskip = 0pt \nonfillfinish}% + % + % @cartouche defines \nonarrowing to inhibit narrowing at next level down. + \ifx\nonarrowing\relax + \advance\leftskip by \lispnarrowing + \advance\rightskip by \lispnarrowing + \exdentamount = \lispnarrowing + \let\nonarrowing = \relax + \fi +} + + +% LaTeX-like @verbatim...@end verbatim and @verb{...} +% If we want to allow any as delimiter, +% we need the curly braces so that makeinfo sees the @verb command, eg: +% `@verbx...x' would look like the '@verbx' command. --janneke@gnu.org +% +% [Knuth]: Donald Ervin Knuth, 1996. The TeXbook. +% +% [Knuth] p.344; only we need to do the other characters Texinfo sets +% active too. Otherwise, they get lost as the first character on a +% verbatim line. +\def\dospecials{% + \do\ \do\\\do\{\do\}\do\$\do\&% + \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~% + \do\<\do\>\do\|\do\@\do+\do\"% +} +% +% [Knuth] p. 380 +\def\uncatcodespecials{% + \def\do##1{\catcode`##1=12}\dospecials} +% +% [Knuth] pp. 380,381,391 +% Disable Spanish ligatures ?` and !` of \tt font +\begingroup + \catcode`\`=\active\gdef`{\relax\lq} +\endgroup +% +% Setup for the @verb command. +% +% Eight spaces for a tab +\begingroup + \catcode`\^^I=\active + \gdef\tabeightspaces{\catcode`\^^I=\active\def^^I{\ \ \ \ \ \ \ \ }} +\endgroup +% +\def\setupverb{% + \tt % easiest (and conventionally used) font for verbatim + \def\par{\leavevmode\endgraf}% + \catcode`\`=\active + \tabeightspaces + % Respect line breaks, + % print special symbols as themselves, and + % make each space count + % must do in this order: + \obeylines \uncatcodespecials \sepspaces +} + +% Setup for the @verbatim environment +% +% Real tab expansion +\newdimen\tabw \setbox0=\hbox{\tt\space} \tabw=8\wd0 % tab amount +% +\def\starttabbox{\setbox0=\hbox\bgroup} +\begingroup + \catcode`\^^I=\active + \gdef\tabexpand{% + \catcode`\^^I=\active + \def^^I{\leavevmode\egroup + \dimen0=\wd0 % the width so far, or since the previous tab + \divide\dimen0 by\tabw + \multiply\dimen0 by\tabw % compute previous multiple of \tabw + \advance\dimen0 by\tabw % advance to next multiple of \tabw + \wd0=\dimen0 \box0 \starttabbox + }% + } +\endgroup +\def\setupverbatim{% + % Easiest (and conventionally used) font for verbatim + \tt + \def\par{\leavevmode\egroup\box0\endgraf}% + \catcode`\`=\active + \tabexpand + % Respect line breaks, + % print special symbols as themselves, and + % make each space count + % must do in this order: + \obeylines \uncatcodespecials \sepspaces + \everypar{\starttabbox}% +} + +% Do the @verb magic: verbatim text is quoted by unique +% delimiter characters. Before first delimiter expect a +% right brace, after last delimiter expect closing brace: +% +% \def\doverb'{'#1'}'{#1} +% +% [Knuth] p. 382; only eat outer {} +\begingroup + \catcode`[=1\catcode`]=2\catcode`\{=12\catcode`\}=12 + \gdef\doverb{#1[\def\next##1#1}[##1\endgroup]\next] +\endgroup +% +\def\verb{\begingroup\setupverb\doverb} +% +% +% Do the @verbatim magic: define the macro \doverbatim so that +% the (first) argument ends when '@end verbatim' is reached, ie: +% +% \def\doverbatim#1@end verbatim{#1} +% +% For Texinfo it's a lot easier than for LaTeX, +% because texinfo's \verbatim doesn't stop at '\end{verbatim}': +% we need not redefine '\', '{' and '}'. +% +% Inspired by LaTeX's verbatim command set [latex.ltx] +%% Include LaTeX hack for completeness -- never know +%% \begingroup +%% \catcode`|=0 \catcode`[=1 +%% \catcode`]=2\catcode`\{=12\catcode`\}=12\catcode`\ =\active +%% \catcode`\\=12|gdef|doverbatim#1@end verbatim[ +%% #1|endgroup|def|Everbatim[]|end[verbatim]] +%% |endgroup +% +\begingroup + \catcode`\ =\active + \obeylines % + % ignore everything up to the first ^^M, that's the newline at the end + % of the @verbatim input line itself. Otherwise we get an extra blank + % line in the output. + \gdef\doverbatim#1^^M#2@end verbatim{#2\end{verbatim}}% +\endgroup +% +\def\verbatim{% + \def\Everbatim{\nonfillfinish\endgroup}% + \begingroup + \nonfillstart + \advance\leftskip by -\defbodyindent + \begingroup\setupverbatim\doverbatim +} + +% @verbatiminclude FILE - insert text of file in verbatim environment. +% +% Allow normal characters that we make active in the argument (a file name). +\def\verbatiminclude{% + \begingroup + \catcode`\\=\other + \catcode`~=\other + \catcode`^=\other + \catcode`_=\other + \catcode`|=\other + \catcode`<=\other + \catcode`>=\other + \catcode`+=\other + \parsearg\doverbatiminclude +} +\def\setupverbatiminclude{% + \begingroup + \nonfillstart + \advance\leftskip by -\defbodyindent + \begingroup\setupverbatim +} +% +\def\doverbatiminclude#1{% + % Restore active chars for included file. + \endgroup + \begingroup + \let\value=\expandablevalue + \def\thisfile{#1}% + \expandafter\expandafter\setupverbatiminclude\input\thisfile + \endgroup + \nonfillfinish + \endgroup +} + +% @copying ... @end copying. +% Save the text away for @insertcopying later. Many commands won't be +% allowed in this context, but that's ok. +% +% We save the uninterpreted tokens, rather than creating a box. +% Saving the text in a box would be much easier, but then all the +% typesetting commands (@smallbook, font changes, etc.) have to be done +% beforehand -- and a) we want @copying to be done first in the source +% file; b) letting users define the frontmatter in as flexible order as +% possible is very desirable. +% +\def\copying{\begingroup + % Define a command to swallow text until we reach `@end copying'. + % \ is the escape char in this texinfo.tex file, so it is the + % delimiter for the command; @ will be the escape char when we read + % it, but that doesn't matter. + \long\def\docopying##1\end copying{\gdef\copyingtext{##1}\enddocopying}% + % + % We must preserve ^^M's in the input file; see \insertcopying below. + \catcode`\^^M = \active + \docopying +} + +% What we do to finish off the copying text. +% +\def\enddocopying{\endgroup\ignorespaces} + +% @insertcopying. Here we must play games with ^^M's. On the one hand, +% we need them to delimit commands such as `@end quotation', so they +% must be active. On the other hand, we certainly don't want every +% end-of-line to be a \par, as would happen with the normal active +% definition of ^^M. On the third hand, two ^^M's in a row should still +% generate a \par. +% +% Our approach is to make ^^M insert a space and a penalty1 normally; +% then it can also check if \lastpenalty=1. If it does, then manually +% do \par. +% +% This messes up the normal definitions of @c[omment], so we redefine +% it. Similarly for @ignore. (These commands are used in the gcc +% manual for man page generation.) +% +% Seems pretty fragile, most line-oriented commands will presumably +% fail, but for the limited use of getting the copying text (which +% should be quite simple) inserted, we can hope it's ok. +% +{\catcode`\^^M=\active % +\gdef\insertcopying{\begingroup % + \parindent = 0pt % looks wrong on title page + \def^^M{% + \ifnum \lastpenalty=1 % + \par % + \else % + \space \penalty 1 % + \fi % + }% + % + % Fix @c[omment] for catcode 13 ^^M's. + \def\c##1^^M{\ignorespaces}% + \let\comment = \c % + % + % Don't bother jumping through all the hoops that \doignore does, it + % would be very hard since the catcodes are already set. + \long\def\ignore##1\end ignore{\ignorespaces}% + % + \copyingtext % +\endgroup}% +} + +\message{defuns,} +% @defun etc. + +% Allow user to change definition object font (\df) internally +\def\setdeffont#1 {\csname DEF#1\endcsname} + +\newskip\defbodyindent \defbodyindent=.4in +\newskip\defargsindent \defargsindent=50pt +\newskip\deflastargmargin \deflastargmargin=18pt + +\newcount\parencount + +% We want ()&[] to print specially on the defun line. +% +\def\activeparens{% + \catcode`\(=\active \catcode`\)=\active + \catcode`\&=\active + \catcode`\[=\active \catcode`\]=\active +} + +% Make control sequences which act like normal parenthesis chars. +\let\lparen = ( \let\rparen = ) + +{\activeparens % Now, smart parens don't turn on until &foo (see \amprm) + +% Be sure that we always have a definition for `(', etc. For example, +% if the fn name has parens in it, \boldbrax will not be in effect yet, +% so TeX would otherwise complain about undefined control sequence. +\global\let(=\lparen \global\let)=\rparen +\global\let[=\lbrack \global\let]=\rbrack + +\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 } +\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} +% This is used to turn on special parens +% but make & act ordinary (given that it's active). +\gdef\boldbraxnoamp{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb\let&=\ampnr} + +% Definitions of (, ) and & used in args for functions. +% This is the definition of ( outside of all parentheses. +\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested + \global\advance\parencount by 1 +} +% +% This is the definition of ( when already inside a level of parens. +\gdef\opnested{\char`\(\global\advance\parencount by 1 } +% +\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0. + % also in that case restore the outer-level definition of (. + \ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi + \global\advance \parencount by -1 } +% If we encounter &foo, then turn on ()-hacking afterwards +\gdef\amprm#1 {{\rm\}\let(=\oprm \let)=\clrm\ } +% +\gdef\normalparens{\boldbrax\let&=\ampnr} +} % End of definition inside \activeparens +%% These parens (in \boldbrax) actually are a little bolder than the +%% contained text. This is especially needed for [ and ] +\def\opnr{{\sf\char`\(}\global\advance\parencount by 1 } +\def\clnr{{\sf\char`\)}\global\advance\parencount by -1 } +\let\ampnr = \& +\def\lbrb{{\bf\char`\[}} +\def\rbrb{{\bf\char`\]}} + +% Active &'s sneak into the index arguments, so make sure it's defined. +{ + \catcode`& = \active + \global\let& = \ampnr +} + +% \defname, which formats the name of the @def (not the args). +% #1 is the function name. +% #2 is the type of definition, such as "Function". +% +\def\defname#1#2{% + % How we'll output the type name. Putting it in brackets helps + % distinguish it from the body text that may end up on the next line + % just below it. + \ifempty{#2}% + \def\defnametype{}% + \else + \def\defnametype{[\rm #2]}% + \fi + % + % Get the values of \leftskip and \rightskip as they were outside the @def... + \dimen2=\leftskip + \advance\dimen2 by -\defbodyindent + % + % Figure out values for the paragraph shape. + \setbox0=\hbox{\hskip \deflastargmargin{\defnametype}}% + \dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line + \dimen1=\hsize \advance \dimen1 by -\defargsindent % size for continuations + \parshape 2 0in \dimen0 \defargsindent \dimen1 + % + % Output arg 2 ("Function" or some such) but stuck inside a box of + % width 0 so it does not interfere with linebreaking. + \noindent + % + {% Adjust \hsize to exclude the ambient margins, + % so that \rightline will obey them. + \advance \hsize by -\dimen2 + \dimen3 = 0pt % was -1.25pc + \rlap{\rightline{\defnametype\kern\dimen3}}% + }% + % + % Allow all lines to be underfull without complaint: + \tolerance=10000 \hbadness=10000 + \advance\leftskip by -\defbodyindent + \exdentamount=\defbodyindent + {\df #1}\enskip % output function name + % \defunargs will be called next to output the arguments, if any. +} + +% Common pieces to start any @def... +% #1 is the \E... control sequence to end the definition (which we define). +% #2 is the \...x control sequence (which our caller defines). +% #3 is the control sequence to process the header, such as \defunheader. +% +\def\parsebodycommon#1#2#3{% + \begingroup\inENV + % If there are two @def commands in a row, we'll have a \nobreak, + % which is there to keep the function description together with its + % header. But if there's nothing but headers, we want to allow a + % break after all. Check for penalty 10002 (inserted by + % \defargscommonending) instead of 10000, since the sectioning + % commands insert a \penalty10000, and we don't want to allow a break + % between a section heading and a defun. + \ifnum\lastpenalty=10002 \penalty0 \fi + \medbreak + % + % Define the \E... end token that this defining construct specifies + % so that it will exit this group. + \def#1{\endgraf\endgroup\medbreak}% + % + \parindent=0in + \advance\leftskip by \defbodyindent + \exdentamount=\defbodyindent +} + +% Common part of the \...x definitions. +% +\def\defxbodycommon{% + % As with \parsebodycommon above, allow line break if we have multiple + % x headers in a row. It's not a great place, though. + \ifnum\lastpenalty=10000 \penalty1000 \fi + % + \begingroup\obeylines +} + +% Process body of @defun, @deffn, @defmac, etc. +% +\def\defparsebody#1#2#3{% + \parsebodycommon{#1}{#2}{#3}% + \def#2{\defxbodycommon \activeparens \spacesplit#3}% + \catcode\equalChar=\active + \begingroup\obeylines\activeparens + \spacesplit#3% +} + +% #1, #2, #3 are the common arguments (see \parsebodycommon above). +% #4, delimited by the space, is the class name. +% +\def\defmethparsebody#1#2#3#4 {% + \parsebodycommon{#1}{#2}{#3}% + \def#2##1 {\defxbodycommon \activeparens \spacesplit{#3{##1}}}% + \begingroup\obeylines\activeparens + % The \empty here prevents misinterpretation of a construct such as + % @deffn {whatever} {Enharmonic comma} + % See comments at \deftpparsebody, although in our case we don't have + % to remove the \empty afterwards, since it is empty. + \spacesplit{#3{#4}}\empty +} + +% Used for @deftypemethod and @deftypeivar. +% #1, #2, #3 are the common arguments (see \defparsebody). +% #4, delimited by a space, is the class name. +% #5 is the method's return type. +% +\def\deftypemethparsebody#1#2#3#4 #5 {% + \parsebodycommon{#1}{#2}{#3}% + \def#2##1 ##2 {\defxbodycommon \activeparens \spacesplit{#3{##1}{##2}}}% + \begingroup\obeylines\activeparens + \spacesplit{#3{#4}{#5}}% +} + +% Used for @deftypeop. The change from \deftypemethparsebody is an +% extra argument at the beginning which is the `category', instead of it +% being the hardwired string `Method' or `Instance Variable'. We have +% to account for this both in the \...x definition and in parsing the +% input at hand. Thus also need a control sequence (passed as #5) for +% the \E... definition to assign the category name to. +% +\def\deftypeopparsebody#1#2#3#4#5 #6 {% + \parsebodycommon{#1}{#2}{#3}% + \def#2##1 ##2 ##3 {\def#4{##1}% + \defxbodycommon \activeparens \spacesplit{#3{##2}{##3}}}% + \begingroup\obeylines\activeparens + \spacesplit{#3{#5}{#6}}% +} + +% For @defop. +\def\defopparsebody #1#2#3#4#5 {% + \parsebodycommon{#1}{#2}{#3}% + \def#2##1 ##2 {\def#4{##1}% + \defxbodycommon \activeparens \spacesplit{#3{##2}}}% + \begingroup\obeylines\activeparens + \spacesplit{#3{#5}}% +} + +% These parsing functions are similar to the preceding ones +% except that they do not make parens into active characters. +% These are used for "variables" since they have no arguments. +% +\def\defvarparsebody #1#2#3{% + \parsebodycommon{#1}{#2}{#3}% + \def#2{\defxbodycommon \spacesplit#3}% + \catcode\equalChar=\active + \begingroup\obeylines + \spacesplit#3% +} + +% @defopvar. +\def\defopvarparsebody #1#2#3#4#5 {% + \parsebodycommon{#1}{#2}{#3}% + \def#2##1 ##2 {\def#4{##1}% + \defxbodycommon \spacesplit{#3{##2}}}% + \begingroup\obeylines + \spacesplit{#3{#5}}% +} + +\def\defvrparsebody#1#2#3#4 {% + \parsebodycommon{#1}{#2}{#3}% + \def#2##1 {\defxbodycommon \spacesplit{#3{##1}}}% + \begingroup\obeylines + \spacesplit{#3{#4}}% +} + +% This loses on `@deftp {Data Type} {struct termios}' -- it thinks the +% type is just `struct', because we lose the braces in `{struct +% termios}' when \spacesplit reads its undelimited argument. Sigh. +% \let\deftpparsebody=\defvrparsebody +% +% So, to get around this, we put \empty in with the type name. That +% way, TeX won't find exactly `{...}' as an undelimited argument, and +% won't strip off the braces. +% +\def\deftpparsebody #1#2#3#4 {% + \parsebodycommon{#1}{#2}{#3}% + \def#2##1 {\defxbodycommon \spacesplit{#3{##1}}}% + \begingroup\obeylines + \spacesplit{\parsetpheaderline{#3{#4}}}\empty +} + +% Fine, but then we have to eventually remove the \empty *and* the +% braces (if any). That's what this does. +% +\def\removeemptybraces\empty#1\relax{#1} + +% After \spacesplit has done its work, this is called -- #1 is the final +% thing to call, #2 the type name (which starts with \empty), and #3 +% (which might be empty) the arguments. +% +\def\parsetpheaderline#1#2#3{% + #1{\removeemptybraces#2\relax}{#3}% +}% + +% Split up #2 (the rest of the input line) at the first space token. +% call #1 with two arguments: +% the first is all of #2 before the space token, +% the second is all of #2 after that space token. +% If #2 contains no space token, all of it is passed as the first arg +% and the second is passed as empty. +% +{\obeylines % + \gdef\spacesplit#1#2^^M{\endgroup\spacesplitx{#1}#2 \relax\spacesplitx}% + \long\gdef\spacesplitx#1#2 #3#4\spacesplitx{% + \ifx\relax #3% + #1{#2}{}% + \else % + #1{#2}{#3#4}% + \fi}% +} + +% Define @defun. + +% This is called to end the arguments processing for all the @def... commands. +% +\def\defargscommonending{% + \interlinepenalty = 10000 + \advance\rightskip by 0pt plus 1fil + \endgraf + \nobreak\vskip -\parskip + \penalty 10002 % signal to \parsebodycommon. +} + +% This expands the args and terminates the paragraph they comprise. +% +\def\defunargs#1{\functionparens \sl +% Expand, preventing hyphenation at `-' chars. +% Note that groups don't affect changes in \hyphenchar. +% Set the font temporarily and use \font in case \setfont made \tensl a macro. +{\tensl\hyphenchar\font=0}% +#1% +{\tensl\hyphenchar\font=45}% +\ifnum\parencount=0 \else \errmessage{Unbalanced parentheses in @def}\fi% + \defargscommonending +} + +\def\deftypefunargs #1{% +% Expand, preventing hyphenation at `-' chars. +% Note that groups don't affect changes in \hyphenchar. +% Use \boldbraxnoamp, not \functionparens, so that & is not special. +\boldbraxnoamp +\tclose{#1}% avoid \code because of side effects on active chars + \defargscommonending +} + +% Do complete processing of one @defun or @defunx line already parsed. + +% @deffn Command forward-char nchars + +\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader} + +\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}% +\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup % +\catcode\equalChar=\other % Turn off change made in \defparsebody +} + +% @defun == @deffn Function + +\def\defun{\defparsebody\Edefun\defunx\defunheader} + +\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{\putwordDeffunc}% +\defunargs {#2}\endgroup % +\catcode\equalChar=\other % Turn off change made in \defparsebody +} + +% @deftypefun int foobar (int @var{foo}, float @var{bar}) + +\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader} + +% #1 is the data type. #2 is the name and args. +\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax} +% #1 is the data type, #2 the name, #3 the args. +\def\deftypefunheaderx #1#2 #3\relax{% +\doind {fn}{\code{#2}}% Make entry in function index +\begingroup\defname {\defheaderxcond#1\relax$.$#2}{\putwordDeftypefun}% +\deftypefunargs {#3}\endgroup % +\catcode\equalChar=\other % Turn off change made in \defparsebody +} + +% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar}) + +\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader} + +% \defheaderxcond#1\relax$.$ +% puts #1 in @code, followed by a space, but does nothing if #1 is null. +\def\defheaderxcond#1#2$.${\ifx#1\relax\else\code{#1#2} \fi} + +% #1 is the classification. #2 is the data type. #3 is the name and args. +\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax} +% #1 is the classification, #2 the data type, #3 the name, #4 the args. +\def\deftypefnheaderx #1#2#3 #4\relax{% +\doind {fn}{\code{#3}}% Make entry in function index +\begingroup +\normalparens % notably, turn off `&' magic, which prevents +% at least some C++ text from working +\defname {\defheaderxcond#2\relax$.$#3}{#1}% +\deftypefunargs {#4}\endgroup % +\catcode\equalChar=\other % Turn off change made in \defparsebody +} + +% @defmac == @deffn Macro + +\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader} + +\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{\putwordDefmac}% +\defunargs {#2}\endgroup % +\catcode\equalChar=\other % Turn off change made in \defparsebody +} + +% @defspec == @deffn Special Form + +\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader} + +\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{\putwordDefspec}% +\defunargs {#2}\endgroup % +\catcode\equalChar=\other % Turn off change made in \defparsebody +} + +% @defop CATEGORY CLASS OPERATION ARG... +% +\def\defop #1 {\def\defoptype{#1}% +\defopparsebody\Edefop\defopx\defopheader\defoptype} +% +\def\defopheader#1#2#3{% + \dosubind{fn}{\code{#2}}{\putwordon\ \code{#1}}% function index entry + \begingroup + \defname{#2}{\defoptype\ \putwordon\ #1}% + \defunargs{#3}% + \endgroup +} + +% @deftypeop CATEGORY CLASS TYPE OPERATION ARG... +% +\def\deftypeop #1 {\def\deftypeopcategory{#1}% + \deftypeopparsebody\Edeftypeop\deftypeopx\deftypeopheader + \deftypeopcategory} +% +% #1 is the class name, #2 the data type, #3 the operation name, #4 the args. +\def\deftypeopheader#1#2#3#4{% + \dosubind{fn}{\code{#3}}{\putwordon\ \code{#1}}% entry in function index + \begingroup + \defname{\defheaderxcond#2\relax$.$#3} + {\deftypeopcategory\ \putwordon\ \code{#1}}% + \deftypefunargs{#4}% + \endgroup +} + +% @deftypemethod CLASS TYPE METHOD ARG... +% +\def\deftypemethod{% + \deftypemethparsebody\Edeftypemethod\deftypemethodx\deftypemethodheader} +% +% #1 is the class name, #2 the data type, #3 the method name, #4 the args. +\def\deftypemethodheader#1#2#3#4{% + \dosubind{fn}{\code{#3}}{\putwordon\ \code{#1}}% entry in function index + \begingroup + \defname{\defheaderxcond#2\relax$.$#3}{\putwordMethodon\ \code{#1}}% + \deftypefunargs{#4}% + \endgroup +} + +% @deftypeivar CLASS TYPE VARNAME +% +\def\deftypeivar{% + \deftypemethparsebody\Edeftypeivar\deftypeivarx\deftypeivarheader} +% +% #1 is the class name, #2 the data type, #3 the variable name. +\def\deftypeivarheader#1#2#3{% + \dosubind{vr}{\code{#3}}{\putwordof\ \code{#1}}% entry in variable index + \begingroup + \defname{\defheaderxcond#2\relax$.$#3} + {\putwordInstanceVariableof\ \code{#1}}% + \defvarargs{#3}% + \endgroup +} + +% @defmethod == @defop Method +% +\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader} +% +% #1 is the class name, #2 the method name, #3 the args. +\def\defmethodheader#1#2#3{% + \dosubind{fn}{\code{#2}}{\putwordon\ \code{#1}}% entry in function index + \begingroup + \defname{#2}{\putwordMethodon\ \code{#1}}% + \defunargs{#3}% + \endgroup +} + +% @defcv {Class Option} foo-class foo-flag + +\def\defcv #1 {\def\defcvtype{#1}% +\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype} + +\def\defcvarheader #1#2#3{% + \dosubind{vr}{\code{#2}}{\putwordof\ \code{#1}}% variable index entry + \begingroup + \defname{#2}{\defcvtype\ \putwordof\ #1}% + \defvarargs{#3}% + \endgroup +} + +% @defivar CLASS VARNAME == @defcv {Instance Variable} CLASS VARNAME +% +\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader} +% +\def\defivarheader#1#2#3{% + \dosubind{vr}{\code{#2}}{\putwordof\ \code{#1}}% entry in var index + \begingroup + \defname{#2}{\putwordInstanceVariableof\ #1}% + \defvarargs{#3}% + \endgroup +} + +% @defvar +% First, define the processing that is wanted for arguments of @defvar. +% This is actually simple: just print them in roman. +% This must expand the args and terminate the paragraph they make up +\def\defvarargs #1{\normalparens #1% + \defargscommonending +} + +% @defvr Counter foo-count + +\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader} + +\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}% +\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup} + +% @defvar == @defvr Variable + +\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader} + +\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index +\begingroup\defname {#1}{\putwordDefvar}% +\defvarargs {#2}\endgroup % +} + +% @defopt == @defvr {User Option} + +\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader} + +\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index +\begingroup\defname {#1}{\putwordDefopt}% +\defvarargs {#2}\endgroup % +} + +% @deftypevar int foobar + +\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader} + +% #1 is the data type. #2 is the name, perhaps followed by text that +% is actually part of the data type, which should not be put into the index. +\def\deftypevarheader #1#2{% +\dovarind#2 \relax% Make entry in variables index +\begingroup\defname {\defheaderxcond#1\relax$.$#2}{\putwordDeftypevar}% + \defargscommonending +\endgroup} +\def\dovarind#1 #2\relax{\doind{vr}{\code{#1}}} + +% @deftypevr {Global Flag} int enable + +\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader} + +\def\deftypevrheader #1#2#3{\dovarind#3 \relax% +\begingroup\defname {\defheaderxcond#2\relax$.$#3}{#1} + \defargscommonending +\endgroup} + +% Now define @deftp +% Args are printed in bold, a slight difference from @defvar. + +\def\deftpargs #1{\bf \defvarargs{#1}} + +% @deftp Class window height width ... + +\def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader} + +\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}% +\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup} + +% These definitions are used if you use @defunx (etc.) +% anywhere other than immediately after a @defun or @defunx. +% +\def\defcvx#1 {\errmessage{@defcvx in invalid context}} +\def\deffnx#1 {\errmessage{@deffnx in invalid context}} +\def\defivarx#1 {\errmessage{@defivarx in invalid context}} +\def\defmacx#1 {\errmessage{@defmacx in invalid context}} +\def\defmethodx#1 {\errmessage{@defmethodx in invalid context}} +\def\defoptx #1 {\errmessage{@defoptx in invalid context}} +\def\defopx#1 {\errmessage{@defopx in invalid context}} +\def\defspecx#1 {\errmessage{@defspecx in invalid context}} +\def\deftpx#1 {\errmessage{@deftpx in invalid context}} +\def\deftypefnx#1 {\errmessage{@deftypefnx in invalid context}} +\def\deftypefunx#1 {\errmessage{@deftypefunx in invalid context}} +\def\deftypeivarx#1 {\errmessage{@deftypeivarx in invalid context}} +\def\deftypemethodx#1 {\errmessage{@deftypemethodx in invalid context}} +\def\deftypeopx#1 {\errmessage{@deftypeopx in invalid context}} +\def\deftypevarx#1 {\errmessage{@deftypevarx in invalid context}} +\def\deftypevrx#1 {\errmessage{@deftypevrx in invalid context}} +\def\defunx#1 {\errmessage{@defunx in invalid context}} +\def\defvarx#1 {\errmessage{@defvarx in invalid context}} +\def\defvrx#1 {\errmessage{@defvrx in invalid context}} + + +\message{macros,} +% @macro. + +% To do this right we need a feature of e-TeX, \scantokens, +% which we arrange to emulate with a temporary file in ordinary TeX. +\ifx\eTeXversion\undefined + \newwrite\macscribble + \def\scanmacro#1{% + \begingroup \newlinechar`\^^M + % Undo catcode changes of \startcontents and \doprintindex + \catcode`\@=0 \catcode`\\=\other \escapechar=`\@ + % Append \endinput to make sure that TeX does not see the ending newline. + \toks0={#1\endinput}% + \immediate\openout\macscribble=\jobname.tmp + \immediate\write\macscribble{\the\toks0}% + \immediate\closeout\macscribble + \let\xeatspaces\eatspaces + \input \jobname.tmp + \endgroup +} +\else +\def\scanmacro#1{% +\begingroup \newlinechar`\^^M +% Undo catcode changes of \startcontents and \doprintindex +\catcode`\@=0 \catcode`\\=\other \escapechar=`\@ +\let\xeatspaces\eatspaces\scantokens{#1\endinput}\endgroup} +\fi + +\newcount\paramno % Count of parameters +\newtoks\macname % Macro name +\newif\ifrecursive % Is it recursive? +\def\macrolist{} % List of all defined macros in the form + % \do\macro1\do\macro2... + +% Utility routines. +% Thisdoes \let #1 = #2, except with \csnames. +\def\cslet#1#2{% +\expandafter\expandafter +\expandafter\let +\expandafter\expandafter +\csname#1\endcsname +\csname#2\endcsname} + +% Trim leading and trailing spaces off a string. +% Concepts from aro-bend problem 15 (see CTAN). +{\catcode`\@=11 +\gdef\eatspaces #1{\expandafter\trim@\expandafter{#1 }} +\gdef\trim@ #1{\trim@@ @#1 @ #1 @ @@} +\gdef\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @} +\def\unbrace#1{#1} +\unbrace{\gdef\trim@@@ #1 } #2@{#1} +} + +% Trim a single trailing ^^M off a string. +{\catcode`\^^M=\other \catcode`\Q=3% +\gdef\eatcr #1{\eatcra #1Q^^MQ}% +\gdef\eatcra#1^^MQ{\eatcrb#1Q}% +\gdef\eatcrb#1Q#2Q{#1}% +} + +% Macro bodies are absorbed as an argument in a context where +% all characters are catcode 10, 11 or 12, except \ which is active +% (as in normal texinfo). It is necessary to change the definition of \. + +% It's necessary to have hard CRs when the macro is executed. This is +% done by making ^^M (\endlinechar) catcode 12 when reading the macro +% body, and then making it the \newlinechar in \scanmacro. + +\def\macrobodyctxt{% + \catcode`\~=\other + \catcode`\^=\other + \catcode`\_=\other + \catcode`\|=\other + \catcode`\<=\other + \catcode`\>=\other + \catcode`\+=\other + \catcode`\{=\other + \catcode`\}=\other + \catcode`\@=\other + \catcode`\^^M=\other + \usembodybackslash} + +\def\macroargctxt{% + \catcode`\~=\other + \catcode`\^=\other + \catcode`\_=\other + \catcode`\|=\other + \catcode`\<=\other + \catcode`\>=\other + \catcode`\+=\other + \catcode`\@=\other + \catcode`\\=\other} + +% \mbodybackslash is the definition of \ in @macro bodies. +% It maps \foo\ => \csname macarg.foo\endcsname => #N +% where N is the macro parameter number. +% We define \csname macarg.\endcsname to be \realbackslash, so +% \\ in macro replacement text gets you a backslash. + +{\catcode`@=0 @catcode`@\=@active + @gdef@usembodybackslash{@let\=@mbodybackslash} + @gdef@mbodybackslash#1\{@csname macarg.#1@endcsname} +} +\expandafter\def\csname macarg.\endcsname{\realbackslash} + +\def\macro{\recursivefalse\parsearg\macroxxx} +\def\rmacro{\recursivetrue\parsearg\macroxxx} + +\def\macroxxx#1{% + \getargs{#1}% now \macname is the macname and \argl the arglist + \ifx\argl\empty % no arguments + \paramno=0% + \else + \expandafter\parsemargdef \argl;% + \fi + \if1\csname ismacro.\the\macname\endcsname + \message{Warning: redefining \the\macname}% + \else + \expandafter\ifx\csname \the\macname\endcsname \relax + \else \errmessage{Macro name \the\macname\space already defined}\fi + \global\cslet{macsave.\the\macname}{\the\macname}% + \global\expandafter\let\csname ismacro.\the\macname\endcsname=1% + % Add the macroname to \macrolist + \toks0 = \expandafter{\macrolist\do}% + \xdef\macrolist{\the\toks0 + \expandafter\noexpand\csname\the\macname\endcsname}% + \fi + \begingroup \macrobodyctxt + \ifrecursive \expandafter\parsermacbody + \else \expandafter\parsemacbody + \fi} + +\def\unmacro{\parsearg\dounmacro} +\def\dounmacro#1{% + \if1\csname ismacro.#1\endcsname + \global\cslet{#1}{macsave.#1}% + \global\expandafter\let \csname ismacro.#1\endcsname=0% + % Remove the macro name from \macrolist: + \begingroup + \expandafter\let\csname#1\endcsname \relax + \let\do\unmacrodo + \xdef\macrolist{\macrolist}% + \endgroup + \else + \errmessage{Macro #1 not defined}% + \fi +} + +% Called by \do from \dounmacro on each macro. The idea is to omit any +% macro definitions that have been changed to \relax. +% +\def\unmacrodo#1{% + \ifx#1\relax + % remove this + \else + \noexpand\do \noexpand #1% + \fi +} + +% This makes use of the obscure feature that if the last token of a +% is #, then the preceding argument is delimited by +% an opening brace, and that opening brace is not consumed. +\def\getargs#1{\getargsxxx#1{}} +\def\getargsxxx#1#{\getmacname #1 \relax\getmacargs} +\def\getmacname #1 #2\relax{\macname={#1}} +\def\getmacargs#1{\def\argl{#1}} + +% Parse the optional {params} list. Set up \paramno and \paramlist +% so \defmacro knows what to do. Define \macarg.blah for each blah +% in the params list, to be ##N where N is the position in that list. +% That gets used by \mbodybackslash (above). + +% We need to get `macro parameter char #' into several definitions. +% The technique used is stolen from LaTeX: let \hash be something +% unexpandable, insert that wherever you need a #, and then redefine +% it to # just before using the token list produced. +% +% The same technique is used to protect \eatspaces till just before +% the macro is used. + +\def\parsemargdef#1;{\paramno=0\def\paramlist{}% + \let\hash\relax\let\xeatspaces\relax\parsemargdefxxx#1,;,} +\def\parsemargdefxxx#1,{% + \if#1;\let\next=\relax + \else \let\next=\parsemargdefxxx + \advance\paramno by 1% + \expandafter\edef\csname macarg.\eatspaces{#1}\endcsname + {\xeatspaces{\hash\the\paramno}}% + \edef\paramlist{\paramlist\hash\the\paramno,}% + \fi\next} + +% These two commands read recursive and nonrecursive macro bodies. +% (They're different since rec and nonrec macros end differently.) + +\long\def\parsemacbody#1@end macro% +{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% +\long\def\parsermacbody#1@end rmacro% +{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% + +% This defines the macro itself. There are six cases: recursive and +% nonrecursive macros of zero, one, and many arguments. +% Much magic with \expandafter here. +% \xdef is used so that macro definitions will survive the file +% they're defined in; @include reads the file inside a group. +\def\defmacro{% + \let\hash=##% convert placeholders to macro parameter chars + \ifrecursive + \ifcase\paramno + % 0 + \expandafter\xdef\csname\the\macname\endcsname{% + \noexpand\scanmacro{\temp}}% + \or % 1 + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\braceorline + \expandafter\noexpand\csname\the\macname xxx\endcsname}% + \expandafter\xdef\csname\the\macname xxx\endcsname##1{% + \egroup\noexpand\scanmacro{\temp}}% + \else % many + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\csname\the\macname xx\endcsname}% + \expandafter\xdef\csname\the\macname xx\endcsname##1{% + \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% + \expandafter\expandafter + \expandafter\xdef + \expandafter\expandafter + \csname\the\macname xxx\endcsname + \paramlist{\egroup\noexpand\scanmacro{\temp}}% + \fi + \else + \ifcase\paramno + % 0 + \expandafter\xdef\csname\the\macname\endcsname{% + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \or % 1 + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\braceorline + \expandafter\noexpand\csname\the\macname xxx\endcsname}% + \expandafter\xdef\csname\the\macname xxx\endcsname##1{% + \egroup + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \else % many + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \expandafter\noexpand\csname\the\macname xx\endcsname}% + \expandafter\xdef\csname\the\macname xx\endcsname##1{% + \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% + \expandafter\expandafter + \expandafter\xdef + \expandafter\expandafter + \csname\the\macname xxx\endcsname + \paramlist{% + \egroup + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \fi + \fi} + +\def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}} + +% \braceorline decides whether the next nonwhitespace character is a +% {. If so it reads up to the closing }, if not, it reads the whole +% line. Whatever was read is then fed to the next control sequence +% as an argument (by \parsebrace or \parsearg) +\def\braceorline#1{\let\next=#1\futurelet\nchar\braceorlinexxx} +\def\braceorlinexxx{% + \ifx\nchar\bgroup\else + \expandafter\parsearg + \fi \next} + +% We mant to disable all macros during \shipout so that they are not +% expanded by \write. +\def\turnoffmacros{\begingroup \def\do##1{\let\noexpand##1=\relax}% + \edef\next{\macrolist}\expandafter\endgroup\next} + + +% @alias. +% We need some trickery to remove the optional spaces around the equal +% sign. Just make them active and then expand them all to nothing. +\def\alias{\begingroup\obeyspaces\parsearg\aliasxxx} +\def\aliasxxx #1{\aliasyyy#1\relax} +\def\aliasyyy #1=#2\relax{\ignoreactivespaces +\edef\next{\global\let\expandafter\noexpand\csname#1\endcsname=% + \expandafter\noexpand\csname#2\endcsname}% +\expandafter\endgroup\next} + + +\message{cross references,} +% @xref etc. + +\newwrite\auxfile + +\newif\ifhavexrefs % True if xref values are known. +\newif\ifwarnedxrefs % True if we warned once that they aren't known. + +% @inforef is relatively simple. +\def\inforef #1{\inforefzzz #1,,,,**} +\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}}, + node \samp{\ignorespaces#1{}}} + +% @node's job is to define \lastnode. +\def\node{\ENVcheck\parsearg\nodezzz} +\def\nodezzz#1{\nodexxx #1,\finishnodeparse} +\def\nodexxx#1,#2\finishnodeparse{\gdef\lastnode{#1}} +\let\nwnode=\node +\let\lastnode=\relax + +% The sectioning commands (@chapter, etc.) call these. +\def\donoderef{% + \ifx\lastnode\relax\else + \expandafter\expandafter\expandafter\setref{\lastnode}% + {Ysectionnumberandtype}% + \global\let\lastnode=\relax + \fi +} +\def\unnumbnoderef{% + \ifx\lastnode\relax\else + \expandafter\expandafter\expandafter\setref{\lastnode}{Ynothing}% + \global\let\lastnode=\relax + \fi +} +\def\appendixnoderef{% + \ifx\lastnode\relax\else + \expandafter\expandafter\expandafter\setref{\lastnode}% + {Yappendixletterandtype}% + \global\let\lastnode=\relax + \fi +} + + +% @anchor{NAME} -- define xref target at arbitrary point. +% +\newcount\savesfregister +\gdef\savesf{\relax \ifhmode \savesfregister=\spacefactor \fi} +\gdef\restoresf{\relax \ifhmode \spacefactor=\savesfregister \fi} +\gdef\anchor#1{\savesf \setref{#1}{Ynothing}\restoresf \ignorespaces} + +% \setref{NAME}{SNT} defines a cross-reference point NAME (a node or an +% anchor), namely NAME-title (the corresponding @chapter/etc. name), +% NAME-pg (the page number), and NAME-snt (section number and type). +% Called from \foonoderef. +% +% We have to set \indexdummies so commands such as @code in a section +% title aren't expanded. It would be nicer not to expand the titles in +% the first place, but there's so many layers that that is hard to do. +% +% Likewise, use \turnoffactive so that punctuation chars such as underscore +% and backslash work in node names. +% +\def\setref#1#2{{% + \atdummies + \pdfmkdest{#1}% + % + \turnoffactive + \dosetq{#1-title}{Ytitle}% + \dosetq{#1-pg}{Ypagenumber}% + \dosetq{#1-snt}{#2}% +}} + +% @xref, @pxref, and @ref generate cross-references. For \xrefX, #1 is +% the node name, #2 the name of the Info cross-reference, #3 the printed +% node name, #4 the name of the Info file, #5 the name of the printed +% manual. All but the node name can be omitted. +% +\def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]} +\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]} +\def\ref#1{\xrefX[#1,,,,,,,]} +\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup + \unsepspaces + \def\printedmanual{\ignorespaces #5}% + \def\printednodename{\ignorespaces #3}% + \setbox1=\hbox{\printedmanual}% + \setbox0=\hbox{\printednodename}% + \ifdim \wd0 = 0pt + % No printed node name was explicitly given. + \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax + % Use the node name inside the square brackets. + \def\printednodename{\ignorespaces #1}% + \else + % Use the actual chapter/section title appear inside + % the square brackets. Use the real section title if we have it. + \ifdim \wd1 > 0pt + % It is in another manual, so we don't have it. + \def\printednodename{\ignorespaces #1}% + \else + \ifhavexrefs + % We know the real title if we have the xref values. + \def\printednodename{\refx{#1-title}{}}% + \else + % Otherwise just copy the Info node name. + \def\printednodename{\ignorespaces #1}% + \fi% + \fi + \fi + \fi + % + % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not + % insert empty discretionaries after hyphens, which means that it will + % not find a line break at a hyphen in a node names. Since some manuals + % are best written with fairly long node names, containing hyphens, this + % is a loss. Therefore, we give the text of the node name again, so it + % is as if TeX is seeing it for the first time. + \ifpdf + \leavevmode + \getfilename{#4}% + {\turnoffactive \otherbackslash + \ifnum\filenamelength>0 + \startlink attr{/Border [0 0 0]}% + goto file{\the\filename.pdf} name{#1}% + \else + \startlink attr{/Border [0 0 0]}% + goto name{#1}% + \fi + }% + \linkcolor + \fi + % + \ifdim \wd1 > 0pt + \putwordsection{} ``\printednodename'' \putwordin{} \cite{\printedmanual}% + \else + % _ (for example) has to be the character _ for the purposes of the + % control sequence corresponding to the node, but it has to expand + % into the usual \leavevmode...\vrule stuff for purposes of + % printing. So we \turnoffactive for the \refx-snt, back on for the + % printing, back off for the \refx-pg. + {\turnoffactive \otherbackslash + % Only output a following space if the -snt ref is nonempty; for + % @unnumbered and @anchor, it won't be. + \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}% + \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi + }% + % output the `[mynode]' via a macro. + \xrefprintnodename\printednodename + % + % But we always want a comma and a space: + ,\space + % + % output the `page 3'. + \turnoffactive \otherbackslash \putwordpage\tie\refx{#1-pg}{}% + \fi + \endlink +\endgroup} + +% This macro is called from \xrefX for the `[nodename]' part of xref +% output. It's a separate macro only so it can be changed more easily, +% since not square brackets don't work in some documents. Particularly +% one that Bob is working on :). +% +\def\xrefprintnodename#1{[#1]} + +% \dosetq is called from \setref to do the actual \write (\iflinks). +% +\def\dosetq#1#2{% + {\let\folio=0% + \edef\next{\write\auxfile{\internalsetq{#1}{#2}}}% + \iflinks \next \fi + }% +} + +% \internalsetq{foo}{page} expands into +% CHARACTERS @xrdef{foo}{...expansion of \page...} +\def\internalsetq#1#2{@xrdef{#1}{\csname #2\endcsname}} + +% Things to be expanded by \internalsetq. +% +\def\Ypagenumber{\folio} +\def\Ytitle{\thissection} +\def\Ynothing{} +\def\Ysectionnumberandtype{% + \ifnum\secno=0 + \putwordChapter@tie \the\chapno + \else \ifnum\subsecno=0 + \putwordSection@tie \the\chapno.\the\secno + \else \ifnum\subsubsecno=0 + \putwordSection@tie \the\chapno.\the\secno.\the\subsecno + \else + \putwordSection@tie \the\chapno.\the\secno.\the\subsecno.\the\subsubsecno + \fi\fi\fi +} + +\def\Yappendixletterandtype{% + \ifnum\secno=0 + \putwordAppendix@tie @char\the\appendixno{}% + \else \ifnum\subsecno=0 + \putwordSection@tie @char\the\appendixno.\the\secno + \else \ifnum\subsubsecno=0 + \putwordSection@tie @char\the\appendixno.\the\secno.\the\subsecno + \else + \putwordSection@tie + @char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno + \fi\fi\fi +} + +% Use TeX 3.0's \inputlineno to get the line number, for better error +% messages, but if we're using an old version of TeX, don't do anything. +% +\ifx\inputlineno\thisisundefined + \let\linenumber = \empty % Pre-3.0. +\else + \def\linenumber{\the\inputlineno:\space} +\fi + +% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME. +% If its value is nonempty, SUFFIX is output afterward. +% +\def\refx#1#2{% + {% + \indexnofonts + \otherbackslash + \expandafter\global\expandafter\let\expandafter\thisrefX + \csname X#1\endcsname + }% + \ifx\thisrefX\relax + % If not defined, say something at least. + \angleleft un\-de\-fined\angleright + \iflinks + \ifhavexrefs + \message{\linenumber Undefined cross reference `#1'.}% + \else + \ifwarnedxrefs\else + \global\warnedxrefstrue + \message{Cross reference values unknown; you must run TeX again.}% + \fi + \fi + \fi + \else + % It's defined, so just use it. + \thisrefX + \fi + #2% Output the suffix in any case. +} + +% This is the macro invoked by entries in the aux file. +% +\def\xrdef#1{\expandafter\gdef\csname X#1\endcsname} + +% Read the last existing aux file, if any. No error if none exists. +\def\readauxfile{\begingroup + \catcode`\^^@=\other + \catcode`\^^A=\other + \catcode`\^^B=\other + \catcode`\^^C=\other + \catcode`\^^D=\other + \catcode`\^^E=\other + \catcode`\^^F=\other + \catcode`\^^G=\other + \catcode`\^^H=\other + \catcode`\^^K=\other + \catcode`\^^L=\other + \catcode`\^^N=\other + \catcode`\^^P=\other + \catcode`\^^Q=\other + \catcode`\^^R=\other + \catcode`\^^S=\other + \catcode`\^^T=\other + \catcode`\^^U=\other + \catcode`\^^V=\other + \catcode`\^^W=\other + \catcode`\^^X=\other + \catcode`\^^Z=\other + \catcode`\^^[=\other + \catcode`\^^\=\other + \catcode`\^^]=\other + \catcode`\^^^=\other + \catcode`\^^_=\other + % It was suggested to set the catcode of ^ to 7, which would allow ^^e4 etc. + % in xref tags, i.e., node names. But since ^^e4 notation isn't + % supported in the main text, it doesn't seem desirable. Furthermore, + % that is not enough: for node names that actually contain a ^ + % character, we would end up writing a line like this: 'xrdef {'hat + % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first + % argument, and \hat is not an expandable control sequence. It could + % all be worked out, but why? Either we support ^^ or we don't. + % + % The other change necessary for this was to define \auxhat: + % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter + % and then to call \auxhat in \setq. + % + \catcode`\^=\other + % + % Special characters. Should be turned off anyway, but... + \catcode`\~=\other + \catcode`\[=\other + \catcode`\]=\other + \catcode`\"=\other + \catcode`\_=\other + \catcode`\|=\other + \catcode`\<=\other + \catcode`\>=\other + \catcode`\$=\other + \catcode`\#=\other + \catcode`\&=\other + \catcode`\%=\other + \catcode`+=\other % avoid \+ for paranoia even though we've turned it off + % + % Make the characters 128-255 be printing characters + {% + \count 1=128 + \def\loop{% + \catcode\count 1=\other + \advance\count 1 by 1 + \ifnum \count 1<256 \loop \fi + }% + }% + % + % Turn off \ as an escape so we do not lose on + % entries which were dumped with control sequences in their names. + % For example, @xrdef{$\leq $-fun}{page ...} made by @defun ^^ + % Reference to such entries still does not work the way one would wish, + % but at least they do not bomb out when the aux file is read in. + \catcode`\\=\other + % + % @ is our escape character in .aux files. + \catcode`\{=1 + \catcode`\}=2 + \catcode`\@=0 + % + \openin 1 \jobname.aux + \ifeof 1 \else + \closein 1 + \input \jobname.aux + \global\havexrefstrue + \global\warnedobstrue + \fi + % Open the new aux file. TeX will close it automatically at exit. + \openout\auxfile=\jobname.aux +\endgroup} + + +% Footnotes. + +\newcount \footnoteno + +% The trailing space in the following definition for supereject is +% vital for proper filling; pages come out unaligned when you do a +% pagealignmacro call if that space before the closing brace is +% removed. (Generally, numeric constants should always be followed by a +% space to prevent strange expansion errors.) +\def\supereject{\par\penalty -20000\footnoteno =0 } + +% @footnotestyle is meaningful for info output only. +\let\footnotestyle=\comment + +\let\ptexfootnote=\footnote + +{\catcode `\@=11 +% +% Auto-number footnotes. Otherwise like plain. +\gdef\footnote{% + \let\indent=\ptexindent + \global\advance\footnoteno by \@ne + \edef\thisfootno{$^{\the\footnoteno}$}% + % + % In case the footnote comes at the end of a sentence, preserve the + % extra spacing after we do the footnote number. + \let\@sf\empty + \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\ptexslash\fi + % + % Remove inadvertent blank space before typesetting the footnote number. + \unskip + \thisfootno\@sf + \dofootnote +}% + +% Don't bother with the trickery in plain.tex to not require the +% footnote text as a parameter. Our footnotes don't need to be so general. +% +% Oh yes, they do; otherwise, @ifset and anything else that uses +% \parseargline fail inside footnotes because the tokens are fixed when +% the footnote is read. --karl, 16nov96. +% +% The start of the footnote looks usually like this: +\gdef\startfootins{\insert\footins\bgroup} +% +% ... but this macro is redefined inside @multitable. +% +\gdef\dofootnote{% + \startfootins + % We want to typeset this text as a normal paragraph, even if the + % footnote reference occurs in (for example) a display environment. + % So reset some parameters. + \hsize=\pagewidth + \interlinepenalty\interfootnotelinepenalty + \splittopskip\ht\strutbox % top baseline for broken footnotes + \splitmaxdepth\dp\strutbox + \floatingpenalty\@MM + \leftskip\z@skip + \rightskip\z@skip + \spaceskip\z@skip + \xspaceskip\z@skip + \parindent\defaultparindent + % + \smallfonts \rm + % + % Because we use hanging indentation in footnotes, a @noindent appears + % to exdent this text, so make it be a no-op. makeinfo does not use + % hanging indentation so @noindent can still be needed within footnote + % text after an @example or the like (not that this is good style). + \let\noindent = \relax + % + % Hang the footnote text off the number. Use \everypar in case the + % footnote extends for more than one paragraph. + \everypar = {\hang}% + \textindent{\thisfootno}% + % + % Don't crash into the line above the footnote text. Since this + % expands into a box, it must come within the paragraph, lest it + % provide a place where TeX can split the footnote. + \footstrut + \futurelet\next\fo@t +} +}%end \catcode `\@=11 + +% @| inserts a changebar to the left of the current line. It should +% surround any changed text. This approach does *not* work if the +% change spans more than two lines of output. To handle that, we would +% have adopt a much more difficult approach (putting marks into the main +% vertical list for the beginning and end of each change). +% +\def\|{% + % \vadjust can only be used in horizontal mode. + \leavevmode + % + % Append this vertical mode material after the current line in the output. + \vadjust{% + % We want to insert a rule with the height and depth of the current + % leading; that is exactly what \strutbox is supposed to record. + \vskip-\baselineskip + % + % \vadjust-items are inserted at the left edge of the type. So + % the \llap here moves out into the left-hand margin. + \llap{% + % + % For a thicker or thinner bar, change the `1pt'. + \vrule height\baselineskip width1pt + % + % This is the space between the bar and the text. + \hskip 12pt + }% + }% +} + +% For a final copy, take out the rectangles +% that mark overfull boxes (in case you have decided +% that the text looks ok even though it passes the margin). +% +\def\finalout{\overfullrule=0pt} + +% @image. We use the macros from epsf.tex to support this. +% If epsf.tex is not installed and @image is used, we complain. +% +% Check for and read epsf.tex up front. If we read it only at @image +% time, we might be inside a group, and then its definitions would get +% undone and the next image would fail. +\openin 1 = epsf.tex +\ifeof 1 \else + \closein 1 + % Do not bother showing banner with epsf.tex v2.7k (available in + % doc/epsf.tex and on ctan). + \def\epsfannounce{\toks0 = }% + \input epsf.tex +\fi +% +% We will only complain once about lack of epsf.tex. +\newif\ifwarnednoepsf +\newhelp\noepsfhelp{epsf.tex must be installed for images to + work. It is also included in the Texinfo distribution, or you can get + it from ftp://tug.org/tex/epsf.tex.} +% +\def\image#1{% + \ifx\epsfbox\undefined + \ifwarnednoepsf \else + \errhelp = \noepsfhelp + \errmessage{epsf.tex not found, images will be ignored}% + \global\warnednoepsftrue + \fi + \else + \imagexxx #1,,,,,\finish + \fi +} +% +% Arguments to @image: +% #1 is (mandatory) image filename; we tack on .eps extension. +% #2 is (optional) width, #3 is (optional) height. +% #4 is (ignored optional) html alt text. +% #5 is (ignored optional) extension. +% #6 is just the usual extra ignored arg for parsing this stuff. +\newif\ifimagevmode +\def\imagexxx#1,#2,#3,#4,#5,#6\finish{\begingroup + \catcode`\^^M = 5 % in case we're inside an example + \normalturnoffactive % allow _ et al. in names + % If the image is by itself, center it. + \ifvmode + \imagevmodetrue + \nobreak\bigskip + % Usually we'll have text after the image which will insert + % \parskip glue, so insert it here too to equalize the space + % above and below. + \nobreak\vskip\parskip + \nobreak + \line\bgroup\hss + \fi + % + % Output the image. + \ifpdf + \dopdfimage{#1}{#2}{#3}% + \else + % \epsfbox itself resets \epsf?size at each figure. + \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi + \setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi + \epsfbox{#1.eps}% + \fi + % + \ifimagevmode \hss \egroup \bigbreak \fi % space after the image +\endgroup} + + +\message{localization,} +% and i18n. + +% @documentlanguage is usually given very early, just after +% @setfilename. If done too late, it may not override everything +% properly. Single argument is the language abbreviation. +% It would be nice if we could set up a hyphenation file here. +% +\def\documentlanguage{\parsearg\dodocumentlanguage} +\def\dodocumentlanguage#1{% + \tex % read txi-??.tex file in plain TeX. + % Read the file if it exists. + \openin 1 txi-#1.tex + \ifeof1 + \errhelp = \nolanghelp + \errmessage{Cannot read language file txi-#1.tex}% + \let\temp = \relax + \else + \def\temp{\input txi-#1.tex }% + \fi + \temp + \endgroup +} +\newhelp\nolanghelp{The given language definition file cannot be found or +is empty. Maybe you need to install it? In the current directory +should work if nowhere else does.} + + +% @documentencoding should change something in TeX eventually, most +% likely, but for now just recognize it. +\let\documentencoding = \comment + + +% Page size parameters. +% +\newdimen\defaultparindent \defaultparindent = 15pt + +\chapheadingskip = 15pt plus 4pt minus 2pt +\secheadingskip = 12pt plus 3pt minus 2pt +\subsecheadingskip = 9pt plus 2pt minus 2pt + +% Prevent underfull vbox error messages. +\vbadness = 10000 + +% Don't be so finicky about underfull hboxes, either. +\hbadness = 2000 + +% Following George Bush, just get rid of widows and orphans. +\widowpenalty=10000 +\clubpenalty=10000 + +% Use TeX 3.0's \emergencystretch to help line breaking, but if we're +% using an old version of TeX, don't do anything. We want the amount of +% stretch added to depend on the line length, hence the dependence on +% \hsize. We call this whenever the paper size is set. +% +\def\setemergencystretch{% + \ifx\emergencystretch\thisisundefined + % Allow us to assign to \emergencystretch anyway. + \def\emergencystretch{\dimen0}% + \else + \emergencystretch = .15\hsize + \fi +} + +% Parameters in order: 1) textheight; 2) textwidth; 3) voffset; +% 4) hoffset; 5) binding offset; 6) topskip; 7) physical page height; 8) +% physical page width. +% +% We also call \setleading{\textleading}, so the caller should define +% \textleading. The caller should also set \parskip. +% +\def\internalpagesizes#1#2#3#4#5#6#7#8{% + \voffset = #3\relax + \topskip = #6\relax + \splittopskip = \topskip + % + \vsize = #1\relax + \advance\vsize by \topskip + \outervsize = \vsize + \advance\outervsize by 2\topandbottommargin + \pageheight = \vsize + % + \hsize = #2\relax + \outerhsize = \hsize + \advance\outerhsize by 0.5in + \pagewidth = \hsize + % + \normaloffset = #4\relax + \bindingoffset = #5\relax + % + \ifpdf + \pdfpageheight #7\relax + \pdfpagewidth #8\relax + \fi + % + \setleading{\textleading} + % + \parindent = \defaultparindent + \setemergencystretch +} + +% @letterpaper (the default). +\def\letterpaper{{\globaldefs = 1 + \parskip = 3pt plus 2pt minus 1pt + \textleading = 13.2pt + % + % If page is nothing but text, make it come out even. + \internalpagesizes{46\baselineskip}{6in}% + {\voffset}{.25in}% + {\bindingoffset}{36pt}% + {11in}{8.5in}% +}} + +% Use @smallbook to reset parameters for 7x9.5 (or so) format. +\def\smallbook{{\globaldefs = 1 + \parskip = 2pt plus 1pt + \textleading = 12pt + % + \internalpagesizes{7.5in}{5in}% + {\voffset}{.25in}% + {\bindingoffset}{16pt}% + {9.25in}{7in}% + % + \lispnarrowing = 0.3in + \tolerance = 700 + \hfuzz = 1pt + \contentsrightmargin = 0pt + \defbodyindent = .5cm +}} + +% Use @afourpaper to print on European A4 paper. +\def\afourpaper{{\globaldefs = 1 + \parskip = 3pt plus 2pt minus 1pt + \textleading = 13.2pt + % + % Double-side printing via postscript on Laserjet 4050 + % prints double-sided nicely when \bindingoffset=10mm and \hoffset=-6mm. + % To change the settings for a different printer or situation, adjust + % \normaloffset until the front-side and back-side texts align. Then + % do the same for \bindingoffset. You can set these for testing in + % your texinfo source file like this: + % @tex + % \global\normaloffset = -6mm + % \global\bindingoffset = 10mm + % @end tex + \internalpagesizes{51\baselineskip}{160mm} + {\voffset}{\hoffset}% + {\bindingoffset}{44pt}% + {297mm}{210mm}% + % + \tolerance = 700 + \hfuzz = 1pt + \contentsrightmargin = 0pt + \defbodyindent = 5mm +}} + +% Use @afivepaper to print on European A5 paper. +% From romildo@urano.iceb.ufop.br, 2 July 2000. +% He also recommends making @example and @lisp be small. +\def\afivepaper{{\globaldefs = 1 + \parskip = 2pt plus 1pt minus 0.1pt + \textleading = 12.5pt + % + \internalpagesizes{160mm}{120mm}% + {\voffset}{\hoffset}% + {\bindingoffset}{8pt}% + {210mm}{148mm}% + % + \lispnarrowing = 0.2in + \tolerance = 800 + \hfuzz = 1.2pt + \contentsrightmargin = 0pt + \defbodyindent = 2mm + \tableindent = 12mm +}} + +% A specific text layout, 24x15cm overall, intended for A4 paper. +\def\afourlatex{{\globaldefs = 1 + \afourpaper + \internalpagesizes{237mm}{150mm}% + {\voffset}{4.6mm}% + {\bindingoffset}{7mm}% + {297mm}{210mm}% + % + % Must explicitly reset to 0 because we call \afourpaper. + \globaldefs = 0 +}} + +% Use @afourwide to print on A4 paper in landscape format. +\def\afourwide{{\globaldefs = 1 + \afourpaper + \internalpagesizes{241mm}{165mm}% + {\voffset}{-2.95mm}% + {\bindingoffset}{7mm}% + {297mm}{210mm}% + \globaldefs = 0 +}} + +% @pagesizes TEXTHEIGHT[,TEXTWIDTH] +% Perhaps we should allow setting the margins, \topskip, \parskip, +% and/or leading, also. Or perhaps we should compute them somehow. +% +\def\pagesizes{\parsearg\pagesizesxxx} +\def\pagesizesxxx#1{\pagesizesyyy #1,,\finish} +\def\pagesizesyyy#1,#2,#3\finish{{% + \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \hsize=#2\relax \fi + \globaldefs = 1 + % + \parskip = 3pt plus 2pt minus 1pt + \setleading{\textleading}% + % + \dimen0 = #1 + \advance\dimen0 by \voffset + % + \dimen2 = \hsize + \advance\dimen2 by \normaloffset + % + \internalpagesizes{#1}{\hsize}% + {\voffset}{\normaloffset}% + {\bindingoffset}{44pt}% + {\dimen0}{\dimen2}% +}} + +% Set default to letter. +% +\letterpaper + + +\message{and turning on texinfo input format.} + +% Define macros to output various characters with catcode for normal text. +\catcode`\"=\other +\catcode`\~=\other +\catcode`\^=\other +\catcode`\_=\other +\catcode`\|=\other +\catcode`\<=\other +\catcode`\>=\other +\catcode`\+=\other +\catcode`\$=\other +\def\normaldoublequote{"} +\def\normaltilde{~} +\def\normalcaret{^} +\def\normalunderscore{_} +\def\normalverticalbar{|} +\def\normalless{<} +\def\normalgreater{>} +\def\normalplus{+} +\def\normaldollar{$}%$ font-lock fix + +% This macro is used to make a character print one way in ttfont +% where it can probably just be output, and another way in other fonts, +% where something hairier probably needs to be done. +% +% #1 is what to print if we are indeed using \tt; #2 is what to print +% otherwise. Since all the Computer Modern typewriter fonts have zero +% interword stretch (and shrink), and it is reasonable to expect all +% typewriter fonts to have this, we can check that font parameter. +% +\def\ifusingtt#1#2{\ifdim \fontdimen3\font=0pt #1\else #2\fi} + +% Same as above, but check for italic font. Actually this also catches +% non-italic slanted fonts since it is impossible to distinguish them from +% italic fonts. But since this is only used by $ and it uses \sl anyway +% this is not a problem. +\def\ifusingit#1#2{\ifdim \fontdimen1\font>0pt #1\else #2\fi} + +% Turn off all special characters except @ +% (and those which the user can use as if they were ordinary). +% Most of these we simply print from the \tt font, but for some, we can +% use math or other variants that look better in normal text. + +\catcode`\"=\active +\def\activedoublequote{{\tt\char34}} +\let"=\activedoublequote +\catcode`\~=\active +\def~{{\tt\char126}} +\chardef\hat=`\^ +\catcode`\^=\active +\def^{{\tt \hat}} + +\catcode`\_=\active +\def_{\ifusingtt\normalunderscore\_} +% Subroutine for the previous macro. +\def\_{\leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em } + +\catcode`\|=\active +\def|{{\tt\char124}} +\chardef \less=`\< +\catcode`\<=\active +\def<{{\tt \less}} +\chardef \gtr=`\> +\catcode`\>=\active +\def>{{\tt \gtr}} +\catcode`\+=\active +\def+{{\tt \char 43}} +\catcode`\$=\active +\def${\ifusingit{{\sl\$}}\normaldollar}%$ font-lock fix + +% Set up an active definition for =, but don't enable it most of the time. +{\catcode`\==\active +\global\def={{\tt \char 61}}} + +\catcode`+=\active +\catcode`\_=\active + +% If a .fmt file is being used, characters that might appear in a file +% name cannot be active until we have parsed the command line. +% So turn them off again, and have \everyjob (or @setfilename) turn them on. +% \otherifyactive is called near the end of this file. +\def\otherifyactive{\catcode`+=\other \catcode`\_=\other} + +\catcode`\@=0 + +% \rawbackslashxx outputs one backslash character in current font, +% as in \char`\\. +\global\chardef\rawbackslashxx=`\\ + +% \rawbackslash defines an active \ to do \rawbackslashxx. +% \otherbackslash defines an active \ to be a literal `\' character with +% catcode other. +{\catcode`\\=\active + @gdef@rawbackslash{@let\=@rawbackslashxx} + @gdef@otherbackslash{@let\=@realbackslash} +} + +% \realbackslash is an actual character `\' with catcode other. +{\catcode`\\=\other @gdef@realbackslash{\}} + +% \normalbackslash outputs one backslash in fixed width font. +\def\normalbackslash{{\tt\rawbackslashxx}} + +\catcode`\\=\active + +% Used sometimes to turn off (effectively) the active characters +% even after parsing them. +@def@turnoffactive{% + @let"=@normaldoublequote + @let\=@realbackslash + @let~=@normaltilde + @let^=@normalcaret + @let_=@normalunderscore + @let|=@normalverticalbar + @let<=@normalless + @let>=@normalgreater + @let+=@normalplus + @let$=@normaldollar %$ font-lock fix +} + +% Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of +% the literal character `\'. (Thus, \ is not expandable when this is in +% effect.) +% +@def@normalturnoffactive{@turnoffactive @let\=@normalbackslash} + +% Make _ and + \other characters, temporarily. +% This is canceled by @fixbackslash. +@otherifyactive + +% If a .fmt file is being used, we don't want the `\input texinfo' to show up. +% That is what \eatinput is for; after that, the `\' should revert to printing +% a backslash. +% +@gdef@eatinput input texinfo{@fixbackslash} +@global@let\ = @eatinput + +% On the other hand, perhaps the file did not have a `\input texinfo'. Then +% the first `\{ in the file would cause an error. This macro tries to fix +% that, assuming it is called before the first `\' could plausibly occur. +% Also back turn on active characters that might appear in the input +% file name, in case not using a pre-dumped format. +% +@gdef@fixbackslash{% + @ifx\@eatinput @let\ = @normalbackslash @fi + @catcode`+=@active + @catcode`@_=@active +} + +% Say @foo, not \foo, in error messages. +@escapechar = `@@ + +% These look ok in all fonts, so just make them not special. +@catcode`@& = @other +@catcode`@# = @other +@catcode`@% = @other + +@c Set initial fonts. +@textfonts +@rm + + +@c Local variables: +@c eval: (add-hook 'write-file-hooks 'time-stamp) +@c page-delimiter: "^\\\\message" +@c time-stamp-start: "def\\\\texinfoversion{" +@c time-stamp-format: "%:y-%02m-%02d.%02H" +@c time-stamp-end: "}" +@c End: diff --git a/tags/gpgme-1.1.6/gpgme.spec.in b/tags/gpgme-1.1.6/gpgme.spec.in new file mode 100644 index 0000000..a5c6996 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme.spec.in @@ -0,0 +1,67 @@ +# This is a template. The dist target uses it to create the real file. +Summary: GPGME - GnuPG Made Easy +Name: gpgme +Version: @pkg_version@ +Release: 1 +URL: http://www.gnupg.org/gpgme.html +Source: ftp://ftp.gnupg.org/gcrypt/alpha/gpgme/%{name}-%{version}.tar.gz +Group: Development/Libraries +Copyright: GPL +BuildRoot: %{_tmppath}/%{name}-%{version} +BuildRequires: make +Prereq: /sbin/ldconfig /sbin/install-info +Requires: gnupg + +%description +GnuPG Made Easy (GPGME) is a library designed to make access to GnuPG easier +for applications. It provides a High-Level Crypto API for encryption, +decryption, signing, signature verification and key management. + +%prep +%setup -q + +%build +CFLAGS="$RPM_OPT_FLAGS"; export CFLAGS +./configure --prefix=/usr +make + +%install +rm -fr $RPM_BUILD_ROOT +mkdir -p $RPM_BUILD_ROOT +make install prefix=$RPM_BUILD_ROOT/usr infodir=$RPM_BUILD_ROOT%{_infodir} +rm -f $RPM_BUILD_ROOT%{_infodir}/dir + +%clean +rm -fr $RPM_BUILD_ROOT +make distclean + +%post +/sbin/ldconfig +/sbin/install-info %{_infodir}/gpgme.info.gz %{_infodir}/dir + +%preun +if [ "$1" = 0 ]; then + /sbin/install-info --delete %{_infodir}/gpgme.info.gz %{_infodir}/dir +fi + +%postun +/sbin/ldconfig + +%files +%defattr(-,root,root) +%doc COPYING COPYING.LESSER AUTHORS README INSTALL NEWS ChangeLog TODO THANKS +%attr(0755,root,root) %{_bindir}/gpgme-config +%attr(0755,root,root) %{_libdir}/*gpgme.so* +%attr(0755,root,root) %{_libdir}/*gpgme.la +%attr(0644,root,root) %{_libdir}/*gpgme.a +%{_includedir}/gpgme.h +%{_datadir}/aclocal/gpgme.m4 +%{_infodir}/gpgme.info* + +%changelog +* Sat Aug 30 2003 Robert Schiele +- %{_infodir}/dir is not packaged, remove to prevent checking failure +* Mon Jul 01 2002 Wojciech Polak +- initial specfile release for GPGME. + +# EOF diff --git a/tags/gpgme-1.1.6/gpgme.txt b/tags/gpgme-1.1.6/gpgme.txt new file mode 100644 index 0000000..88d629b --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme.txt @@ -0,0 +1,90 @@ +%%comments: +Copyright (C) 2001, 2004 Free Software Foundation, Inc. + +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.1 or +any later version published by the Free Software Foundation; with no +Invariant Sections, with no Front-Cover Texts, and with no Back-Cover +Texts. A copy of the license is included in the file COPYING. + +%%name: GPGME + +%%short-description: GnuPG Made Easy + +%%full-description: GPGME is a library designed to make access to +GnuPG easier for applications. It provides a high-level crypto API +for encryption, decryption, signing, signature verification and key +management. Currently it uses GnuPG and GpgSM as its backends to +support OpenPGP and the Cryptographic Message Syntax. + +%%category: security, libraries + +%%license: GPL +%%license verified by: +%%license verified on: + +%%maintainer: g10 Code GmbH + +%%updated: 2004-09-30 + +%%keywords: encryption, public key, digital signature, GnuPG + +%%interface: + +%%programs: + +%%GNU: no + +%%web-page: http://www.gnupg.org/gpgme.html + +%%support: paid extension/consulting from http://www.g10code.com + +%%doc: English programmer reference in Texinfo, Postscript, HTML included + +%%developers: Werner Koch . + +%%contributors: + +%%sponsors: + +%%source: ftp://ftp.gnupg.org/gcrypt/gpgme/ + +%%debian: + +%%redhat: + +%%repository: See http://www.gnupg.org/cvs-access.html + +%%related: + +%%source-language: C + +%%supported-languages: C, C++ + +%%use-requirements: GnuPG 1.2.2, GpgSM 1.9.6 + +%%build-prerequisites: libgpg-error 0.5 + +%%weak-prerequisites: Pth 1.2.0 + +%%source-prerequisites: + +%%version: 1.0.0 released on 2004-09-30 + +%%announce-list: announce@gnupg.org announce-request@gnupg.org + +%%announce-news: + +%%help-list: + +%%help-news: + +%%dev-list: gnupg-devel@gnupg.org gnupg-devel-request@gnupg.org + +%%dev-news: + +%%bug-list: + +%%bug-database: + +%%entry written by: Werner Koch diff --git a/tags/gpgme-1.1.6/gpgme/ChangeLog b/tags/gpgme-1.1.6/gpgme/ChangeLog new file mode 100644 index 0000000..ea6a9a0 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/ChangeLog @@ -0,0 +1,5642 @@ +2008-01-04 Marcus Brinkmann + + * Makefile.am (gpgconf_components): New variable. + (main_sources): Add gpgconf.c. + * gpgme.h (gpgme_protocol_t): New protocol GPGME_PROTOCOL_GPGCONF. + (gpgme_conf_level_t, gpgme_conf_type_t, gpgme_conf_arg_t) + (gpgme_conf_opt_t, gpgme_conf_comp_t, gpgme_conf_arg_new) + (gpgme_conf_arg_release, gpgme_conf_opt_change) + (gpgme_conf_release, gpgme_op_conf_load, gpgme_op_conf_save): New + types. + * gpgconf.c, engine-gpgconf.c: New files. + * engine.h: (_gpgme_engine_op_conf_load, + (_gpgme_engine_op_conf_save): New prototypes. + * op-support.c (_gpgme_op_reset): Ignore not implemented locale + function. + * posix-util.c (_gpgme_get_gpgconf_path): New function. + * w32-util.c (_gpgme_get_gpgconf_path): New function. + * engine-gpgsm.c: + (_gpgme_engine_ops_gpgsm): Add stubs for conf_load and conf_save. + * rungpg.c: + (_gpgme_engine_ops_gpg): Add stubs for conf_load and conf_save. + * gpgme.def: Add new gpgconf related interfaces. + * libgpgme.vers: Likewise. + * util.h (_gpgme_get_gpgconf_path): New prototype. + * gpgme.h (gpgme_protocol_t): Add GPGME_PROTOCOL_GPGCONF. + * engine-backend.h (_gpgme_engine_ops_gpgconf): New prototype. + (struct engine_ops): Add members for conf_load and conf_save. + * engine.c (engine_ops): Add _gpgme_engine_ops_gpgconf. + (_gpgme_engine_op_conf_load, + (_gpgme_engine_op_conf_save): New functions. + (gpgme_get_engine_info): Allow protocol GPGME_PROTOCOL_GPGCONF. + +2007-11-28 Marcus Brinkmann + + * w32-util.c (_gpgme_get_gpg_path, _gpgme_get_gpgsm_path): Search + for installation directory. Remove old fallback default. + (find_program_in_inst_dir): New function. + +2007-11-26 Werner Koch + + * engine-gpgsm.c (struct engine_gpgsm): Add field INLINE_DATA and + always reset it before calling start. + (gpgsm_new): Clear it. + (status_handler): Implement it. + (gpgsm_getauditlog) [USE_DESCRIPTOR_PASSING]: Use INLINE_DATA. + +2007-11-23 Werner Koch + + * op-support.c (_gpgme_op_reset): Implement a no-reset flag. + * getauditlog.c (getauditlog_start): Use that flag. + +2007-11-22 Werner Koch + + * gpgme.h (gpgme_op_getauditlog_start, gpgme_op_getauditlog): New. + * libgpgme.vers: Ditto. + * gpgme.def: Ditto. + * getauditlog.c: New. + * engine-backend.h (struct engine_ops): Add member GETAUDITLOG. + * engine-gpgsm.c (gpgsm_getauditlog): New. + (_gpgme_engine_ops_gpgsm): Insert new function. + (gpgsm_new): Try to enable audit log support. + * rungpg.c (_gpgme_engine_ops_gpg): Insert dummy entry. + +2007-11-20 Werner Koch + + * op-support.c (_gpgme_parse_inv_recp): Add new reason code 11. + +2007-11-12 Marcus Brinkmann + + * kdpipeiodevice.cpp: New version from Frank Osterfeld. + +2007-10-11 Marcus Brinkmann + + * kdpipeiodevice.cpp: New version from Frank Osterfeld. + +2007-10-09 Marcus Brinkmann + + * kdpipeiodevice.cpp: New version from Frank Osterfeld and Marc + Mutz. + +2007-10-05 Marcus Brinkmann + + * kdpipeiodevice.cpp, w32-qt-io.cpp: New versions from Frank + Osterfeld. + +2007-10-04 Marcus Brinkmann + + * kdpipeiodevice.h, kdpipeiodevice.cpp, kdpipeiodevice.moc, + w32-qt-io.cpp: New versions from Frank Osterfeld. + +2007-10-02 Marcus Brinkmann + + * kdpipeiodevice.cpp, kdpipeiodevice.moc: New versions. + * w32-qt-io.cpp (_gpgme_io_fd2str): Print actual_fd if available. + (_gpgme_io_dup): Only acquire a reference, do not actually dup. + Submitted by Frank Osterfeld. + + * priv-io.h, engine-gpgsm.c: Add comments. + * w32-qt-io.cpp (_gpgme_io_select): Remove code handling frozen FDs. + * w32-glib-io.c (_gpgme_io_close): Always dereference the channel, + even if not primary. + (_gpgme_io_dup): Acquire a reference. Replace unused + implementation by assertion. + +2007-09-28 Werner Koch + + * engine-gpgsm.c (iocb_data_t): Add SERVER_FD_STR. + (gpgsm_new): Set it. + (gpgsm_set_fd): Use it. + + * w32-glib-io.c (find_channel): Add a new primary flag. + (_gpgme_io_close): Close channel only if primary. + (_gpgme_io_dup): Put newfd into the table as shallow copy. + + * priv-io.h (struct io_select_fd_s): Remove member FROZEN. + * w32-io.c (_gpgme_io_select): Ditto. + * w32-glib-io.c (_gpgme_io_select): Ditto. + + * posix-io.c (_gpgme_io_select): Ditto. + * rungpg.c (read_status): Ditto. + * wait.c (fd_table_put): Ditto. + + * rungpg.c (gpg_io_event): Add tracing. + (start): Use gpg_io_event for sending the start event. + * engine-gpgsm.c (gpgsm_io_event): Add tracing. + (start): Use gpgsm_io_event for sending the start event. + * wait.c (_gpgme_add_io_cb, _gpgme_run_io_cb): Add tracing. + +2007-09-28 Marcus Brinkmann + + * kdpipeiodevice.moc, w32-qt-io.cpp, kdpipeiodevice.cpp: New + versions from Frank Osterfeld. + +2007-09-27 Marcus Brinkmann + + * w32-glib-io.c (_gpgme_io_spawn), + w32-qt-io.cpp (_gpgme_io_spawn), w32-io.c (_gpgme_io_spawn): Close + the process handle, return 0. + + * gpgme.h (gpgme_protocol_t): Add GPGME_PROTOCOL_UNKNOWN. + * gpgme.c (gpgme_get_protocol_name): Implement support for + GPGME_PROTOCOL_UNKNOWN. + + * kdpipeiodevice.h: Fix last change. + + * w32-glib-io.c (_gpgme_io_pipe), w32-qt-io.c (_gpgme_io_pipe), + w32-io.c (_gpgme_io_pipe), posix-io.c (_gpgme_io_pipe): Fix debug + output. + +2007-09-25 Marcus Brinkmann + + * conversion.c, keylist.c: Include . + + * kdpipeiodevice.h: Use namespace _gpgme_. + * kdpipeiodevice.cpp: Use namespace _gpgme_. + [Q_OS_WIN32 && NOMINMAX]: Do not define NOMINMAX again. + * w32-qt-io.cpp: Change namespace of KDPipeIODevice to + _gpgme_::KDPipeIODevice. + +2007-09-17 Werner Koch + + * rungpg.c (gpg_new): Make robust against undefined ttyname or + ttytype. + +2007-09-14 Werner Koch + + * data-mem.c (gpgme_data_release_and_get_mem): Fix tracing bug. + +2007-09-14 Marcus Brinkmann + + * gpgme.c (gpgme_release): Call gpgme_sig_notation_clear. + +2007-09-13 Marcus Brinkmann + + * rungpg.c (gpg_new): Handle return value of _gpgme_getenv (fixes + small memory leak). + +2007-09-07 Marcus Brinkmann + + * Makefile.am (libgpgme_qt_la_SOURCES): Move + moc_kdpipeiodevice.cpp to EXTRA_DIST, as this is only included by + another file (it's more like a header file than a cpp file, but + automake doesn't know that). + + * w32-qt-io.cpp (_gpgme_io_spawn): Fix several cast errors and typos. + * w32-io.c (_gpgme_io_write): Use TRACE_SYSRES instead of TRACE_SYS. + (libgpgme_qt_la_LIBADD): Add QT4_CORE_LIBS, not QT4_CORE_LIB. + + * kdpipeiodevice.h, kdpipeiodevice.cpp, moc_kdpipeiodevice.cpp, + kdpipeiodevice.moc, w32-qt-io.c: New files. + * Makefile.am (ltlib_gpgme_extra): Rename to ltlib_gpgme_glib. + (ltlib_gpgme_qt): New variable. + (lib_LTLIBRARIES): Add $(ltlib_gpgme_qt). + (libgpgme_qt_la_SOURCES): New variable. + (AM_CPPFLAGS): Add @QT4_CORE_INCLUDES@ + (AM_CFLAGS): Add @QT4_CORE_CFLAGS@. + (libgpgme_qt_la_LDFLAGS, libgpgme_qt_la_DEPENDENCIES) + (libgpgme_qt_la_LIBADD): New variables. + + * sema.h (struct critsect_s): Rename "private" to "priv" to make + C++ users happy. Change users. + * posix-sema.c (_gpgme_sema_cs_enter, _gpgme_sema_cs_leave) + (_gpgme_sema_cs_destroy): Likewise. + * w32-sema.c (critsect_init, _gpgme_sema_cs_enter) + (_gpgme_sema_cs_leave, _gpgme_sema_cs_destroy): Likewise. + * w32-glib-io.c (gpgme_get_giochannel): Change return type to + void*. + (gpgme_get_fdptr): New function. + * w32-io.c (gpgme_get_fdptr): New function + * gpgme.def: Add gpgme_get_fdptr. + +2007-08-22 Marcus Brinkmann + + * w32-io.c (_gpgme_io_write): Return early if COUNT is zero. + (writer): Remove superfluous check. + +2007-08-20 Marcus Brinkmann + + * gpgme.h: Move include of gpg-error.h out of extern "C". + +2007-08-07 Werner Koch + + * gpgme.h (struct _gpgme_signature): Add member CHAIN_MODEL. + * verify.c (parse_trust): Set Chain_MODEL. + +2007-08-02 Werner Koch + + * w32-glib-io.c (_gpgme_io_spawn): Use DETACHED_PROCESS flag. + * w32-io.c (_gpgme_io_spawn): Ditto. + (_gpgme_io_write): Map ERROR_NO_DATA to EPIPE. + * debug.c (_gpgme_debug): Enable assuan logging. + (_gpgme_debug_subsystem_init): New. * version.c + (do_subsystem_inits): Disable assuan logging and initialize de + debug system. + (gpgme_check_version): Do not trace before the subsystems are + initialized. + +2007-07-17 Marcus Brinkmann + + * debug.c: Include and "debug.h". + (_gpgme_debug): Save and restore ERRNO. + (TOHEX): New macro. + (_gpgme_debug_buffer): New function. + * conversion.c, data-compat.c, data-mem.c, data.c, engine-gpgsm.c, + gpgme.c, keylist.c, posix-io.c, rungpg.c, sign.c, version.c, + w32-io.c, wait.c: Replace DEBUG macros by TRACE_* variants. In + most of these files, add many more tracepoints. + +2007-07-16 Marcus Brinkmann + + * engine-gpgsm.c (status_handler): Do not send BYE here. + + * w32-io.c (struct reader_context_s, struct writer_context_s): New + members REFCOUNT. + (create_reader, create_writer): Initialize C->refcount to 1. + (destroy_reader, destroy_writer): Only destroy if C->refcount + drops to 0. + (find_reader, find_writer, kill_reader, kill_writer): Beautify. + * priv-io.h (_gpgme_io_dup): New prototype. + * posix-io.c (_gpgme_io_dup): New function. + * w32-io.c (_gpgme_io_dup): Likewise. + * w32-glib-io.c (_gpgme_io_dup): Likewise. + * engine-gpgsm.c (start): Reverting to version 2007-07-10. + +2007-07-13 Marcus Brinkmann + + * data-user.c (user_read, user_write, user_seek): Set errno and + return -1 instead returning the error code directly. + * data-compat.c (old_user_seek): Likewise. + * gpgme.c (gpgme_sig_notation_add): Return error properly. + + * Revert the "close_notify_handler" returns int stuff. Always + close in the _gpgme_io_close implementations. + * engine-gpgsm.c (status_handler): Try to terminate the connection + in case of error. + * w32-io.c (_gpgme_io_read): Return C->error_code in ERRNO. + (_gpgme_io_write): Likewise. + + * priv-io.h (_gpgme_io_set_close_notify): Change type of HANDLER + to _gpgme_close_notify_handler. + (_gpgme_close_notify_handler): New type. + (_gpgme_io_dup): Remove prototype. + * posix-io.c (notify_table, _gpgme_io_set_close_notify): Change + type of HANDLER to _gpgme_close_notify_handler_t. + (_gpgme_io_close): Do not close the FD if handler returns 0. + (_gpgme_io_dup): Remove function. + * w32-io.c (notify_table, _gpgme_io_set_close_notify, + _gpgme_io_close): Change type of HANDLER to + _gpgme_close_notify_handler_t. + (_gpgme_io_close): Do not close the FD if handler returns 0. + (_gpgme_io_dup): Remove function. + * w32-glib-io.c (_gpgme_io_dup): Remove function. + (_gpgme_io_set_close_notify, notify_table): Change type of HANDLER + to _gpgme_close_notify_handler_t. + (_gpgme_io_close): Do not close the FD if handler returns 0. + * rungpg.c (close_notify_handler): Change return type to int, + return 1. + * engine-gpgsm.c (close_notify_handler): Change return type to + int, return 0 for status FD and 1 for all other FDs. + (start): Do not duplicate the status FD. + +2007-07-12 Marcus Brinkmann + + * Makefile.am: Replace implicite rule by suffix rule. Add + SUFFIXES for that. + +2007-07-12 Werner Koch + + * version.c (do_subsystem_inits) [W32]: Make sure that the socket + system has been started. + +2007-07-10 Marcus Brinkmann + + * priv-io.h (_gpgme_io_dup): New prototype. + * posix-io.c (_gpgme_io_dup): New function. + * w32-io.c (_gpgme_io_dup): Likewise. + * w32-glib-io.c (_gpgme_io_dup): Likewise. + * engine-gpgsm.c (start): Use _gpgme_dup() instead of dup(). + +2007-07-08 Marcus Brinkmann + + * engine-gpgsm.c [HAVE_W32_SYSTEM]: Enable the bunch of the file. + * funopen.c (funopen): Rename to _gpgme_funopen. + +2007-04-30 Marcus Brinkmann + + * engine-gpgsm.c (gpgsm_new): Fix error handling for ttyname_r. + * rungpg.c (gpg_new): Likewise. + Submitted by Stephen Tether. + +2007-02-26 Werner Koch + + * verify.c (op_data_t): New element PLAINTEXT_SEEN. + (_gpgme_verify_status_handler): Return an error if more than one + plaintext has been seen. + (parse_error): New arg SET_STATUS. Also detect it based on an + ERROR status (gpg > 1.4.6). + +2007-01-26 Werner Koch + + * w32-io.c (build_commandline): Fixed stupid quoting bug. + * w32-glib-io.c (build_commandline): Ditto. + + * rungpg.c (gpg_set_locale): Avoid dangling pointer after free. + + * gpgme-config.in: New options --get-gpg and --get-gpgsm. + +2007-01-18 Marcus Brinkmann + + * data.h (_gpgme_data_get_fd): Add prototype. + (gpgme_data_get_fd_cb): New type. + (struct _gpgme_data_cbs): New member get_fd. + * data.c (_gpgme_data_get_fd): New function. + * data-fd.c (fd_get_fd): New function. + (fd_cbs): Add fd_get_fd. + * data-stream.c (stream_get_fd): New function. + (stream_cbs): Add stream_get_fd. + * data-mem.c (mem_cbs): Add NULL for get_fd callback. + * data-user.c (user_cbs): Likewise. + * engine-gpgsm.c (gpgsm_set_fd) [USE_DESCRIPTOR_PASSING]: Try to + short-cut by passing the data descriptor directly. + +2007-01-17 Marcus Brinkmann + + * w32-io.c (build_commandline): Quote all command line arguments. + * w32-glib-io.c (build_commandline): Likewise. + +2007-01-10 Werner Koch + + * ttyname_r.c (ttyname_r) [W32]: Return a dummy name. + +2007-01-08 Werner Koch + + * version.c (do_subsystem_inits): Do assuan init only if building + with Assuan. + * setenv.c: Include assuan-def.h only if building with Assuan + support. + + * op-support.c (_gpgme_op_reset): Set LC_MESSAGES only if + if defined. + * engine-gpgsm.c (gpgsm_set_locale): Ditto. + * rungpg.c (gpg_set_locale): Ditto. + +2006-12-17 Marcus Brinkmann + + * gpgme.c (gpgme_set_protocol): Shut down the engine when + switching protocols. + (gpgme_ctx_set_engine_info): Likewise for engine info. + * engine.h (_gpgme_engine_reset): New function prototype. + * engine.c (_gpgme_engine_reset): New function. + * engine-backend.h (struct engine_ops): New member RESET. + * rungpg.c (_gpgme_engine_ops_gpg): Add NULL for reset function. + * engine-gpgsm.c (_gpgme_engine_ops_gpgsm) + [USE_DESCRIPTOR_PASSING]: Add gpgsm_reset for reset. + (_gpgme_engine_ops_gpgsm) [!USE_DESCRIPTOR_PASSING]: Add NULL for + reset function. + (gpgsm_reset) [USE_DESCRIPTOR_PASSING]: New function. + * op-support.c (_gpgme_op_reset): Try to use the engine's reset + function if available. + * engine-gpgsm.c (gpgsm_new): Move code to dup status_fd to ... + (start): ... here. + * posix-io.c (_gpgme_io_recvmsg, _gpgme_io_sendmsg): New functions. + + * engine.h (_gpgme_engine_new): Remove arguments lc_ctype and + lc_messages from prototype. + (_gpgme_engine_set_locale): New prototype. + * engine.c (_gpgme_engine_set_locale): New function. + * op-support.c (_gpgme_op_reset): Call _gpgme_engine_set_locale. + * engine-backend.h (struct engine_ops): Add new member SET_LOCALE. + Remove arguments lc_messages and lc_ctype from member NEW. + * engine-gpgsm.c (struct engine_gpgsm): New members lc_ctype_set + and lc_messages_set. + (gpgsm_new): Remove lc_messages and lc_ctype + arguments. + (gpgsm_set_locale): New function. + (_gpgme_engine_ops_gpgsm): Add gpgsm_set_locale. + * rungpg.c (struct engine_gpg): Add new members lc_messages and + lc_ctype. + (gpg_release): Release lc_messages and lc_ctype if set. + (gpg_new): Remove lc_messages and lc_ctype arguments. + (gpg_set_locale): New function. + (_gpgme_engine_ops_gpg): Add gpg_set_locale. + (add_arg): Implement in terms of: + (add_arg_ext): New function. + (start): Set lc-messages and lc-ctype arguments here. + +2006-12-03 Marcus Brinkmann + + * engine-gpgsm.c (struct engine_gpgsm): Move members + input_fd_server, output_fd_server, message_fd_server to ... + (iocb_data): ... here (as server_fd). + (close_notify_handler): Reset tags as well. + (gpgsm_new): Implement support for descriptor + passing. + (fd_type_t): New type. + (gpgsm_clear_fd): New function. Use it instead of _gpgsm_io_close + for unused communication channels. + (gpgsm_set_fd): Rewritten to support descriptor passing. All + relevant callers adjusted as well (previously of _gpgme_io_close). + +2006-12-02 Marcus Brinkmann + + * version.c: Include "assuan.h". + (do_subsystem_inits): Call assuan_set_assuan_err_source. + +2006-12-01 Marcus Brinkmann + + * Makefile.am (libgpgme_real_la_SOURCES): Rename to main_sources. + (libgpgme_la_SOURCES, libgpgme_pthread_la_SOURCES, + libgpgme_glib_la_SOURCES, libgpgme_pth_la_SOURCES): Add + $(main_sources). + (libgpgme_la_DEPENDENCIES, libgpgme_la_LIBADD, + libgpgme_pthread_la_DEPENDENCIES, libgpgme_pthread_la_LIBADD, + libgpgme_pth_la_DEPENDENCIES, libgpgme_pth_la_LIBADD, + libgpgme_glib_la_DEPENDENCIES, libgpgme_glib_la_LIBADD): Remove + libgpgme-real.la. + (noinst_LTLIBRARIES): Removed. + (libgpgme_glib_la_CFLAGS, libgpgme_pth_la_CFLAGS): Removed. + (AM_CFLAGS): New variable. + +2006-11-30 Marcus Brinkmann + + * engine-gpgsm.c: Replace AssuanError with gpg_error_t and + ASSUAN_CONTEXT with assuan_context_t. + +2006-11-29 Marcus Brinkmann + + * engine-gpgsm.c (gpgsm_new): Check return value of + assuan_pipe_connect. + + * rungpg.c: Include . + (gpg_new): Support --display, --ttyname, --ttytype, --lc-ctype and + --lc-messages. Fixes issue 734. + +2006-10-24 Marcus Brinkmann + + * trustlist.c (gpgme_op_trustlist_next): Return error if OPD is + NULL. + +2006-10-23 Marcus Brinkmann + + * wait-global.c (gpgme_wait): Unlock CTX_LIST_LOCK while calling + _gpgme_engine_io_event(). + + * keylist.c (gpgme_op_keylist_next): Return error if OPD is NULL. + +2006-09-25 Marcus Brinkmann + + * data-mem.c (gpgme_data_release_and_get_mem): Release the data + object properly. + +2006-09-22 Marcus Brinkmann + + * keylist.c (keylist_colon_handler): Move debug output after + initialising KEY. + +2006-07-29 Marcus Brinkmann + + * gpgme-config.in (Options): Add NETLIBS. + * Makefile.am (libgpgme_la_LIBADD, libgpgme_pthread_la_LIBADD, + libgpgme_pth_la_LIBADD, libgpgme_glib_la_LIBADD): Add NETLIBS. + + * rungpg.c (read_status): Fix comparison disguising as an + assignment. + +2005-03-24 Marcus Brinkmann + + * gpgme.c (gpgme_set_locale): Remove conditional on + HAVE_W32_SYSTEM, and just check for LC_MESSAGES. + +2006-07-16 Marcus Brinkmann + + * rungpg.c (read_status): Strip potential carriage return. + * genkey.c (get_key_parameter): Skip potential carriage return. + * version.c (_gpgme_get_program_version): Strip potential carriage + return. + + * data.c (gpgme_data_set_file_name): Allow to clear the file name + by passing NULL. + +2006-06-22 Marcus Brinkmann + + * keylist.c (gpgme_get_key): Also clone the engine info. + +2006-03-06 Marcus Brinkmann + + * gpgme-config.in (cflags_pth): Revert accidential removal of + pthread support with last change. + +2006-02-28 Marcus Brinkmann + + * w32-glib-io.c (O_BINARY) [!O_BINARY]: New macro. + (_gpgme_io_pipe): Open pipes in binary mode. + +2006-02-22 Marcus Brinkmann + + * engine.c (gpgme_engine_check_version): Reimplemented to allow + checking the version correctly even after changing the engine + information. Bug reported by Stéphane Corthésy. + + * rungpg.c (read_colon_line): Invoke colon preprocess handler if + it is set. + (colon_preprocessor_t): New type. + (struct engine_gpg): New member colon.preprocess_fnc. + (gpg_keylist_preprocess): New function. + * keylist.c (keylist_colon_handler): Allow short key IDs. + +2006-02-15 Marcus Brinkmann + + * w32-io.c (create_writer): Make C->have_data a manually resetted + event. + (writer): Move code from end of if block to beginning, so it + is also run the first time. + (_gpgme_io_write): Move assert check after error check. Reset + the is_empty event, and also do it eagerly. + (_gpgme_io_select): Unconditionally wait for the is_empty event. + +2006-01-26 Werner Koch + + * w32-util.c (_gpgme_get_conf_int): New. + * posix-util.c (_gpgme_get_conf_int): New. + * w32-io.c (get_desired_thread_priority): New. + (create_reader, create_writer): Use it here. + +2006-01-04 Werner Koch + + * debug.h (_gpgme_debug_srcname): New. Use it with the debug macros. + + * w32-glib-io.c (_gpgme_io_set_nonblocking): Add debug + statements. Disable error return for failed nonblocking call. + +2006-01-03 Marcus Brinkmann + + * w32-glib-io.c (_gpgme_io_close): Only close fd if there is no + channel for it. + +2005-12-31 Marcus Brinkmann + + * w32-glib-io.c (find_channel): Set channel to unbuffered. + (_gpgme_io_select): Fix debug output. + +2005-12-23 Werner Koch + + * gpgme.h (struct _gpgme_signature): Append field PKA_ADDRESS. + * verify.c (release_op_data, _gpgme_verify_status_handler): Set + this field. + +2005-12-20 Werner Koch + + * gpgme.h (gpgme_status_code_t): Added GPGME_STATUS_PKA_TRUST_BAD + and GPGME_STATUS_PKA_TRUST_GOOD. + (struct _gpgme_signature): New field pka_trust. + * verify.c (_gpgme_verify_status_handler): Set pka_trust. + +2005-12-06 Werner Koch + + * keylist.c (keylist_colon_handler): Store fingerprints of the + subkeys. Reset the secret flag of subkeys for stub secret keys. + (NR_FIELDS): Bumped up to 16 + +2005-11-27 Marcus Brinkmann + + * engine.c (_gpgme_set_engine_info): Use new_file_name in + engine_get_version invocation. Reported by Stéphane Corthésy. + +2005-11-24 Marcus Brinkmann + + * w32-glib-io.c (_gpgme_io_fd2str): Remove debug printf. + +2005-11-18 Werner Koch + + * w32-glib-io.c: Include glib.h before windows to avoid a symbol + shadowing warning. + (find_channel): Better use g_io_channel_win32_new_fd instead of + the autodetection function g_io_channel_unix_new. + (_gpgme_io_select): Rewritten. It is now a fully working select + implementation. + +2005-11-18 Marcus Brinkmann + + * priv-io.h (_gpgme_io_fd2str): New prototype. + * posix-io.c (_gpgme_io_fd2str): New function. + * w32-io.c (_gpgme_io_fd2str): New function. + * rungpg.c: Use this new function. + * w32-glib-io.c (_gpgme_io_fd2str): Rewrote the file handle code + again. Two's company, three's the musketeers. + + * w32-glib-io.c: Rewrote the file handle code. We don't create + system fds for every handle (doesn't work for inherited handles), + but we create pseudo fds in a private namespace that designate a + handle and potentially a giochannel. + +2005-11-18 Werner Koch + + * versioninfo.rc.in: Set file version to LT-version + Svn-revision. + +2005-11-17 Marcus Brinkmann + + * w32-glib-io.c: New file. + * gpgme.def (gpgme_get_giochannel): Add symbol. + * Makefile.am (system_components) [HAVE_DOSISH_SYSTEM]: Remove + w32-io.c. + (ltlib_gpgme_extra): New variable. + (lib_LTLIBRARIES): Add $(ltlib_gpgme_extra). + (system_components_not_extra): New variable. + (libgpgme_la_SOURCES, libgpgme_pthread_la_SOURCES, + (libgpgme_pth_la_SOURCES): Add $(system_components_not_extra). + (libgpgme_glib_la_LDFLAGS, libgpgme_glib_la_DEPENDENCIES, + (libgpgme_glib_la_LIBADD, libgpgme_glib_la_CFLAGS) + [BUILD_W32_GLIB]: New variables. + * gpgme-config.in (glib): New option. + * gpgme.m4 (AM_PATH_GPGME_GLIB): New macro. + +2005-11-17 Marcus Brinkmann + + * priv-io.h (_gpgme_io_waitpid, _gpgme_io_kill): Removed. + * w32-io.c (_gpgme_io_waitpid, _gpgme_io_kill): Removed. + * posix-io.c (_gpgme_io_kill): Removed. + (_gpgme_io_waitpid): Declare static. + +2005-10-24 Marcus Brinkmann + + * w32-io.c (_gpgme_io_spawn): Don't minimize window, hide it. + +2005-10-21 Werner Koch + + * Makefile.am: Fixed cut+paste problem + +2005-10-20 Marcus Brinkmann + + * Makefile.am: Build versioninfo.lo, not versioninfo.o. Also, fix + the whole mess. + +2005-10-16 Marcus Brinkmann + + * rungpg.c (gpg_edit): Don't add a key argument if in card edit + mode. + +2005-10-06 Marcus Brinkmann + + * Makefile.am (gpgme.dll gpgme.dll.a): Use $(srcdir) for + gpgme.def. + + * gpgme.h (gpgme_free): New prototype. + * data-mem.c (gpgme_free): New function. + * libgpgme.vers (GPGME_1.1): Add gpgme_free. + * gpgme.def: Add gpgme_free. + +2005-10-02 Marcus Brinkmann + + * util.h (_gpgme_decode_percent_string): Add new argument BINARY + to prototype. + * verify.c (parse_notation): Likewise for invocation. + * conversion.c (_gpgme_decode_percent_string): Likewise to + declaration. If set, do not replace '\0' characters with a + printable string. + * gpgme.h (struct _gpgme_key_sig): New field notations. + * ops.h (_gpgme_parse_notation): New prototype. + * sig-notation.c (_gpgme_parse_notation): New function. + * key.c (gpgme_key_unref): Free all signature notations. + * keylist.c (op_data_t): New member tmp_keysig. + (finish_key): Clear OPD->tmp_keysig. + * gpgme.c (gpgme_set_keylist_mode): Remove check. + * rungpg.c (gpg_keylist): Support listing signature notations. + (gpg_keylist_ext): Likewise. + +2005-10-01 Marcus Brinkmann + + * engine.h (_gpgme_set_engine_info): Add prototype. + * engine-backend.h (struct engine_ops): Change return type of + get_file_name() to const char * to silence gcc warning. + * engine.c (engine_get_file_name): Change return type to const + char * to silence gcc warning. + (gpgme_get_engine_info): Use transitional variable to go from + const char * to char * to silence gcc warning. + (_gpgme_set_engine_info): Likewise. + * engine-gpgsm.c (struct engine_gpgsm): Change type of LINE to + char * to silence gcc warning. + (gpgsm_new): Make ARGV a pointer to const char. + (status_handler): Change type of SRC, END, DST, ALINE and NEWLINE + to char * to silence gcc warning. + + * gpgme.def: Add gpgme_data_set_file_name, + gpgme_data_get_file_name, gpgme_sig_notation_clear, + gpgme_sig_notation_add and gpgme_sig_notation_get. + * libgpgme.vers: Add gpgme_sig_notation_clear, + gpgme_sig_notation_add and gpgme_sig_notation_get. + * Makefile.am (libgpgme_real_la_SOURCES): Add sig-notation.c. + * context.h (struct gpgme_context): New field sig_notations. + * gpgme.h (struct _gpgme_sig_notation): New member value_len and + critical. + (GPGME_SIG_NOTATION_CRITICAL): New symbol. + (gpgme_sig_notation_flags_t): New type. + (gpgme_sig_notation_add, gpgme_sig_notation_clear, + gpgme_sig_notation_get): New prototypes. + * ops.h (_gpgme_sig_notation_create, _gpgme_sig_notation_free): + New prototypes. + * sig-notation.c (_gpgme_sig_notation_free): New file. + * verify.c (parse_notation): Use support functions. + (release_op_data): Likewise. + * rungpg.c (append_args_from_sig_notations): New function. + (gpg_encrypt_sign, gpg_sign): Call it. + +2005-09-30 Marcus Brinkmann + + * data.h (struct gpgme_data): New member file_name. + * data.c (gpgme_data_set_filename): New function. + (_gpgme_data_release): Free DH->filename if necessary. + (gpgme_data_get_filename): New function. + * rungpg.c (gpg_encrypt): Set filename option. + (gpg_encrypt_sign): Likewise. + (gpg_sign): Likewise. + * libgpgme.vers (GPGME_1.1): Add gpgme_data_set_file_name and + gpgme_data_get_file_name. + + * decrpyt.c, verify.c, gpgme.h: Replace plaintext_filename with + file_name. + +2005-09-29 Marcus Brinkmann + + * gpgme.h (struct _gpgme_key): Add field is_qualified. + (struct _gpgme_subkey): Likewise. + * keylist.c (set_subkey_capability, set_mainkey_capability): Set + field is_qualified. + +2005-09-23 Werner Koch + + * w32-io.c (_gpgme_io_pipe): Removed use of environment variable + again. + (create_reader, create_writer): Set thread priority higher. + +2005-09-19 Werner Koch + + * w32-io.c (_gpgme_io_pipe): New environment variable to change + the size of the pipe buffer. + +2005-09-13 Werner Koch + + * ath.c: Changes to make it work under W32. + +2005-09-12 Marcus Brinkmann + + * Makefile.am (libgpgme_la_SOURCES): Set to ath.h and ath.c. + (ath_pth_src, ath_pthread_src): Removed. + (w32_o_files): Replace ath-compat.o with ath.o. + (libgpgme_pth_la_CFLAGS): New variable. + * ath-compat.c, ath-pthread-compat.c, ath-pth-compat.c: Removed. + * ath.h (ath_pthread_available, ath_pth_available): Removed. + (ath_init) [!_ATH_EXT_SYM_PREFIX]: Do not define macro. + (struct ath_ops, ath_init) [_ATH_COMPAT]: Removed. + (_ATH_COMPAT): Macro removed. + * posix-sema.c (_gpgme_sema_subsystem_init): Do not call + _gpgme_ath_init. + +2005-09-12 Marcus Brinkmann + + * keylist.c (release_op_data): Do not free opd->tmp_uid. + +2005-09-07 Werner Koch + + * w32-io.c (build_commandline): Quote argv[0]. + +2005-08-26 Marcus Brinkmann + + * rungpg.c (command_handler): Use _gpgme_io_write instead of write. + + * edit.c (command_handler): Do not depend on PROCESSED being + available. + + * engine.h (engine_command_handler_t): Add new argument processed. + * ops.h (_gpgme_passphrase_command_handler_internal): Rename + prototype to ... + (_gpgme_passphrase_command_handler): ... this one. + * passphrase.c (_gpgme_passphrase_command_handler_internal): + Rename to ... + (_gpgme_passphrase_command_handler): ... this one. + * edit.c (command_handler): Add new argument processed. Remove + local variable with the same name. Always return processed as + true. + * rungpg.c (command_handler): Send a newline character if the + handler did not. + +2005-08-26 Werner Koch + + * w32-util.c (read_w32_registry_string): Updated from code used by + GnuPG. This allows for expanding strings and features the + implicit fallback key. + (w32_shgetfolderpath, find_program_at_standard_place): New. + (_gpgme_get_gpg_path, _gpgme_get_gpgsm_path): With no registry + entry, locate the programs at the standard place. + (dlopen, dlsym, dlclose): New, so that we can keep on using what + we are accustomed to. + + * debug.c (debug_init): Use PATHSEP_C so that under W32 a + semicolon is used which allows us to create files with drive + letters. + + * w32-io.c (_gpgme_io_read, _gpgme_io_write): Print content in + debug mode too. + +2005-08-19 Werner Koch + + * gpgme.def: New. + * versioninfo.rc.in: New. + * Makefile.am: Addes support for building a W32 DLL. + + * ttyname_r.c (ttyname_r) [W32]: Return error. + * ath-compat.c [W32]: select and co are not yet supported; return + error. + * data-stream.c (stream_seek): Use ftell if ftello is not available. + +2005-08-08 Werner Koch + + * util.h (stpcpy): Renamed to .. + (_gpgme_stpcpy): .. this and made inline. This avoids duplicate + definitions when linking statically. + * stpcpy.c: Removed. + +2005-07-27 Marcus Brinkmann + + * gpgme.h (gpgme_status_code_t): Add GPGME_STATUS_PLAINTEXT. + (struct _gpgme_op_decrypt_result): New member plaintext_filename. + (struct _gpgme_op_verify_result): Likewise. + * ops.h (_gpgme_parse_plaintext): Add prototype. + * op-support.c (_gpgme_parse_plaintext): New function. + * decrypt.c (release_op_data): Release + OPD->result.plaintext_filename. + (_gpgme_decrypt_status_handler): Handle GPGME_STATUS_PLAINTEXT. + * verify.c (release_op_data): Release + OPD->result.plaintext_filename. + (_gpgme_verify_status_handler): Handle GPGME_STATUS_PLAINTEXT. + +2005-07-26 Marcus Brinkmann + + * keylist.c (gpgme_get_key): Allow key IDs. + +2005-06-20 Marcus Brinkmann + + * gpgme.m4: Only call GPGME_CONFIG if found. + +2005-06-03 Marcus Brinkmann + + * gpgme.h (struct _gpgme_signature): New members pubkey_algo and + hash_algo. + * verify.c (parse_valid_sig): Parse pubkey and hash algo numbers. + (parse_new_sig): Parse pubkey, hash algo and timestamp for ERRSIG. + + (_gpgme_decrypt_status_handler): Fix last change. + + * gpgme.h (struct _gpgme_recipient): New structure. + (gpgme_recipient_t): New type. + (struct _gpgme_op_decrypt_result): Add member recipients. + * decrypt.c (op_data_t): New member last_recipient_p. + (_gpgme_op_decrypt_init_result): Initialize last_recipient_p. + (parse_enc_to): New function. + (_gpgme_decrypt_status_handler): Handle status ENC_TO and + NO_SECKEY. + + * wait-global.c (gpgme_wait): Break out of the fd processing loop + after an error. + Reported by Igor Belyi . + +2005-06-02 Marcus Brinkmann + + * wait.h (_gpgme_run_io_cb): New prototype. + * wait.c (_gpgme_run_io_cb): New function. + * wait-global.c (gpgme_wait): Call it. + * wait-user.c (_gpgme_user_io_cb_handler): Likewise. + * wait-private.c (_gpgme_wait_on_condition): Likewise. + +2005-06-02 Werner Koch + + * passphrase.c (_gpgme_passphrase_status_handler): Take care of + GPGME_STATUS_NEED_PASSPHRASE_PIN. + (_gpgme_passphrase_command_handler_internal): Also act on the key + "passphrase.pin.ask". + + * gpgme.h: Added status codes GPGME_STATUS_SIG_SUBPACKET, + GPGME_STATUS_NEED_PASSPHRASE_PIN, GPGME_STATUS_SC_OP_FAILURE, + GPGME_STATUS_SC_OP_SUCCESS, GPGME_STATUS_CARDCTRL, + GPGME_STATUS_BACKUP_KEY_CREATED. + +2005-05-28 Marcus Brinkmann + + * data-user.c: Include . + +2005-05-17 Marcus Brinkmann + + * gpgme.c (gpgme_new): Set the CTX->include_certs default to the + default. + +2005-05-11 Marcus Brinkmann + + * w32-io.c (_gpgme_io_select): Fix loop increment. + +2005-05-05 Marcus Brinkmann + + * data-user.c (user_release): Only call user hook if provided. + (user_seek): Return EBADF if no user hook is provided. + (user_read): Likewise. + (user_write): Likewise. + +2005-04-28 Marcus Brinkmann + + * gpgme.h (GPGME_INCLUDE_CERTS_DEFAULT): New macro. + * engine-gpgsm.c (gpgsm_sign): Send the include-certs option after + the reset, just for cleanliness, and do not sent it at all if the + default is requested. + * gpgme.c (gpgme_set_include_certs): Allow to use + GPGME_INCLUDE_CERTS_DEFAULT. + +2005-04-21 Werner Koch + + * verify.c (calc_sig_summary): Set the key revoked bit. + +2005-04-14 Marcus Brinkmann + + * wait-global.c (gpgme_wait): Use LI->ctx when checking a context + in the list, not the user-provided CTX. + Reported by Igor Belyi . + + * wait-global.c (gpgme_wait): If no context is found, and we + should not hang, set *status to 0 and return NULL. + Reported by Igor Belyi . + +2005-03-24 Marcus Brinkmann + + * data.h (EOPNOTSUPP) [_WIN32]: Remove definition. + * data.c (EOPNOTSUPP) [HAVE_W32_SYSTEM]: Remove definition. + (gpgme_data_read, gpgme_data_write, gpgme_data_seek): Return + ENOSYS instead EOPNOTSUPP. + * data-compat.c (EOPNOTSUPP) [HAVE_W32_SYSTEM]: Remove definition. + (gpgme_error_to_errno): Map GPG_ERR_NOT_SUPPORTED + to ENOSYS. + +2005-03-24 Marcus Brinkmann + + * io.h: Rename to ... + * priv-io.h: ... this. + * Makefile.am (libgpgme_real_la_SOURCES): Change io.h to priv-io.h. + * data.c, engine-gpgsm.c, posix-io.c, rungpg.c, version.c, + w32-io.c, wait-private.c, wait-global.c, wait-user.c, wait.c: + Change all includes of "io.h" to "priv-io.h" + +2005-03-09 Werner Koch + + * w32-util.c (_gpgme_get_gpg_path, _gpgme_get_gpgsm_path): Do not + cast away type checks. + + * io.h [W32]: Do not include stdio.h. If it is needed do it at + the right place. + + * data.h [W32]: Removed kludge for EOPNOTSUP. + * data.c, data-compat.c [W32]: Explicitly test for it here. + + Replaced use of _WIN32 by HAVE_W32_SYSTEM except for public header + files. + +2005-03-07 Timo Schulz + + * gpgme.h: [_WIN32] Removed ssize_t typedef. + * ath.h: [_WIN32] Added some (dummy) types. + * io.h: [_WIN32] include stdio.h. + * data.h: [_WIN32] Define EOPNOTSUPP. + * w32-io.c [_WIN32] (_gpgme_io_subsystem_init): New. + * gpgme.c [_WIN32] (gpgme_set_locale): Disabled. + +2004-12-12 Marcus Brinkmann + + * engine.c (_gpgme_set_engine_info): Fix assertion. + +2004-12-11 Marcus Brinkmann + + * util.h [HAVE_CONFIG_H && HAVE_TTYNAME_R] (ttyname_r): Define + prototype. + * ttyname_r.c: New file. + +2004-12-07 Marcus Brinkmann + + * putc_unlocked.c, funopen.c: I just claim copyright on these + files and change their license to LGPL, because they are totally + trivial wrapper functions. + * isascii.c: Change copyright notice to the one from ctype/ctype.h + in the GNU C Library (CVS Head 2004-10-10), where isascii is + defined as a macro doing exactly the same as the function in this + file. + * memrchr.c: Update from the GNU C Library (CVS Head 2001-07-06). + * stpcpy.c: Update from the GNU C Library (CVS Head 2004-10-10). + * ath.c, ath-compat.c, ath.h, ath-pth.c, ath-pth-compat.c, + ath-pthread.c, ath-pthread-compat.c, context.h, conversion.c, + data.c, data-compat.c, data-fd.c, data.h, data-mem.c, + data-stream.c, data-user.c, debug.c, debug.h, decrypt.c, + decrypt-verify.c, delete.c, edit.c, encrypt.c, encrypt-sign.c, + engine-backend.h, engine.c, engine-gpgsm.c, engine.h, error.c, + export.c, genkey.c, get-env.c, gpgme.c, gpgme.h, import.c, io.h, + key.c, keylist.c, mkstatus, Makefile.am, ops.h, op-support.c, + passphrase.c, posix-io.c, posix-sema.c, posix-util.c, progress.c, + rungpg.c, sema.h, sign.c, signers.c, trust-item.c, trustlist.c, + util.h, verify.c, version.c, w32-io.c, w32-sema.c, w32-util.c, + wait.c, wait-global.c, wait.h, wait-private.c, wait-user.c: Change + license to LGPL. + +2004-12-07 Marcus Brinkmann + + * libgpgme.vers (GPGME_1.1): New version. + * engine-backend.h (struct engine_ops): Add argument FILE_NAME to + member get_version(). Add arguments FILE_NAME and HOME_DIR to + member new(). Change return type of get_file_name and get_version + to char *. + * engine-gpgsm.c (gpgsm_get_version): Change return type to char + pointer. Do not cache result. + (gpgsm_new): Add file_name and home_dir argument, and use them + instead of the defaults, if set. + * rungpg.c (struct engine_gpg): New member file_name. + (gpg_get_version): Change return type to char pointer, and do not + cache result. + (gpg_release): Free gpg->file_name. + (gpg_new): Take new arguments file_name and home_dir. Set the + --homedir argument if HOME_DIR is not NULL. Set gpg->file_name. + (start): Use gpg->file_name instead _gpgme_get_gpg_path, if set. + * engine.h (_gpgme_engine_info_copy, _gpgme_engine_info_release): + New prototypes. + (_gpgme_engine_new): Change first argument to gpgme_engine_info_t + info. + * engine.c: Include . + (gpgme_get_engine_info): Set *INFO within the lock. Move + ENGINE_INFO and ENGINE_INFO_LOCK to .... + (engine_info, engine_info_lock): ... here. New static variables. + (engine_get_version): Add file_name argument to + get_version invocation. Change return type to char pointer. + (gpgme_engine_check_version): Rewritten to free() the return value + of engine_get_version after using it. + (_gpgme_engine_info_release): New function. + (gpgme_get_engine_info): Rewritten. + (_gpgme_engine_info_copy): New function. + (_gpgme_set_engine_info): New function. + (gpgme_set_engine_info): New function. + (_gpgme_engine_new): Change first argument to gpgme_engine_info_t + info, and use that. + * gpgme.h (struct _gpgme_engine_info): Change type of file_name + and version to char * (remove the const). New member home_dir. + (gpgme_set_engine_info, gpgme_ctx_get_engine_info, + gpgme_ctx_set_engine_info): New prototypes. + * context.h (struct gpgme_context): New member engine_info. + * gpgme.c (gpgme_new): Allocate CTX->engine_info. + (gpgme_release): Deallocate CTX->engine_info. + (gpgme_ctx_get_engine_info, gpgme_ctx_set_engine_info): New + functions. + * op-support.c (_gpgme_op_reset): Look for correct engine info and + pass it to _gpgme_engine_new. + * version.c (gpgme_check_version): Adjust to + _gpgme_compare_versions returning an int. + (_gpgme_compare_versions): Return an int value, not a const char + pointer. + * ops.h (_gpgme_compare_versions): Same for prototype. + +2004-10-03 Marcus Brinkmann + + * verify.c (parse_trust): If no reason is provided, set + SIG->validity_reason to 0. + (calc_sig_summary): Set GPGME_SIGSUM_CRL_TOO_OLD if appropriate. + +2004-10-22 Marcus Brinkmann + + * engine-gpgsm.c (map_assuan_error): Return 0 if ERR is 0. + (start): Call map_assuan_error on return value of + assuan_write_line. + +2004-10-05 Marcus Brinkmann + + * op-support.c (_gpgme_op_data_lookup): Use char pointer for + pointer arithmetic. + +2004-09-30 Marcus Brinkmann + + * gpgme.m4: Implement the --api-version check. + + * rungpg.c (read_status): Move the polling of the output data pipe + to just before removing the command fd, from just before adding + it. This avoids buffering problems. + + * data.c (_gpgme_data_inbound_handler): Use _gpgme_io_read, not + read, to improve debug output. + +2004-09-29 Marcus Brinkmann + + * gpgme.h (GPGME_IMPORT_NEW, GPGME_IMPORT_UID, GPGME_IMPORT_SIG, + GPGME_IMPORT_SUBKEY, GPGME_IMPORT_SECRET, + (GPGME_KEYLIST_MODE_LOCAL, GPGME_KEYLIST_MODERN_EXTERN, + GPGME_KEYLIST_MODE_SIGS, GPGME_KEYLIST_MODE_VALIDATE): Change from + enum to macros. + (gpgme_keylist_mode_t): Define as unsigned int. + (gpgme_key_t): Change type of keylist_mode to + gpgme_keylist_mode_t. + +2004-09-23 Marcus Brinkmann + + * data.c (_gpgme_data_outbound_handler): Close the file descriptor + if we get an EPIPE. + + * data-stream.c (stream_seek): Call ftello and return the current + offset. + * data.h (struct gpgme_data): Change type of data.mem.offset to + off_t. + * data.c (gpgme_data_seek): Check dh->cbs->seek callback, not read + callback. If SEEK_CUR, adjust the offset by the pending buffer + size. Clear pending buffer on success. + + +2004-09-14 Marcus Brinkmann + + * gpgme.m4: Add copyright notice. + +2004-08-18 Marcus Brinkmann + + * passphrase.c (_gpgme_passphrase_status_handler): Always run the + status handler. + +2004-08-17 Marcus Brinkmann + + * rungpg.c (build_argv): Use --no-sk-comment, not --no-comment. + +2004-06-23 Marcus Brinkmann + + * key.c (_gpgme_key_append_name): Make sure tail points to the + byte following the uid. + (_gpgme_key_add_sig): Likewise. Don't use calloc, but malloc and + memset. + +2004-06-02 Marcus Brinkmann + + * libgpgme.vers: Remove C-style comment, which is not supported by + older binutils. + +2004-05-21 Marcus Brinkmann + + * gpgme-config.in (Options): Support --api-version. + + * libgpgme.vers: List all gpgme symbols under version GPGME_1.0. + + * decrypt.c (_gpgme_decrypt_status_handler): Fix last change. + * verify.c (parse_error): Likewise. + + * verify.c (parse_error): Do not skip location of where token. + + * gpgme.h (gpgme_status_code_t): Add GPGME_STATUS_REVKEYSIG. + * verify.c (_gpgme_verify_status_handler): Add handling of + GPGME_STATUS_REVKEYSIG. + (parse_trust): Likewise. + +2004-05-21 Marcus Brinkmann + + * gpgme.h (struct _gpgme_decrypt_result): New fields + wrong_key_usage and _unused. + * decrypt.c (_gpgme_decrypt_status_handler): Don't skip over + character after a matched string, as in a protocol error this + could skip over the trailing binary zero. + Handle decrypt.keyusage error notifications. + + * gpgme.h (struct _gpgme_key): New member keylist_mode. + * keylist.c (keylist_colon_handler): Set the keylist_mode of KEY. + +2004-04-29 Marcus Brinkmann + + * gpgme.h (struct _gpgme_signature): Change member WRONG_KEY_USAGE + to unsigned int. Same for member _unused. + + * keylist.c (set_mainkey_trust_info): Rewritten. + (set_subkey_capability): Handle 'd' (disabled). + (set_mainkey_capability): Rewritten. + +2004-04-22 Marcus Brinkmann + + * gpgme.m4: Quote first argument to AC_DEFUN. + +2004-04-21 Werner Koch + + * key.c (gpgme_key_unref): Allow passing NULL like free does. + The rule of least surprise. + +2004-04-15 Werner Koch + + * verify.c (prepare_new_sig, _gpgme_verify_status_handler): Remove + unused result.signatures items. + + * keylist.c (gpgme_get_key): Return an error if FPR is NULL. + +2004-04-08 Werner Koch + + * verify.c (_gpgme_verify_status_handler): Ignore the error status + if we can't process it. + * decrypt-verify.c (decrypt_verify_status_handler): Backed out + yesterday's hack. It is not any longer required. + +2004-04-07 Werner Koch + + * decrypt-verify.c (decrypt_verify_status_handler): Hack to cope + with meaningless error codes from the verify status function. + +2004-04-05 Werner Koch + + * gpgme.h: Add GPGME_STATUS_NEWSIG. + + * verify.c (parse_error): Compare only the last part of the where + token. + (prepare_new_sig): New. + (parse_new_sig): Use prepare_new_sig when required. + (_gpgme_verify_status_handler): Handle STATUS_NEWSIG. + + * engine-gpgsm.c (gpgsm_keylist_ext): Send with-validation + option. Fixed pattern construction. + (status_handler): Add debugging output. + +2004-03-23 Marcus Brinkmann + + * engine-gpgsm.c (gpgsm_new): Protect _only_ tty related code with + isatty(). Submitted by Bernhard Herzog. + +2004-03-11 Marcus Brinkmann + + * engine-gpgsm.c (gpgsm_new): Protect all tty related code with + isatty(). + + * rungpg.c (gpg_cancel): Set GPG->fd_data_map to NULL after + releasing it. + * engine-gpgsm.c (gpgsm_cancel): Only call assuan_disconnect if + GPGSM->assuan_ctx is not NULL. Set it to NULL afterwards. + +2004-03-07 Marcus Brinkmann + + * gpgme-config.in: Do not emit include and lib directory for + prefix "/usr" or "". + +2004-03-03 Werner Koch + + * engine-gpgsm.c (gpgsm_export_ext): Properly insert a space + beween patterns. + +2004-02-18 Werner Koch + + * gpgme-config.in: Ignore setting of --prefix. + +2004-02-25 Marcus Brinkmann + + * rungpg.c (gpg_cancel): New function. + (gpg_release): Call it here. + (_gpgme_engine_ops_gpg): Add it here. + * engine-gpgsm.c (gpgsm_cancel): Fix last change. + +2004-02-24 Marcus Brinkmann + + * gpgme.c (gpgme_cancel): New function. + * engine-backend.h (struct engine_ops): New member cancel. + * engine.h (_gpgme_engine_cancel): New prototype. + * engine.c (_gpgme_engine_cancel): New function. + * engine-gpgsm.c (_gpgme_engine_ops_gpgsm): Add new member cancel. + (gpgsm_cancel): New function. + (gpgsm_release): Use it. + * rungpg.c (_gpgme_engine_ops_gpg): Add new member cancel. + +2004-02-17 Werner Koch + + * gpgme.h: Add GPGME_KEYLIST_MODE_VALIDATE. + * engine-gpgsm.c (gpgsm_keylist): Send this to gpgsm. + +2004-02-15 Werner Koch + + * memrchr.c (memrchr): Fixed implementation. Problem pointed out + by Adriaan de Groot. + +2004-02-01 Marcus Brinkmann + + * rungpg.c (build_argv): Use --no-comment, not --comment "". + + * data-compat.c (gpgme_data_new_from_filepart): Call fseeko if + available. + * data-stream.c (stream_seek): Likewise. + +2004-01-16 Werner Koch + + * conversion.c (_gpgme_map_gnupg_error): Handle numerical codes as + used by GnuPG 1.9.x + +2004-01-13 Marcus Brinkmann + + * gpgme.h (struct _gpgme_key_sig): Fix comment on REVOKED. + +2004-01-12 Werner Koch + + * sign.c: Include util.h for prototype of _gpgme_parse_timestamp. + +2003-12-25 Marcus Brinkmann + + * gpgme.h (_GPGME_D_CLASS): Revert this change. + (struct _gpgme_key_sig): For C++ compilers, rename class + member to _obsolete_class. Add new member sig_class. + (struct _gpgme_new_signature): Same here. + * key.c (gpgme_key_sig_get_ulong_attr): Use CERTSIG->sig_class, + not CERTSIG->class. + * keylist.c (keylist_colon_handler): Likewise for KEYSIG, but keep + setting KEYSIG->class, too. Rename variable CLASS to SIG_CLASS. + * sign.c (parse_sig_created): Set SIG->sig_class. + +2003-12-22 Werner Koch + + * gpgme.h (_GPGME_D_CLASS): Kludge for C++ compatibility without + changing the C API. + +2003-11-19 Werner Koch + + * conversion.c (_gpgme_parse_timestamp): New. + (atoi_1, atoi_2, atoi_4): New. + * keylist.c (parse_timestamp): Removed. Changed all callers to use + the new function. + * verify.c (parse_valid_sig): Ditto. Repalced the errno check. + * sign.c (parse_sig_created): Ditto. + +2003-10-31 Werner Koch + + * keylist.c (parse_timestamp): Detect ISO 8601 timestamps and try + to convert them. + +2003-10-10 Marcus Brinkmann + + * genkey.c (get_key_parameter): Make a copy of the key parameters. + Submitted by Miguel Coca . + +2003-10-06 Marcus Brinkmann + + * data-compat.c: Include before for + broken systems. + + * engine-gpgsm.c (map_assuan_error): If ERR is -1, return sensible + error. + + * io.h (_gpgme_io_subsystem_init): New prototype. + * posix-io.c (_gpgme_io_subsystem_init): Add function. + (_gpgme_io_spawn): Do not fixup signal handler here. + * version.c (do_subsystem_inits): Call _gpgme_io_subsystem_init. + + * debug.c (debug_init): Drop const qualifier from E. + + * ath.h (struct ath_ops): Make ADDR argument of CONNECT prototype + const. + (ath_connect): Make ADDR argument const. + * ath-pthread.c (ath_connect): Likewise. + * ath-pth.c (ath_connect): Likewise. + * ath-compat.c (ath_connect): Likewise. + * ath.c (ath_connect): Likewise. + + * ath.h [HAVE_SYS_SELECT_H]: Include for fd_set. + [!HAVE_SYS_SELECT_H]: Include . + + * conversion.c (_gpgme_hextobyte): Drop "unsigned" from type of + SRC argument. + * util.h (_gpgme_hextobyte): Likewise for prototype. + + * gpgme.h: Remove trailing comma in enum. + + * rungpg.c: Do not include , , , + , , or "unistd.h". + +2003-10-02 Marcus Brinkmann + + * engine-backend.h (struct engine_ops): Add argument TYPE. + * engine.c (_gpgme_engine_op_edit): Likewise. + * engine.h: Likewise. + * rungpg.c (gpg_edit): Likewise. Use it. + * edit.c (edit_start): Likewise. Pass it on. + (gpgme_op_edit_start, gpgme_op_edit): Likewise. + (gpgme_op_card_edit_start, gpgme_op_card_edit): New functions. + +2003-09-30 Marcus Brinkmann + + * gpgme.h (gpg_strerror_r): Change prototype to match + gpg_strerror_r change. + * error.c (gpg_strerror_r): Likewise, also update implementation. + + * gpgme.c (gpgme_hash_algo_name): Change name of RMD160 to + RIPEMD160, name of TIGER to TIGER192, name of CRC32-RFC1510 to + CRC32RFC1510, and name of CRC24-RFC2440 to CRC24RFC2440. + +2003-09-14 Marcus Brinkmann + + * gpgme.h: Add prototype for gpgme_set_locale. + + * gpgme.h: Define macro _GPGME_INLINE depending on the compiler + characteristics and use that instead __inline__. + + * context.h (struct gpgme_context): New members lc_ctype and + lc_messages. + * gpgme.c: Include . + (def_lc_lock, def_lc_ctype, def_lc_messages): New static + variables. + (gpgme_set_locale): New function. + * engine.c (_gpgme_engine_new): Add arguments lc_ctype and + lc_messages. + * engine.h (_gpgme_engine_new): Likewise. + * engine-gpgsm.c (gpgsm_new): Likewise. + * rungpg.c (gpg_new): Likewise. + * engine-backend.h (struct engine_ops): Likewise to NEW. + * op-support.c (_gpgme_op_reset): Likewise to invocation of + _gpgme_engine_new. + +2003-09-13 Marcus Brinkmann + + * gpgme.h (gpgme_strerror_r): New prototype. + * error.c (gpgme_strerror_r): New function. + + * get-env.c: New file. + * util.h (_gpgme_getenv): Add prototype. + * Makefile.am (libgpgme_real_la_SOURCES): Add get-env.c. + * rungpg.c (build_argv): Use _gpgme_getenv. + * debug.c (debug_init): Likewise. + * engine-gpgsm.c (gpgsm_new): Likewise. + (gpgsm_new): Use ttyname_r. + * w32-io.c (_gpgme_io_spawn): Disable debugging for now. + +2003-09-03 Marcus Brinkmann + + * gpgme-config.in: Use $libdir, not @libdir@, for the echo + command. + + * gpgme-config.in: Rewritten. + * gpgme.m4: Rewritten. + +2003-08-19 Marcus Brinkmann + + The ath files (ath.h, ath.c, ath-pth.c, ath-pthread.c, + ath-compat.c, ath-pth-compat.c and ath-pthread-compat.c) have been + updated to have better thread support, and the Makefile.am was + changed to reflect that. + + * util.h [!HAVE_FOPENCOOKIE]: Remove fopencookie declaration. + * engine-gpgsm.c (gpgsm_assuan_simple_command): Set ERR to return + value of status_fnc. + * rungpg.c (start): Return SAVED_ERRNO, not errno. + +2003-08-18 Marcus Brinkmann + + * rungpg.c (start): Use saved_errno instead errno. + +2003-08-18 Marcus Brinkmann + + * funopen.c, putc_unlocked.c, isascii.c, memrchr.c: New files. + * fopencookie.c: File removed. + +2003-08-15 Marcus Brinkmann + + * gpgme-config.in: Put gpg-error related flags after gpgme's. + +2003-08-14 Marcus Brinkmann + + * gpgme.h (struct _gpgme_new_signature): Rename member CLASS to + _OBSOLETE_CLASS, add member CLASS with type unsigned int. + * sign.c (parse_sig_created): Also set SIG->_unused_class for + backward compatibility. + +2003-08-04 Marcus Brinkmann + + * verify.c (parse_new_sig): Fix status parsing case. + +2003-07-31 Marcus Brinkmann + + * gpgme.h (struct _gpgme_subkey): Add flag CAN_AUTHENTICATE. + Lower _UNUSED to 23 bits. + (struct _gpgme_key): Likewise. + * keylist.c (set_mainkey_capability): Support 'a' and 'A'. + (set_subkey_capability): Support 'a'. + + * keylist.c (gpgme_get_key): Check if there is more than one key + listed, and return GPG_ERR_AMBIGUOUS_NAME in that case. + + * util.h (_gpgme_decode_c_string): Change type of LEN argument to + size_t. + (_gpgme_decode_percent_string): Likewise. + * conversion.c (_gpgme_decode_c_string): Likewise. + (_gpgme_decode_percent_string): Likewise. + (_gpgme_map_gnupg_error): Change type of I to unsigned int. + * signers.c (gpgme_signers_clear): Likewise. + (gpgme_signers_enum): New unsigned variable SEQNO, set to SEQ. + Use SEQNO instead SEQ. + * wait.c (fd_table_put): Change type of I and J to unsigned int. + * wait-global.c (_gpgme_wait_global_event_cb): Change type of IDX + to unsigned int. + (gpgme_wait): Change type of I and IDX to unsigned int. + * wait-private.c (_gpgme_wait_on_condition): Change type of IDX + and I to unsigned int. + * posix-io.c (_gpgme_io_close): Cast return value of macro DIM to + int to suppress gcc warning. + (_gpgme_io_set_close_notify): Likewise. + (_gpgme_io_select): Change type of I to unsigned int. + * engine.c (gpgme_get_engine_info): Change type of PROTO to + unsigned int. + * wait-user.c (_gpgme_user_io_cb_handler): Change type of IDX and + I to unsigned int. + +2003-07-29 Marcus Brinkmann + + * decrypt-verify.c (decrypt_verify_status_handler): Expand silly + and wrong expression. + * encrypt-sign.c (encrypt_sign_status_handler): Likewise. + * encrypt.c (encrypt_sym_status_handler): Likewise. + * sign.c (sign_status_handler): Likewise. + * verify.c (verify_status_handler): Likewise. + * decrypt.c (decrypt_status_handler): Likewise. + + * engine.c (gpgme_get_engine_info): Initialize NULL. + +2003-07-23 Marcus Brinkmann + + * gpgme-config.in (gpg_error_libs): Quote GPG_ERROR_CFLAGS and + GPG_ERROR_LIBS when setting the corresponding variables. + Reported by Stéphane Corthésy. + +2003-07-22 Marcus Brinkmann + + * engine-gpgsm.c (set_recipients): Move declaration of NEWLEN to + the beginning of the block. + +2003-06-22 Marcus Brinkmann + + * data-mem.c (mem_write): Copy original buffer content. + +2003-06-22 Marcus Brinkmann + + * gpgme.h (gpgme_user_ids_release, gpgme_user_ids_append): Remove + prototypes. + +2003-06-06 Marcus Brinkmann + + * Makefile.am (AM_CPPFLAGS): Add @GPG_ERROR_CFLAGS@. + * gpgme-config.in (gpg_error_libs, gpg_error_cflags): New variables. + Print them. + + * op-support.c (_gpgme_parse_inv_userid): Rename to + _gpgme_parse_inv_recp and change to new datatype. + * ops.h (_gpgme_parse_inv_key): Fix prototype. + * gpgme.h (struct _gpgme_invalid_user_id): Rename to + __gpgme_invalid_key. Rename field ID to KEY. + (gpgme_invalid_user_id_t): Rename to gpgme_invalid_key_t. + (struct _gpgme_op_encrypt_result): Here, too. + (struct _gpgme_op_sign_result): Likewise. + * encrypt.c (struct op_data): Likewise. + (release_op_data): Likewise. + * sign.c (struct op_data): Likewise. + (release_op_data): Likewise. + + * posix-io.c (_gpgme_io_read): Save errno across debug calls. + (_gpgme_io_write): Likewise. + (_gpgme_io_pipe): Likewise. + (_gpgme_io_select): Likewise. + + * rungpg.c (struct engine_gpg): Remove arg_error. + (add_arg): Don't set arg_error. + (add_data): Likewise. + (start): Don't check arg_error. + (gpg_new): Check return value of add_arg. + * verify.c (parse_notation): Free allocated memory at error. + +2003-06-05 Marcus Brinkmann + + Everywhere: Use libgpg-error error codes. + + * Makefile.am (EXTRA_DIST): Remove mkerrors. + (BUILT_SOURCES): Remove errors.c. + (MOSTLYCLEANFILES): Likewise. + (libgpgme_la_SOURCES): Likewise. Add error.c. + (errors.c): Remove target. + * mkerrors: File removed. + * error.c: New file. + + * gpgme.h (gpgme_error_t): Change to type gpg_error_t. + (gpgme_err_code_t, gpgme_err_source_t): New types. + (gpgme_err_code, gpgme_err_source, gpgme_error, gpgme_err_make): + New static inline functions. + (gpgme_strsource, gpgme_err_code_from_errno, + gpgme_err_code_to_errno, gpgme_err_make_from_errno, + gpgme_error_from_errno): New prototypes. + +2003-05-29 Marcus Brinkmann + + * gpgme.h (gpgme_op_export_start): Change second arg to const char *. + (gpgme_op_export): Likewise. + (gpgme_op_export_ext_start): New prototype. + (gpgme_op_export_ext): Likewise. + * engine.h: Likewise for _gpgme_engine_op_export and + _gpgme_engine_op_export_ext. + * engine-backend.h (struct engine_ops): Change second argument of + prototype of export to const char *, and add reserverd int as + third argument. Add prototype for export_ext. + * engine.c (_gpgme_engine_op_export_ext): New function. + (_gpgme_engine_op_export): Change second argument of prototype of + export to const char *, and add reserverd int as third argument. + * rungpg.c (gpg_export): Change second argument of prototype of + export to const char *, and add reserverd int as third argument. + (gpg_export_ext): New function. + (gpg_keylist_ext): Break loop at error. + (_gpgme_engine_ops_gpg): Add gpg_export_ext. + * engine-gpgsm.c (gpgsm_export): Change second argument of + prototype of export to const char *, and add reserverd int as + third argument. + (gpgsm_export_ext): New function. + (_gpgme_engine_ops_gpgsm): Add gpgsm_export_ext. + * export.c (export_start): Change second argument of prototype of + export to const char *, and add reserverd int as third argument. + (gpgme_op_export_start): Likewise. + (export_ext_start): New function. + (gpgme_op_export_ext_start): Likewise. + (gpgme_op_export_ext): Likewise. + + * gpgme.h (gpgme_keylist_mode_t): New type for anonymous enum. + (gpgme_sigsum_t): New type for anonymous enum. + + * encrypt-sign.c (encrypt_sign_start): Check for errors earlier, + and return an error if RECP is not set. + + * Makefile.am (libgpgme_la_SOURCES): Remove user-id.c. + * user-id.c: Remove file. + * ops.h: Remove prototype for _gpgme_user_ids_all_valid. + * gpgme.h (gpgme_encrypt_flags_t): New type. + (gpgme_op_encrypt_start): Change second parameter to type + gpgme_key_t[], and add third parameter. + (gpgme_op_encrypt): Likewise. + (gpgme_op_encrypt_sign_start): Likewise. + (gpgme_op_encrypt_sign): Likewise. + * encrypt.c (encrypt_start): Likewise. + (gpgme_op_encrypt_start): Likewise. + (gpgme_op_encrypt): Likewise. Pass flags to engine. + * encrypt-sign.c (encrypt_sign_start): Likewise. + (gpgme_op_encrypt_sign_start): Likewise. + (gpgme_op_encrypt_sign): Likewise. + * engine-backend.h (struct engine_ops): Likewise for prototypes of + encrypt and encrypt_sign. + * engine.h: Likewise for prototypes of _gpgme_engine_op_encrypt + and _gpgme_engine_op_encrypt_sign. + * engine.c (_gpgme_engine_op_encrypt): Likewise. + (_gpgme_engine_op_encrypt_sign): Likewise. + * rungpg.c (gpg_encrypt): Likewise. + (gpg_encrypt_sign): Likewise. + * rungpg.c (gpg_encrypt): Check flags for always trust option. + * engine-gpgsm.c (gpgsm_encrypt): Likewise. + (set_recipients): Rewritten to use keys instead user IDs. + * rungpg.c (append_args_from_recipients): Rewritten to use keys + instead user IDs. + * encrypt.c (_gpgme_encrypt_status_handler): Change errors + returned to GPGME_Invalid_Key and GPGME_General_Error. + +2003-05-28 Marcus Brinkmann + + * engine-gpgsm.c: Rename GpgsmObject to engine_gpgsm_t. + (struct gpgsm_object_s): Rename to struct engine_gpgsm. + * rungpg.c: Rename GpgObject to engine_gpg_t. + (struct gpg_object_s): Rename to struct engine_gpg. + + * context.h (struct gpgme_context): Change EngineObject to + engine_object_t. + (enum ctx_op_data_type): Rename to ctx_op_data_id_t. + (ctx_op_data_t): New type. + (struct gpgme_context): Use it. + * ops.h (_gpgme_op_data_lookup): Use new type name. + * op-support.c (_gpgme_op_data_lookup): Likewise. + * engine.c: Rename EngineObject to engine_t in the file. Also + EngineStatusHandler to engine_status_handler_t, + EngineCommandHandler to engine_command_handler_t and + EngineColonLineHandler to engine_colon_line_handler. + * rungpg.c (start): Likewise. + * engine-gpgsm.c: Likewise. + * engine-backend.h (struct engine_ops): Likewise + * engine.h (struct engine_object_s): Rename to struct engine. + (EngineObject): Rename to engine_t. Also everywhere else in the + file. + (EngineStatusHandler): Rename to engine_status_handler_t. + (EngineColonLineHandler): Rename to engine_colon_line_handler_t. + (EngineCommandHandler): Rename to engine_command_handler_t. + + * engine-gpgsm.c (gpgsm_export): Fix bug in last change. + + * Makefile.am (libgpgme_la_SOURCES): Remove recipient.c, add + user-id.c. + * gpgme.h (gpgme_recipients_t): Removed. + (gpgme_recipients_new, gpgme_recipients_release, + gpgme_recipients_add_name, + gpgme_recipients_add_name_with_validity, gpgme_recipients_count, + gpgme_recipients_enum_open, gpgme_recipients_enum_read, + gpgme_recipients_enum_close): Removed. + (gpgme_op_encrypt, gpgme_op_encrypt_start, gpgme_op_encrypt_sign, + gpgme_op_encrypt_sign_start, gpgme_op_export_start, + gpgme_op_export): Change second argument to gpgme_user_id_t. + (gpgme_user_ids_release): New prototype. + (gpgme_user_ids_append): Likewise. + * ops.h (_gpgme_recipients_all_valid): Remove. + (_gpgme_user_ids_all_valid): Add. + * context.h (struct gpgme_recipients): Removed. + * user-id.c: New file. + * recipient.c: Removed file. + * rungpg.c (append_args_from_recipients): Change last arg to + gpgme_user_id_t. Reimplement. + (gpg_encrypt): Change second arg to gpgme_user_id_t. + (gpg_encrypt_sign): Likewise. + (gpg_export): Likewise. Rewrite user ID list code. + * engine.c (_gpgme_engine_op_encrypt): Change second arg to + gpgme_user_id_t. + (_gpgme_engine_op_encrypt_sign): Likewise. + (_gpgme_engine_op_export): Likewise. + * engine.h (_gpgme_engine_op_encrypt, _gpgme_engine_op_encrypt_sign, + _gpgme_engine_op_export): Likewise. + * engine-gpgsm.c (set_recipients): Likewise. Rewrite loop code. + (gpgsm_encrypt): Likewise. + (gpgsm_export): Likewise. + * engine-backend.h (struct engine_ops): Likewise for members + ENCRYPT, ENCRYPT_SIGN and EXPORT. + * export.c (export_start, gpgme_op_export_start, gpgme_op_export): + Likewise. + * encrypt.c (encrypt_start): Likewise. Don't check for count of + recipients. + (gpgme_op_encrypt_start): Likewise. + (gpgme_op_encrypt): Likewise. + * encrypt-sign.c (encrypt_sign_start): Likewise. + (gpgme_op_encrypt_sign): Likewise. + (gpgme_op_encrypt_sign_start): Likewise. + +2003-05-27 Marcus Brinkmann + + * gpgme.h (struct _gpgme_op_import_result): Add skipped_new_keys. + * import.c (parse_import_res): Add skipped_new_keys parser. + + * op-support.c (_gpgme_parse_inv_userid): Add missing break + statements. + * encrypt.c (gpgme_op_encrypt): Use gpgme_error_t instead of int. + +2003-05-27 Marcus Brinkmann + + * encrypt.c (gpgme_op_encrypt_result): Use intermediate variable + HOOK to avoid compiler warning. Don't ask, you don't want to know. + (_gpgme_encrypt_status_handler): Likewise. + (_gpgme_op_encrypt_init_result): Likewise. + * decrypt.c (gpgme_op_decrypt_result): Likewise. + (_gpgme_decrypt_status_handler): Likewise. + (_gpgme_op_decrypt_init_result): Likewise. + * verify.c (gpgme_op_verify_result): Likewise. + (_gpgme_verify_status_handler): Likewise. + (_gpgme_op_verify_init_result): Likewise. + * edit.c (edit_status_handler): Likewise. + (command_handler): Likewise. + (edit_start): Likewise. + * genkey.c (gpgme_op_genkey_result): Likewise. + (genkey_status_handler): Likewise. + (genkey_start): Likewise. + * import.c (gpgme_op_import_result): Likewise. + (import_status_handler): Likewise. + (_gpgme_op_import_start): Likewise. + * trustlist.c (gpgme_op_trustlist_next): Likewise. + (_gpgme_op_trustlist_event_cb): Likewise. + (gpgme_op_trustlist_start): Likewise. + * keylist.c (gpgme_op_keylist_result): Likewise. + (keylist_colon_handler): Likewise. + (keylist_status_handler): Likewise. + (_gpgme_op_keylist_event_cb): Likewise. + (gpgme_op_keylist_start): Likewise. + (gpgme_op_keylist_ext_start): Likewise. + (gpgme_op_keylist_next): Likewise. + * passphrase.c (_gpgme_passphrase_status_handler): Likewise. + (_gpgme_passphrase_command_handler_internal): Likewise. + * sign.c (gpgme_op_sign_result): Likewise. + (_gpgme_sign_status_handler): Likewise. + (_gpgme_op_sign_init_result): Likewise. + + * passphrase.c (_gpgme_passphrase_command_handler_internal): Fix + access to pointer type. + +2003-05-26 Marcus Brinkmann + + * engine.h (EngineCommandHandler): Change last argument to int fd. + * gpgme.h (gpgme_passphrase_cb_t): Rewritten to take parts of the + description and fd. + (gpgme_edit_cb_t): Change last argument to int fd. + * ops.h (_gpgme_passphrase_command_handler_internal): New prototype. + * passphrase.c: Include . + (op_data_t): Rename userid_hint to uid_hint, remove last_pw_handle. + (release_op_data): Check values before calling free. + (_gpgme_passphrase_status_handler): Likewise. + (_gpgme_passphrase_command_handler_internal): New function. + (_gpgme_passphrase_command_handler): Rewritten. + * edit.c (edit_status_handler): Pass -1 as fd argument. + (command_handler): Update prototype. New variable processed. Use + it to store return value of + _gpgme_passphrase_command_handler_internal which is now used + instead _gpgme_passphrase_command_handler. Use it also to check + if we should call the user's edit function. Pass fd to user's + edit function. + * rungpg.c (struct gpg_object_s): Change type of cmd.cb_data to + void *. + (gpg_release): Check value before calling free. Do not release + cmd.cb_data. + (command_cb): Function removed. + (command_handler): New function. Thus we don't use a data object + for command handler stuff anymore, but handle it directly. This + allows proper error reporting (cancel of passphrase requests, for + example). Also all callbacks work via direct writes to the file + descriptor (so that passphrases are not kept in insecure memory). + (gpg_set_command_handler): Rewritten to use even more ugly hacks. + (read_status): Check cmd.keyword before calling free. Install + command_handler as the I/O callback handler with GPG as private + data. + + * rungpg.c (gpg_new): Add --enable-progress-filter to gpg + invocation. + * decrypt-verify.c (_gpgme_op_decrypt_verify_start): Rename to + decrypt_verify_start. + (gpgme_op_decrypt_verify_start): Call decrypt_verify_start. + (gpgme_op_decrypt_verify): Likewise. + * verify.c (verify_status_handler): New function that also calls + progress status handler. + (_gpgme_op_verify_start): Set status handler to verify_status_handler. + Rename to (verify_start). + (gpgme_op_verify_start): Call verify_start. + (gpgme_op_verify): Likewise. + * encrypt.c (encrypt_status_handler): New function. + (_gpgme_encrypt_sym_status_handler): Call progress status handler. + Make static. Rename to encrypt_sym_status_handler. + (encrypt_start): Set status handler to encrypt_sym_status_handler + or encrypt_status_handler. + * sign.c (sign_status_handler): New function. + (sign_start): Set status handler to sign_status_handler. + * decrypt.c (decrypt_status_handler): New function that also calls + progress status handler. + (decrypt_start): Set status handler to decrypt_status_handler. + * encrypt-sign.c (encrypt_sign_status_handler): Likewise. + * decrypt-verify.c (decrypt_verify_status_handler): Call + _gpgme_progress_status_handler. + + * conversion.c (_gpgme_decode_c_string): Add missing break + statement. + + * recipient.c (gpgme_recipients_add_name_with_validity): Add one + to buffer to allocate. + +2003-05-19 Marcus Brinkmann + + * verify.c (parse_new_sig): Fix ERRSIG case. + Submitted by Benjamin Lee . + +2003-05-18 Marcus Brinkmann + + * gpgme.h: The following types are renamed. The old name is kept + as a deprecated typedef. + (GpgmeCtx): Rename to gpgme_ctx_t. + (GpgmeData): Rename to gpgme_data_t. + (GpgmeRecipients): Rename to gpgme_recipients_t. + (GpgmeError): Rename to gpgme_error_t. + (GpgmeDataEncoding): Rename to gpgme_data_encoding_t. + (GpgmePubKeyAlgo): Rename to gpgme_pubkey_algo_t. + (GpgmeHashAlgo): Rename to gpgme_hash_algo_t. + (GpgmeSigStat): Rename to gpgme_sig_stat_t. + (GpgmeSigMode): Rename to gpgme_sig_mode_t. + (GpgmeAttr): Rename to gpgme_attr_t. + (GpgmeValidity): Rename to gpgme_validity_t. + (GpgmeProtocol): Rename to gpgme_protocol_t. + (GpgmeStatusCode): Rename to gpgme_status_code_t. + (GpgmeEngineInfo): Rename to gpgme_engine_info_t. + (GpgmeSubkey): Rename to gpgme_subkey_t. + (GpgmeKeySig): Rename to gpgme_keysig_t. + (GpgmeUserID): Rename to gpgme_user_id_t. + (GpgmePassphraseCb): Rename to gpgme_passphrase_cb_t. + (GpgmeProgressCb): Rename to gpgme_progress_cb_t. + (GpgmeEditCb): Rename to gpgme_edit_cb_t. + (GpgmeIOCb): Rename to gpgme_io_cb_t. + (GpgmeRegisterIOCb): Rename to gpgme_register_io_cb_t. + (GpgmeRemoveIOCb): Rename to gpgme_remove_io_cb_t. + (GpgmeEventIO): Rename to gpgme_event_io_t. + (GpgmeEventIOCb): Rename to gpgme_event_io_cb_t. + (GpgmeIOCbs): Rename to gpgme_io_cbs. + (gpgme_io_cbs_t): New type. + (GpgmeDataReadCb): Rename to gpgme_data_read_cb_t. + (GpgmeDataWriteCb): Rename to gpgme_data_write_cb_t. + (GpgmeDataSeekCb): Rename to gpgme_data_seek_cb_t. + (GpgmeDataReleaseCb): Rename to gpgme_data_release_cb_t. + (GpgmeDataCbs): Rename to gpgme_data_cbs. + (gpgme_data_cbs_t): New type. + (GpgmeInvalidUserID): Rename to gpgme_invalid_user_id_t. + (GpgmeEncryptResult): Rename to gpgme_encrypt_result_t. + (GpgmeDecryptResult): Rename to gpgme_decrypt_result_t. + (GpgmeNewSignature): Rename to gpgme_new_signature_t. + (GpgmeSignResult): Rename to gpgme_sign_result_t. + (GpgmeSigNotation): Rename to gpgme_sig_notation_t. + (GpgmeSignature): Rename to gpgme_signature_t. + (GpgmeVerifyResult): Rename to gpgme_verify_result_t. + (GpgmeImportStatus): Rename to gpgme_import_status_t. + (GpgmeImportResult): Rename to gpgme_import_result_t. + (GpgmeGenKeyResult): Rename to gpgme_genkey_result_t. + (GpgmeKeyListResult): Rename to gpgme_keylist_result_t. + (GpgmeTrustItem): Rename to gpgme_trust_item_t. + * gpgme.h (gpgme_deprecated_error_t): New type, swallowing macros + GPGME_No_Recipients, GPGME_Invalid_Recipient and + GPGME_No_Passphrase. + * data.h (struct gpgme_data_s): Rename to struct gpgme_data. + * context.h (struct gpgme_context_s): Rename to struct + gpgme_context. + (struct gpgme_recipients_s): Rename to gpgme_recipients. + +2003-05-18 Marcus Brinkmann + + * keylist.c (finish_key): Clear OPD->tmp_uid. + +2003-05-18 Marcus Brinkmann + + * verify.c (_gpgme_verify_status_handler): Return GPGME_No_Data + for NODATA status without signatures. + +2003-05-05 Marcus Brinkmann + + * key.c (_gpgme_key_append_name): Use decoded string to parse user id. + (_gpgme_key_add_sig): Likewise. + +2003-05-04 Marcus Brinkmann + + * context.h (struct gpgme_context_s): Remove member op_info. + + * key.c (_gpgme_key_add_sig): Initialize SIG->uid. + + * gpgme.h (GpgmeError): Add deprecated values for + GPGME_Invalid_Type and GPGME_Invalid_Mode. + +2003-04-30 Marcus Brinkmann + + * gpgme.h (gpgme_get_op_info): Remove prototype. + * ops.h (_gpgme_set_op_info, + _gpgme_data_release_and_return_string, _gpgme_data_get_as_string, + _gpgme_data_append, _gpgme_data_append_string, + _gpgme_data_append_string_for_xml, _gpgme_data_append_for_xml, + _gpgme_data_append_percentstring_for_xml): Likewise. + (_gpgme_progress_status_handler): Change first arg to void *. + * progress.c (_gpgme_progress_status_handler): Likewise. + * conversion.c: Do not include , , , + and , but . + (_gpgme_data_append): Remove function. + (_gpgme_data_append_string): Likewise. + (_gpgme_data_append_for_xml): Likewise. + (_gpgme_data_append_string_for_xml): Likewise. + (_gpgme_data_append_percentstring_for_xml): Likewise. + * data-mem.c (_gpgme_data_get_as_string): Likewise. + (_gpgme_data_release_and_return_string): Likewise. + * gpgme.c (gpgme_get_op_info): Likewise. + (_gpgme_set_op_info): Likewise. + + * gpgme.h (struct _gpgme_key): New structure. + (GpgmeKey): Define using _gpgme_key. + (struct _gpgme_subkey): New structure. + (GpgmeSubKey): New type. + (struct _gpgme_key_sig): New structure. + (GpgmeKeySig): New type. + (struct _gpgme_user_id): New structure. + (GpgmeUserID): New type. + (struct _gpgme_op_keylist_result): New structure. + (GpgmeKeyListResult): New type. + (gpgme_op_keylist_result): New function. + (gpgme_key_get_as_xml): Remove prototype. + * context.h (struct gpgme_context_s): Remove members tmp_key, + tmp_uid, key_cond and key_queue. + (struct key_queue_item_s): Remove structure. + (struct user_id_s): Remove structure. + (struct gpgme_recipients_s): Replace with simple + GpgmeUserID list. + * gpgme.c (gpgme_release): Do not release CTX->tmp_key. + * ops.h (_gpgme_key_add_subkey, _gpgme_key_append_name, + _gpgme_key_add_sig, _gpgme_trust_item_new): New prototypes. + * rungpg.c (command_cb): Return GpgmeError instead int. + New variable ERR. Use it to hold return value of cmd handler. + (gpg_delete): Access fingerprint of key directly. + (append_args_from_signers): Likewise. + (gpg_edit): Likewise. + (append_args_from_recipients): Use GpgmeUserID for recipient list. + * engine-gpgsm.c: Do not include "key.h". + (gpgsm_delete): Access fingerprint of key directly. + (gpgsm_sign): Likewise. + (set_recipients): Use GpgmeUserID for recipients. Invert invalid + user ID flag. + * key.h: File removed. + * key.c: Completely reworked to use exposed GpgmeKey data types. + * keylist.c: Likewise. + * recipient.c: Completely reworked to use GpgmeUserID. + +2003-04-29 Marcus Brinkmann + + * gpgme.h (gpgme_get_key): Remove force_update argument. + * key-cache.c: File removed. + * Makefile.am (libgpgme_la_SOURCES): Remove key-cache.c. + * ops.h (_gpgme_key_cache_add, _gpgme_key_cache_get): Remove + prototypes. + * keylist.c (_gpgme_op_keylist_event_cb): Don't call + _gpgme_key_cache_add. + (gpgme_get_key): New function. + * verify.c (gpgme_get_sig_key): Remove last argument to + gpgme_get_key invocation. + + * gpgme.h (struct _gpgme_trust_item): New structure. + (GpgmeTrustItem): New type. + (gpgme_trust_item_ref, gpgme_trust_item_unref): New prototypes. + * context.h (struct trust_queue_item_s): Remove structure. + (struct gpgme_context_s): Remove trust_queue member. + * Makefile.am (libgpgme_la_SOURCES): Add trust-item.c. + * trust-item.c: New file. + * trustlist.c: Do not include or , but + "gpgme.h". + (struct trust_queue_item_s): Change to new type op_data_t. + (trust_status_handler): Change first argument to void *. + (trust_colon_handler): Likewise. + (_gpgme_op_trustlist_event_cb): Use op_data_t type. + (gpgme_op_trustlist_start): Use op_data_t and rework error + handling. + (gpgme_op_trustlist_next): Use op_data_t. + (gpgme_trust_item_release): Remove function. + (gpgme_trust_item_get_string_attr): Likewise. + (gpgme_trust_item_get_int_attr): Likewise. + + * verify.c (calc_sig_summary): Do not set GPGME_SIGSUM_SYS_ERROR + for bad signatures. + +2003-04-28 Marcus Brinkmann + + * context.h: Remove OPDATA_VERIFY_COLLECTING. + (struct gpgme_context_s): Remove member notation. + * gpgme.h: Make enum for GPGME_KEYLIST_MODE_* values. + + * gpgme.h (struct _gpgme_sig_notation): New structure. + (GpgmeSigNotation): New type. + (struct _gpgme_signature): New structure. + (GpgmeSignature): New type. + (struct _gpgme_op_verify_result): New structure. + (GpgmeVerifyResult): New type. + (gpgme_op_verify_result): New prototype. + (gpgme_get_notation): Remove prototype. + * ops.h (_gpgme_op_verify_init_result): New prototype. + (_gpgme_verify_status_handler): Change first argument to void *. + * util.h (_gpgme_decode_percent_string, _gpgme_map_gnupg_error): + New prototypes. + * conversion.c (_gpgme_decode_percent_string): New function. + (gnupg_errors): New static global. + (_gpgme_map_gnupg_error): New function. + * gpgme.c (gpgme_release): Don't release CTX->notation. + (gpgme_get_notation): Remove function. + * decrypt-verify.c (_gpgme_op_decrypt_verify_start): Call + _gpgme_op_verify_init_result. + * verify.c: Do not include , and "key.h", but + do include "gpgme.h". + (struct verify_result): Replace with ... + (op_data_t): ... this type. + (release_verify_result): Remove function. + (release_op_data): New function. + (is_token): Remove function. + (skip_token): Remove function. + (copy_token): Remove function. + (gpgme_op_verify_result): New function. + (calc_sig_summary): Rewritten. + (finish_sig): Remove function. + (parse_new_sig): New function. + (parse_valid_sig): New function. + (parse_notation): New function. + (parse_trust): New function. + (parse_error): New function. + (_gpgme_verify_status_handler): Rewritten. Change first argument + to void *. + (_gpgme_op_verify_start): Rework error handling. Call + _gpgme_op_verify_init_result. + (gpgme_op_verify): Do not release or clear CTX->notation. + (gpgme_get_sig_status): Rewritten. + (gpgme_get_sig_string_attr): Likewise. + (gpgme_get_sig_ulong_attr): Likewise. + (gpgme_get_sig_key): Likewise. + + * gpgme.h (struct _gpgme_op_decrypt_result): New structure. + (GpgmeDecryptResult): New type. + (gpgme_op_decrypt_result): New prototype. + * ops.h (_gpgme_op_decrypt_init_result): New prototype. + (_gpgme_decrypt_status_handler): Fix prototype. + (_gpgme_decrypt_start): Remove prototype. + * decrypt-verify.c: Do not include , , + and , "util.h" and "context.h", but + "gpgme.h". + (decrypt_verify_status_handler): Change first argument to void *, + and rework error handling. + (_gpgme_op_decrypt_verify_start): New function. + (gpgme_op_decrypt_verify_start): Rewrite using + _gpgme_op_decrypt_verify_start. + (gpgme_op_decrypt_verify): Likewise. + * decrypt.c: Include , "gpgme.h" and "util.h". + (struct decrypt_result): Change to typedef op_data_t, rewritten. + (is_token): Remove function. + (release_op_data): New function. + (skip_token): Remove function. + (gpgme_op_decrypt_result): New function. + (_gpgme_decrypt_status_handler): Change first argument to void *. + Rework error handling. + (_gpgme_decrypt_start): Rename to ... + (decrypt_start): ... this. Call _gpgme_op_decrypt_init_result. + (_gpgme_op_decrypt_init_result): New function. + (gpgme_op_decrypt_start): Use decrypt_start. + (gpgme_op_decrypt): Likewise. + +2003-04-27 Marcus Brinkmann + + * encrypt-sign.c: Do not include , , + , , and "util.h", but "gpgme.h". + (_gpgme_op_encrypt_sign_start): Rename to ... + (encrypt_sign_start): ... this. + (gpgme_op_encrypt_sign_start): Use encrypt_sign_start, not + _gpgme_op_encrypt_sign_start. + (gpgme_op_encrypt_sign): Likewise. + + * gpgme.h (GpgmeEncryptResult): New data type. + (gpgme_op_encrypt_result): New prototype. + * ops.h (_gpgme_op_encrypt_init_result): New prototype. + (_gpgme_op_encrypt_status_handler): Fix prototype. + * encrypt-sign.c (_gpgme_op_encrypt_sign_start): Call + _gpgme_op_encrypt_init_result. + * encrypt.c: Do not include , , "util.h" and + "wait.h". Include and "gpgme.h". + (SKIP_TOKEN_OR_RETURN): Remove macro. + (struct encrypt_result): Rename to ... + (op_data_t): ... new data type. Rewrite for user result data. + (append_xml_encinfo): Remove function. + (release_op_data): New function. + (gpgme_op_encrypt_result): New function. + (_gpgme_op_encrypt_status_handler): Change first argument to void *. + Rewrite result parsing. + (_gpgme_op_encrypt_sym_status_handler): Change first argument to + void *. + (_gpgme_op_encrypt_init_result): New function. + (_gpgme_op_encrypt_start): Rename to ... + (encrypt_start): ... this. + (gpgme_op_encrypt_start): Use encrypt_start, not + gpgme_op_encrypt_start. + (gpgme_op_encrypt): Likewise. + + * gpgme.h (GpgmePubKeyAlgo, GpgmeHashAlgo, GpgmeInvalidUserID, + GpgmeNewSignature, GpgmeSignResult): New data types. + (gpgme_op_sign_result, gpgme_pubkey_algo_name, + gpgme_hash_algo_name): New prototypes. + * gpgme.c (gpgme_pubkey_algo_name): New function. + (gpgme_hash_algo_name): Likewise. + * ops.h (_gpgme_parse_inv_userid, _gpgme_op_sign_init_result): New + prototype. + (_gpgme_op_sign_status_handler): Fix prototype. + * op-support.c: Include and . + (_gpgme_parse_inv_userid): New function. + * sign.c: Include and "gpgme.h", but not , + and "util.h". + (SKIP_TOKEN_OR_RETURN): Remove macro. + (struct sign_result): Change to op_data_t type and rework it. + (release_sign_result): Rename to ... + (release_op_data): ... this and rewrite it. + (append_xml_info): Remove function. + (gpgme_op_sign_result): New function. + (parse_sig_created): New function. + (_gpgme_sign_status_handler): Change first argument to void *. + Rewrite the function to use the new result structure and functions. + (_gpgme_op_sign_init_result): New function. + (_gpgme_op_sign_start): Rename to ... + (sign_start): ... this. Call _gpgme_op_sign_init_result. + (gpgme_op_sign_start): Use sign_start instead _gpgme_op_sign_start. + (gpgme_op_sign): Likewise. + * encrypt-sign.c (_gpgme_op_encrypt_sign_start): Call + _gpgme_op_sign_init_result. + + * delete.c: Include and "gpgme.h", but not "util.h" or + "key.h". + (enum delete_problem): Move into function delete_status_handler. + (delete_status_handler): Change first argument to void *. Parse + delete problem with strtol instead atoi. Return better error + values. + (_gpgme_op_delete_start): Rename to ... + (delete_start): ... this. Rework error handling. + (gpgme_op_delete_start): Use delete_start instead + _gpgme_op_delete_start. + (gpgme_op_delete): Likewise. + * gpgme.h (GpgmeDataType): Removed. + +2003-04-25 Marcus Brinkmann + + * gpgme.h: Change GPGME_IMPORT_PRIVATE to GPGME_IMPORT_SECRET. + * import.c (parse_import_res): Parse unchanged field. + + * gpgme.h: New enum for GPGME_IMPORT_NEW, GPGME_IMPORT_UID, + GPGME_IMPORT_SIG, GPGME_IMPORT_SUBKEY, GPGME_IMPORT_PRIVATE. + (GpgmeError): GPGME_Unknown_Reason, GPGME_Not_Found, + GPGME_Ambiguous_Specification, GPGME_Wrong_Key_Usage, + GPGME_Key_Revoked, GPGME_Key_Expired, GPGME_No_CRL_Known, + GPGME_CRL_Too_Old, GPGME_Policy_Mismatch, GPGME_No_Secret_Key, + GPGME_Key_Not_Trusted, GPGME_Issuer_Missing, GPGME_Chain_Too_Long, + GPGME_Unsupported_Algorithm, GPGME_Sig_Expired, + GPGME_Bad_Signature, GPGME_No_Public_Key added as new error codes. + (struct _gpgme_import_status): New structure. + (GpgmeImportStatus): New type. + (struct _gpgme_op_import_result): New structure. + (GpgmeImportResult): New type. + (gpgme_op_import_result): New function. + * import.c: Include and "gpgme.h", but not "util.h". + (struct import_result): Change to type op_data_t. + (release_import_result): Rename to ... + (release_op_data): ... this. + (append_xml_impinfo): Function removed. + (gpgme_op_import_result): New function. + (parse_import): New function. + (parse_import_res): Likewise. + (import_status_handler): Change first argument to void *. Rewrite + to use new functions. + (_gpgme_op_import_start): Rework error handling. + + * edit.c: Do not include , "util.h", but "gpgme.h". + (edit_resut): Change to typedef for op_data_t. + (edit_status_handler): Change first argument to void *. + Rework error handling. + (command_handler): Rework error handling. + (_gpgme_op_edit_start): Rename to ... + (edit_start): ... this. Rework error handling. + (gpgme_op_edit_start): Rewrite using edit_start. + (gpgme_op_edit): Likewise. + + * ops.h (_gpgme_passphrase_start): Remove prototype. + * passphrase.c: Do not include , "util.h" or + "debug.h", but "gpgme.h". + (struct passphrase_result): Change to typedef for op_data_t. + (release_passphrase_result): Rename to release_op_data. + (_gpgme_passphrase_status_handler): Change first argument to void *. + Use new op_data_t type. + (_gpgme_passphrase_command_handler): Use new op_data_t type. + (_gpgme_passphrase_start): Remove function. + * decrypt.c (_gpgme_decrypt_start): Rewrite error handling. Do + not call _gpgme_passphrase_start, but install command handler. + * encrypt.c (_gpgme_op_encrypt_start): Likewise. + * encrypt-sign.c (_gpgme_op_encrypt_sign_start): Likewise. + * sign.c (_gpgme_op_sign_start): Likewise. + + * context.h (struct gpgme_context_s): Remove member initialized, + use_cms and help_data_1. Add member protocol. Make use_armor and + use_textmode bit flags. Make keylist_mode, include_certs, + signers_len and signers_size unsigned. + * gpgme.c (gpgme_new): Initialize CTX->protocol. + (gpgme_set_protocol): Do not check CTX. Use CTX->protocol. + (gpgme_get_protocol): Likewise. + (gpgme_release): Do not release CTX->help_data_1. + * op-support.c (_gpgme_op_reset): Use CTX->protocol. + + * wait-private.c (_gpgme_wait_private_event_cb): Remove variable CTX. + + * data.c: Do not include , but "gpgme.h". + (_gpgme_data_inbound_handler): Expand _gpgme_data_append, because + it will go. Do not assert DH. + (_gpgme_data_outbound_handler): Do not assert DH. + + * export.c: Do not include , "debug.h" and "util.h", but + "gpgme.h". + (export_status_handler): Change type of first argument to void *. + (_gpgme_op_export_start): Rename to ... + (export_start): ... this. Rework error handling. + (gpgme_op_export_start): Rewritten to use export_start instead + _gpgme_op_export_start. + (gpgme_op_export): Likewise. + + * gpgme.h (GpgmeError): Add GPGME_Busy, GPGME_No_Request. + (GPGME_No_Recipients, GPGME_Invalid_Recipient, + GPGME_No_Passphrase): New macros. + + * key.c (gpgme_key_get_string_attr): Fix validity attribute. + +2003-04-24 Marcus Brinkmann + + * gpgme.h (struct _gpgme_op_genkey_result): New structure. + (GpgmeGenKeyResult): New type. + (gpgme_op_genkey): Drop last argument. + (gpgme_op_genkey_result): New function. + * genkey.c: Do not include "util.h", but "gpgme.h". + (struct genkey_result): Replace with ... + (op_data_t): ... this new type. + (release_genkey_result): Replace with ... + (release_op_data): ... this new function. + (gpgme_op_genkey_result): New function. + (genkey_status_handler): Rewritten using new op_data_t type. + (get_key_parameter): New function. + (_gpgme_op_genkey_start): Renamed to + (genkey_start): ... this and rewritten. + (gpgme_op_genkey_start): Use genkey_start instead + _gpgme_op_genkey_start. + (gpgme_op_genkey): Rewritten. Remove FPR argument. + + * context.h (struct gpgme_context_s): Remove member verbosity. + * gpgme.c (gpgme_new): Do not set member verbosity. + * engine.h (_gpgme_engine_set_verbosity): Remove prototype. + * engine.c (_gpgme_engine_set_verbosity): Remove function. + * engine-backend.h (struct engine_ops): Remove set_verbosity. + * engine-gpgsm.c (_gpgme_engine_ops_gpgsm): Remove set_verbosity member. + * rungpg.c (_gpgme_engine_ops_gpg): Likewise. + (gpg_set_verbosity): Remove function. + * decrypt.c (_gpgme_decrypt_start): Don't call + _gpgme_engine_set_verbosity. + * delete.c (_gpgme_op_delete_start): Likewise. + * edit.c (_gpgme_op_edit_start): Likewise. + * encrypt.c (_gpgme_op_encrypt_start): Likewise. + * encrypt-sign.c (_gpgme_op_encrypt_sign_start): Likewise. + * export.c (_gpgme_op_export_start): Likewise. + * genkey.c (_gpgme_op_genkey_start): Likewise. + * import.c (_gpgme_op_import_start): Likewise. + * keylist.c (gpgme_op_keylist_start): Likewise. + (gpgme_op_keylist_ext_start): Likewise. + * sign.c (_gpgme_op_sign_start): Likewise. + * verify.c (_gpgme_op_verify_start): Likewise. + + * Makefile.am (libgpgme_la_SOURCES): Add key-cache.c. + * key.c (key_cache_initialized, key_cache_size, + key_cache_max_chain_length, ): Removed. + (struct key_cache_item_s, key_cache_lock, key_cache, + key_cache_unused_items, hash_key, _gpgme_key_cache_add, + _gpgme_key_cache_get, gpgme_get_key): Moved to ... + * key-cache.c: ... here. New file. + * key.h (_gpgme_key_cache_init): Remove prototypes. + (_gpgme_key_cache_add,_gpgme_key_cache_get): Move to ... + * ops.h: ... here. + * version.c: Do not include "key.h". + (do_subsystem_inits): Do not call _gpgme_key_cache_init. + + * mkstatus: Strip trailing comma. + * gpgme.h (GpgmeStatus): Pretty print. + + * gpgme.h (GpgmeError): Rename GPGME_No_Passphrase to + GPGME_Bad_Passphrase. + * passphrase.c (_gpgme_passphrase_status_handler): Use + GPGME_Bad_Passphrase instead GPGME_No_Passphrase. + + * gpgme.h (GpgmeError): Rename GPGME_No_Recipients to + GPGME_No_UserID and GPGME_Invalid_Recipient to + GPGME_Invalid_UserID. + * encrypt.c (_gpgme_encrypt_status_handler): Use GPGME_No_UserID + instead GPGME_No_Recipients and GPGME_Invalid_UserID instead + GPGME_Invalid_Recipient. + (_gpgme_op_encrypt_start): Likewise. + + * gpgme.h (GpgmeError): Remove GPGME_Busy and GPGME_No_Request. + * wait-user.c (_gpgme_wait_user_event_cb): Don't clear CTX->pending. + * wait-private.c (_gpgme_wait_private_event_cb): Likewise. + * wait-global.c (gpgme_wait): Likewise. + * verify.c (_gpgme_op_verify_start): Likewise. + (gpgme_get_sig_status): Don't check pending flag. + (gpgme_get_sig_string_attr): Likewise. + (gpgme_get_sig_ulong_attr): Likewise. + (gpgme_get_sig_key): Likewise. + * op-support.c (_gpgme_op_reset): Likewise. + * trustlist.c (gpgme_op_trustlist_start): Don't clear pending flag. + (gpgme_op_trustlist_next): Don't check or clear pending flag. + (gpgme_op_trustlist_end): Likewise. + * sign.c (_gpgme_op_sign_start): Likewise. + * context.h (struct gpgme_context_s): Remove member PENDING. + * decrypt.c (_gpgme_decrypt_start): Likewise. + * delete.c (_gpgme_op_delete_start): Likewise. + * edit.c (_gpgme_op_edit_start): Likewise. + * encrypt.c (_gpgme_op_encrypt_start): Likewise. + * encrypt-sign.c (_gpgme_op_encrypt_sign_start): Likewise. + * export.c (_gpgme_op_export_start): Likewise. + * genkey.c (_gpgme_op_genkey_start): Likewise. + * import.c (_gpgme_op_import_start): Likewise. + * key.c (gpgme_get_key): Likewise. + * keylist.c (gpgme_op_keylist_start): Likewise. + (gpgme_op_keylist_ext_start): Likewise. + (gpgme_op_keylist_next): Likewise. + (gpgme_op_keylist_end): Likewise. + * data-compat.c (gpgme_error_to_errno): Don't convert EBUSY. + +2003-02-06 Marcus Brinkmann + + * gpgme.h (GpgmePassphraseCb): Change type to return GpgmeError, + and add argument for returning the result string. + (gpgme_cancel): Remove prototype. + * gpgme.c (gpgme_cancel): Remove function. + * context.h (struct gpgme_context_s): Remove member cancel. + * passphrase.c (_gpgme_passphrase_command_handler): Call the + passphrase callback in the new way. + +2003-01-30 Marcus Brinkmann + + * edit.c (_gpgme_edit_status_handler): Call the progress status + handler. + +2003-02-05 Marcus Brinkmann + + * wait-user.c (_gpgme_wait_user_remove_io_cb): Move check for no + I/O handlers left to ... + (_gpgme_user_io_cb_handler): ... here. + +2003-02-04 Marcus Brinkmann + + * trustlist.c (trustlist_colon_handler): Release ITEM if name + could not be allocated. + (gpgme_trust_item_release): Only release name if it is allocated. + Reported by Marc Mutz . + +2003-02-04 Marcus Brinkmann + + * rungpg.c (read_status): If he status handler returns an error, + return it. + (status_handler): If read_status fails, just return the error. + +2003-02-01 Marcus Brinkmann + + * engine-gpgsm.c (start): Handle all errors, not only most of + them. + (xtoi_1, xtoi_2): Remove macro. + (status_handler): Replace use of xtoi_2 with _gpgme_hextobyte. + +2003-02-01 Marcus Brinkmann + + * engine-gpgsm.c (map_assuan_error): Replace + ASSUAN_Bad_Certificate_Path with ASSUAN_Bad_Certificate_Chain. + (gpgsm_new): Use assuan_pipe_connect instead assuan_pipe_connect2. + + * util.h (DIMof): Remove macro. + + * ops.h (_gpgme_op_event_cb, _gpgme_op_event_cb_user, + _gpgme_data_unread): Prototypes removed. + +2003-01-30 Marcus Brinkmann + + * types.h: File removed. + * Makefile.am (libgpgme_la_SOURCES): Remove types.h. + * io.h (struct spawn_fd_item_s): Do not include "types.h". + * key.h: Likewise. + * context.h: Likewise. + * cengine-gpgsm.h: Likewise. + * engine.h: Include "gpgme.h" instead "types.h". Add prototypes + for EngineStatusHandler, EngineColonLineHandler and + EngineCommandHandler. + (_gpgme_engine_set_status_handler): Change parameter type from + GpgmeStatusHandler to EngineStatusHandler. + (_gpgme_engine_set_command_handler): Change parameter type from + GpgmeCommandHandler to EngineCommandHandler. + (_gpgme_engine_set_colon_line_handler): Change parameter type from + GpgmeColonLineHandler to EngineColonLineHandler. + * engine-backend.h: Include "engine.h" instead "types.h". + (struct engine_ops): Change Gpgme*Handler parameters in members + set_command_handler, set_colon_line_handler and set_status_handler + to Engine*Handler. + * engine.c (_gpgme_engine_set_status_handler): Change parameter + type from GpgmeStatusHandler to EngineStatusHandler. + (_gpgme_engine_set_command_handler): Change parameter type from + GpgmeCommandHandler to EngineCommandHandler. + (_gpgme_engine_set_colon_line_handler): Change parameter type from + GpgmeColonLineHandler to EngineColonLineHandler. + * rungpg.c (struct gpg_object_s): Change type of member status.fnc + from GpgmeStatusHandler to EngineStatusHandler. Change type of + member colon.fnc from GpgmeColonLineHandler to + EngineColonLineHandler. Change type of member cmd.fnc from + GpgmeCommandHandler to EngineCommandHandler. + * engine-gpgsm.c (struct gpgsm_object_s): Likewise. + * rungpg.c (gpg_set_status_handler): Change parameter type from + GpgmeStatusHandler to EngineStatusHandler. + * engine-gpgsm.c (gpgsm_set_status_handler): Likewise. + (assuan_simple_command): Likewise. + * rungpg.c (gpg_set_colon_line_handler): Change parameter type + from GpgmeColonLineHandler to EngineColonLineHandler. + * engine-gpgsm.c (gpgsm_set_colon_line_handler): Likewise. + * rungpg.c (gpg_set_command_handler): Change parameter type from + GpgmeCommandHandler to EngineCommandHandler. + + * engine-gpgsm.c (status_handler): Do not close status fd at end + of function. + + * ops.h (_gpgme_op_data_lookup): Add prototype. + * op-support.c: Include . + (_gpgme_op_data_lookup): New function. + * decrypt.c (_gpgme_release_decrypt_result): Function removed. + (struct decrypt_result_s): Rename to ... + (struct decrypt_resul): ... this. + (DecryptResult): New type. + (_gpgme_decrypt_status_handler): Don't use + test_and_allocate_result, but use _gpgme_op_data_lookup to + retrieve result data object. + * sign.c (_gpgme_release_sign_result): Function removed. + (release_sign_result): New function. + (struct sign_result_s): Rename to ... + (struct sign_result): ... this. + (SignResult): New type. + (_gpgme_sign_status_handler): Don't use + test_and_allocate_result, but use _gpgme_op_data_lookup to + retrieve result data object. + * encrypt.c (struct encrypt_result_s): Rename to ... + (struct encrypt_result): ... this. + (_gpgme_release_encrypt_result): Function removed. + (release_encrypt_result): New function. + (_gpgme_encrypt_status_handler): Don't use + test_and_allocate_result, but use _gpgme_op_data_lookup to + retrieve result data object. + * verify.c (struct verify_result_s): Rename to ... + (struct verify_result): ... this. Remove member next. + (VerifyResult): New type. + (_gpgme_release_verify_result): Function removed. + (release_verify_result): New function. + (finish_sig): Change first argument to type VerifyResult. Diddle + the type of the op_data structure. + (add_notation): Change first argument to type VerifyResult. + (_gpgme_verify_status_handler): Don't use + test_and_allocate_result, but use _gpgme_op_data_lookup to + retrieve result data object. + * passphrase.c (struct passphrase_result_s): Rename to ... + (struct passphrase_result): ... this. Remove member next. + (PassphraseResult): New type. + (_gpgme_release_passphrase_result): Function removed. + (release_passphrase_result): New function. + (_gpgme_passphrase_status_handler): Don't use + test_and_allocate_result, but use _gpgme_op_data_lookup to + retrieve result data object. + (_gpgme_passphrase_command_handler): Likewise. + * keylist.c (struct keylist_result_s): Rename to ... + (struct keylist_result): ... this. Remove member next. + (KeylistResult): New type. + (_gpgme_release_keylist_result): Function removed. + (release_keylist_result): New function. + (keylist_status_handler): Don't use + test_and_allocate_result, but use _gpgme_op_data_lookup to + retrieve result data object. + * edit.c (struct edit_result_s): Rename to ... + (struct edit_result): ... this. Remove member next. + (EditResult): New type. + (_gpgme_release_edit_result): Function removed. + (release_edit_result): New function. + (edit_status_handler): Don't use + test_and_allocate_result, but use _gpgme_op_data_lookup to + retrieve result data object. + (command_handler): Likewise. + * types.h (DecryptResult, SignResult, EncryptResult, + PassphraseResult, ImportResult, DeleteResult, GenKeyResult, + KeylistResult, EditResult): Types removed. + * ops.h: Don't include "types.h", but "gpgme.h" and "context.h". + (test_and_allocate_result): Remove macro. + (_gpgme_release_decrypt_result): Remove prototype. + (_gpgme_decrypt_result): Remove prototype. + (_gpgme_release_sign_result): Remove prototype. + (_gpgme_release_encrypt_result): Remove prototype. + (_gpgme_release_passphrase_result): Remove prototype. + (_gpgme_release_import_result): Remove prototype. + (_gpgme_release_delete_result): Remove prototype. + (_gpgme_release_genkey_result): Remove prototype. + (_gpgme_release_keylist_result): Remove prototype. + (_gpgme_release_edit_result): Remove prototype. + (_gpgme_release_verify_result): Remove prototype. + * gpgme.c (_gpgme_release_result): Rewritten. + * context.h (enum ctx_op_data_type): New enum. + (struct ctx_op_data): New structure. + (struct gpgme_context_s): Replace the member result with a member + op_data. + (fail_on_pending_request): Remove macro. + * op-support.c (_gpgme_op_reset): Expand macro + fail_on_pending_request. + * util.h: Don't include "types.h" or "debug.h", but include "gpgme.h". + +2003-01-30 Marcus Brinkmann + + * types.h (EngineObject): Move typedef to ... + * engine.h: ... here. + * types.h (GpgObject): Move typedef to ... + * rungpg.c: ... here. + * types.h (GpgsmObject): Move typedef to ... + * engine-gpgsm.c: ... here. + + * util.h (return_if_fail, return_null_if_fail, + return_val_if_fail): Remove macro. + * gpgme.c (gpgme_cancel): Don't use return_if_fail. + * key.c (gpgme_key_ref): Likewise. + * signers.c (gpgme_signers_enum): Likewise. + (gpgme_signers_clear): Likewise. + + * engine-backend.h (struct engine_ops): Rename get_path to + get_file_name. + * gpgme.h (struct _gpgme_engine_info): Rename member path to + file_name. + * version.c: Do not include , , context.h and + util.h. Other clean ups. + (parse_version_number): Protect more seriously against + overflow. + (gpgme_get_engine_info): Move to ... + * engine.c (gpgme_get_engine_info): ... here. + (_gpgme_engine_get_info): Function removed. + (_gpgme_engine_get_path): Make static and rename to ... + (engine_get_file_name): .. this. + (_gpgme_engine_get_version): Make static and rename to ... + (engine_get_version): ... this. + (_gpgme_engine_get_req_version): Make static and rename to ... + (engine_get_req_version): ... this. + * engine.h (_gpgme_engine_get_path, _gpgme_engine_get_version, + _gpgme_engine_req_version, _gpgme_engine_get_info.): Remove + prototypes. + + * gpgme.h (enum GpgmeProtocol): Remove GPGME_PROTOCOL_AUTO. + * gpgme.c (gpgme_set_protocol): Don't handle GPGME_PROTOCOL_AUTO. + (gpgme_get_protocol_name): New function. + + * engine-backend.h (struct engine_ops): New member + get_req_version, remove member check_version. + * engine.h (_gpgme_Engine_get_version): New prototype. + * rungpg.c (gpg_get_req_version): New function. + (gpg_check_version): Function removed. + (_gpgme_engine_ops_gpg): Add gpg_get_req_version, remove + gpg_check_version. + * engine-gpgsm.c (gpgsm_get_req_version): New function. + (gpgsm_check_version): Function removed. + (_gpgme_engine_ops_gpgsm): Add gpgsm_get_req_version, remove + gpgsm_check_version. + * engine.c: Include ops.h. + (_gpgme_engine_get_req_version): New function. + (gpgme_engine_check_version): Rewritten. + * version.c (gpgme_get_engine_info): Rewritten. + * gpgme.h (gpgme_engine_info): New structure. + (GpgmeEngineInfo): New type. + +2003-01-29 Marcus Brinkmann + + * types.h: Remove byte and ulong types. + * util.h (_gpgme_hextobyte): Change prototype to unsigned char + instead byte. + * conversion.c (_gpgme_hextobyte): Change argument to unsigned + char instead byte. + (_gpgme_decode_c_string): Likewise, and beautify. Also support a + few more escaped characters. Be more strict about buffer size. + (_gpgme_data_append_percentstring_for_xml): Change type of SRC, + BUF and DST to unsigned char instead byte. + * progress.c (_gpgme_progress_status_handler): Use unsigned char + instead byte. + * debug.c (trim_spaces): Likewise. + + * util.h (mk_error): Remove macro. + * conversion.c, data.c, data-compat.c, decrypt.c, delete.c, + edit.c, encrypt.c, encrypt-sign.c, engine.c, engine-gpgsm.c, + export.c, genkey.c, gpgme.c, import.c, key.c, keylist.c, + passphrase.c, progress.c, recipient.c, rungpg.c, sign.c, + signers.c, trustlist.c, verify.c, wait.c, wait-global.c, + wait-private (literally everywhere): Expand the mk_error macro. + + * context.h (wait_on_request_or_fail): Remove macro. + + * context.h (gpgme_context_s): Remove member ERROR. + * types.h (GpgmeStatusHandler): Change return type to GpgmeError. + (GpgmeCommandHandler): Change return type to GpgmeError and add + new argument RESULT. + * gpgme.h (GpgmeIOCb): Change return type to GpgmeError. + (GpgmeEventIO): New event GPGME_EVENT_START. + (GpgmeIdleFunc): Remove type. + (gpgme_register_idle): Remove prototype. + * data.c: Include . + (_gpgme_data_inbound_handler): Change return type to GpgmeError. + Return any error instead ignoring it, don't close file descriptor + on error. + (_gpgme_data_outbound_handler): Likewise. + * decrypt.c: Do not include , and . + (_gpgme_decrypt_status_handler): Change return type to GpgmeError. + Return error instead setting ctx->error. Return success at end of + function. + (gpgme_op_decrypt): Don't work around the old kludge anymore. + * decrypt-verify.c (decrypt_verify_status_handler): Change return + type to GpgmeError. Return possible errors. + * delete.c: Do not include , , and + . + (delete_status_handler): Change return type to GpgmeError. Return + error instead setting ctx->error. Return success at end of + function. + * edit.c: Do not include and . + (_gpgme_edit_status_handler): Change type to GpgmeError, + make static and rename to ... + (edit_status_handler): ... this. Return error directly. + (command_handler): Change return type to GpgmeError, add result + argument. Return error directly. + * encrypt.c (status_handler_finish): Remove function. + (_gpgme_encrypt_status_handler): Change return type to GpgmeError. + Return error directly. + (_gpgme_encrypt_sym_status_handler): Likewise. + * encrypt-sign.c (encrypt_sign_status_handler): Likewise. + * engine-gpgsm.c (close_notify_handler): Do not signal done event + anymore. + (status_handler): Change return type to GpgmeError. Diddle things + around a bit to return errors directly. + (start): Send start event. + * export.c: Do not include , and . + (export_status_handler): Change return type to GpgmeError. Don't + check ctx->error. + * genkey.c: Do not include and . + (genkey_status_handler): Change return type to GpgmeError. Don't + check ctx->error. Return errors directly. + * gpgme.c (_gpgme_release_result): Do not initialize ctx->error. + (_gpgme_op_event_cb): Function removed. + (_gpgme_op_event_cb_user): Likewise. + * import.c: Do not include , and . + (import_status_handler): Change return type to GpgmeError. Don't + check ctx->error. + * keylist.c (keylist_colon_handler, keylist_status_handler, finish_key): + Change return type to GpgmeError, return error directly. + * Makefile (libgpgme_la_SOURCES): Add wait-global.c, + wait-private.c and wait-user.c + * ops.h (test_and_allocate_result): Return error instead setting + ctx->error. + (_gpgme_data_inbound_handler, _gpgme_data_outbound_handler, + _gpgme_verify_status_handler, _gpgme_decrypt_status_handler, + _gpgme_sign_status_handler, _gpgme_encrypt_staus_handler, + _gpgme_passphrase_status_handler, _gpgme_progress_status_handler): + Change return type to GpgmeError. + (_gpgme_passphease_command_handler): Change return type to + GpgmeError and add new argument RESULT. + * op-support.c: Use new callback functions, and change private + data to ctx everywhere. + * passphrase.c (_gpgme_passphrase_status_handler): Change return + type to GpgmeError, return error directly. + (_gpgme_passphrase_command_handler): Change return type to + GpgmeError, add result argument. Return results accordingly. + * progress.c (_gpgme_progress_status_handler): Change return type + to GpgmeError, return errors directly. + * rungpg.c (status_handler): Change return type to GpgmeError. + Return error directly. + (close_notify_handler): Don't send done event. + (colon_line_handler): Change return type to GpgmeError, return + errors directly. + * rungpg.c (start): Send start event. + * sign.c (_gpgme_sign_status_handler): Change return type to + GpgmeError, return errors directly. + * trustlist.c (trustlist_status_handler): Change return type to + GpgmeError. Return 0. + (trustlist_colon_handler): Change return type GpgmeError. Return + errors directly. + * verify.c (add_notation): Change return type to GpgmeError, + return errors directly. + (_gpgme_verify_status_handler): Likewise. + * wait.h (struct fd_table): Remove lock member. + (struct wait_item_s): Moved here from wait.c. + (struct tag): New structure. + (_gpgme_wait_event_cb): Remove prototype. + (_gpgme_wait_private_event_cb, _gpgme_wait_global_event_cb, + _gpgme_wait_user_add_io_cb, _gpgme_wait_user_remove_io_cb, + _gpgme_wait_user_event_io_cb): New prototypes. + * wait.c: Don't include . + (ftd_global, ctx_done_list, ctx_done_list_size, + ctx_done_list_length, ctx_done_list_lock, idle_function): Remove + global variable. + (gpgme_register_idle, do_select, _gpgme_wait_event_cb): Remove + function. + (gpgme_wait): Move to file wait-global.c. + (_gpgme_add_io_cb): Take ctx as private argument, initialize ctx + member in wait item and tag. + (_gpgme_remove_io_cb): Take ctx from tag. Don't use FDT lock. + (_gpgme_wait_one, _gpgme_wait_on_condition): Move to + wait-private.c. + (gpgme_fd_table_init): Don't initialize FDT->lock. + (gpgme_fd_table_deinit): Don't destroy FDT->lock. + (_gpgme_fd_table_put): Make static and rename to ... + (fd_table_put): ... this function. Don't use FDT->lock. + (struct wait_item_s): Move to wait.h. + * wait-global.c: New file. + * wait-private.c: New file. + * wait-user.c: New file. + + * key.c (gpgme_key_sig_get_string_attr): Use validity_to_string + instead otrust_to_string to calculate validity. + +2003-01-19 Miguel Coca + + * w32-io.c (_gpgme_io_select): Add missing argument in calls to + DEBUG_BEGIN. + * w32-util.c: Include "sema.h". + (find_program_in_registry): Change DEBUG1 to DEBUG2, fixes compilation + error. + +2003-01-19 Marcus Brinkmann + + * rungpg.c (_gpgme_engine_ops_gpg): Remove gpg_start. + (gpg_start): Rename to ... + (start): ... this function. Change arguments to GpgObject. + (gpg_decrypt): Call start. + (gpg_edit): Likewise. + (gpg_encrypt): Likewise. + (gpg_encrypt_sign): Likewise. + (gpg_export): Likewise. + (gpg_import): Likewise. + (gpg_keylist): Likewise. + (gpg_keylist_ext): Likewise. + (gpg_trustlist): Likewise. + (gpg_verify): Likewise. + + * engine-gpgsm.c (_gpgme_engine_ops_encrypt): Remove gpgsm_start. + (gpgsm_start): Rename to ... + (struct gpgsm_object_s): Remove member command. + (gpgsm_release): Don't free command. + (start): ... this function. Change arguments to GpgsmObject and + const char *. + (gpgsm_decrypt): Call start. + (gpgsm_delete): Likewise. + (gpgsm_encrypt): Likewise. + (gpgsm_export): Likewise. + (gpgsm_genkey): Likewise. + (gpgsm_import): Likewise. + (gpgsm_keylist): Likewise. + (gpgsm_keylist_ext): Likewise. + (gpgsm_verify): Likewise. + + * decrypt.c (_gpgme_decrypt_start): Don't call + _gpgme_engine_start. + * delete.c (_gpgme_op_delete_start): Likewise. + * edit.c (_gpgme_op_edit_start): Likewise. + * encrypt.c (_gpgme_op_encrypt_start): + * encrypt-sign.c (_gpgme_op_encrypt_sign_start): + * export.c (_gpgme_op_export_start): Likewise. + * genkey.c (_gpgme_op_genkey_start): Likewise. + * import.c (_gpgme_op_import_start): Likewise. + * keylist.c (gpgme_op_keylist_ext_start): Likewise. + (gpgme_op_keylist_start): Likewise. + * sign.c (_gpgme_op_sign_start): Likewise. + * trustlist.c (gpgme_op_trustlist_start): Likewise. + * verify.c (_gpgme_op_verify_start): Likewise. + + * engine-backend.h (struct engine_ops): Remove member start. + + * engine.h (_gpgme_engine_start): Remove prototype. + * engine.c (_gpgme_engine_start): Remove function. + +2003-01-06 Werner Koch + + * keylist.c (set_mainkey_capability): Handle 'd' and 'D' used + since gpg 1.3 to denote disabled keys. + +2003-01-06 Marcus Brinkmann + + * data-mem.c: Include . + * engine.c: Likewise. + +2003-01-06 Marcus Brinkmann + + * Makefile.am (libgpgme_la_DEPENDENCIES): Correct bug in last change. + +2002-12-24 Marcus Brinkmann + + * gpgme.h (gpgme_op_verify, gpgme_op_decrypt_verify): Drop R_STAT + argument. + * decrypt-verify.c (gpgme_op_decrypt_verify): Drop R_STAT + argument. + * verify.c (gpgme_op_verify): Drop R_STAT argument. + (_gpgme_intersect_stati): Function removed. + * ops.h (_gpgme_intersect_stati): Remove prototype. + +2002-12-24 Marcus Brinkmann + + * libgpgme.vers: New file. + * Makefile.am (EXTRA_DIST): Add libgpgme.vers. + (libgpgme_version_script_cmd): New variable. + (libgpgme_la_LDFLAGS): Add libgpgme_version_script_cmd here. + (libgpgme_la_DEPENDENCIES): New variable. + +2002-12-23 Marcus Brinkmann + + * key.c (gpgme_key_get_string_attr): Don't accept GPGME_ATTR_IS_SECRET. + (otrust_to_string): New function. + (gpgme_key_get_as_xml): Use it. + (validity_to_string): New function. + (gpgme_key_get_string_attr): Beautify using above functions. + (gpgme_key_get_ulong_attr): Likewise. + +2002-12-23 Marcus Brinkmann + + * data-mem.c (mem_release): Fix gcc warning. + * data-user.c (user_release): Likewise. + +2002-12-06 Marcus Brinkmann + + * data.h (gpgme_data_release_cb): Change return type to void. + (gpgme_data_read_cb): Change return type to ssize_t. + * data.c (gpgme_data_read): Likewise. + * data-stream.c (stream_read): Likewise. + * data-fd.c (fd_read): Likewise. + * data-mem.c (mem_read): Likewise. + (mem_release): Change return type to void. + * data-user.c (user_read): Change return type to ssize_t. + (user_release): Change return type to void. + * data-compat.c (old_user_read): Change return type to ssize_t. + * gpgme.h (GpgmeDataReadCb): Likewise. + (gpgme_data_read): Likewise. + (GpgmeDataSeekCb): Change return type to off_t. + +2002-12-04 Marcus Brinkmann + + * gpgme.h: Add prototype for gpgme_get_key. + * key.c (gpgme_get_key): New function. + * verify.c (gpgme_get_sig_key): Rewrite using gpgme_get_key. + + * gpgme.h: Add prototypes for new interfaces + gpgme_key_sig_get_string_attr and gpgme_key_get_ulong_attr. + (enum GpgmeAttr): New attribute GPGME_ATTR_SIG_CLASS. + * gpgme.c (gpgme_set_keylist_mode): Allow GPGME_KEYLIST_MODE_SIGS. + * key.h (struct certsig_s): New members ALGO, NAME_PART, + EMAIL_PART, COMMENT_PART, NAME, SIG_STAT and SIG_CLASS. + + * conversion.c (_gpgme_decode_c_string): Add new parameter LEN. + Use that to determine if allocation is desired or not. + * util.h: Adjust prototype of _gpgme_decode_c_string. + * keylist.c (keylist_colon_handler): Adjust caller of + _gpgme_decode_c_string. + + * key.h (struct gpgme_key_s): New member last_uid. + * key.c (_gpgme_key_append_name): Rewritten using + _gpgme_decode_c_string and the last_uid pointer. + (my_isdigit): Macro removed. + (ALLOC_CHUNK): Likewise. + * keylist.c (set_userid_flags): Use last_uid member of KEY. + + * context.h (struct user_id_s): New member last_certsig. + * key.h: Add prototype for _gpgme_key_add_certsig. + * key.c (_gpgme_key_add_certsig): New function. + (set_user_id_part): Move function before _gpgme_key_add_certsig. + (parse_user_id): Change first argument to SRC, add new arguments + NAME, EMAIL and COMMENT. Change code to use these arguments + instead going through UID. Move function before + _gpgme_add_certsig. + (parse_x509_user_id): Likewise. + (_gpgme_key_append_name): Adjust arguments to parse_x509_user_id + and parse_user_id invocation. + (one_certsig_as_xml): New function. + (one_uid_as_xml): Print signatures. + * context.h (struct gpgme_context_s): New member TMP_UID. + * keylist.c (keylist_colon_handler): Rewritten, implement "sig" + record entries. + + * key.c (get_certsig): New function. + (gpgme_key_sig_get_string_attr): Likewise. + (gpgme_key_sig_get_ulong_attr): Likewise. + + * keylist.c: Include . + (my_isdigit): Macro removed. + (set_mainkey_trust_info): Use isdigit, not my_isdigit. + (set_userid_flags): Likewise. + (set_subkey_trust_info): Likewise. + (set_ownertrust): Likewise. + (finish_key): Move function up a bit and remove prototype. + + * rungpg.c (gpg_keylist_ext): Correct precedence of signature + listing mode. + (gpg_keylist_ext): Implement signature listing mode. + +2002-11-25 Marcus Brinkmann + + * rungpg.c (_gpgme_gpg_spawn): Do not set parent fds to -1. + * posix-io.c (_gpgme_io_spawn): Call _gpgme_io_close instead close + for parent fds. + * w32-io.c (_gpgme_io_spawn): Call _gpgme_io_close instead + CloseHandle for parent fds. + +2002-11-22 Marcus Brinkmann + + * gpgme.h [_MSC_VER]: Define ssize_t as long. + +2002-11-22 Werner Koch + + * engine-gpgsm.c (_gpgme_gpgsm_new): Save the result of a first + setlocale before doing another setlocale. + +2002-11-21 Marcus Brinkmann + + * decrypt.c: Some beautyfication. + + * verify.c (_gpgme_verify_status_handler): Treat + GPGME_STATUS_UNEXPECTED like GPGME_STATUS_NODATA. + Reported by Miguel Coca . + +2002-11-19 Marcus Brinkmann + + * genkey.c: Only include if [HAVE_CONFIG_H]. + (struct genkey_result_s): Add new member FPR. + (_gpgme_release_genkey_result): Free RESULT->fpr if set. + (genkey_status_handler): Extract the fingerprint from the status + line. + (gpgme_op_genkey): Add new argument FPR and return the fingerprint + in it. + * gpgme.h: Adjust prototype of gpgme_op_genkey. + +2002-11-19 Marcus Brinkmann + + * rungpg.c (gpg_keylist): Add --with-fingerprint to gpg invocation + twice, to get fingerprints on subkeys. Suggested by Timo Schulz + . + (gpg_keylist_ext): Likewise. + +2002-11-05 Marcus Brinkmann + + * import.c (append_xml_impinfo): Use + _gpgme_data_append_string_for_xml rather than + _gpgme_data_append_string for the field content. + Submitted by Miguel Coca . + +2002-10-10 Marcus Brinkmann + + * rungpg.h, engine-gpgsm.h: File removed. + * engine-backend.h: New file. + * Makefile.am (gpgsm_components): New variable, set depending on + automake conditional HAVE_GPGSM. + (libgpgme_la_SOURCES): Add engine-backend.h, remove rungpg.h and + engine-gpgsm.h. Replace engine-gpgsm.c with ${gpgsm_components}. + (status-table.h): Depend on gpgme.h, not rungpg.h. + * conversion.c: Include . + * engine-gpgsm.c: Do not set ENABLE_GPGSM here. Include + "engine-backend.h" instead "engine-gpgsm.h". Reorder some + functions and remove all function prototypes. + (_gpgme_gpgsm_get_version): Make static and rename to ... + (gpgsm_get_version): ... this. + (_gpgme_gpgsm_check_version): Make static and rename to ... + (gpgsm_check_version): ... this. + (_gpgme_gpgsm_new): Make static. Change argument type from + GpgsmObject * to void **. Call gpgsm_release instead + _gpgme_gpgsm_release. + (_gpgme_gpgsm_op_decrypt): Make static and rename to ... + (gpgsm_check_decrypt): ... this. + (_gpgme_gpgsm_op_delete): Make static and rename to ... + (gpgsm_check_delete): ... this. + (_gpgme_gpgsm_set_recipients): Make static and rename to ... + (gpgsm_check_set_recipients): ... this. + (_gpgme_gpgsm_op_encrypt): Make static and rename to ... + (gpgsm_encrypt): ... this. + (_gpgme_gpgsm_op_export): Make static and rename to ... + (gpgsm_export): ... this. + (_gpgme_gpgsm_op_genkey): Make static and rename to ... + (gpgsm_genkey): ... this. + (_gpgme_gpgsm_op_import): Make static and rename to ... + (gpgsm_import): ... this. + (_gpgme_gpgsm_op_keylist): Make static and rename to ... + (gpgsm_keylist): ... this. + (_gpgme_gpgsm_op_keylist_ext): Make static and rename to ... + (gpgsm_keylist_ext): ... this. + (_gpgme_gpgsm_op_sign): Make static and rename to ... + (gpgsm_sign): ... this. + (_gpgme_gpgsm_op_trustlist): Make static and rename to ... + (gpgsm_trustlist): ... this. + (_gpgme_gpgsm_op_verify): Make static and rename to ... + (gpgsm_verify): ... this. + (gpgsm_status_handler): Rename to ... + (status_handler): ... this. + (_gpgme_gpgsm_set_status_handler): Make static and rename to ... + (gpgsm_set_status_handler): ... this. + (_gpgme_gpgsm_set_colon_line_handler): Make static and rename to ... + (gpgsm_set_colon_line_handler): ... this. + (_gpgme_gpgsm_add_io_cb): Rename to ... + (add_io_cb): ... this. + (_gpgme_gpgsm_start): Make static and rename to ... + (gpgsm_start): ... this. + (_gpgme_gpgsm_set_io_cb): Make static and rename to ... + (gpgsm_set_io_cb): ... this. + (_gpgme_gpgsm_io_event): Make static and rename to ... + (gpgsm_io_event): ... this. + (struct _gpgme_engine_ops_gpgsm): New variable. + [!ENABLE_GPGSM]: Removed. + * engine.c: Do not include , , , + , "io.h", "rungpg.h" and "engine-gpgsm.h". Include + and "engine-backend.h". + (struct engine_object_s): Rewritten. + (engine_ops): New variable. + * engine.c (_gpgme_engine_get_path, _gpgme_engine_get_version, + _gpgme_engine_check_version, _gpgme_engine_new, + _gpgme_engine_release, _gpgme_engine_set_verbosity, + _gpgme_engine_set_status_handler, + _gpgme_engine_set_command_handler, + _gpgme_engine_set_colon_line_handler, _gpgme_engine_op_decrypt, + _gpgme_engine_op_delete, _gpgme_engine_op_edit, + _gpgme_engine_op_encrypt, _gpgme_engine_op_encrypt_sign, + _gpgme_engine_op_export, _gpgme_engine_op_genkey, + _gpgme_engine_op_import, _gpgme_engine_op_keylist, + _gpgme_engine_op_keylist_ext, _gpgme_engine_op_sign, + _gpgme_engine_op_trustlist, _gpgme_engine_op_verify, + _gpgme_engine_start, _gpgme_engine_set_io_cbs, + _gpgme_engine_io_event): Reimplement. + * engine.h: Fix a few comments and a variable name in a prototype. + * ops.h: Do not include "rungpg.h". + * passphrase.c: Include config.h only if [HAVE_CONFIG_H]. Do not + include "rungpg.h". + * recipient.c: Likewise. + * signers.c: Likewise. + * version.c: Likewise. + * rungpg.c: Likewise. Include "engine-backend.h". Reorder + functions and remove prototypes. + (_gpgme_gpg_get_version): Make static and rename to ... + (gpg_get_version): ... this. + (_gpgme_gpg_check_version): Make static and rename to ... + (gpg_check_version): ... this. + (_gpgme_gpg_new): Make static. Change argument type from + GpgObject * to void **. Call gpg_release instead + _gpgme_gpg_release. + (_gpgme_gpg_op_decrypt): Make static and rename to ... + (gpg_check_decrypt): ... this. + (_gpgme_gpg_op_delete): Make static and rename to ... + (gpg_check_delete): ... this. + (_gpgme_gpg_set_recipients): Make static and rename to ... + (gpg_check_set_recipients): ... this. + (_gpgme_gpg_op_encrypt): Make static and rename to ... + (gpg_encrypt): ... this. + (_gpgme_gpg_op_export): Make static and rename to ... + (gpg_export): ... this. + (_gpgme_gpg_op_genkey): Make static and rename to ... + (gpg_genkey): ... this. + (_gpgme_gpg_op_import): Make static and rename to ... + (gpg_import): ... this. + (_gpgme_gpg_op_keylist): Make static and rename to ... + (gpg_keylist): ... this. + (_gpgme_gpg_op_keylist_ext): Make static and rename to ... + (gpg_keylist_ext): ... this. + (_gpgme_gpg_op_sign): Make static and rename to ... + (gpg_sign): ... this. + (_gpgme_gpg_op_trustlist): Make static and rename to ... + (gpg_trustlist): ... this. + (_gpgme_gpg_op_verify): Make static and rename to ... + (gpg_verify): ... this. + (gpg_status_handler): Rename to ... + (status_handler): ... this. + (_gpgme_gpg_set_status_handler): Make static and rename to ... + (gpg_set_status_handler): ... this. + (_gpgme_gpg_set_colon_line_handler): Make static and rename to ... + (gpg_set_colon_line_handler): ... this. + (gpgme_gpg_add_io_cb): Rename to ... + (add_io_cb): ... this. + (_gpgme_gpg_start): Make static and rename to ... + (gpg_start): ... this. + (_gpgme_gpg_set_io_cb): Make static and rename to ... + (gpg_set_io_cb): ... this. + (_gpgme_gpg_io_event): Make static and rename to ... + (gpg_io_event): ... this. + (struct _gpgme_engine_ops_gpg): New variable. + +2002-10-10 Marcus Brinkmann + + * engine-gpgsm.c (_gpgme_gpgsm_op_verify) [!ENABLE_GPGSM]: Add + missing argument. + +2002-10-09 Marcus Brinkmann + + * data.h, data-user.c, data-stream.c, data-mem.c, data-fd.c, + data-compat.c: New file. Really check them in this time, completes + 2002-10-08 change. + + * rungpg.h (GpgStatusHandler): Rename type to GpgmeStatusHandler + and move to ... + * types.h (GpgmeStatusHandler): ... here. + * rungpg.h (GpgColonLineHandler): Rename type to GpgmeColonLineHandler. + and move to ... + * types.h (GpgmeColonLineHandler): ... here. + * rungpg.h (GpgCommandHandler): Rename type to GpgmeCommandHandler. + and move to ... + * types.h (GpgmeCommandHandler): ... here. + * engine.h: Don't include "rungpg.h". + (_gpgme_engine_set_status_handler): Change type of + argument from GpgStatusHandler to GpgmeStatusHandler. + (_gpgme_engine_set_colon_line_handler): Change type of + argument from GpgColonLineHandler to GpgmeColonLineHandler. + (_gpgme_engine_set_command_handler): Change type of + argument from GpgCommandHandler to GpgmeCommandHandler. + * engine-gpgsm.h: Don't include "rungpg.h". + (_gpgme_gpgsm_set_status_handler): Change type of + argument from GpgStatusHandler to GpgmeStatusHandler. + (_gpgme_gpgsm_set_colon_line_handler): Change type of + argument from GpgColonLineHandler to GpgmeColonLineHandler. + * engine-gpgsm.c: Do not include "rungpg.h". + (struct gpgsm_object_s): Change type of + status.fnc to GpgmeStatusHandler. Change type of colon.fnc to + GpgmeColonLineHandler. + (gpgsm_assuan_simple_command): Change type of argument from + GpgStatusHandler to GpgmeStatusHandler. + (_gpgme_gpgsm_set_status_handler): Likewise. + (_gpgme_gpgsm_set_colon_line_handler): Change type of argument from + GpgColonLineHandler to GpgmeColonLineHandler. + * rungpg.h (_gpgme_gpg_set_status_handler): Change type of + argument from GpgStatusHandler to GpgmeStatusHandler. + (_gpgme_gpg_set_colon_line_handler): Change type of + argument from GpgColonLineHandler to GpgmeColonLineHandler. + (_gpgme_gpg_set_command_handler): Change type of + argument from GpgCommandHandler to GpgmeCommandHandler. + * rungpg.c (struct gpg_object_s): Change type of status.fnc to + GpgmeStatusHandler. Change type of colon.fnc to + GpgmeColonLineHandler. Change type of cmd.fnc to + GpgmeCommandLineHandler. + (_gpgme_gpg_set_status_handler): Change type of argument FNC to + GpgmeStatusHandler. + (_gpgme_gpg_set_colon_line_handler): Change type of argument FNC + to GpgmeColonLineHandler. + (_gpgme_gpg_set_command_handler): Change type of argument FNC to + GpgmeCommandHandler. + * engine.c (_gpgme_engine_set_status_handler): Change type of + argument FNC to GpgmeStatusHandler. + (_gpgme_engine_set_colon_line_handler): Change type of argument FNC + to GpgmeColonLineHandler. + (_gpgme_engine_set_command_handler): Change type of argument FNC to + GpgmeCommandHandler. + + * rungpg.h (_gpgme_gpg_enable_pipemode): Remove prototype. + * rungpg.c (struct gpg_object_s): Remove PM. + (pipemode_cb): Prototype removed. + (add_pm_data): Function removed. + (_gpgme_gpg_enable_pipemode): Likewise. + (pipemode_copy): Likewise. + (pipemode_cb): Likewise. + (add_arg): Don't check for pipemode. + (add_data): Likewise. + (_gpgme_gpg_set_status_handler): Likewise. + (_gpgme_gpg_set_colon_line_handler): Likewise. + (_gpgme_gpg_set_command_handler): Likewise. + (_gpgme_gpg_spawn): Likewise. + (_gpgme_gpg_spawn): Don't set PM.active. + (_gpgme_gpg_op_verify): Remove pipemode case. + * verify.c (_gpgme_op_verify_start): Remove pipemode case. + + * rungpg.h (_gpgme_gpg_add_arg, _gpgme_gpg_add_data, + _gpgme_gpg_add_pm_data, _gpgme_gpg_housecleaning, + _gpgme_gpg_set_simple_line_handler): Prototype removed. + (_gpgme_gpg_set_verbosity): New prototype. + * rungpg.c (_gpgme_gpg_add_data): Make static and rename to ... + (add_data): ... this. + (_gpgme_gpg_add_pm_data): Call add_data, not _gpgme_gpg_add_data. + (_gpgme_gpg_set_command_handler): Likewise. + (_gpgme_gpg_op_decrypt, _gpgme_gpg_op_edit, _gpgme_gpg_op_encrypt, + _gpgme_gpg_op_encrypt_sign, _gpgme_gpg_op_export, + _gpgme_gpg_op_genkey, _gpgme_gpg_op_import, _gpgme_gpg_op_sign, + _gpgme_gpg_op_verify): Likewise. + (_gpgme_gpg_add_pm_data): Rename to ... + (add_pm_data): ... this. + (_gpgme_gpg_op_verify): Call add_pm_data, not + _gpgme_gpg_add_pm_data. + (_gpgme_gpg_add_arg): Make static and rename to ... + (add_arg): ... this. + (_gpgme_gpg_set_command_handler, _gpgme_gpg_new, + _gpgme_gpg_op_decrypt, _gpgme_gpg_op_delete, + _gpgme_append_gpg_args_from_signers, _gpgme_gpg_op_edit, + _gpgme_append_gpg_args_from_recipients, _gpgme_gpg_op_encrypt, + _gpgme_gpg_op_encrypt_sign, _gpgme_gpg_op_export, + _gpgme_gpg_op_genkey, _gpgme_gpg_op_import, _gpgme_gpg_op_keylist, + _gpgme_gpg_op_keylist_ext, _gpgme_gpg_op_trustlist, + _gpgme_gpg_op_sign, _gpgme_gpg_op_verify): Use add_arg, not + _gpgme_gpg_add_arg. + (_gpgme_gpg_set_verbosity): New function. + (struct gpg_object_s): Remove member simple from colon. + (_gpgme_gpg_set_colon_line_handler): Don't initialize simple. + (_gpgme_gpg_set_simple_line_handler): Removed function. + (read_colon_line): Don't check the GPG->colon.simple. + * engine.c (_gpgme_engine_set_verbosity): Call + _gpgme_gpg_set_verbosity instead _gpgme_gpg_add_arg. + +2002-10-08 Marcus Brinkmann + + * util.h (_gpgme_malloc, _gpgme_realloc, _gpgme_calloc, + _gpgme_strdup, _gpgme_free): Remove prototypes. + (xtrymalloc, xtrycalloc, xtryrealloc, xtrystrdup, xfree): Remove + macros. + * util.c: File removed. + * Makefile.am (libgpgme_la_SOURCES): Remove util.h. + * conversion.c (_gpgme_decode_c_string): Use malloc instead of + xtrymalloc, realloc instead of xtryrealloc, calloc instead of + xtrycalloc, free instead of xfree. + (_gpgme_data_append_percentstring_for_xml): Likewise. + * data.c (_gpgme_data_new, _gpgme_data_release): Likewise. + * data-compat.c (gpgme_data_new_from_filepart): Likewise. + * data-mem.c (mem_write, mem_release, gpgme_data_new_from_mem, + _gpgme_data_get_as_string): Likewise. + * debug.c (debug_init): Likewise. + * decrypt.c (_gpgme_release_decrypt_result): Likewise. + * delete.c (_gpgme_release_delete_result): Likewise. + * edit.c (_gpgme_release_edit_result, _gpgme_op_edit_start): + Likewise. + * encrypt.c (_gpgme_release_encrypt_result): Likewise. + * engine.c (_gpgme_engine_get_info, _gpgme_engine_new, + _gpgme_engine_release): Likewise. + * engine-gpgsm.c (_gpgme_gpgsm_new, _gpgme_gpgsm_release, + _gpgme_gpgsm_op_decrypt, _gpgme_gpgsm_op_delete, + gpgsm_set_recipients, _gpgme_gpgsm_op_encrypt, + _gpgme_gpgsm_op_export, _gpgme_gpgsm_op_genkey, + _gpgme_gpgsm_op_import, _gpgme_gpgsm_op_keylist, + _gpgme_gpgsm_op_keylist_ext, _gpgme_gpgsm_op_sign, + _gpgme_gpgsm_op_verify, gpgsm_status_handler): Likewise. + * genkey.c (_gpgme_release_genkey_result): Likewise. + * gpgme.c (gpgme_new, gpgme_release): Likewise. + * import.c (_gpgme_release_import_result): Likewise. + * key.c (_gpgme_key_cache_init, _gpgme_key_cache_add, key_new, + add_subkey, gpgme_key_release, _gpgme_key_append_name): Likewise. + * keylist.c (_gpgme_release_keylist_result, keylist_colon_handler, + _gpgme_op_keylist_event_cb, gpgme_op_keylist_next): Likewise. + * ops.h (test_and_allocate_result): Likewise. + * passphrase.c (_gpgme_release_passphrase_result, + _gpgme_passphrase_status_handler, + _gpgme_passphrase_command_handler): Likewise. + * progress.c (_gpgme_progress_status_handler): Likewise. + * recipient.c (gpgme_recipients_new, gpgme_recipients_release, + gpgme_recipients_add_name_with_validity): Likewise. + * rungpg.c (_gpgme_gpg_new, _gpgme_gpg_release, + _gpgme_gpg_add_arg, _gpgme_gpg_add_data, + _gpgme_gpg_set_colon_line_handler, free_argv, free_fd_data_map, + build_argv, _gpgme_gpg_spawn, read_status, read_colon_line): + Likewise. + * sign.c (_gpgme_release_sign_result): Likewise. + * signers.c (_gpgme_signers_add): Likewise. + * trustlist.c (trust_item_new, trustlist_colon_handler, + _gpgme_op_trustlist_event_cb, gpgme_op_trustlist_next, + gpgme_trustitem_release): Likewise. + * verify.c (_gpgme_release_verify_result, finish_sig): Likewise. + * version.c (gpgme_get_engine_info, _gpgme_get_program_version): + Likewise. + * w32-io.c (create_reader, create_writer, destroy_reader, + destroy_writer, build_commandline, _gpgme_io_spawn): Likewise. + * w32-sema.c (critsect_init, _gpgme_sema_cs_destroy): Likewise. + * w32-util.c (read_w32_registry_string): Likewise. + * wait.c (_gpgme_fd_table_deinit, _gpgme_fd_table_put, + _gpgme_wait_event_cb, _gpgme_add_io_cb, _gpgme_remove_io_cb) + * data-compat.c: Include . + +2002-10-08 Marcus Brinkmann + + New data object component: + + * gpgme.h (GpgmeDataReadCb, GpgmeDataWriteCb, GpgmeDataSeekCb, + GpgmeDataReleaseCb): New types. + (struct GpgmeDataCbs): New structure. + (gpgme_data_read): Changed prototype to match that of read() closely. + (gpgme_data_write): Similar for write(). + (gpgme_data_seek, gpgme_data_new_from_cbs, gpgme_data_new_from_fd, + gpgme_data_new_from_stream): New prototypes. + (gpgme_data_get_type, gpgme_check_engine): Prototype removed. + + * Makefile.am (libgpgme_la_SOURCES): Add data.h, data-fd.c, + data-stream.c, data-mem.c, data-user.c and data-compat.c. + * data.c: Reimplemented from scratch. + * (data-compat.c, data-fd.c, data.h, data-mem.c, data-stream.c, + data-user.c): New file. + * context.h (struct gpgme_data_s): Removed. + * conversion.c: Include and . + (_gpgme_data_append): New function. + * data.c (_gpgme_data_append_string): Move to ... + * conversion.c (_gpgme_data_append_string): ... here. + * data.c (_gpgme_data_append_for_xml): Move to ... + * conversion.c (_gpgme_data_append_for_xml): ... here. + * data.c (_gpgme_data_append_string_for_xml): Move to ... + * conversion.c (_gpgme_data_append_string_for_xml): ... here. + * data.c (_gpgme_data_append_percentstring_for_xml): Move to ... + * conversion.c (_gpgme_data_append_percentstring_for_xml): ... here. + + * ops.h (_gpgme_data_get_mode, _gpgme_data_set_mode): Prototype + removed. + * types.h (GpgmeDataMode): Type removed. + + * decrypt.c (_gpgme_decrypt_start): Don't check data type or mode. + * edit.c (_gpgme_op_edit_start): Likewise. + * encrypt.c (_gpgme_op_encrypt_start): Likewise. + * encrypt-sign.c (_gpgme_op_encrypt_sign_start): Likewise. + * encrypt-sign.c (_gpgme_op_encrypt_sign_start): Likewise. + * export.c (_gpgme_op_export_start): Likewise. + * genkey.c (_gpgme_op_genkey_start): Likewise. + * import.c (_gpgme_op_import_start): Likewise. + * sign.c (_gpgme_op_sign_start): Likewise. + * verify.c (_gpgme_op_verify_start): Likewise. + + * encrypt.c (gpgme_op_encrypt): Remove hack that returns invalid + no recipient if no data was returned. + * encrypt-sign.c (gpgme_op_encrypt_sign): Remove hack that returns + no recipient if no data was returned. + * encrypt-sign.c (gpgme_op_encrypt_sign): Remove hack that returns + no recipient if no data was returned. + + * engine.c (_gpgme_engine_op_verify): Add new argument to + differentiate detached from normal signatures. + * engine.h (_gpgme_engine_op_verify): Likewise for prototype. + * engine-gpgsm.c (_gpgme_gpgsm_op_verify): Likewise. Don't check + mode of data argument. + * engine-gpgsm.h (_gpgme_gpgsm_op_verify): Likewise for prototype. + * gpgme.h (gpgme_op_verify_start): Likewise for prototype. + (gpgme_op_verify): Likewise for prototype. + * rungpg.c (_gpgme_gpg_op_verify): Likewise. + * rungpg.h (_gpgme_gpg_op_verify): Likewise for prototype. + * verify.c (_gpgme_op_verify_start): Likewise. + (gpgme_op_verify_start): Likewise. + (gpgme_op_verify): Likewise. + + * rungpg.c (struct arg_and_data_s): New member INBOUND to hold + direction of data object. + (_gpgme_gpg_add_data): Add new argument INBOUND. Use it to + determine direction of data object. + (_gpgme_gpg_add_pm_data, _gpgme_gpg_set_command_handler, + _gpgme_gpg_op_decrypt, _gpgme_gpg_op_edit, _gpgme_gpg_op_encrypt, + _gpgme_gpg_op_encrypt_sign, _gpgme_gpg_op_export, + _gpgme_gpg_op_genkey, _gpgme_gpg_op_import, _gpgme_gpg_op_sign, + _gpgme_gpg_op_verify): Add new argument to _gpgme_gpg_add_data + invocation. + (build_argv): Use new member INBOUND to determine direction of + file descriptor. Don't check the data type. + * rungpg.h (_gpgme_gpg_add_data): Add new argument to prototype. + + * gpgme.c (gpgme_get_op_info): Don't call + _gpgme_data_get_as_string if CTX->op_info is NULL. + + * version.c (gpgme_check_engine): Function removed. + +2002-09-30 Werner Koch + + * keylist.c (keylist_colon_handler): Take care when printing a + NULL with the DEBUG. + + * engine-gpgsm.c (struct gpgsm_object_s): New member ANY. + (gpgsm_status_handler): Run the colon function to indicate EOF. + (_gpgme_gpgsm_set_colon_line_handler): Better reset ANY here. + +2002-09-28 Marcus Brinkmann + + * conversion.c (_gpgme_hextobyte): Prevent superfluous + multiplication with base. Reported by Stéphane Corthésy. + + * keylist.c (gpgme_op_keylist_ext_start): Use private asynchronous + operation type in invocation of _gpgme_op_reset. + +2002-09-20 Werner Koch + + * ath.c: Include sys/time.h if sys/select.h is not available. + +2002-09-13 Marcus Brinkmann + + * keylist.c (keylist_status_handler): Do not call finish_key() here. + (gpgme_op_keylist_ext_start): Set CTX->tmp_key to NULL. + +2002-09-03 Marcus Brinkmann + + * Makefile.am (assuan_libobjs): Remove @LTLIBOBJS@ as we link them + into gpgme unconditionally. + (libgpgme_la_LIBADD): Change @LIBOBJS@ into @LTLIBOBJS@. + +2002-09-02 Marcus Brinkmann + + * Makefile.am (assuan_libobjs): Use @LTLIBOBJS@ instead @LIBOBJS@. + +2002-09-02 Marcus Brinkmann + + * debug.c (_gpgme_debug_add): Test *LINE, not LINE. + (_gpgme_debug_end): Likewise. + Reported by Dr. Stefan Dalibor . + +2002-09-02 Marcus Brinkmann + + * posix-io.c (_gpgme_io_select): Don't use a non-constant struct + initializer. + * version.c (_gpgme_get_program_version): Likewise. + Reported by Dr. Stefan Dalibor . + +2002-09-02 Marcus Brinkmann + + * conversion.c (_gpgme_decode_c_string): Set DESTP before + modifying DEST. + + * conversion.c (_gpgme_decode_c_string): Fix off by one error in + last change. + * rungpg.c (_gpgme_append_gpg_args_from_signers): Move before + _gpgme_op_edit so its prototype is known early on. + + * conversion.c: New file. + * util.h: Add prototypes for _gpgme_decode_c_string and + _gpgme_hextobyte. + * keylist.c (keylist_colon_handler): Call _gpgme_decode_c_string + on issuer name. + * Makefile.am (libgpgme_la_SOURCES): Add conversion.c + * key.c (_gpgme_key_append_name): Replace calls to hextobyte by + calls to _gpgme_hextobyte. + (hash_key): Likewise. + +2002-09-01 Marcus Brinkmann + + * op-support.c (_gpgme_op_reset): Set CTX->pending after calling + _gpgme_engine_release, as this will reset pending to zero in the + event done callback on cancelled operations. + +2002-08-30 Marcus Brinkmann + + * rungpg.c (_gpgme_gpg_op_edit): Add args from signers. + Suggested by Miguel Coca . + + * rungpg.c (_gpgme_gpg_op_edit): Add bogus ctx argument. + * rungpg.h: Also to prototype. + * engine.c (_gpgme_engine_op_edit): Likewise. + * engine.h: Likewise. + * edit.c (_gpgme_op_edit_start): Likewise. + +2002-08-29 Werner Koch + + * engine-gpgsm.c (_gpgme_gpgsm_op_sign): Implement signer + selection. + * vasprintf.c (va_copy): Define macro if not yet defined. + +2002-08-29 Marcus Brinkmann + + * passphrase.c (_gpgme_passphrase_status_handler): Reset + CTX->result.passphrase->no_passphrase if passphrase is given (good + or bad). Submitted by Jean DIRAISON . + +2002-08-28 Marcus Brinkmann + + * posix-io.c (_gpgme_io_spawn): Use a double-fork approach. + Return 0 on success, -1 on error. + * version.c (_gpgme_get_program_version): Don't wait for the child. + * engine.c (_gpgme_engine_housecleaning): Function removed. + (do_reaping): Likewise. + (_gpgme_engine_add_child_to_reap_list): Likewise. + (struct reap_s): Removed. + (reap_list): Likewise. + (reap_list_lock): Likewise. + * engine.h (_gpgme_engine_io_event): Remove prototypes for + _gpgme_engine_housecleaning and + _gpgme_engine_add_child_to_reap_list. + * rungpg.c (_gpgme_gpg_release): Don't add child to reap list. + (struct gpg_object_s): Remove PID member. + (_gpgme_gpg_new): Don't initialize GPG->pid. + (_gpgme_gpg_spawn): Don't set GPG->pid. + * wait.c (run_idle): Removed. + (gpgme_wait): Run idle_function directly. + +2002-08-21 Marcus Brinkmann + + * encrypt-sign.c (encrypt_sign_status_handler): Remove dead + variables encrypt_info and encrypt_info_len. + * trustlist.c (gpgme_op_trustlist_start): Set colon line handler. + * posix-sema.c (sema_fatal): Remove function. + All these reported by Stéphane Corthésy. + +2002-08-23 Werner Koch + + * gpgme-config.in: Made --prefix work for --libs. + +2002-08-21 Marcus Brinkmann + + * ath.h: Update list of symbols that get a prefix: Rename the + ath_mutex_*_available symbols to ath_*_available. + +2002-08-21 Marcus Brinkmann + + * stpcpy.c: New file from gnulib. + * Makefile.am (assuan_libobjs): Remove jnlib. + +2002-08-20 Marcus Brinkmann + + * gpgme.h: Add prototype for gpgme_op_import_ext. + * import.c (struct import_result_s): New member `nr_considered'. + Rename `any_imported' to `nr_imported'. + (import_status_handler): Increment nr_imported. Set nr_considered + if appropriate. + (gpgme_op_import_ext): New function. + (gpgme_op_import): Implement in terms of gpgme_op_import_ext. + +2002-08-20 Werner Koch + + * gpgme.m4: Replaced with a new and faster version. This does not + anymore try to build test programs. If we really need test + programs, we should add an option to gpgme-config to do so. + + * vasprintf.c (int_vasprintf): Hack to handle NULL passed for %s. + +2002-08-20 Marcus Brinkmann + + * gpgme.c (_gpgme_set_op_info): Append data on subsequent calls. + * encrypt-sign.c (encrypt_sign_status_handler): Remove op_info + handling. + +2002-08-19 Werner Koch + + * decrypt.c (is_token,skip_token): Duplicated from verify.c + (gpgme_op_decrypt): Hack to properly return Decryption_Failed.. + (_gpgme_decrypt_status_handler): Create an operation info. + +2002-08-14 Werner Koch + + * key.h (struct certsig_s): New. Use it in gpgme_key_s. + * key.c (gpgme_key_release): Release it. We need to add more code + of course. + (_gpgme_key_append_name): Use memset to intialize the struct. + * gpgme.h (GPGME_KEYLIST_MODE_SIGS): New. + * rungpg.c (_gpgme_gpg_op_keylist): Include sigs in listing depending + non the list mode. + + * key.c (gpgme_key_get_string_attr): Use GPGME_ATTR_TYPE to return + information about the key type (PGP or X.509). + (gpgme_key_get_ulong_attr): Likewise. + + * keylist.c (keylist_colon_handler): Include 1 in the check for + valid algorithms so that RSA is usable. Store the issuer name and + serial number also for "crs" records. Parse the expire date for + subkeys. + (set_userid_flags): Put them onto the last appended key. + +2002-07-29 Marcus Brinkmann + + * rungpg.c (_gpgme_gpg_op_edit): Use --with-colons. + +2002-07-28 Marcus Brinkmann + + * data.c (gpgme_data_read): For GPGME_DATA_TYPE_NONE, return EOF + instead an error. + + The following changes make it possible to flush an inbound data + pipe before invoking a command handler: + + * posix-io.c (_gpgme_io_select): Accept new argument NONBLOCK to + _gpgme_io_select. Set timeout of 0 if this is set. + * w32-io.c (_gpgme_io_select): Likewise. + * io.h: Add new argument NONBLOCK to _gpgme_io_select prototype. + * wait.c (do_select): Add new argument to _gpgme_io_select + invocation. + * rungpg.h (_gpgme_gpg_set_command_handler): Add new argument + linked_data to prototype. + * engine.h (_gpgme_engine_set_command_handler): Likewise. + * engine.c (_gpgme_engine_set_command_handler): Likewise. + * passphrase.c (_gpgme_passphrase_start): Pass NULL as linked_data + argument to _gpgme_engine_set_command_handler. + * rungpg.c (struct gpg_object_s): New members linked_data and + linked_idx in CMD. + (_gpgme_gpg_new): Initialize those new members. + (_gpgme_gpg_set_command_handler): Accept new argument linked_data. + (build_argv): Handle linked_data in the same hack as cb_data. + (read_status): If linked_data is in use, flush the pipe before + activating the command handler. + * gpgme.h: Add prototypes for gpgme_op_edit_start and + gpgme_op_edit. + + The next changes export the status codes to the user: + + * decrypt.c (_gpgme_decrypt_status_handler): Likewise, also prefix + all STATUS_ with GPGME_. + * delete.c (delete_status_handler): Likewise. + * decrypt-verify.c (decrypt_verify_status_handler): Likewise. + * encrypt.c (_gpgme_encrypt_status_handler): Likewise. + (_gpgme_encrypt_sym_status_handler): Likewise. + * encrypt-sign.c (encrypt_sign_status_handler): Likewise. + * engine-gpgsm.c (parse_status): Likewise. + (gpgsm_status_handler): Likewise. + (gpgsm_set_recipients): Likewise. + * export.c (export_status_handler): Likewise. + * genkey.c (genkey_status_handler): Likewise. + * import.c (append_xml_impinfo): Likewise. + (import_status_handler): Likewise. + * keylist.c (keylist_status_handler): Likewise. + * passphrase.c (_gpgme_passphrase_status_handler): Likewise. + (command_handler): Likewise. + * progress.c (_gpgme_progress_status_handler): Likewise. + * sign.c (_gpgme_sign_status_handler): Likewise. + * trustlist.c (trustlist_status_handler): Likewise. + * verify.c (_gpgme_verify_status_handler): Likewise. + * gpgme.h (GpgmeEditCb): New type. + * rungpg.h (GpgStatusCode): Rename and move to ... + * gpgme.h (GpgmeStatusCode): ... this and here. + * Makefile.am (status-table.h): Run mkstatus on gpgme.h, not rungpg.h. + * mkstatus: Prefix STATUS with GPGME_. + * rungpg.h (GpgStatusHandler, GpgCommandHandler): Change type + accordingly. + * ops.h (_gpgme_verify_status_handler, + _gpgme_decrypt_status_handler, _gpgme_sign_status_handler, + _gpgme_encrypt_status_handler, _gpgme_passphrase_status_handler, + _gpgme_progress_status_handler): Likewise. + * rungpg.c (struct gpg_object_s): Likewise for CMD.code. + + These changes add an edit operation to GPGME: + + * context.h (struct gpgme_context_s): New member RESULT.edit. * + ops.h: Add prototype for _gpgme_release_edit_result and + _gpgme_passphrase_command_handler. + * passphrase.c (command_handler): Make non-static and rename to ... + (_gpgme_passphrase_command_handler): ... this. + (_gpgme_passphrase_start): Use new name for command handler. + * types.h: Add EditResult type. + * gpgme.c (_gpgme_release_result): Release EDIT result. + * edit.c: New file. + * Makefile.am (libgpgme_la_SOURCES): Add edit.c. + (libgpgme_la_LDADD): Rename to libgpgme_la_LIBADD, and include + assuan_libobjs. + (assuan_libobjs): New variable, set this instead + libgpgme_la_LIBADD. + * engine.h (_gpgme_engine_op_edit): New prototype. + * engine.c (_gpgme_engine_op_edit): New function. + * rungpg.h (_gpgme_gpg_op_edit): New prototype. + * rungpg.c (_gpgme_gpg_op_edit): New function. + +2002-07-27 Marcus Brinkmann + + * delete.c (delete_problem): New case ambigious specification. + (delete_status_handler): Handle new case (poorly). + +2002-07-25 Marcus Brinkmann + + * engine-gpgsm.c (_gpgme_gpgsm_op_delete): Implement this. + +2002-07-25 Marcus Brinkmann + + * Makefile.am (libgpgme_la_LDADD): Add @LIBOBJS@ for vasprintf and + fopencookie. + * vasprintf.c: Update to more recent libiberty version. + * debug.h: Replace #elsif with #elif. + + Submitted by Stéphane Corthésy: + * util.h (vasprintf): Correct prototype. + * encrypt-sign.c: Include . + (encrypt_sign_status_handler): Change type of ENCRYPT_INFO_LEN to + size_t. + * ath-pthread.c: Include , not . + * ath-pth.c: Likewise. + +2002-07-25 Marcus Brinkmann + + * wait.c (fdt_global): Make static. Reported by Stéphane + Corthésy. + + * rungpg.c (_gpgme_gpg_op_keylist_ext): Skip empty string + patterns. Reported by Stéphane Corthésy. + + * key.c (gpgme_key_get_as_xml): Add OTRUST attribute. Requested + by Stéphane Corthésy. + (gpgme_key_get_string_attr): Add GPGME_ATTR_SIG_SUMMARY case to + silence gcc warning. + + * rungpg.c (_gpgme_gpg_new): Always set utf8 as charset. + +2002-07-03 Marcus Brinkmann + + * gpgme.c (gpgme_set_io_cbs): Deal with CTX being NULL. + + * gpgme.c (_gpgme_op_event_cb_user): New function. + * op-support.c (_gpgme_op_reset): Support a new mode of operation + for private or user event loop. Use new user event callback + wrapper. + * trustlist.c (gpgme_op_trustlist_start): Use this new mode. + * keylist.c (gpgme_op_keylist_start): Likewise. + + * rungpg.c (_gpgme_gpg_io_event): New function. + * rungpg.h (_gpgme_gpg_io_event): New prototype. + * engine-gpgsm.c (_gpgme_gpg_io_event): New function. + * engine-gpgsm.h (_gpgme_gpgsm_io_event): New prototype. + * engine.c (_gpgme_engine_io_event): New function. + * engine.h (_gpgme_engine_io_event): New prototype. + * keylist.c (finish_key): Call _gpgme_engine_io_event, and move + the real work for the default IO callback routines to ... + (_gpgme_op_keylist_event_cb): ... here. New function. + * trustlist.c (trustlist_colon_handler): Signal + GPGME_EVENT_NEXT_TRUSTITEM. Move queue manipulation to ... + (_gpgme_op_trustlist_event_cb): ... here. New function. + * gpgme.c (_gpgme_op_event_cb): Call _gpgme_op_keylist_event_cb + and _gpgme_op_trustlist_event_cb when appropriate. + * ops.h (_gpgme_op_keylist_event_cb): New prototype. + (_gpgme_op_trustlist_event_cb): Likewise. + * op-support.c (_gpgme_op_reset): Add comment why we don't use the + user provided event handler directly. + * gpgme.h (GpgmeRegisterIOCb): Return GpgmeError value, and TAG in + a pointer argument. + * wait.c (_gpgme_add_io_cb): Likewise. + * wait.h (_gpgme_add_io_cb): Likewise for prototype. + * rungpg.c (_gpgme_gpg_add_io_cb): Call IO_CBS->add with new + argument. Fix up error handling. + * engine-gpgsm.c (_gpgme_gpgsm_add_io_cb): Call IO_CBS->add with + new argument, fix up error handling. + +2002-07-03 Werner Koch + + * encrypt.c (status_handler_finish): New. + (_gpgme_encrypt_status_handler): Moved some code out to the new + function and call this function also in case we get into the + status handler with an error which might happen due to a kludge in + engine-gpgsm.c + +2002-06-28 Marcus Brinkmann + + * keylist.c (gpgme_op_keylist_ext_start): Always use our own FD + table (eg use synchronous mode). + +2002-06-28 Marcus Brinkmann + + * ops.h (_gpgme_wait_on_condition): Remove HANG argument from + prototype and change return type to GpgmeError. + (_gpgme_wait_one): New prototype. + * wait.c (gpgme_wait): Replace with the meat from + _gpgme_wait_on_condition here, and remove the support for + conditions. + (_gpgme_wait_on_condition): Remove HANG argument from prototype + and change return type to GpgmeError. Replace with meat from + _gpgme_wait_one and add support for conditions. + (_gpgme_wait_one): Just call _gpgme_wait_on_condition without + condition. + * keylist.c (gpgme_op_keylist_ext_start): Always use our own FD + table (eg use synchronous mode). + (gpgme_op_keylist_next): Remove HANG argument from + _gpgme_wait_on_condition. Check its return value. + * trustlist.c (gpgme_op_trustlist_start): Always use our own FD + table (eg use synchronous mode). + (gpgme_op_trustlist_next): Remove HANG argument from + _gpgme_wait_on_condition. Check its return value. + +2002-06-27 Marcus Brinkmann + + * gpgme.h: Fix documentation of key attribute retrieval functions. + +2002-06-26 Werner Koch + + * engine-gpgsm.c (map_assuan_error): Map No_Data_Available to EOF. + + * import.c (append_xml_impinfo): Kludge to print fingerprint + instead of keyid for use with gpgsm. + (import_status_handler): Set a flag to know whether any import + occured. + (gpgme_op_import): Reurn -1 if no certificate ewas imported. + +2002-06-25 Werner Koch + + * engine-gpgsm.c (_gpgme_gpgsm_set_io_cbs) [ENABLE_GPGSM]: Fixed + function arguments. + +2002-06-25 Marcus Brinkmann + + * engine-gpgsm.c (_gpgme_gpgsm_op_export): Only export the keys + listed in RECP. + * export.c (gpgme_op_export): If no data was returned, return + GPGME_No_Recipients. + +2002-06-25 Marcus Brinkmann + + * engine-gpgsm.c (_gpgme_gpgsm_op_export): Implement. + +2002-06-21 Marcus Brinkmann + + * engine-gpgsm.c (gpgsm_assuan_simple_command): Return ERR. + (parse_status): New function. + (gpgsm_status_handler): Use parse_status. + (gpgsm_assuan_simple_command): Accept new arguments STATUS_FNC and + STATUS_FNC_VALUE and process status messages. + (gpgsm_set_recipients): Pass new arugments to gpgsm_assuan_simple_command. + (gpgsm_set_fd): Likewise. + (_gpgme_gpgsm_op_keylist): Likewise. + (_gpgme_gpgsm_op_keylist_ext): Likewise. + (_gpgme_gpgsm_op_sign): Likewise. + +2002-06-21 Marcus Brinkmann + + * wait.c (_gpgme_remove_io_cb): Unlock FDT->lock. + +2002-06-20 Werner Koch + + * rungpg.c (build_argv): Ignore GPG_AGENT_INFO if set but empty. + + * verify.c (calc_sig_summary): Set bad policy for wrong key usage. + (skip_token): New. + (_gpgme_verify_status_handler): Watch out for wrong key usage. + (gpgme_get_sig_string_attr): Hack to return info on the key + usage. Does now make use of the former RESERVED argument which + has been renamed to WHATIDX. + (gpgme_get_sig_ulong_attr): Renamed RESERVED to WHATIDX. + +2002-06-14 Marcus Brinkmann + + * wait.c (do_select): Return -1 on error, and 0 if nothing to run. + (_gpgme_wait_one): Only set HANG to zero if do_select returned an + error, or there are no more file descriptors to wait on. + (_gpgme_wait_on_condition): Ignore return value from do_select for + now. + +2002-06-13 Werner Koch + + * verify.c (gpgme_op_verify): Make sure that we never access an + unitialized result structure. + +2002-06-12 Werner Koch + + * keylist.c (struct keylist_result_s): New. + (_gpgme_release_keylist_result): Release it here + (keylist_status_handler): Handle truncated. + (append_xml_keylistinfo): New. + * gpgme.c (_gpgme_release_result): and use it here. + * types.h: Declare the new type here. + * context.h (struct gpgme_context_s): Use it here. + +2002-06-11 Marcus Brinkmann + + * engine-gpgsm.c (_gpgme_gpgsm_release): Close status_cb.fd. + (_gpgme_gpgsm_new): Duplicate status file descriptor, so we can + use our own close notification mechanism without interfering with + assuan. + +2002-06-11 Werner Koch + + * gpgme.h: Add GPGME_ATTR_SIG_SUMMARY and the GPGME_SIGSUM_ + constants. + * verify.c (calc_sig_summary): New. + (gpgme_get_sig_ulong_attr): And use it here. + +2002-06-10 Werner Koch + + * rungpg.h: Add new status codes TRUNCATED and ERROR. + * verify.c (is_token, copy_token): New. + (_gpgme_verify_status_handler): Use copy_token, handle the new + ERROR status and store the errorcode used withgpgsm and trust + status codes. + * gpgme.h: New attribute ERRTOK. + * key.c (gpgme_key_get_string_attr): Add dummy case for it. + (gpgme_get_sig_string_attr): Use it here to return the last error. + +2002-06-10 Marcus Brinkmann + + * engine-gpgsm.c (_gpgme_gpgsm_start): Move the code that sets the + close notification for the status fd to ... + (_gpgme_gpgsm_new): ... here. + * wait.h: Include "sema.h". Remove prototypes of + _gpgme_remove_proc_from_wait_queue and + _gpgme_register_pipe_handler. Add prototypes of + _gpgme_fd_table_init, _gpgme_fd_table_deinit, _gpgme_fd_table_put, + _gpgme_add_io_cb, _gpgme_remove_io_cb, _gpgme_wait_event_cb and + _gpgme_wait_one.. + * wait.c: Remove global variables PROC_QUEUE, PROC_QUEUE_LOCK, + FD_TABLE_SIZE, FD_TABLE, FD_TABLE_LOCK. New global variables + FDT_GLOBAL, CTX_DONE_LIST, CTX_DONE_LIST_SIZE, + CTX_DONE_LIST_LENGTH and CTX_DONE_LIST_LOCK. Remove struct + proc_s. Replace struct wait_item_s. + (_gpgme_fd_table_init): New function. + (_gpgme_fd_table_deinit): Likewise. + (_gpgme_fd_table_put): Likewise. + (set_process_done): Remove function. + (do_select): Take argument FDT. Use that to decide which fds to + select on. + (_gpgme_remove_proc_from_wait_queue): Remove function. + (_gpgme_wait_event_cb): New function. + (_gpgme_wait_one): Likewise. + (_gpgme_register_pipe_hanldler): Remove function. + (_gpgme_add_io_cb): New function. + (_gpgme_remove_io_cb): Likewise. + (_gpgme_freeze_fd): Remove function. + (_gpgme_thaw_fd): Remove function. + * rungpg.c (struct fd_data_map_s): Add new member TAG. + (struct gpg_object_s): Likewise for STATUS and COLON. Add member + IDX to CMD. Add new member IO_CBS. + (close_notify_handler): New variables POSSIBLY_DONE and NOT_DONE. + For each I/O callback, check if it should be unregistered. If all + callbacks have been unregistered, trigger GPGME_EVENT_DONE. + Remove member RUNNING. + (_gpgme_gpg_new): Initialize new members. + (_gpgme_gpg_release): Check PID not RUNNING. Don't call + _gpgme_remove_proc_from_wait_queue. Close GPG->CMD.FD if set. + (build_argv): Store away the index instead the file descriptor for + CMD. + (_gpgme_gpg_add_io_cb): New function. + (_gpgme_gpg_spawn): Use _gpgme_gpg_add_io_cb to register IO + callbacks. + (gpg_status_handler): Change return type to void, remove PID + argument, close filedescriptor if EOF or error occurs. + (read_status): Use _gpgme_gpg_add_io_cb instead _gpgme_thaw_fd. + Use IO_CBS->remove instead _gpgme_freeze_fd. + (gpg_colon_line_handler): Change return type to void, remove PID + argument, close filedescriptor if EOF or error occurs. + (command_cb): Use IO_CBS->remove instead _gpgme_freeze_fd. + (_gpgme_gpg_set_io_cbs): New function. + * rungpg.h (_gpgme_gpg_set_io_cbs): Prototype for + _gpgme_gpg_set_io_cbs. + * gpgme.h (GpgmeIOCb): New type. + (GpgmeRegisterIOCb): Likewise. + (GpgmeRemoveIOCb): Likewise. + (GpgmeEventIO): Likewise. + (GpgmeEventIOCb): Likewise. + (struct GpgmeIOCbs): New structure to hold I/O callbacks. + (gpgme_set_op_io_cbs): New prototype. + (gpgme_get_op_io_cbs): Likewise. + * ops.h: New prototype for _gpgme_op_event_cb. Remove prototypes + for _gpgme_freeze_fd and _gpgme_thaw_fd. Remove PID argument from + _gpgme_data_inbound_handler and _gpgme_data_outbound_handler + prototype. Add prototype for _gpgme_op_reset. + Add synchronous argument to _gpgme_decrypt_start prototype. + * io.h: Beautification. + * gpgme.c: Include "wait.h". + (gpgme_new): Initialize FDT. + (gpgme_set_io_cbs): New function. + (gpgme_get_io_cbs): Likewise. + (_gpgme_op_event_cb): Likewise. + * data.c (_gpgme_data_inbound_handler): Change return type to + void. Drop PID argument. Close FD on error and EOF. + (write_mem_data): Don't close FD here ... + (write_cb_data): ... or here ... + (_gpgme_data_outbound_handler): ... but here. Change return type + to void. Drop PID argument. + * context.h: Include "wait.h". + (struct gpgme_context_s): New members FDT and IO_CBS. + * op-support.c: New file. + * Makefile.am (libgpgme_la_SOURCES): Add op-support.c. + * ops.h: Add prototype for _gpgme_op_reset(). + * decrypt.c (_gpgme_decrypt_start): New argument SYNCHRONOUS. Use + _gpgme_op_reset. + (gpgme_op_decrypt_start): Add synchronous argument. + (gpgme_op_decrypt): Likewise. Use _gpgme_wait_one instead + gpgme_wait. + * delete.c (gpgme_op_delete_start): Rename to ... + (_gpgme_op_delete_start): ... this. New argument SYNCHRONOUS. + Use _gpgme_op_reset. Make function static. + (gpgme_op_delete_start): Just a wrapper around + _gpgme_op_delete_start now. + (gpgme_op_delete): Add synchronous argument. Use _gpgme_wait_one + instead gpgme_wait. + * encrypt.c: Include "wait.h". + (ggpgme_op_encrypt_start): Rename to ... + (_gpgme_op_encrypt_start): ... this. New argument SYNCHRONOUS. + Use _gpgme_op_reset. Make function static. + (gpgme_op_encrypt_start): Just a wrapper around + _gpgme_op_encrypt_start now. + (gpgme_op_encrypt): Add synchronous argument. Use _gpgme_wait_one + instead gpgme_wait. + * encrypt_sign.c (gpgme_op_encrypt_sign_start): Rename to ... + (_gpgme_op_encrypt_sign_start): ... this. New argument + SYNCHRONOUS. Use _gpgme_op_reset. Make function static. + (gpgme_op_encrypt_sign_start): Just a wrapper around + _gpgme_op_encrypt_sign_start now. + (gpgme_op_encrypt_sign): Add synchronous argument. Use + _gpgme_wait_one instead gpgme_wait. + * export.c (gpgme_op_export_start): Rename to ... + (_gpgme_op_export_start): ... this. New argument SYNCHRONOUS. + Use _gpgme_op_reset. Make function static. + (gpgme_op_export_start): Just a wrapper around + _gpgme_op_export_start now. + (gpgme_op_export): Add synchronous argument. Use _gpgme_wait_one + instead gpgme_wait. + * genkey.c (gpgme_op_genkey_start): Rename to ... + (_gpgme_op_genkey_start): ... this. New argument SYNCHRONOUS. + Use _gpgme_op_reset. Make function static. + (gpgme_op_genkey_start): Just a wrapper around + _gpgme_op_genkey_start now. + (gpgme_op_genkey): Add synchronous argument. Use _gpgme_wait_one + instead gpgme_wait. + * import.c (gpgme_op_import_start): Rename to ... + (_gpgme_op_import_start): ... this. New argument SYNCHRONOUS. + Use _gpgme_op_reset. Make function static. + (gpgme_op_import_start): Just a wrapper around + _gpgme_op_import_start now. + (gpgme_op_import): Add synchronous argument. Use _gpgme_wait_one + instead gpgme_wait. + * keylist.c (gpgme_op_keylist_start): Use _gpgme_op_reset. + (gpgme_op_keylist_ext_start): Likewise. + * sign.c (gpgme_op_sign_start): Rename to ... + (_gpgme_op_sign_start): ... this. New argument SYNCHRONOUS. Use + _gpgme_op_reset. Make function static. + (gpgme_op_sign_start): Just a wrapper around _gpgme_op_sign_start + now. + (gpgme_op_sign): Add synchronous argument. Use _gpgme_wait_one + instead gpgme_wait. + * trustlist.c (gpgme_op_trustlist_start): Use _gpgme_op_reset. + * verify.c (gpgme_op_verify_start): Rename to ... + (_gpgme_op_verify_start): ... this. New argument SYNCHRONOUS. + Use _gpgme_op_reset. Make function static. + (gpgme_op_verify_start): Just a wrapper around + _gpgme_op_verify_start now. + (gpgme_op_verify): Add synchronous argument. Use _gpgme_wait_one + instead gpgme_wait. + * engine-gpgsm.c (iocb_data_t): New type. + (struct gpgsm_object_s): New member status_cb. Replace input_fd + and input_data with input_cb. Replace output_fd and output_data + with output_cb. Replace message_fd and message_data with + message_cb. New member io_cbs. + (_gpgme_gpgsm_new): Initialize all new members (and drop the old + ones). + (close_notify_handler): New variable POSSIBLY_DONE. For each I/O + callback, check if it should be unregistered. If all callbacks + have been unregistered, trigger GPGME_EVENT_DONE. + (_gpgme_gpgsm_release): Remove variable PID. Use new variable + names to close the file descriptors. + (_gpgme_gpgsm_op_decrypt): Use new variable names, + (_gpgme_gpgsm_op_encrypt): Likewise. + (_gpgme_gpgsm_op_genkey): Likewise. + (_gpgme_gpgsm_op_import): Likewise. + (_gpgme_gpgsm_op_keylist): Likewise. + (_gpgme_gpgsm_op_keylist_ext): Likewise. + (_gpgme_gpgsm_op_sign): Likewise. + (_gpgme_gpgsm_op_verify): Likewise. + (gpgsm_status_handler): Drop argument PID. Change return type to + void. Close status pipe before returning because of EOF or error. + (_gpgme_gpgsm_add_io_cb): New function. + (_gpgme_gpgsm_start): Use _gpgme_gpgsm_add_io_cb to register + callback function. + (_gpgme_gpgsm_set_io_cbs): New function. + * engine-gpgsm.h: New prototype for _gpgme_gpgsm_set_io_cbs. + * engine.c (_gpgme_engine_set_io_cbs): New function. + * engine.h: New prototype for _gpgme_engine_set_io_cbs. + +2002-06-04 Marcus Brinkmann + + * Makefile.am (libgpgme_la_SOURCES): Remove mutex.h. + +2002-06-03 Marcus Brinkmann + + * key.c: Include . + (_gpgme_key_append_name): Skip one more char when + processing escaped char. Submitted by Marc Mutz . + Handle hexadecimal encodings. Also reported by Marc. Thanks! + +2002-06-02 Marcus Brinkmann + + * ath.h: Enable the _gpgme_ prefix. Fix all those prefix macros. + * posix-sema.c: Use that prefix here. + * posix-io.c: Include "ath.h". + (_gpgme_io_read): Use _gpgme_ath_read instead read. + (_gpgme_io_write): Use _gpgme_ath_write instead write. + (_gpgme_io_waitpid): Use _gpgme_ath_waitpid instead waitpid. + (_gpgme_io_select): Use _gpgme_ath_select instead select. + +2002-06-02 Marcus Brinkmann + + * Makefile.am (ath_components): New variable. + (ath_components_pthread): Likewise. + (ath_components_pth): Likewise. + (system_components): Add ath_componentes. + + * ath.h: New file. + * ath.c: Likewise. + * ath-pthread.c: Likewise. + * ath-pth.c: Likewise. + * posix-sema.c (_gpgme_sema_cs_enter): Rework to use the ATH + interface. + * mutex.h: Remove file. + +2002-05-30 Werner Koch + + * key.c (gpgme_key_get_string_attr): Return NULL when asking for + an issuer with IDX > 0. We don't support altIssuerNames for now. + +2002-05-22 Werner Koch + + * engine-gpgsm.c (_gpgme_gpgsm_op_keylist_ext): Aehmm, added + missing variable definition. Oohh - Marcus was faster. + +2002-05-22 Marcus Brinkmann + + * engine-gpgsm.c (_gpgme_gpgsm_op_keylist_ext): Fix last change. + +2002-05-21 Werner Koch + + * engine-gpgsm.c (_gpgme_gpgsm_op_keylist) + (_gpgme_gpgsm_op_keylist_ext): Pass the keylist mode to gpgsm. + +2002-05-10 Werner Koch + + * key.h (gpgme_key_s): Add OTRUST. + * keylist.c (set_ownertrust): New. + (keylist_colon_handler): Get the ownertrust value + * key.c (gpgme_key_get_string_attr,gpgme_key_get_ulong_attr): + Return that value. + +2002-05-08 Marcus Brinkmann + + * w32-util.c: New static variable GET_PATH_LOCK. + (_gpgme_get_gpg_path): Remove superfluous NULL initializer. + Take lock while determining path. + (_gpgme_get_gpgsm_path): Likewise. + * version.c (do_subsystem_inits): Set DONE to 1 after + initialization. + (gpgme_get_engine_info): New variable ENGINE_INFO_LOCK. Take lock + while determining engine info. + * rungpg.c (_gpgme_gpg_get_version): New variable + GPG_VERSION_LOCK. Take the lock while determining the program + version. + * posix-io.c: Include "sema.h". + (_gpgme_io_spawn): New variable FIXED_SIGNALS_LOCK. Take the lock + while fixing the signals. + (_gpgme_io_select): Make READFDS and WRITEFDS non-static. + * key.c: Include "sema.h". New globals KEY_CACHE_LOCK and + KEY_REF_LOCK. + (capabilities_to_string): Make STRINGS very const. + (_gpgme_key_cache_add): Lock the key cache. + (_gpgme_key_cache_get): Likewise. + (gpgme_key_ref, gpgme_key_release): Lock the key_ref_lock. + * import.c (append_xml_impinfo): Make IMPORTED_FIELDS and + IMPORT_RES_FIELDS very const. Make FIELD and FIELD_NAME a litle + const. + * engine.c (_gpgme_engine_get_info): New variable + ENGINE_INFO_LOCK. Take lock while determining engine info. + * engine-gpgsm.c: Include "sema.h". + (_gpgme_gpgsm_get_version): New variable GPGSM_VERSION_LOCK. Take + lock while getting program version. + +2002-05-08 Marcus Brinkmann + + * debug.h: New file. + * Makefile.am (libgpgme_la_SOURCES): Add debug.h. + * util.h: Removed all prototypes and declarations related to + debugging. Include "debug.h". + + * debug.c (debug_level): Comment variable and remove superfluous + zero initializer. + (errfp): Likewise. + (_gpgme_debug_enabled): Function removed. + (struct debug_control_s): Definition removed. + (_gpgme_debug_level): Function removed. + (_gpgme_debug_begin): Rewritten to use vasprintf. Accept a + pritnf-style format specification and a variable number of + arguments. + (_gpgme_debug_add): Rewritten using vasprintf. Expect that format + starts out with "%s" for simplicity. + (_gpgme_debug_end): Rewritten using vasprintf. Do not accept a + TEXT argument anymore. + + * posix-io.c (_gpgme_io_select): Use new level argument for + DEBUG_BEGIN instead explicit if construct. + + * debug.c (debug_init): Remove superfluous zero initializer, + remove volatile flag of INITIALIZED. Do not use the + double-checked locking algorithm, it is fundamentally flawed and + will empty your fridge (on a more serious note, despite the + volatile flag it doesn't give you the guarantee you would expect, + for example on a DEC Alpha or an SMP machine. The volatile only + serializes accesses to the volatile variable, but not to the other + variables). + +2002-05-03 Werner Koch + + * engine-gpgsm.c (_gpgme_gpgsm_new): Redirect any gpgsm error + output to /dev/null. + + * verify.c (gpgme_get_sig_key): Set the protocol of the listctx. + * gpgme.c (gpgme_get_protocol): New. + + * data.c (gpgme_data_write): Changed type of BUFFER to void*. + (gpgme_data_read): Ditto. + + * verify.c (_gpgme_verify_status_handler): Handle TRUST_* status + lines so that a claim can be made without looking up the key. + (gpgme_get_sig_string_attr): New. + (gpgme_get_sig_ulong_attr): New. + + * gpgme.h (GpgmeAttr): Added GPGME_ATTR_SIG_STATUS. + + * rungpg.h: Add new status codes from gpg 1.0.7 and formatted the + list to align with the status.h file from gnupg. + + * gpgme.h (GpgmeSigStat): Add _GOOD_EXP and _GOOD_EXPKEY. + * verify.c (_gpgme_verify_status_handler, finish_sig): Handle + these new status codes. Store the expiration time + +2002-04-27 Werner Koch + + * gpgme.h (GpgmeData_Encoding): New. + * data.c (gpgme_data_get_encoding,gpgme_data_set_encoding): New. + * engine-gpgsm.c (map_input_enc): New. Use it in all local + functions where the INPUT command gets send. + +2002-04-27 Marcus Brinkmann + + * engine-gpgsm.c (_gpgme_gpgsm_op_verify): Close the output + descriptor only when we don't need it anymore. Close the message + descriptor if we don't need it. + +2002-04-26 Werner Koch + + * Makefile.am (libgpgme_la_LIBADD): Use libtool libraries. + +2002-04-25 Marcus Brinkmann + + * rungpg.c (_gpgme_gpg_release): Call gpgme_data_release on + GPG->cmd.cb_data, not xfree. + +2002-04-25 Marcus Brinkmann + + * engine-gpgsm.c (_gpgme_gpgsm_new): Set the display, ttyname, + ttytype, lc_ctype and lc_messages options in the server. + +2002-04-24 Marcus Brinkmann + + * engine-gpgsm.c (map_assuan_error): Add new error codes. + +2002-04-23 Werner Koch + + * key.c (gpgme_key_get_ulong_attr): Swapped use of can_encrypt and + can_certify to return the requested values. + +2002-04-23 Marcus Brinkmann + + * gpgme.c (gpgme_get_progress_cb): Allow either return parameter + to be NULL. + (gpgme_get_passphrase_cb): Likewise. + +2002-04-22 Marcus Brinkmann + + * gpgme.c (gpgme_get_passphrase_cb): New function. + (gpgme_get_progress_cb): New function. + * gpgme.h: Add new prototypes for gpgme_get_passphrase_cb and + gpgme_get_progress_cb. + +2002-03-28 Werner Koch + + * gpgme.h (GpgmeAttr): Add values for issuer and chaining. + * key.h (gpgme_key_s): Add issuer and chaining elements for X509. + * keylist.c (keylist_colon_handler): Store them. + * key.c (gpgme_key_release): Free them. + (gpgme_key_get_as_xml,gpgme_key_get_string_attr): Print them. + +2002-03-26 Werner Koch + + * Makefile.am (libgpgme_la_SOURCES): Add mutex.h + +2002-03-21 Werner Koch + + * util.h [!HAVE_FOPENCOOKIE]: Make sure off_t and ssize_t are + defined. + +2002-03-18 Marcus Brinkmann + + * Makefile.am (system_components): New variable, set depending on + HAVE_DOSISH_SYSTEM. + (libgpgme_la_SOURCES): Use system_components. Remove `syshdr.h'. + * syshdr.h: File removed. + + * posix-io.c: Remove !HAVE_DOSISH_SYSTEM safeguard. Clean up source. + * posix-sema.c: Likewise. + * posix-util.c: Likewise. + + * w32-io.c: Remove HAVE_DOSISH_SYSTEM safeguard. + * w32-sema.c: Likewise. + * w32-util.c: Likewise. + + * posix-io.c: Include `unistd.h', do not include `syshdr.h'. + * posix-sema.c: Likewise. + * w32-io.c: Include `io.h', do not include `syshdr.h' + * w32-sema.c: Likewise. + * w32-util.c: Likewise. + * data.c: Do not include `syshdr.h'. + * wait.c: Likewise. + * wait.h: Code cleanup. + + * mutex.h: New file. + * posix-sema.c: Implement. + +2002-03-08 Werner Koch + + * util.h [!HAVE_FOPENCOOKIE]: Fixed type. Thanks to Frank Heckenbach. + +2002-03-07 Werner Koch + + * gpgme.h (gpgme_op_keylist_ext_start): Add prototype. + +2002-03-06 Marcus Brinkmann + + * encrypt.c (_gpgme_encrypt_sym_status_handler): New function. + (gpgme_op_encrypt_start): New variable SYMMETRIC, set it if RECP + is null, and if it is set, use _gpgme_encrypt_sym_status_handler + as status handler and run _gpgme_passphrase_start. + * rungpg.c (_gpgme_gpg_op_encrypt): If RECP is zero, do symmetric + encryption. + * engine-gpgsm.c (_gpgme_gpgsm_op_encrypt): If RECP is zero, + return error value. + + * rungpg.c (_gpgme_gpg_op_verify): Add "--" argument. + +2002-03-03 Marcus Brinkmann + + * passphrase.c (_gpgme_passphrase_status_handler): Also set the + error No_Passphrase if only a bad passphrase was provided. + +2002-03-03 Marcus Brinkmann + + * rungpg.c (_gpgme_gpg_op_verify): If TEXT is of mode + GPGME_DATA_MODE_IN, construct a command line that stores the + plaintext in TEXT. + * verify.c (gpgme_op_verify_start): Accept TEXT being + uninitialized, and in this case interpret SIG as a normal or + cleartext signature and TEXT as a return data object. + * engine-gpgsm.c (_gpgme_gpgsm_op_verify): Likewise. + +2002-03-03 Marcus Brinkmann + + * engine-gpgsm.c (_gpgme_gpgsm_op_keylist_ext) [!ENABLE_GPGSM]: + Add stub function. + +2002-02-28 Werner Koch + + * key.h (subkey_s): New member expires_at. + * keylist.c (keylist_colon_handler): Set it here + * key.c (gpgme_key_get_as_xml,gpgme_key_get_ulong_attr): Return it. + +2002-02-27 Marcus Brinkmann + + * rungpg.h (_gpgme_gpg_op_keylist_ext): New prototype. + * rungpg.c (_gpgme_gpg_op_keylist_ext): New function. + * engine-gpgsm.h (_gpgme_gpgsm_op_keylist_ext): New prototype. + * engine-gpgsm.c (_gpgme_gpgsm_op_keylist_ext): New function. + * engine.h (_gpgme_engine_op_keylist_ext): New prototype. + * engine.c (_gpgme_engine_op_keylist_ext): New function. + * keylist.c (gpgme_op_keylist_ext_start): New function. + +2002-02-27 Marcus Brinkmann + + * gpgme.h: Add new error code GPGME_Invalid_Recipient. + * encrypt.c (struct encrypt_result_s): New member invalid_recipients, + rename no_recipients to no_valid_recipients. + (_gpgme_encrypt_status_handler): Include error for invalid + recipients. + * engine-gpgsm.c (gpgsm_set_recipients): Change type of first + argument to GpgsmObject. Use that to report back the status about + the recipients. + +2002-02-26 Marcus Brinkmann + + * verify.c (_gpgme_verify_status_handler): Fix the last change. + +2002-02-25 Marcus Brinkmann + + * engine.c (_gpgme_engine_op_encrypt_sign): New function. + * engine.h (_gpgme_engine_op_encrypt_sign): New prototype. + * rungpg.c (_gpgme_append_gpg_args_from_signers): New function. + (_gpgme_gpg_op_sign): Use that new function. + (_gpgme_gpg_op_encrypt_sign): New function. + * rungpg.h (_gpgme_gpg_op_encrypt_sign): New prototype. + * gpgme.h (gpgme_op_encrypt_sign_start): New prototype. + (gpgme_op_encrypt_sign): Likewise. + * Makefile.am (libgpgme_la_SOURCES): Add encrypt-sign.c. + * ops.h (_gpgme_encrypt_status_handler): Add prototype. + (_gpgme_sign_status_handler): Add prototype. + * sign.c (sign_status_handler): Rename to ... + (_gpgme_sign_status_handler): ... this and make non-static. + * encrypt.c (encrypt_status_handler): Rename to ... + (_gpgme_encrypt_status_handler): ... this and make non-static. + * encrypt.c (gpgme_op_encrypt_start): Use new status handler name. + * sign.c (gpgme_op_sign_start): Likewise. + +2002-02-25 Marcus Brinkmann + + * verify.c (_gpgme_verify_status_handler): Parse the args line to + see if the problem is due to a missing key, and report that back + to the user. + +2002-02-25 Marcus Brinkmann + + * context.h (struct gpgme_context_s): New member include_certs. + * gpgme.h (gpgme_set_include_certs): Add prototype. + (gpgme_get_include_certs): Likewise. + * gpgme.c (gpgme_set_include_certs): New function. + (gpgme_get_include_certs): Likewise. + (gpgme_new): Set include_certs to 1 (the default). + * engine.c (_gpgme_engine_op_sign): Accept new argument include_certs, + and pass it to _gpgme_gpgsm_op_sign. + * engine.h (_gpgme_engine_op_sign): Likewise for prototype. + * engine-gpgsm.c (_gpgme_gpgsm_op_sign): Accept new argument + include_certs and handle it. + * engine-gpgsm.h (_gpgme_gpgsm_start): Add new argument include_certs. + * sign.c (gpgme_op_sign_start): Add new argument to + _gpgme_engine_op_sign call. + +2002-02-14 Werner Koch + + * keylist.c (gpgme_op_keylist_start): Do not use a verbose listing. + +2002-02-13 Werner Koch + + * vasprintf.c, fopencookie.c: Add replacement functions. + * util.h: Add prototypes for them. + +2002-02-09 Marcus Brinkmann + + * engine-gpgsm.c (gpgsm_assuan_simple_command): Return 0 if we + reach the end of the function. + +2002-02-09 Marcus Brinkmann + + * genkey.c (gpgme_op_genkey_start): Fix logic in validity check. + (gpgme_op_genkey_start): Skip newlines after opening tag. + + * engine-gpgsm.c (_gpgme_gpgsm_start): Remove cruft. + +2002-02-08 Marcus Brinkmann + + * genkey.c (gpgme_op_genkey_start): Allow PUBKEY and SECKEY to be + set, and pass them down to the crypto engine. + * engine-gpgsm.h (_gpgme_gpgsm_start): New arguments PUBKEY and SECKEY. + * engine.h: Likewise. + * rungpg.h (_gpgme_gpg_spawn): Likewise. + * engine.c (_gpgme_engine_op_genkey): Likewise. Use those + arguments. + * rungpg.c (_gpgme_gpg_op_genkey): Likewise. Complain if those + arguments are set. + * engine-gpgsm.c (_gpgme_gpgsm_op_genkey): Likewise. Implement + function. + + * engine-gpgsm.c (_gpgme_gpgsm_op_keylist): Beautify comment. + +2002-02-06 Marcus Brinkmann + + * rungpg.c (_gpgme_gpg_op_keylist): Remove handling of keylist + mode (for now). + +2002-02-06 Marcus Brinkmann + + * wait.c (gpgme_wait): Add new argument STATUS, in which the + status of the returned context is returned. + (_gpgme_wait_on_condition): Rework the function a bit, to make it + aware of cancelled processes, and to allow to use gpgme_wait with + CTX being NULL (as documented in the source). + (struct proc_s): New member REPORTED. + * gpgme.h: Fix prototype. + * verify.c (gpgme_op_verify): Fix use of gpgme_wait. + * sign.c (gpgme_op_sign): Likewise. + * import.c (gpgme_op_import): Likewise. + * genkey.c (gpgme_op_genkey): Likewise. + * export.c (gpgme_op_export): Likewise. + * encrypt.c (gpgme_op_encrypt): Likewise. + * delete.c (gpgme_op_delete): Likewise. + * decrypt-verify.c (gpgme_op_decrypt_verify): Likewise. + +2002-02-06 Marcus Brinkmann + + * gpgme.c (gpgme_set_keylist_mode): Possibly return an error + value. + (gpgme_get_keylist_mode): New function. + (gpgme_new): Set the default for keylist_mode member of CTX. + + * gpgme.h (gpgme_set_keylist_mode): Fix prototype. + (gpgme_get_keylist_mode): New prototype. + (GPGME_KEYLIST_MODE_LOCAL): New macro. + (GPGME_KEYLIST_MODE_EXTERN): Likewise.. + +2002-02-02 Marcus Brinkmann + + This patch has gotten a bit large... mmh. The main thing that + happens here is that error values are now not determined in the + operation function after gpgme_wait completed, but in the status + handler when EOF is received. It should always be the case that + either an error is flagged or EOF is received, so that after a + gpgme_wait you should never have the situation that no error is + flagged and EOF is not received. One problem is that the engine + status handlers don't have access to the context, a horrible + kludge works around this for now. All errors that happen during a + pending operation should be catched and reported in ctx->error, + including out-of-core and cancellation. This rounds up neatly a + couple of loose ends, and makes it possible to pass up any errors + in the communication with the backend as well. As a bonus, there + will be a function to access gpgme->wait, so that the operations + can truly be implemented with their _start function. + + * engine-gpgsm.c (gpgsm_status_handler): Horrible kludge to report + error back to the context. + * rungpg.c (gpg_status_handler): Same horrible kludge applied here. + + * engine-gpgsm.c (gpgsm_assuan_simple_command): Add error checking. + + * wait.c (_gpgme_wait_on_condition): If canceled, set CTX->error + to a value indication that. + + * verify.c (add_notation): Set error, not out_of_core. + (finish_sig): Likewise. + (gpgme_op_verify_start): Don't clear out_of_core. + (_gpgme_verify_status_handler): At EOF, clean up the notation data. + (gpgme_op_verify): And don't do it here. + + * trustlist.c (trustlist_status_handler): Check error, not out_of_core. + (gpgme_op_trustlist_start): Don't clear out_of_core. + (gpgme_op_trustlist_next): Check error, not out_of_core. + (gpgme_op_trustlist_end): Likewise. + + * ops.h (test_and_allocate_result): New macro. + (_gpgme_passphrase_result): Remove prototype. + * delete.c (gpgme_op_delete): Return error from context. + (delete_status_handler): Use macro test_and_allocate_result. + Perform error checking at EOF. + (gpgme_op_delete_start): Release result. + * passphrase.c (_gpgme_passphrase_status_handler): Use macro + test_and_allocate_result, and perform error checking here. + (_gpgme_passphrase_result): Function removed. + * sign.c (gpgme_op_sign_start): Do not set out_of_core to zero. + (gpgme_op_sign): Just return the error value from the context. + (sign_status_handler): Only progress if no error is set yet. If + we process an EOF, set the resulting error value (if any). + * decrypt.c (_gpgme_decrypt_result): Function removed. + (create_result_struct): Function removed. + (_gpgme_decrypt_status_handler): Use macro test_and_allocate_result, + caclulate error on EOF, do not progress with errors. + (_gpgme_decrypt_start): Do not set out_of_core to zero. + (gpgme_op_decrypt): Just return the error value from the context. + * encrypt.c (encrypt_status_handler): Perform the error checking + here. + (gpgme_op_encrypt_start): Do not clear out_of_core. + * export.c (export_status_handler): Return if error is set in context. + (gpgme_op_export_start): Release result. + (gpgme_op_export): Return error from context. + * decrypt-verify.c (gpgme_op_decrypt_verify): Return the error in + the context. + * genkey.c (genkey_status_handler): Use macro + test_and_allocate_result. Perform error checking at EOF. + (gpgme_op_genkey): Just return the error from context. + * import.c (gpgme_op_import): Return the error from context. + (import_status_handler): Use macro test_and_allocate_result. + * keylist.c (gpgme_op_keylist_start): Do not clear out_of_core. + (gpgme_op_keylist_next): Return error of context. + (keylist_colon_handler): Set error instead out_of_code. + (finish_key): Likewise. + + * context.h: Remove member out_of_core, add member error. + * gpgme.c (_gpgme_release_result): Clear error flag. + + * engine.h (_gpgme_engine_get_error): New prototype. + * engine.c (_gpgme_engine_get_error): New function. + * engine-gpgsm.c (_gpgme_gpgsm_get_error): New function. + + * engine-gpgsm.c (map_assuan_error): New function. + (gpgsm_assuan_simple_command): Change return type to GpgmeError, + use the new function to map error values. + (gpgsm_set_fd): Change return type tp GpgmeError. + (_gpgme_gpgsm_op_decrypt): Change type of ERR to GpgmeError. + (gpgsm_set_recipients): Likewise. Change type of return value + equivalently. Adjust error values. + (_gpgme_gpgsm_op_import): Likewise. + (_gpgme_gpgsm_op_sign): Likewise. + (struct gpgsm_object_s): New member error. + (gpgsm_status_handler): Set error if error occurs. Determine + error number from ERR line received. If assuan_read_line fails, + terminate the connection. + +2002-02-01 Marcus Brinkmann + + * Makefile.am (MOSTLYCLEANFILES): New variable. + +2002-02-01 Marcus Brinkmann + + * engine-gpgsm.c (gpgsm_status_handler): At error, terminate the + connection to the server. + +2002-01-31 Marcus Brinkmann + + * rungpg.h: Add STATUS_KEY_CREATED. + + * progress.c: New file. + * Makefile.am (libgpgme_la_SOURCES): Add progress.c. + + * genkey.c (genkey_status_handler): Use + _gpgme_progress_status_handler. Add check for status. + (struct genkey_result_s): New structure. + (_gpgme_release_genkey_result): New function. + (gpgme_op_genkey): Check for error. + * gpgme.c (_gpgme_release_result): Call + _gpgme_release_genkey_result. + * ops.h (_gpgme_release_genkey_result): Add prototype. + * types.h (GenKeyResult): New type. + * context.h (gpgme_context_s): Add GenKeyResult to member result. + +2002-01-30 Marcus Brinkmann + + * gpgme.c (_gpgme_release_result): Call + _gpgme_release_delete_result. + * ops.h (_gpgme_release_delete_result): Add prototype. + * types.h (DeleteResult): New type. + * context.h (gpgme_context_s): Add DeleteResult to member result. + + * delete.c (enum delete_problem): New type. + (struct delete_result_s): New structure. + (_gpgme_release_delete_result): New function. + (delete_status_handler): Implement more status codes. + (gpgme_op_delete): Return error on failure. + + * import.c (MAX_IMPORTED_FIELDS): Bump up to 14. + +2002-01-30 Marcus Brinkmann + + * import.c (struct import_result_s): New structure. + (_gpgme_release_import_result): New function. + (append_xml_impinfo): Likewise. + (import_status_handler): Implement. + * gpgme.c (_gpgme_release_result): Add call to + _gpgme_release_import_result. + * ops.h (_gpgme_release_import_result): Add prototype. + * types.h (ImportResult): New type. + * context.h (gpgme_context_s): Add ImportResult to member result. + + * encrypt.c (gpgme_op_encrypt): Code clean up. + +2002-01-30 Marcus Brinkmann + + * gpgme.h: Add lots of comment and fix the formatting. Add + gpgme_trustlist_end prototype. + +2002-01-29 Marcus Brinkmann + + * gpgme.h: Add new type GpgmeIdleFunc. Change type of + gpgme_register_idle to return and accept this type. + * wait.c (gpgme_register_idle): Fix type. + Save and return old value of idle_function. + +2002-01-29 Werner Koch + + * engine-gpgsm.c (_gpgme_gpgsm_op_keylist): Implement secret only mode. + + * keylist.c (keylist_colon_handler): Add support for the new "crs" + record type. + +2002-01-22 Marcus Brinkmann + + * engine-gpgsm.c (_gpgme_gpgsm_release): Call assuan_disconnect, + not assuan_pipe_disconnect. + + * Makefile.am (libgpgme_la_LIBADD): Change to link assuan and + jnlib (needed by assuan) statically into libgpgme. Linking a + static library into a shared library this way is not portable. + +2002-01-22 Marcus Brinkmann + + * gpgme.h (GpgmePassphraseCb): Change type of R_HD from void* to + void**. + +2002-01-22 Marcus Brinkmann + + * data.c (gpgme_data_new_from_filepart): Change type of LENGTH + from off_t to size_t. + * gpgme.h: Likewise. + +2002-01-22 Marcus Brinkmann + + * wait.c (_gpgme_wait_on_condition): If the process finished, + reset the pending flag. Also if the operation was cancelled. + + (struct proc_s): Rename READY to DONE. + (wait_item_s): Likewise. + (set_process_ready): Rename to ... + (set_process_done): ... this. + (_gpgme_remove_proc_from_wait_queue): Call set_process_done + instead set_process_ready. + (_gpgme_wait_on_condition): Likewise. + (do_select): Rename READY to DONE. + + * verify.c (gpgme_op_verify): Do not set pending to zero here. + * sign.c (gpgme_op_sign): Likewise. + * import.c (gpgme_op_import): Likewise. + * genkey.c (gpgme_op_genkey): Likewise. + * export.c (gpgme_op_export): Likewise. + * encrypt.c (gpgme_op_encrypt): Likewise. + * delete.c (gpgme_op_delete): Likewise. + * decrypt-verify.c (gpgme_op_decrypt_verify): Likewise. + * decrypt.c (gpgme_op_decrypt): Likewise. + +2002-01-22 Marcus Brinkmann + + * export.c: Cleanup. + +2002-01-15 Marcus Brinkmann + + * trustlist.c: Various source clean ups. + (my_isdigit): Removed. + (gpgme_op_trustlist_end): New function. + +2002-01-13 Marcus Brinkmann + + * gpgme.c: Various source clean ups, like renaming C to CTX where + appropriate. + (gpgme_new): Clear R_CTX before starting the work. + (my_isdigit): Removed. + (my_isxdigit): Likewise. + + * data.c: Various source clean ups. + (gpgme_data_new_from_mem): Check BUFFER after clearing R_DH. + (gpgme_data_new_with_read_cb): Similar for READ_CB. + (gpgme_data_new_from_file): Loop over fread while EINTR. + (gpgme_data_new_from_filepart): Rediddled a bit. Allow LENGTH to + be zero. Loop over fread while EINTR. + + (my_isdigit): Removed. + (my_isxdigit): Likewise. + +2001-12-21 Marcus Brinkmann + + * engine-gpgsm.c (_gpgme_gpgsm_new): Replace General_Error with + Pipe_Error where appropriate. + +2001-12-19 Marcus Brinkmann + + * engine.c: Include `string.h'. Reported by Stéphane Corthésy. + + * version.c (get_engine_info): Remove prototype. + +2001-12-19 Marcus Brinkmann + + * engine-gpgsm.c (_gpgme_gpgsm_new): New variable CHILD_FDS. + Fill it with the servers fds, and pass it to assuan_pipe_connect. + +2001-12-18 Marcus Brinkmann + + * keylist.c (gpgme_op_keylist_end): New function. + * gpgme.h (gpgme_op_keylist_end): New prototype. + + * engine.h (gpgme_engine_check_version): Move prototype to ... + * gpgme.h (gpgme_engine_check_version): ... here. + + * genkey.c (gpgme_op_genkey_start): Remove unused variable. + +2001-12-18 Marcus Brinkmann + + * version.c (gpgme_get_engine_info): Reimplemented. + (gpgme_check_engine): Reimplemented. + (_gpgme_compare_versions): Return NULL if MY_VERSION is NULL. + + * engine.c: Include `io.h'. + (gpgme_engine_get_info): New function. + * engine.h (gpgme_engine_check_version, _gpgme_engine_get_info): + Add prototype. + +2001-12-18 Marcus Brinkmann + + * rungpg.c (struct reap_s, reap_list, reap_list_lock): Moved to ... + * engine.c (struct reap_s, reap_list, reap_list_lock): ... here. + Include `time.h', `sys/types.h', `assert.h', and `sema.h'. + + * rungpg.c (_gpgme_engine_add_child_to_reap_list): New function. + (do_reaping, _gpgme_gpg_housecleaning): Moved to ... + * engine.c (do_reaping, _gpgme_engine_housecleaning): ... here. + * rungpg.c (_gpgme_gpg_release): Replace code that is now in its + own function by call to _gpgme_engine_add_child_to_reap_list(). + + * wait.c: Include `engine.h'. + (run_idle): Call _gpgme_engine_housecleaning(), not + _gpgme_gpg_housecleaning(). + +2001-12-18 Marcus Brinkmann + + * key.c (_gpgme_key_append_name): Append, not prepend, the uid. + Initialize the next field of the uid structure. + (gpgme_key_get_as_xml): Do not list last uid first. + +2001-12-17 Marcus Brinkmann + + * engine-gpgsm.c (_gpgme_gpgsm_set_colon_line_handler): New + function [!ENABLE_GPGSM]. + +2001-12-14 Marcus Brinkmann + + * engine-gpgsm.c (_gpgme_gpgsm_op_verify): Put TEXT into + message_data, not SIG. + (_gpgme_gpgsm_op_sign): Use `--detached', not `--detach'. + + * sign.c (sign_status_handler): Call + _gpgme_passphrase_status_handler early. + +2001-12-14 Marcus Brinkmann + + * engine-gpgsm.c: Revert last change. + +2001-12-14 Marcus Brinkmann + + * engine-gpgsm.c (gpgsm_status_handler): Freeze the output file + handler when ending this operation, otherwise the wait function + will sit on it. + +2001-12-14 Marcus Brinkmann + + * engine-gpgsm.c (struct gpgsm_object_s): New member colon.attic. + (_gpgme_gpgsm_new): Initialize some more members. + (_gpgme_gpgsm_release): Free the colon line handler's attic line. + (gpgsm_status_handler): Rework the inline-data processing. + +2001-12-13 Marcus Brinkmann + + * rungpg.c (_gpgme_gpg_spawn): Do not add the fds to the child + list that are not dup'ed, for those the close-on-exec flag is set + now. + * version.c (_gpgme_get_program_version): Remove first entry in + CFD, as the close-on-exec flag is now set for this fd. + +2001-12-13 Marcus Brinkmann + + * engine-gpgsm.c (_gpgme_gpgsm_op_encrypt): Do not add `armor' + option to `ENCRYPT'. + * engine-gpgsm.c (gpgsm_set_recipients): Free LINE when returning + successfully. + +2001-12-13 Marcus Brinkmann + + * engine-gpgsm.c (close_notify_handler): New function. + (_gpgme_gpgsm_new): Manage the file descriptors a + bit differently. Do not set close-on-exec flags. + (_gpgme_gpgsm_op_decrypt): Do not set message_fd + to -1, this is done by the close handler. + (_gpgme_gpgsm_op_encrypt): Likewise. + (_gpgme_gpgsm_op_import): Likewise (also for output_fd). + (_gpgme_gpgsm_op_keylist): Likewise (also for input_fd and output_fd). + (_gpgme_gpgsm_op_sign): Likewise. + (_gpgme_gpgsm_op_verify): Likewise, but for output_fd. + + * posix-io.c (_gpgme_io_pipe): Set the close-on-exec flag for the + non-inherited file descriptor index of the pipe. + +2001-12-13 Werner Koch + + * engine-gpgsm.c (_gpgme_gpgsm_set_colon_line_handler): New. + (gpgsm_status_handler): Pass datalines to a colon handler + * engine.c (_gpgme_engine_set_colon_line_handler): Set the colon + handler for gpgsm. + + * engine-gpgsm.c (_gpgme_gpgsm_op_keylist): Allow NULL for + pattern. + (gpgsm_assuan_simple_command): Removed underscore from + assuan_write_line. + (_gpgme_gpgsm_start): Ditto. + (gpgsm_assuan_simple_command): Replaced interal Assuan read + function by the new assuan_read_line. Removed the use of the + internal header. + (gpgsm_status_handler): Ditto. Use the new assuan_pending_line. + (_gpgme_gpgsm_start): Use the documented way to get an fd from + assuan. + + * keylist.c (keylist_colon_handler): Handle "crt" records + * key.h (gpgme_key_s): Add an x509 flag. + * key.c (parse_x509_user_id): New. + (_gpgme_key_append_name): Handle x.509 names. + +2001-12-05 Marcus Brinkmann + + * engine-gpgsm.c (gpgsm_status_handler): Make it work with current + version of assuan. + +2001-12-05 Marcus Brinkmann + + * engine-gpgsm.c (gpgsm_set_fd): Accept one more argument OPT. + (_gpgme_gpgsm_op_encrypt): Pass armor argument to gpgsm_set_fd for + output descriptor. + (_gpgme_gpgsm_op_sign): Likewise. + +2001-12-05 Marcus Brinkmann + + * keylist.c (gpgme_op_keylist_next): Set pending to 0 if EOF + occurs. + +2001-11-26 Marcus Brinkmann + + * engine-gpgsm.c (_gpgme_gpgsm_op_sign): Fix stupid typo. + +2001-11-24 Marcus Brinkmann + + * engine-gpgsm.c (gpgsm_status_handler): Don't break if bsearch fails. + Deal with assuan read line returning more than one line (for now). + +2001-11-23 Marcus Brinkmann + + * engine-gpgsm.c (_gpgme_gpgsm_op_sign): Implement it according to + the current protocol definition. + +2001-11-23 Marcus Brinkmann + + * engine-gpgsm.c (_gpgme_gpgsm_new): Set CLOEXEC flag for parent + ends of the pipe. + +2001-11-22 Marcus Brinkmann + + * engine-gpgsm.c: Include stdlib.h and string.h. Also include, + for now, rungpg.h and status-table.h. + (gpgsm_status_handler): Implement more of the status handler. + +2001-11-22 Marcus Brinkmann + + * engine.c (_gpgme_engine_op_decrypt): Implement CMS case. + (_gpgme_engine_op_delete): Likewise. + (_gpgme_engine_op_encrypt): Likewise. + (_gpgme_engine_op_export): Likewise. + (_gpgme_engine_op_genkey): Likewise. + (_gpgme_engine_op_keylist): Likewise. + (_gpgme_engine_op_sign): Likewise. + (_gpgme_engine_op_trustlist): Likewise. + + * engine-gpgsm.c (_gpgme_gpgsm_op_encrypt): New function. + (gpgsm_assuan_simple_command): Likewise. + (gpgsm_set_recipients): Likewise. + (gpgsm_set_fd): Reimplement using gpgsm_assuan_simple_command. + (_gpgme_gpgsm_op_delete): New function. + (_gpgme_gpgsm_op_export): Likewise. + (_gpgme_gpgsm_op_genkey): Likewise. + (_gpgme_gpgsm_op_sign): Likewise. + (_gpgme_gpgsm_op_keylist): Likewise. + (_gpgme_gpgsm_op_trustlist): Likewise. + (_gpgme_gpgsm_release): Release command. + (_gpgme_gpgsm_op_decrypt): Allocate command. + (_gpgme_gpgsm_op_import): Likewise. + (gpgsm_status_handler): Also treat `ERR' strings as EOF. + +2001-11-22 Marcus Brinkmann + + * gpgme.h (gpgme_set_protocol): New prototype. + +2001-11-22 Marcus Brinkmann + + * engine-gpgsm.c (_gpgme_gpgsm_op_decrypt): New function. + (_gpgme_gpgsm_op_import): Likewise. + +2001-11-22 Marcus Brinkmann + + * engine-gpgsm.c: Shuffle around header inclusion a bit, to still + keep them seperate. + (_gpgme_set_status_handler) [!ENABLE_GPGSM]: New function. + +2001-11-22 Werner Koch + + * engine-gpgsm.c: Include more headers so that NULL and mk_error + is defined even with an undefined GPGSM_PATH. + +2001-11-22 Marcus Brinkmann + + * rungpg.c (gpg_inbound_handler, write_mem_data, write_cb_data, + gpg_outbound_handler): Moved to ... + * data.c (_gpgme_data_inbound_handler, write_mem_data, + write_cb_data, _gpgme_data_outbound_handler): ... here. Make the + _gpgme_* ones non-static. + * data.c: Include io.h. + + * ops.h (_gpgme_data_inbound_handler): New prototype. + (_gpgme_data_outbound_handler): Likewise. + (_gpgme_gpg_spawn): Use these new functions. + + * engine-gpgsm.h (_gpgme_gpgsm_op_decrypt, _gpgme_gpgsm_op_delete, + _gpgme_gpgsm_op_encrypt, _gpgme_gpgsm_op_export, + _gpgme_gpgsm_op_genkey, _gpgme_gpgsm_op_import, + _gpgme_gpgsm_op_keylist, _gpgme_gpgsm_op_sign, + _gpgme_gpgsm_op_trustlist, _gpgme_gpgsm_op_verify, + _gpgme_gpgsm_start, _gpgme_gpgsm_set_status_handler): New prototype. + Include for status handler function. + + * engine-gpgsm.c (struct gpgsm_object_s): New members input_fd, + input_data, output_fd, output_data, message_fd, message_data, command + and status. + (_gpgme_gpgsm_new): Open input, output and message pipes before + connecting to the client. Close server's ends afterwards. + (_gpgme_gpgsm_release): Close open file descriptors. Remove + server process from wait queue. + (_gpgme_gpgsm_op_verify, _gpgme_gpgsm_start, + _gpgme_gpgsm_set_status_handler, gpgms_status_handler): New function. + + * engine.c (_gpgme_engine_start): Implement for GPGME_PROTOCOL_CMS. + (_gpgme_engine_set_status_handler): Likewise. + (_gpgme_engine_op_verify): Likewise. + +2001-11-21 Marcus Brinkmann + + * context.h: Do not include rungpg.h, but engine.h. + (struct gpgme_context_s): Replace member gpg with engine. + * gpgme.c (gpgme_release): Release engine, not gpg. + + * recipient.c (_gpgme_append_gpg_args_from_recifgpients): Function + moved ... + * rungpg.c (_gpgme_append_gpg_args_from_recipients): ... here. + Make static, change order of arguments, and return an error value. + * ops.h (_gpgme_append_gpg_args_from_recipients): Removed prototype. + + * rungpg.h (_gpgme_gpg_op_verify): Add prototype. + (_gpgme_gpg_op_encrypt): Likewise. + (_gpgme_gpg_op_decrypt): Likewise. + (_gpgme_gpg_op_delete): Likewise. + (_gpgme_gpg_op_export): Likewise. + (_gpgme_gpg_op_genkey): Likewise. + (_gpgme_gpg_op_import): Likewise. + (_gpgme_gpg_op_keylist): Likewise. + (_gpgme_gpg_op_sign): Likewise. + (_gpgme_gpg_op_trustlist): Likewise. + * rungpg.c (_gpgme_gpg_op_verify): New function. + (_gpgme_gpg_op_encrypt): Likewise. + (_gpgme_gpg_op_decrypt): Likewise. + (_gpgme_gpg_op_delete): Likewise. + (_gpgme_gpg_op_export): Likewise. + (_gpgme_gpg_op_genkey): Likewise. + (_gpgme_gpg_op_import): Likewise. + (_gpgme_gpg_op_keylist): Likewise. + (_gpgme_gpg_op_sign): Likewise. + (_gpgme_gpg_op_trustlist): Likewise. + + * engine.h (_gpgme_engine_set_status_handler): Add prototype. + (_gpgme_engine_set_command_handler): Likewise. + (_gpgme_engine_set_colon_line_handler): Likewise. + (_gpgme_engine_op_decrypt): Likewise. + (_gpgme_engine_op_delete): Likewise. + (_gpgme_engine_op_encrypt): Likewise. + (_gpgme_engine_op_export): Likewise. + (_gpgme_engine_op_genkey): Likewise. + (_gpgme_engine_op_import): Likewise. + (_gpgme_engine_op_keylist): Likewise. + (_gpgme_engine_op_sign): Likewise. + (_gpgme_engine_op_trustlist): Likewise. + (_gpgme_engine_op_verify): Likewise. + (_gpgme_engine_start): Likewise. + * engine.c (_gpgme_engine_set_status_handler): New function. + (_gpgme_engine_set_command_handler): Likewise. + (_gpgme_engine_set_colon_line_handler): Likewise. + (_gpgme_engine_op_decrypt): Likewise. + (_gpgme_engine_op_delete): Likewise. + (_gpgme_engine_op_encrypt): Likewise. + (_gpgme_engine_op_export): Likewise. + (_gpgme_engine_op_genkey): Likewise. + (_gpgme_engine_op_import): Likewise. + (_gpgme_engine_op_keylist): Likewise. + (_gpgme_engine_op_sign): Likewise. + (_gpgme_engine_op_trustlist): Likewise. + (_gpgme_engine_op_verify): Likewise. + (_gpgme_engine_start): Likewise. + + * verify.c (gpgme_op_verify_start): Reimplement in terms of above + functions. + * encrypt.c (gpgme_op_encrypt_start): Likewise. + * decrypt.c (_gpgme_decrypt_start): Likewise. + * passphrase.c (_gpgme_passphrase_start): Likewise. + * keylist.c (gpgme_op_keylist_start): Likewise. + +2001-11-20 Marcus Brinkmann + + * types.h: Add types EngineObject and GpgsmObject. + + * Makefile.am (libgpgme_la_SOURCES): Add engine-gpgsm.h, + engine-gpgsm.c, engine.h and engine.c. + * engine.h: New file. + * engine.c: Likewise. + * engine-gpgsm.h: Likewise. + * engine-gpgsm.c: Likewise. + + * rungpg.c (_gpgme_gpg_get_version): New function. + (_gpgme_gpg_check_version): Likewise. + * rungpg.h: Add prototypes for _gpgme_gpg_get_version and + _gpgme_gpg_check_version. + + * version.c (compare_versions): Rename to ... + (_gpgme_compare_versions): ... this. Make non-static. + (gpgme_check_version): Use _gpgme_compare_versions rather than + compare_versions. + (gpgme_check_engine): Likewise. + * ops.h (_gpgme_get_program_version): Add prototype. + +2001-11-20 Marcus Brinkmann + + * Makefile.am (libgpgme_la_INCLUDES): Remove obsolete directive. + (AM_CPPFLAGS): New directive [BUILD_ASSUAN]. + (libgpgme_la_LIBADD): Likewise. + +2001-11-20 Marcus Brinkmann + + * version.c: Remove global variables lineno and + tmp_engine_version. + (version_handler): Removed. + (_gpgme_get_program_version): New function. + (get_engine_info): Don't use context and version_handler, + but _gpgme_get_program_version. + * ops.h (_gpgme_get_program_version): Add prototype for + _gpgme_get_program_version (we expect to use it elsewhere soon). + +2001-11-18 Marcus Brinkmann + + * version.c (get_engine_info): If GnuPG is not available, return + an error message. + * posix-util.c (_gpgme_get_gpg_path): Allow GPG_PATH to be + undefined. + (_gpgme_get_gpgsm_path): New function. + * w32-util.c (find_program_in_registry): New static function. + (_gpgme_get_gpg_path): Allow GPG_PATH to be undefined. Rework + to use find_program_in_registry. + (_gpgme_get_gpgsm_path): New function. + (util.h): Prototype _gpgme_get_gpgsm_path). + * rungpg.c (_gpgme_gpg_spawn): Verify that _gpgme_get_gpg_path() + returns non-null. + +2001-11-16 Marcus Brinkmann + + * decrypt-verify.c: New file. + * Makefile.am (libgpgme_la_SOURCES): Add decrypt-verify.c. + * types.h: Add decrypt-verify types. + * ops.h: Likewise. + * context.h: Add result type for decrypt-verify. + * gpgme.h: Add decrypt-verify prototypes. + + * decrypt.c (decrypt_status_handler): Renamed to ... + (_gpgme_decrypt_status_handler): ... this. Make non-static. + (_gpgme_decrypt_start): New function, derived from + gpgme_op_decrypt_start. + (gpgme_op_decrypt_start): Reimplement in terms of + _gpgme_decrypt_start. + (_gpgme_decrypt_result): New function to retrieve error value. + (gpgme_op_decrypt): Use _gpgme_decrypt_result. + * ops.h: Add prototypes for new functions. + + * verify.c (verify_status_handler): Renamed to ... + (_gpgme_verify_status_handler): ... this. Make non-static. + (gpgme_op_verify_start): Use new function name. + (intersect_stati): Renamed to ... + (_gpgme_intersect_stati): ... this. Make non-static. + (gpgme_op_verify): Use new name. + * ops.h: Add prototypes for new functions. + +2001-11-16 Marcus Brinkmann + + * passphrase.c: New file. + * Makefile.am (libgpgme_la_SOURCES): Add passphrase.c. + * ops.h (_gpgme_passphrase_result): Add prototypes from + passphrase.c. + * types.h: Likewise. + * context.h: Add member passphrase to result. + * gpgme.c (_gpgme_release_result): Release passphrase member. + + * decrypt.c: Some formatting and variable name changes (like + CTX instead C). + (struct decrypt_result_s): Remove members now found in + passphrase result. + (_gpgme_release_decrypt_result): Don't release removed members. + (decrypt_status_handler): Call _gpgme_passphrase_status_handler, + and don't handle the cases catched there. + (command_handler): Removed. + (gpgme_op_decrypt_start): Don't set command handler, but invoke + _gpgme_passphrase_start which does it. + (gpgme_op_decrypt): Invoke _gpgme_passphrase_result and drop the + cases covered by it. + + * sign.c Some formatting and variable name changes (like + CTX instead C). + (struct sign_result_s): Remove members now found in + passphrase result. + (_gpgme_release_sign_result): Don't release removed members. + (sign_status_handler): Call _gpgme_passphrase_status_handler, + and don't handle the cases catched there. + (command_handler): Removed. + (gpgme_op_sign_start): Don't set command handler, but invoke + _gpgme_passphrase_start which does it. + (gpgme_op_sign): Invoke _gpgme_passphrase_result and drop the + cases covered by it. + +2001-11-15 Marcus Brinkmann + + * decrypt.c (command_handler): Fix last change. + +2001-11-15 Marcus Brinkmann + + * verify.c (_gpgme_release_verify_result): Rename RES to RESULT. + Rename R2 to NEXT_RESULT. + (intersect_stati): Rename RES to RESULT. + (gpgme_get_sig_status): Likewise. Do not check return_type, but + the member verify of result. + (gpgme_get_sig_key): Likewise. + + * sign.c (_gpgme_release_sign_result): Rename RES to RESULT. If + RESULT is zero, return. + (sign_status_handler, command_handler): Do not check return_type, + but the member sign of result. + (gpgme_op_sign): Likewise. Drop assertion. + + * encrypt.c (_gpgme_release_encrypt_result): Rename RES to RESULT. + If RESULT is zero, return. + (encrypt_status_handler): Do not check return_type, but the member + encrypt of result. + (gpgme_op_encrypt): Likewise. Drop assertion. + + * decrypt.c (_gpgme_release_decrypt_result): Rename RES to RESULT. + (create_result_struct): Do not set result_type. + (command_handler, decrypt_status_handler): Do not check + return_type, but the member decrypt of result. + (gpgme_op_decrypt): Likewise. Drop assertion. + + * context.h (enum ResultType): Removed. + (struct gpgme_context_s): Remove member result_type. + (struct result): Replaces union result. + * gpgme.c: Include string.h. + (_gpgme_release_result): Release all members of c->result, which + is now a struct. Zero out all members of the struct afterwards. + +2001-11-11 Marcus Brinkmann + + * rungpg.c (_gpgme_gpg_release): Release GPG->cmd.cb_data. + Release all members of the list GPG->arglist. + Reported by Michael Schmidt . + +2001-11-02 Marcus Brinkmann + + * rungpg.c (pipemode_copy): Change type of NBYTES to size_t. + + * key.c: Include string.h. + * data.c: Likewise. + * recipient.c: Likewise. + +2001-10-29 Marcus Brinkmann + + * context.h: New member signers_len. + * signers.c (gpgme_signers_clear): Require that signers are + non-NULL with assertion. Use signers_len to determine how much + keys to release. Add documentation. + (gpgme_signers_add): Use signers_len to determine if the buffer is + large enough. Use xtryrealloc rather than xtrymalloc and copying. + Add documentation. + (gpgme_signers_enum): Use signers_len to determine if key is + available. Add documentation. + +2001-10-22 Marcus Brinkmann + + * data.c (_gpgme_data_append): Check if LENGTH is smaller than + ALLOC_CHUNK, not DH->length. + +2001-10-17 Marcus Brinkmann + + * gpgme.c (gpgme_set_protocol): Fix last change. + +2001-10-15 Werner Koch + + * gpgme.h (GpgmeProtocol): New. + * gpgme.c (gpgme_set_protocol): New. + +2001-09-26 Werner Koch + + * gpgme.c (gpgme_set_passphrase_cb): Ignore a NULL context. + (gpgme_set_progress_cb): Ditto. Suggested by Mark Mutz. + +2001-09-17 Werner Koch + + * keylist.c (finish_key): Shortcut for no tmp_key. Changed all + callers to use this function without a check for tmp_key. + + * keylist.c (gpgme_op_keylist_next): Reset the key_cond after + emptying the queue. Bug reported by Stéphane Corthésy. + +2001-09-12 Werner Koch + + * data.c (gpgme_data_rewind): Allow rewind for callbacks. + +2001-09-07 Werner Koch + + * rungpg.h: Add NO_RECP. + * encrypt.c (encrypt_status_handler): Take on No_RECP. + (gpgme_op_encrypt): Better error return. + + * verify.c (verify_status_handler): Take on NODATA. + +2001-09-03 Werner Koch + + * rungpg.h: Added STATUS_INV_RECP. + * gpgme.c (_gpgme_release_result): Add support for new + EncryptResult object. + * encrypt.c (append_xml_encinfo): New. + (encrypt_status_handler): Add some status parsing. + (_gpgme_release_encrypt_result): New. + +2001-08-29 Werner Koch + + * recipient.c (gpgme_recipients_release): Free the list. By Timo. + + * keylist.c (keylist_colon_handler): Do a finish key if we receive + an EOF here. This is probably the reason for a lot of bugs + related to keylisting. It is so obvious. Kudos to Enno Cramer + for pointing that out. + +2001-08-28 Werner Koch + + * gpgme.c, gpgme.h (gpgme_get_op_info): New. + (_gpgme_set_op_info): New. + (_gpgme_release_result): Reset the op_info here. + * sign.c (append_xml_siginfo): New. + (sign_status_handler): Store the sig create information. + +2001-07-31 Werner Koch + + * encrypt.c (gpgme_op_encrypt): Hack to detect no valid recipients. + +2001-07-30 Werner Koch + + * gpgme.c (gpgme_get_armor,gpgme_get_textmode): New. + + * rungpg.c (build_argv): Disable armor comments + * w32-io.c (build_commandline): Need to add quotes here + +2001-07-24 Werner Koch + + * data.c (gpgme_data_read): Add a a way to return the available bytes. + +2001-07-23 Werner Koch + + * util.c: Removed stpcpy() because we use the version from jnlib. + +2001-07-19 Werner Koch + + * mkstatus: Define the collating sequence for sort. + +2001-06-26 Werner Koch + + * rungpg.h: Add STATUS_UNEXPECTED as suggested by Timo. + +2001-06-15 Werner Koch + + * keylist.c (set_userid_flags): Fixed the assigned values. Kudos + to Timo for pointing this out. + +2001-06-01 Werner Koch + + * debug.c (_gpgme_debug_begin): Fixed a /tmp race. Noted by + Johannes Poehlmann. + +2001-05-28 Werner Koch + + * version.c (gpgme_check_engine): Stop version number parsing at + the opening angle and not the closing one. By Tommy Reynolds. + +2001-05-01 José Carlos García Sogo + + * encrypt.c (gpgme_op_encrypt_start): Deleted the assert ( !c->gpg ) + line, because it gave an error if another operation had been made + before using the same context. + + * decrypt.c (gpgme_op_decrypt_start): The same as above. Also added + one line to release the gpg object in the context (if any). + +2001-04-26 Werner Koch + + * key.c, key.h (_gpgme_key_cache_init): New. + (_gpgme_key_cache_add): New. + (_gpgme_key_cache_get): New. + * version.c (do_subsystem_inits): Init the cache. + * keylist.c (finish_key): Put key into the cache + * verify.c (gpgme_get_sig_key): First look into the cache. + +2001-04-19 Werner Koch + + * keylist.c (parse_timestamp): Adjusted for the changed + --fixed-list-mode of gpg 1.0.4h. + +2001-04-05 Werner Koch + + * verify.c (gpgme_op_verify_start): Enabled pipemode for detached sigs. + +2001-04-04 Werner Koch + + * w32-io.c (_gpgme_io_select): Don't select on the writer if there + are still bytes pending. Timo found this not easy to track down + race condition. + +2001-04-02 Werner Koch + + * gpgme.h: Add GPGME_ATTR_KEY_{EXPIRED,DISABLED}. + * key.c (gpgme_key_get_ulong_attr): And return those attribs. + + * verify.c (gpgme_get_sig_key): Set keyliosting mode depending on + the mode set in the current context. Suggested by Timo. + + * key.c (gpgme_key_get_ulong_attr): Return can_certify and not + can_encrypt. By Timo. + +2001-03-30 Werner Koch + + * debug.c (debug_init): Allow to specify a debug file. + (_gpgme_debug_level): New. + + * posix-io.c (_gpgme_io_read, _gpgme_io_write): Print output. + (_gpgme_io_select): Debug only with level > 2. + +2001-03-15 Werner Koch + + * rungpg.c: Included time.h. + + * key.h: New keyflags for capabilities. + * keylist.c (set_mainkey_capability, set_subkey_capability): New. + (keylist_colon_handler): Parse them. + * gpgme.h: New attribute values for capabilties. + * key.c (gpgme_key_get_string_attr): Return them. + (capabilities_to_string): New. + (gpgme_key_get_ulong_attr): Return the global caps. + +2001-03-14 Werner Koch + + * w32-io.c (destroy_reader,destroy_writer): Fixed syntax error. + Thanks to Jan Oliver Wagner. + +2001-03-13 Werner Koch + + * context.h: Add invalid and revoke flags to user_id structure. + * keylist.c (gpgme_op_keylist_start): Use --fixed-list-mode. + (keylist_colon_handler): Adjust for that. + (set_userid_flags): New. + (set_mainkey_trust_info): Handle new key invalid flag + (set_subkey_trust_info): Ditto. + * gpgme.h: Add new attributes for key and user ID flags. + * key.c (_gpgme_key_append_name): Init these flags + (gpgme_key_get_as_xml): Print them. + (one_uid_as_xml): New helper for above. + (gpgme_key_get_string_attr, gpgme_key_get_ulong_attr): + Return the new attributes. Enhanced, so that subkey information + can be returned now. + +2001-02-28 Werner Koch + + * w32-io.c (destroy_reader): Set stop_me flag. + (writer,create_writer,destroy_writer,find_writer,kill_writer): New. + (_gpgme_io_write): Use a writer thread to avaoid blocking. + (_gpgme_io_close): Cleanup a writer thread + (_gpgme_io_select): Repalce tthe faked wait on writing by a real + waiting which is now possible due to the use of a writer thread. + +2001-02-20 Werner Koch + + * w32-io.c (destroy_reader,kill_reader): New. + (create_reader, reader): Add a new event to stop the thread. + (_gpgme_io_close): Kill the reader thread. + + * posix-io.c (_gpgme_io_select): Handle frozen fds here. + * 32-io.c (_gpgme_io_select): Ditto. Removed a bunch of unused code. + + * wait.c: Reworked the whole thing. + * rungpg.c (_gpgme_gpg_new): Init pid to -1. + (_gpgme_gpg_release): Remove the process from the wait queue. + +2001-02-19 Werner Koch + + * w32-io.c (_gpgme_io_set_close_notify): New. + (_gpgme_io_close): Do the notification. + + * posix-io.c (_gpgme_io_select): Use a 1 sec timeout and not 200 + microseconds. + + * wait.c (remove_process): Don't close the fd here. + (do_select): Set the fd to -1 and remove the is_closed flag everywhere. + (_gpgme_wait_on_condition): Remove the assert on the queue and + break out if we could not find the queue. The whole thing should + be reworked. + + * posix-io.c (_gpgme_io_set_close_notify): New. + (_gpgme_io_close): Do the notification. + + * rungpg.c (close_notify_handler): New. + (_gpgme_gpg_new): Register a callback for the fd. + (_gpgme_gpg_set_colon_line_handler): Ditto. + (build_argv): Ditto + +2001-02-13 Werner Koch + + * rungpg.c (struct reap_s): Replaced pid_t by int. + + * types.h: Add ulong typedef. + + * rungpg.c (do_reaping,_gpgme_gpg_housecleaning): New. + (_gpgme_gpg_release): Reap children. + * io.h, posix-io.c (_gpgme_io_kill): New. + * w32-io.c (_gpgme_io_kill): New (dummy). + + * keylist.c (gpgme_op_keylist_start): Cancel a pending request. + + * posix-io.c (_gpgme_io_read): Add some debug output. + (_gpgme_io_write): Ditto. + (_gpgme_io_select): Increased the timeout. + +2001-02-12 Werner Koch + + Enhanced the signature verification, so that it can how handle + more than one signature and is able to return more information on + the signatures. + * verify.c (gpgme_get_sig_key): New. + (gpgme_get_sig_status): New. + + * gpgme.h: Add stdio.h. + (GpgmeSigStat): New status DIFF. + +2001-02-01 Werner Koch + + * w32-io.c (set_synchronize): Add EVENT_MODIFY_STATE. Add Debug + code to all Set/ResetEvent(). + + * rungpg.c (read_status): Check for end of stream only if we have + an r. By Timo. + +2001-01-31 Werner Koch + + * wait.c (_gpgme_wait_on_condition): Removed all exit code processing. + (propagate_term_results,clear_active_fds): Removed. + (count_active_fds): Renamed to .. + (count_active_and_thawed_fds): .. this and count only thawed fds. + + * rungpg.c (gpg_colon_line_handler): Return colon.eof and not + status.eof ;-) + +2001-01-30 Werner Koch + + * w32-io.c (_gpgme_io_spawn): Use the supplied path arg. + + * version.c (get_engine_info): Return better error information. + + * posix-util.c, w32-util.c: New. + (_gpgme_get_gpg_path): New, suggested by Jan-Oliver. + * rungpg.c (_gpgme_gpg_spawn): Use new function to get GPG's path. + + * signers.c (gpgme_signers_add): Ooops, one should test code and + not just write it; the newarr was not assigned. Thanks to José + for pointing this out. Hmmm, still not tested, why shoudl a coder + test his fix :-) + + * w32-io.c: Does now use reader threads, so that we can use + WaitForMultipleObjects. + * sema.h, posix-sema.c, w32-sema.c: Support for Critcial sections. + Does currently only work for W32. + + * debug.c, util.h : New. Changed all fprintfs to use this new + set of debugging functions. + +2001-01-23 Werner Koch + + * data.c (_gpgme_data_release_and_return_string): Fixed string + termination. + +2001-01-22 Werner Koch + + * delete.c: New. + + * signers.c: New. + * key.c (gpgme_key_ref, gpgme_key_unref): New. + * sign.c (gpgme_op_sign_start): Allow the use of other keys. + + * version.c (gpgme_get_engine_info,gpgme_check_engine): New. + * rungpg.c (_gpgme_gpg_set_simple_line_handler): New. + +2001-01-05 Werner Koch + + * data.c (gpgme_data_rewind): Allow to rewind data_type_none. + + + Copyright 2001,2002,2003,2004,2005,2006,2007 g10 Code GmbH + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/tags/gpgme-1.1.6/gpgme/Makefile.am b/tags/gpgme-1.1.6/gpgme/Makefile.am new file mode 100644 index 0000000..bd0191a --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/Makefile.am @@ -0,0 +1,227 @@ +# Copyright (C) 2000 Werner Koch (dd9jn) +# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 g10 Code GmbH +# +# This file is part of GPGME. +# +# GPGME is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser 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 + +## Process this file with automake to produce Makefile.in + +# Note: moc_kdpipeiodevice should actually be a dependcy below. +EXTRA_DIST = gpgme-config.in gpgme.m4 mkstatus libgpgme.vers \ + versioninfo.rc.in gpgme.def moc_kdpipeiodevice.cpp +BUILT_SOURCES = status-table.h +MOSTLYCLEANFILES = status-table.h +bin_SCRIPTS = gpgme-config +m4datadir = $(datadir)/aclocal +m4data_DATA = gpgme.m4 +include_HEADERS = gpgme.h + +if HAVE_PTHREAD +ltlib_gpgme_pthread = libgpgme-pthread.la +else +ltlib_gpgme_pthread = +endif +if HAVE_PTH +ltlib_gpgme_pth = libgpgme-pth.la +else +ltlib_gpgme_pth = +endif + +if BUILD_W32_GLIB +ltlib_gpgme_glib = libgpgme-glib.la +else +ltlib_gpgme_glib = +endif + +if BUILD_W32_QT +ltlib_gpgme_qt = libgpgme-qt.la +else +ltlib_gpgme_qt = +endif + +lib_LTLIBRARIES = libgpgme.la $(ltlib_gpgme_glib) $(ltlib_gpgme_qt) \ + $(ltlib_gpgme_pthread) $(ltlib_gpgme_pth) + +if HAVE_LD_VERSION_SCRIPT +libgpgme_version_script_cmd = -Wl,--version-script=$(srcdir)/libgpgme.vers +else +libgpgme_version_script_cmd = +endif + +if BUILD_ASSUAN +assuan_cppflags = -I$(top_srcdir)/assuan +assuan_libobjs = ../assuan/libassuan.la +else +assuan_cppflags = +assuan_libobjs = +endif + +if HAVE_DOSISH_SYSTEM +system_components = w32-util.c w32-sema.c +system_components_not_extra = w32-io.c +else +system_components = ath.h posix-util.c posix-sema.c posix-io.c +system_components_not_extra = +endif + +if HAVE_GPGSM +gpgsm_components = engine-gpgsm.c +else +gpgsm_components = +endif + +if HAVE_GPGCONF +gpgconf_components = engine-gpgconf.c +else +gpgconf_components = +endif + +# These are the source files common to all library versions. We used +# to build a non-installed library for that, but that does not work +# correctly on all platforms (in particular, one can not specify the +# right linking order with libtool, as the non-installed version has +# unresolved symbols to the thread module. +main_sources = \ + gpgme.h util.h conversion.c get-env.c context.h ops.h \ + data.h data.c data-fd.c data-stream.c data-mem.c data-user.c \ + data-compat.c \ + signers.c sig-notation.c \ + wait.c wait-global.c wait-private.c wait-user.c wait.h \ + op-support.c \ + encrypt.c encrypt-sign.c decrypt.c decrypt-verify.c verify.c \ + sign.c passphrase.c progress.c \ + key.c keylist.c trust-item.c trustlist.c \ + import.c export.c genkey.c delete.c edit.c getauditlog.c \ + engine.h engine-backend.h engine.c rungpg.c status-table.h \ + $(gpgsm_components) $(gpgconf_components) gpgconf.c \ + sema.h priv-io.h $(system_components) \ + debug.c debug.h gpgme.c version.c error.c + +libgpgme_la_SOURCES = $(main_sources) \ + ath.h ath.c $(system_components_not_extra) +libgpgme_pthread_la_SOURCES = $(main_sources) \ + ath.h ath-pthread.c $(system_components_not_extra) +libgpgme_pth_la_SOURCES = $(main_sources) \ + ath.h ath-pth.c $(system_components_not_extra) + +if BUILD_W32_GLIB +libgpgme_glib_la_SOURCES = $(main_sources) ath.h ath.c w32-glib-io.c +endif + +if BUILD_W32_QT +libgpgme_qt_la_SOURCES = $(main_sources) ath.h ath.c w32-qt-io.cpp \ + kdpipeiodevice.h kdpipeiodevice.cpp kdpipeiodevice.moc +# FIXME: Add extra depedency: moc_kdpipeiodevice.cpp + +# These are built sources (normally). +# moc_kdpipeiodevice.cpp: kdpipeiodevice.h +# $(MOC4) -o $@ $< +# +# kdpipeiodevice.moc: kdpipeiodevice.cpp +# $(MOC4) -o $@ $< +endif + +# We use a global CFLAGS and CPPFLAGS setting for all library +# versions, because then every object file is only compiled once. +AM_CPPFLAGS = $(assuan_cppflags) @GPG_ERROR_CFLAGS@ @PTH_CPPFLAGS@ \ + @QT4_CORE_CFLAGS@ +AM_CFLAGS = @PTH_CFLAGS@ @GLIB_CFLAGS@ @QT4_CORE_CFLAGS@ + +if HAVE_W32_SYSTEM + +LTRCCOMPILE = $(LIBTOOL) --mode=compile $(RC) \ + `echo $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) | \ + sed -e 's/-I/--include-dir /g;s/-D/--define /g'` + +SUFFIXES: .rc .lo + +.rc.lo: + $(LTRCCOMPILE) -i $< -o $@ + +gpgme_res = versioninfo.lo +gpgme_res_ldflag = -Wl,.libs/versioninfo.o + +no_undefined = -no-undefined +export_symbols = -export-symbols $(srcdir)/gpgme.def + +install-def-file: + $(INSTALL) $(srcdir)/gpgme.def $(DESTDIR)$(libdir)/gpgme.def + +uninstall-def-file: + -rm $(DESTDIR)$(libdir)/gpgme.def + +gpgme_deps = $(gpgme_res) gpgme.def + +else +gpgme_res = +gpgme_res_ldflag = +no_undefined = +export_symbols = +install-def-file: +uninstall-def-file: + +gpgme_deps = +endif + +libgpgme_la_LDFLAGS = $(gpgme_res_ldflag) $(no_undefined) $(export_symbols) \ + $(libgpgme_version_script_cmd) -version-info \ + @LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@ +libgpgme_la_DEPENDENCIES = $(assuan_libobjs) \ + @LTLIBOBJS@ $(srcdir)/libgpgme.vers $(gpgme_deps) +libgpgme_la_LIBADD = $(assuan_libobjs) @LTLIBOBJS@ \ + @GPG_ERROR_LIBS@ @NETLIBS@ + +libgpgme_pthread_la_LDFLAGS = $(libgpgme_version_script_cmd) -version-info \ + @LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@ +libgpgme_pthread_la_DEPENDENCIES = $(assuan_libobjs) \ + @LTLIBOBJS@ $(srcdir)/libgpgme.vers +libgpgme_pthread_la_LIBADD = $(assuan_libobjs) @LTLIBOBJS@ \ + -lpthread @GPG_ERROR_LIBS@ @NETLIBS@ + +libgpgme_pth_la_LDFLAGS = @PTH_LDFLAGS@ \ + $(libgpgme_version_script_cmd) -version-info \ + @LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@ +libgpgme_pth_la_DEPENDENCIES = $(assuan_libobjs) \ + @LTLIBOBJS@ $(srcdir)/libgpgme.vers +libgpgme_pth_la_LIBADD = $(assuan_libobjs) @LTLIBOBJS@ \ + @PTH_LIBS@ @GPG_ERROR_LIBS@ @NETLIBS@ + +if BUILD_W32_GLIB +libgpgme_glib_la_LDFLAGS = $(gpgme_res_ldflag) $(no_undefined) \ + $(export_symbols) $(libgpgme_version_script_cmd) -version-info \ + @LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@ +libgpgme_glib_la_DEPENDENCIES = $(assuan_libobjs) \ + @LTLIBOBJS@ $(srcdir)/libgpgme.vers $(gpgme_deps) +libgpgme_glib_la_LIBADD = $(assuan_libobjs) @LTLIBOBJS@ \ + @GPG_ERROR_LIBS@ @GLIB_LIBS@ @NETLIBS@ +endif + +if BUILD_W32_QT +libgpgme_qt_la_LDFLAGS = $(gpgme_res_ldflag) $(no_undefined) \ + $(export_symbols) $(libgpgme_version_script_cmd) -version-info \ + @LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@ +libgpgme_qt_la_DEPENDENCIES = $(assuan_libobjs) \ + @LTLIBOBJS@ $(srcdir)/libgpgme.vers $(gpgme_deps) +libgpgme_qt_la_LIBADD = $(assuan_libobjs) @LTLIBOBJS@ \ + @GPG_ERROR_LIBS@ @QT4_CORE_LIBS@ @NETLIBS@ +endif + +status-table.h : gpgme.h + $(srcdir)/mkstatus < $(srcdir)/gpgme.h > status-table.h + +install-data-local: install-def-file + +uninstall-local: uninstall-def-file diff --git a/tags/gpgme-1.1.6/gpgme/ath-pth.c b/tags/gpgme-1.1.6/gpgme/ath-pth.c new file mode 100644 index 0000000..4c883a3 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/ath-pth.c @@ -0,0 +1,178 @@ +/* ath-pth.c - Pth module for self-adapting thread-safeness library + Copyright (C) 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include + +#include "ath.h" + + +/* The lock we take while checking for lazy lock initialization. */ +static pth_mutex_t check_init_lock = PTH_MUTEX_INIT; + +/* Initialize the mutex *PRIV. If JUST_CHECK is true, only do this if + it is not already initialized. */ +static int +mutex_pth_init (ath_mutex_t *priv, int just_check) +{ + int err = 0; + + if (just_check) + pth_mutex_acquire (&check_init_lock, 0, NULL); + if (!*priv || !just_check) + { + pth_mutex_t *lock = malloc (sizeof (pth_mutex_t)); + if (!lock) + err = ENOMEM; + if (!err) + { + err = pth_mutex_init (lock); + if (err == FALSE) + err = errno; + else + err = 0; + + if (err) + free (lock); + else + *priv = (ath_mutex_t) lock; + } + } + if (just_check) + pth_mutex_release (&check_init_lock); + return err; +} + + +void +ath_init (void) +{ + /* Nothing to do. */ +} + + +int +ath_mutex_init (ath_mutex_t *lock) +{ + return mutex_pth_init (lock, 0); +} + + +int +ath_mutex_destroy (ath_mutex_t *lock) +{ + int err = mutex_pth_init (lock, 1); + if (!err) + { + /* GNU Pth has no destructor function. */ + free (*lock); + } + return err; +} + + +int +ath_mutex_lock (ath_mutex_t *lock) +{ + int ret = mutex_pth_init (lock, 1); + if (ret) + return ret; + + ret = pth_mutex_acquire ((pth_mutex_t *) *lock, 0, NULL); + return ret == FALSE ? errno : 0; +} + + +int +ath_mutex_unlock (ath_mutex_t *lock) +{ + int ret = mutex_pth_init (lock, 1); + if (ret) + return ret; + + ret = pth_mutex_release ((pth_mutex_t *) *lock); + return ret == FALSE ? errno : 0; +} + + +ssize_t +ath_read (int fd, void *buf, size_t nbytes) +{ + return pth_read (fd, buf, nbytes); +} + + +ssize_t +ath_write (int fd, const void *buf, size_t nbytes) +{ + return pth_write (fd, buf, nbytes); +} + + +ssize_t +ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset, + struct timeval *timeout) +{ + return pth_select (nfd, rset, wset, eset, timeout); +} + + +ssize_t +ath_waitpid (pid_t pid, int *status, int options) +{ + return pth_waitpid (pid, status, options); +} + + +int +ath_accept (int s, struct sockaddr *addr, socklen_t *length_ptr) +{ + return pth_accept (s, addr, length_ptr); +} + + +int +ath_connect (int s, const struct sockaddr *addr, socklen_t length) +{ + return pth_connect (s, addr, length); +} + +int +ath_sendmsg (int s, const struct msghdr *msg, int flags) +{ + /* FIXME: GNU Pth is missing pth_sendmsg. */ + return sendmsg (s, msg, flags); +} + + +int +ath_recvmsg (int s, struct msghdr *msg, int flags) +{ + /* FIXME: GNU Pth is missing pth_recvmsg. */ + return recvmsg (s, msg, flags); +} + diff --git a/tags/gpgme-1.1.6/gpgme/ath-pthread.c b/tags/gpgme-1.1.6/gpgme/ath-pthread.c new file mode 100644 index 0000000..b201f08 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/ath-pthread.c @@ -0,0 +1,175 @@ +/* ath-pthread.c - pthread module for self-adapting thread-safeness library + Copyright (C) 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#ifdef HAVE_SYS_SELECT_H +# include +#else +# include +#endif +#include +#include + +#include + +#include "ath.h" + + +/* The lock we take while checking for lazy lock initialization. */ +static pthread_mutex_t check_init_lock = PTHREAD_MUTEX_INITIALIZER; + +/* Initialize the mutex *PRIV. If JUST_CHECK is true, only do this if + it is not already initialized. */ +static int +mutex_pthread_init (ath_mutex_t *priv, int just_check) +{ + int err = 0; + + if (just_check) + pthread_mutex_lock (&check_init_lock); + if (!*priv || !just_check) + { + pthread_mutex_t *lock = malloc (sizeof (pthread_mutex_t)); + if (!lock) + err = ENOMEM; + if (!err) + { + err = pthread_mutex_init (lock, NULL); + if (err) + free (lock); + else + *priv = (ath_mutex_t) lock; + } + } + if (just_check) + pthread_mutex_unlock (&check_init_lock); + return err; +} + + +void +ath_init (void) +{ + /* Nothing to do. */ +} + + +int +ath_mutex_init (ath_mutex_t *lock) +{ + return mutex_pthread_init (lock, 0); +} + + +int +ath_mutex_destroy (ath_mutex_t *lock) +{ + int err = mutex_pthread_init (lock, 1); + if (!err) + { + err = pthread_mutex_destroy ((pthread_mutex_t *) *lock); + free (*lock); + } + return err; +} + + +int +ath_mutex_lock (ath_mutex_t *lock) +{ + int ret = mutex_pthread_init (lock, 1); + if (ret) + return ret; + + return pthread_mutex_lock ((pthread_mutex_t *) *lock); +} + + +int +ath_mutex_unlock (ath_mutex_t *lock) +{ + int ret = mutex_pthread_init (lock, 1); + if (ret) + return ret; + + return pthread_mutex_unlock ((pthread_mutex_t *) *lock); +} + + +ssize_t +ath_read (int fd, void *buf, size_t nbytes) +{ + return read (fd, buf, nbytes); +} + + +ssize_t +ath_write (int fd, const void *buf, size_t nbytes) +{ + return write (fd, buf, nbytes); +} + + +ssize_t +ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset, + struct timeval *timeout) +{ + return select (nfd, rset, wset, eset, timeout); +} + + +ssize_t +ath_waitpid (pid_t pid, int *status, int options) +{ + return waitpid (pid, status, options); +} + + +int +ath_accept (int s, struct sockaddr *addr, socklen_t *length_ptr) +{ + return accept (s, addr, length_ptr); +} + + +int +ath_connect (int s, const struct sockaddr *addr, socklen_t length) +{ + return connect (s, addr, length); +} + +int +ath_sendmsg (int s, const struct msghdr *msg, int flags) +{ + return sendmsg (s, msg, flags); +} + + +int +ath_recvmsg (int s, struct msghdr *msg, int flags) +{ + return recvmsg (s, msg, flags); +} diff --git a/tags/gpgme-1.1.6/gpgme/ath.c b/tags/gpgme-1.1.6/gpgme/ath.c new file mode 100644 index 0000000..dda7c31 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/ath.c @@ -0,0 +1,169 @@ +/* ath.c - Thread-safeness library. + Copyright (C) 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#ifdef HAVE_SYS_SELECT_H +# include +#else +# include +#endif +#include +#ifndef HAVE_W32_SYSTEM +#include +#endif + +#include "ath.h" + + +#define MUTEX_UNLOCKED ((ath_mutex_t) 0) +#define MUTEX_LOCKED ((ath_mutex_t) 1) +#define MUTEX_DESTROYED ((ath_mutex_t) 2) + + +int +ath_mutex_init (ath_mutex_t *lock) +{ +#ifndef NDEBUG + *lock = MUTEX_UNLOCKED; +#endif + return 0; +} + + +int +ath_mutex_destroy (ath_mutex_t *lock) +{ +#ifndef NDEBUG + assert (*lock == MUTEX_UNLOCKED); + + *lock = MUTEX_DESTROYED; +#endif + return 0; +} + + +int +ath_mutex_lock (ath_mutex_t *lock) +{ +#ifndef NDEBUG + assert (*lock == MUTEX_UNLOCKED); + + *lock = MUTEX_LOCKED; +#endif + return 0; +} + + +int +ath_mutex_unlock (ath_mutex_t *lock) +{ +#ifndef NDEBUG + assert (*lock == MUTEX_LOCKED); + + *lock = MUTEX_UNLOCKED; +#endif + return 0; +} + + +ssize_t +ath_read (int fd, void *buf, size_t nbytes) +{ + return read (fd, buf, nbytes); +} + + +ssize_t +ath_write (int fd, const void *buf, size_t nbytes) +{ + return write (fd, buf, nbytes); +} + + +ssize_t +ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset, + struct timeval *timeout) +{ +#ifdef HAVE_W32_SYSTEM + return -1; /* Not supported. */ +#else + return select (nfd, rset, wset, eset, timeout); +#endif +} + + +ssize_t +ath_waitpid (pid_t pid, int *status, int options) +{ +#ifdef HAVE_W32_SYSTEM + return -1; /* Not supported. */ +#else + return waitpid (pid, status, options); +#endif +} + + +int +ath_accept (int s, struct sockaddr *addr, socklen_t *length_ptr) +{ +#ifdef HAVE_W32_SYSTEM + return -1; /* Not supported. */ +#else + return accept (s, addr, length_ptr); +#endif +} + + +int +ath_connect (int s, const struct sockaddr *addr, socklen_t length) +{ +#ifdef HAVE_W32_SYSTEM + return -1; /* Not supported. */ +#else + return connect (s, addr, length); +#endif +} + + +int +ath_sendmsg (int s, const struct msghdr *msg, int flags) +{ +#ifdef HAVE_W32_SYSTEM + return -1; /* Not supported. */ +#else + return sendmsg (s, msg, flags); +#endif +} + + +int +ath_recvmsg (int s, struct msghdr *msg, int flags) +{ +#ifdef HAVE_W32_SYSTEM + return -1; /* Not supported. */ +#else + return recvmsg (s, msg, flags); +#endif +} diff --git a/tags/gpgme-1.1.6/gpgme/ath.h b/tags/gpgme-1.1.6/gpgme/ath.h new file mode 100644 index 0000000..7491f72 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/ath.h @@ -0,0 +1,89 @@ +/* ath.h - Interfaces for thread-safeness library. + Copyright (C) 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 ATH_H +#define ATH_H + +#ifdef HAVE_W32_SYSTEM + /* fixme: Check how we did it in libgcrypt. */ + struct msghdr { int dummy; }; + typedef int socklen_t; +# include +# include + +#else /*!HAVE_W32_SYSTEM*/ + +# ifdef HAVE_SYS_SELECT_H +# include +# else +# include +# endif +# include +# include + +#endif /*!HAVE_W32_SYSTEM*/ + + + +/* Define _ATH_EXT_SYM_PREFIX if you want to give all external symbols + a prefix. */ +#define _ATH_EXT_SYM_PREFIX _gpgme_ + +#ifdef _ATH_EXT_SYM_PREFIX +#define _ATH_PREFIX1(x,y) x ## y +#define _ATH_PREFIX2(x,y) _ATH_PREFIX1(x,y) +#define _ATH_PREFIX(x) _ATH_PREFIX2(_ATH_EXT_SYM_PREFIX,x) +#define ath_mutex_init _ATH_PREFIX(ath_mutex_init) +#define ath_mutex_destroy _ATH_PREFIX(ath_mutex_destroy) +#define ath_mutex_lock _ATH_PREFIX(ath_mutex_lock) +#define ath_mutex_unlock _ATH_PREFIX(ath_mutex_unlock) +#define ath_read _ATH_PREFIX(ath_read) +#define ath_write _ATH_PREFIX(ath_write) +#define ath_select _ATH_PREFIX(ath_select) +#define ath_waitpid _ATH_PREFIX(ath_waitpid) +#define ath_connect _ATH_PREFIX(ath_connect) +#define ath_accept _ATH_PREFIX(ath_accept) +#define ath_sendmsg _ATH_PREFIX(ath_sendmsg) +#define ath_recvmsg _ATH_PREFIX(ath_recvmsg) +#endif + + +typedef void *ath_mutex_t; +#define ATH_MUTEX_INITIALIZER 0; + +/* Functions for mutual exclusion. */ +int ath_mutex_init (ath_mutex_t *mutex); +int ath_mutex_destroy (ath_mutex_t *mutex); +int ath_mutex_lock (ath_mutex_t *mutex); +int ath_mutex_unlock (ath_mutex_t *mutex); + +/* Replacement for the POSIX functions, which can be used to allow + other (user-level) threads to run. */ +ssize_t ath_read (int fd, void *buf, size_t nbytes); +ssize_t ath_write (int fd, const void *buf, size_t nbytes); +ssize_t ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset, + struct timeval *timeout); +ssize_t ath_waitpid (pid_t pid, int *status, int options); +int ath_accept (int s, struct sockaddr *addr, socklen_t *length_ptr); +int ath_connect (int s, const struct sockaddr *addr, socklen_t length); +int ath_sendmsg (int s, const struct msghdr *msg, int flags); +int ath_recvmsg (int s, struct msghdr *msg, int flags); + +#endif /* ATH_H */ diff --git a/tags/gpgme-1.1.6/gpgme/context.h b/tags/gpgme-1.1.6/gpgme/context.h new file mode 100644 index 0000000..e7e2afa --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/context.h @@ -0,0 +1,118 @@ +/* context.h - Definitions for a GPGME context. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 "engine.h" +#include "wait.h" + + +/* Operations might require to remember arbitrary information and data + objects during invocations of the status handler. The + ctx_op_data structure provides a generic framework to hook in + such additional data. */ +typedef enum + { + OPDATA_DECRYPT, OPDATA_SIGN, OPDATA_ENCRYPT, OPDATA_PASSPHRASE, + OPDATA_IMPORT, OPDATA_GENKEY, OPDATA_KEYLIST, OPDATA_EDIT, + OPDATA_VERIFY, OPDATA_TRUSTLIST + } ctx_op_data_id_t; + + +struct ctx_op_data +{ + /* The next element in the linked list, or NULL if this is the last + element. */ + struct ctx_op_data *next; + + /* The type of the hook data, which can be used by a routine to + lookup the hook data. */ + ctx_op_data_id_t type; + + /* The function to release HOOK and all its associated resources. + Can be NULL if no special dealllocation routine is necessary. */ + void (*cleanup) (void *hook); + + /* The hook that points to the operation data. */ + void *hook; +}; +typedef struct ctx_op_data *ctx_op_data_t; + + +/* The context defines an environment in which crypto operations can + be performed (sequentially). */ +struct gpgme_context +{ + /* The engine info for this context. */ + gpgme_engine_info_t engine_info; + + /* The protocol used by this context. */ + gpgme_protocol_t protocol; + + /* The running engine process. */ + engine_t engine; + + /* True if armor mode should be used. */ + unsigned int use_armor : 1; + + /* True if text mode should be used. */ + unsigned int use_textmode : 1; + + /* Flags for keylist mode. */ + gpgme_keylist_mode_t keylist_mode; + + /* Number of certs to be included. */ + unsigned int include_certs; + + /* The number of keys in signers. */ + unsigned int signers_len; + + /* Size of the following array. */ + unsigned int signers_size; + gpgme_key_t *signers; + + /* The signature notations for this context. */ + gpgme_sig_notation_t sig_notations; + + /* The locale for the pinentry. */ + char *lc_ctype; + char *lc_messages; + + /* The operation data hooked into the context. */ + ctx_op_data_t op_data; + + /* The user provided passphrase callback and its hook value. */ + gpgme_passphrase_cb_t passphrase_cb; + void *passphrase_cb_value; + + /* The user provided progress callback and its hook value. */ + gpgme_progress_cb_t progress_cb; + void *progress_cb_value; + + /* A list of file descriptors in active use by the current + operation. */ + struct fd_table fdt; + struct gpgme_io_cbs io_cbs; +}; + +#endif /* CONTEXT_H */ diff --git a/tags/gpgme-1.1.6/gpgme/conversion.c b/tags/gpgme-1.1.6/gpgme/conversion.c new file mode 100644 index 0000000..f431238 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/conversion.c @@ -0,0 +1,420 @@ +/* conversion.c - String conversion helper functions. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif + +#include +#include +/* Solaris 8 needs sys/types.h before time.h. */ +#include +#include +#include + +#include "gpgme.h" +#include "util.h" +#include "debug.h" + +#define atoi_1(p) (*(p) - '0' ) +#define atoi_2(p) ((atoi_1(p) * 10) + atoi_1((p)+1)) +#define atoi_4(p) ((atoi_2(p) * 100) + atoi_2((p)+2)) + + + +/* Convert two hexadecimal digits from STR to the value they + represent. Returns -1 if one of the characters is not a + hexadecimal digit. */ +int +_gpgme_hextobyte (const char *str) +{ + int val = 0; + int i; + +#define NROFHEXDIGITS 2 + for (i = 0; i < NROFHEXDIGITS; i++) + { + if (*str >= '0' && *str <= '9') + val += *str - '0'; + else if (*str >= 'A' && *str <= 'F') + val += 10 + *str - 'A'; + else if (*str >= 'a' && *str <= 'f') + val += 10 + *str - 'a'; + else + return -1; + if (i < NROFHEXDIGITS - 1) + val *= 16; + str++; + } + return val; +} + + +/* Decode the C formatted string SRC and store the result in the + buffer *DESTP which is LEN bytes long. If LEN is zero, then a + large enough buffer is allocated with malloc and *DESTP is set to + the result. Currently, LEN is only used to specify if allocation + is desired or not, the caller is expected to make sure that *DESTP + is large enough if LEN is not zero. */ +gpgme_error_t +_gpgme_decode_c_string (const char *src, char **destp, size_t len) +{ + char *dest; + + /* Set up the destination buffer. */ + if (len) + { + if (len < strlen (src) + 1) + return gpg_error (GPG_ERR_INTERNAL); + + dest = *destp; + } + else + { + /* The converted string will never be larger than the original + string. */ + dest = malloc (strlen (src) + 1); + if (!dest) + return gpg_error_from_errno (errno); + + *destp = dest; + } + + /* Convert the string. */ + while (*src) + { + if (*src != '\\') + { + *(dest++) = *(src++); + continue; + } + + switch (src[1]) + { +#define DECODE_ONE(match,result) \ + case match: \ + src += 2; \ + *(dest++) = result; \ + break; + + DECODE_ONE ('\'', '\''); + DECODE_ONE ('\"', '\"'); + DECODE_ONE ('\?', '\?'); + DECODE_ONE ('\\', '\\'); + DECODE_ONE ('a', '\a'); + DECODE_ONE ('b', '\b'); + DECODE_ONE ('f', '\f'); + DECODE_ONE ('n', '\n'); + DECODE_ONE ('r', '\r'); + DECODE_ONE ('t', '\t'); + DECODE_ONE ('v', '\v'); + + case 'x': + { + int val = _gpgme_hextobyte (&src[2]); + + if (val == -1) + { + /* Should not happen. */ + *(dest++) = *(src++); + *(dest++) = *(src++); + if (*src) + *(dest++) = *(src++); + if (*src) + *(dest++) = *(src++); + } + else + { + if (!val) + { + /* A binary zero is not representable in a C + string. */ + *(dest++) = '\\'; + *(dest++) = '0'; + } + else + *((unsigned char *) dest++) = val; + src += 4; + } + } + break; + + default: + { + /* Should not happen. */ + *(dest++) = *(src++); + *(dest++) = *(src++); + } + } + } + *(dest++) = 0; + + return 0; +} + + +/* Decode the percent escaped string SRC and store the result in the + buffer *DESTP which is LEN bytes long. If LEN is zero, then a + large enough buffer is allocated with malloc and *DESTP is set to + the result. Currently, LEN is only used to specify if allocation + is desired or not, the caller is expected to make sure that *DESTP + is large enough if LEN is not zero. If BINARY is 1, then '\0' + characters are allowed in the output. */ +gpgme_error_t +_gpgme_decode_percent_string (const char *src, char **destp, size_t len, + int binary) +{ + char *dest; + + /* Set up the destination buffer. */ + if (len) + { + if (len < strlen (src) + 1) + return gpg_error (GPG_ERR_INTERNAL); + + dest = *destp; + } + else + { + /* The converted string will never be larger than the original + string. */ + dest = malloc (strlen (src) + 1); + if (!dest) + return gpg_error_from_errno (errno); + + *destp = dest; + } + + /* Convert the string. */ + while (*src) + { + if (*src != '%') + { + *(dest++) = *(src++); + continue; + } + else + { + int val = _gpgme_hextobyte (&src[1]); + + if (val == -1) + { + /* Should not happen. */ + *(dest++) = *(src++); + if (*src) + *(dest++) = *(src++); + if (*src) + *(dest++) = *(src++); + } + else + { + if (!val && !binary) + { + /* A binary zero is not representable in a C + string. */ + *(dest++) = '\\'; + *(dest++) = '0'; + } + else + *((unsigned char *) dest++) = val; + src += 3; + } + } + } + *(dest++) = 0; + + return 0; +} + + +/* Parse the string TIMESTAMP into a time_t. The string may either be + seconds since Epoch or in the ISO 8601 format like + "20390815T143012". Returns 0 for an empty string or seconds since + Epoch. Leading spaces are skipped. If ENDP is not NULL, it will + point to the next non-parsed character in TIMESTRING. */ +time_t +_gpgme_parse_timestamp (const char *timestamp, char **endp) +{ + /* Need to skip leading spaces, because that is what strtoul does + but not our ISO 8601 checking code. */ + while (*timestamp && *timestamp== ' ') + timestamp++; + if (!*timestamp) + return 0; + + if (strlen (timestamp) >= 15 && timestamp[8] == 'T') + { + struct tm buf; + int year; + + year = atoi_4 (timestamp); + if (year < 1900) + return (time_t)(-1); + + /* Fixme: We would better use a configure test to see whether + mktime can handle dates beyond 2038. */ + if (sizeof (time_t) <= 4 && year >= 2038) + return (time_t)2145914603; /* 2037-12-31 23:23:23 */ + + memset (&buf, 0, sizeof buf); + buf.tm_year = year - 1900; + buf.tm_mon = atoi_2 (timestamp+4) - 1; + buf.tm_mday = atoi_2 (timestamp+6); + buf.tm_hour = atoi_2 (timestamp+9); + buf.tm_min = atoi_2 (timestamp+11); + buf.tm_sec = atoi_2 (timestamp+13); + + if (endp) + *endp = (char*)(timestamp + 15); +#ifdef HAVE_TIMEGM + return timegm (&buf); +#else + { + time_t tim; + + putenv ("TZ=UTC"); + tim = mktime (&buf); +#ifdef __GNUC__ +#warning fixme: we must somehow reset TZ here. It is not threadsafe anyway. +#endif + return tim; + } +#endif /* !HAVE_TIMEGM */ + } + else + return (time_t)strtoul (timestamp, endp, 10); +} + + + + +static struct +{ + char *name; + gpgme_error_t err; +} gnupg_errors[] = + { + { "EOF", GPG_ERR_EOF }, + { "No_Error", GPG_ERR_NO_ERROR }, + { "General_Error", GPG_ERR_GENERAL }, + { "Out_Of_Core", GPG_ERR_ENOMEM }, + { "Invalid_Value", GPG_ERR_INV_VALUE }, + { "IO_Error", GPG_ERR_GENERAL }, + { "Resource_Limit", GPG_ERR_RESOURCE_LIMIT }, + { "Internal_Error", GPG_ERR_INTERNAL }, + { "Bad_Certificate", GPG_ERR_BAD_CERT }, + { "Bad_Certificate_Chain", GPG_ERR_BAD_CERT_CHAIN}, + { "Missing_Certificate", GPG_ERR_MISSING_CERT }, + { "No_Data", GPG_ERR_NO_DATA }, + { "Bad_Signature", GPG_ERR_BAD_SIGNATURE }, + { "Not_Implemented", GPG_ERR_NOT_IMPLEMENTED }, + { "Conflict", GPG_ERR_CONFLICT }, + { "Bug", GPG_ERR_BUG }, + { "Read_Error", GPG_ERR_GENERAL }, + { "Write_Error", GPG_ERR_GENERAL }, + { "Invalid_Line", GPG_ERR_GENERAL }, + { "Incomplete_Line", GPG_ERR_INCOMPLETE_LINE }, + { "Invalid_Response", GPG_ERR_INV_RESPONSE }, + { "Agent_Error", GPG_ERR_AGENT }, + { "No_Public_Key", GPG_ERR_NO_PUBKEY }, + { "No_Secret_Key", GPG_ERR_NO_SECKEY }, + { "File_Open_Error", GPG_ERR_GENERAL }, + { "File_Create_Error", GPG_ERR_GENERAL }, + { "File_Error", GPG_ERR_GENERAL }, + { "Not_Supported", GPG_ERR_NOT_SUPPORTED }, + { "Invalid_Data", GPG_ERR_INV_DATA }, + { "Assuan_Server_Fault", GPG_ERR_ASSUAN_SERVER_FAULT }, + { "Assuan_Error", GPG_ERR_ASSUAN }, + { "Invalid_Session_Key", GPG_ERR_INV_SESSION_KEY }, + { "Invalid_Sexp", GPG_ERR_INV_SEXP }, + { "Unsupported_Algorithm", GPG_ERR_UNSUPPORTED_ALGORITHM }, + { "No_PIN_Entry", GPG_ERR_NO_PIN_ENTRY }, + { "PIN_Entry_Error", GPG_ERR_NO_PIN_ENTRY }, + { "Bad_PIN", GPG_ERR_BAD_PIN }, + { "Bad_Passphrase", GPG_ERR_BAD_PASSPHRASE }, + { "Invalid_Name", GPG_ERR_INV_NAME }, + { "Bad_Public_Key", GPG_ERR_BAD_PUBKEY }, + { "Bad_Secret_Key", GPG_ERR_BAD_SECKEY }, + { "Bad_Data", GPG_ERR_BAD_DATA }, + { "Invalid_Parameter", GPG_ERR_INV_PARAMETER }, + { "Tribute_to_D_A", GPG_ERR_TRIBUTE_TO_D_A }, + { "No_Dirmngr", GPG_ERR_NO_DIRMNGR }, + { "Dirmngr_Error", GPG_ERR_DIRMNGR }, + { "Certificate_Revoked", GPG_ERR_CERT_REVOKED }, + { "No_CRL_Known", GPG_ERR_NO_CRL_KNOWN }, + { "CRL_Too_Old", GPG_ERR_CRL_TOO_OLD }, + { "Line_Too_Long", GPG_ERR_LINE_TOO_LONG }, + { "Not_Trusted", GPG_ERR_NOT_TRUSTED }, + { "Canceled", GPG_ERR_CANCELED }, + { "Bad_CA_Certificate", GPG_ERR_BAD_CA_CERT }, + { "Certificate_Expired", GPG_ERR_CERT_EXPIRED }, + { "Certificate_Too_Young", GPG_ERR_CERT_TOO_YOUNG }, + { "Unsupported_Certificate", GPG_ERR_UNSUPPORTED_CERT }, + { "Unknown_Sexp", GPG_ERR_UNKNOWN_SEXP }, + { "Unsupported_Protection", GPG_ERR_UNSUPPORTED_PROTECTION }, + { "Corrupted_Protection", GPG_ERR_CORRUPTED_PROTECTION }, + { "Ambiguous_Name", GPG_ERR_AMBIGUOUS_NAME }, + { "Card_Error", GPG_ERR_CARD }, + { "Card_Reset", GPG_ERR_CARD_RESET }, + { "Card_Removed", GPG_ERR_CARD_REMOVED }, + { "Invalid_Card", GPG_ERR_INV_CARD }, + { "Card_Not_Present", GPG_ERR_CARD_NOT_PRESENT }, + { "No_PKCS15_App", GPG_ERR_NO_PKCS15_APP }, + { "Not_Confirmed", GPG_ERR_NOT_CONFIRMED }, + { "Configuration_Error", GPG_ERR_CONFIGURATION }, + { "No_Policy_Match", GPG_ERR_NO_POLICY_MATCH }, + { "Invalid_Index", GPG_ERR_INV_INDEX }, + { "Invalid_Id", GPG_ERR_INV_ID }, + { "No_Scdaemon", GPG_ERR_NO_SCDAEMON }, + { "Scdaemon_Error", GPG_ERR_SCDAEMON }, + { "Unsupported_Protocol", GPG_ERR_UNSUPPORTED_PROTOCOL }, + { "Bad_PIN_Method", GPG_ERR_BAD_PIN_METHOD }, + { "Card_Not_Initialized", GPG_ERR_CARD_NOT_INITIALIZED }, + { "Unsupported_Operation", GPG_ERR_UNSUPPORTED_OPERATION }, + { "Wrong_Key_Usage", GPG_ERR_WRONG_KEY_USAGE } + }; + + +gpgme_error_t +_gpgme_map_gnupg_error (char *errstr) +{ + unsigned int i; + gpgme_error_t err = gpg_err_make (GPG_ERR_SOURCE_GPG, GPG_ERR_GENERAL); + + /* Future version of GnuPG might return the error code directly, so + we first test for a a numerical value and use that verbatim. + Note that this numerical value might be followed by an + underschore and the textual representation of the error code. */ + if (*errstr >= '0' && *errstr <= '9') + return strtoul (errstr, NULL, 10); + + /* Well, this is a token, use the mapping table to get the error. + The drawback is that we won't receive an error source and have to + use GPG as source. */ + for (i = 0; i < DIM (gnupg_errors); i++) + if (!strcmp (gnupg_errors[i].name, errstr)) + err = gpg_err_make (GPG_ERR_SOURCE_GPG, gnupg_errors[i].err); + + TRACE3 (DEBUG_CTX, "_gpgme_map_gnupg_error", 0, + "mapped %s to %s <%s>", errstr, gpgme_strerror (err), + gpgme_strsource (err)); + return err; +} diff --git a/tags/gpgme-1.1.6/gpgme/data-compat.c b/tags/gpgme-1.1.6/gpgme/data-compat.c new file mode 100644 index 0000000..cabe24e --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/data-compat.c @@ -0,0 +1,242 @@ +/* data-compat.c - Compatibility interfaces for data objects. + Copyright (C) 2002, 2003, 2004, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include "data.h" +#include "util.h" +#include "debug.h" + + +/* Create a new data buffer filled with LENGTH bytes starting from + OFFSET within the file FNAME or stream STREAM (exactly one must be + non-zero). */ +gpgme_error_t +gpgme_data_new_from_filepart (gpgme_data_t *r_dh, const char *fname, + FILE *stream, off_t offset, size_t length) +{ + gpgme_error_t err; + char *buf = NULL; + int res; + + TRACE_BEG4 (DEBUG_DATA, "gpgme_data_new_from_filepart", r_dh, + "file_name=%s, stream=%p, offset=%lli, length=%u", + fname, stream, offset, length); + + if (stream && fname) + return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); + + if (fname) + stream = fopen (fname, "rb"); + if (!stream) + return TRACE_ERR (gpg_error_from_errno (errno)); + +#ifdef HAVE_FSEEKO + res = fseeko (stream, offset, SEEK_SET); +#else + /* FIXME: Check for overflow, or at least bail at compilation. */ + res = fseek (stream, offset, SEEK_SET); +#endif + + if (res) + { + int saved_errno = errno; + if (fname) + fclose (stream); + return TRACE_ERR (gpg_error_from_errno (saved_errno)); + } + + buf = malloc (length); + if (!buf) + { + int saved_errno = errno; + if (fname) + fclose (stream); + return TRACE_ERR (gpg_error_from_errno (saved_errno)); + } + + while (fread (buf, length, 1, stream) < 1 + && ferror (stream) && errno == EINTR); + if (ferror (stream)) + { + int saved_errno = errno; + if (buf) + free (buf); + if (fname) + fclose (stream); + return TRACE_ERR (gpg_error_from_errno (saved_errno)); + } + + if (fname) + fclose (stream); + + err = gpgme_data_new (r_dh); + if (err) + { + if (buf) + free (buf); + return err; + } + + (*r_dh)->data.mem.buffer = buf; + (*r_dh)->data.mem.size = length; + (*r_dh)->data.mem.length = length; + + return TRACE_SUC1 ("r_dh=%p", *r_dh); +} + + +/* Create a new data buffer filled with the content of file FNAME. + COPY must be non-zero (delayed reads are not supported yet). */ +gpgme_error_t +gpgme_data_new_from_file (gpgme_data_t *r_dh, const char *fname, int copy) +{ + gpgme_error_t err; + struct stat statbuf; + TRACE_BEG3 (DEBUG_DATA, "gpgme_data_new_from_filepart", r_dh, + "file_name=%s, copy=%i (%s)", fname, copy, copy ? "yes" : "no"); + + if (!fname || !copy) + return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); + + if (stat (fname, &statbuf) < 0) + return TRACE_ERR (gpg_error_from_errno (errno)); + + err = gpgme_data_new_from_filepart (r_dh, fname, NULL, 0, statbuf.st_size); + return TRACE_ERR (err); +} + + +static int +gpgme_error_to_errno (gpgme_error_t err) +{ + int res = gpg_err_code_to_errno (err); + + if (!err) + { + switch (gpg_err_code (err)) + { + case GPG_ERR_EOF: + res = 0; + break; + case GPG_ERR_INV_VALUE: + res = EINVAL; + break; + case GPG_ERR_NOT_SUPPORTED: + res = ENOSYS; + break; + default: + /* FIXME: Yeah, well. */ + res = EINVAL; + break; + } + } + TRACE3 (DEBUG_DATA, "gpgme:gpgme_error_to_errno", 0, + "mapping %s <%s> to: %s", gpgme_strerror (err), + gpgme_strsource (err), strerror (res)); + errno = res; + return res ? -1 : 0; +} + + +static ssize_t +old_user_read (gpgme_data_t dh, void *buffer, size_t size) +{ + gpgme_error_t err; + size_t amt; + TRACE_BEG2 (DEBUG_DATA, "gpgme:old_user_read", dh, + "buffer=%p, size=%u", buffer, size); + + err = (*dh->data.old_user.cb) (dh->data.old_user.handle, + buffer, size, &amt); + if (err) + return TRACE_SYSRES (gpgme_error_to_errno (err)); + return TRACE_SYSRES (amt); +} + + +static off_t +old_user_seek (gpgme_data_t dh, off_t offset, int whence) +{ + gpgme_error_t err; + TRACE_BEG2 (DEBUG_DATA, "gpgme:old_user_seek", dh, + "offset=%llu, whence=%i", offset, whence); + + if (whence != SEEK_SET || offset) + { + errno = EINVAL; + return TRACE_SYSRES (-1); + } + err = (*dh->data.old_user.cb) (dh->data.old_user.handle, NULL, 0, NULL); + if (err) + return TRACE_SYSRES (gpgme_error_to_errno (err)); + return TRACE_SYSRES (0); +} + + +static struct _gpgme_data_cbs old_user_cbs = + { + old_user_read, + NULL, + old_user_seek, + NULL + }; + + +/* Create a new data buffer which retrieves the data from the callback + function READ_CB. */ +gpgme_error_t +gpgme_data_new_with_read_cb (gpgme_data_t *r_dh, + int (*read_cb) (void *, char *, size_t, size_t *), + void *read_cb_value) +{ + gpgme_error_t err; + TRACE_BEG2 (DEBUG_DATA, "gpgme_data_new_with_read_cb", r_dh, + "read_cb=%p/%p", read_cb, read_cb_value); + + err = _gpgme_data_new (r_dh, &old_user_cbs); + + if (err) + return TRACE_ERR (err); + + (*r_dh)->data.old_user.cb = read_cb; + (*r_dh)->data.old_user.handle = read_cb_value; + return TRACE_ERR (0); +} + + +gpgme_error_t +gpgme_data_rewind (gpgme_data_t dh) +{ + gpgme_error_t err; + TRACE_BEG (DEBUG_DATA, "gpgme_data_rewind", dh); + + err = (gpgme_data_seek (dh, 0, SEEK_SET) == -1) + ? gpg_error_from_errno (errno) : 0; + + return TRACE_ERR (err); +} diff --git a/tags/gpgme-1.1.6/gpgme/data-fd.c b/tags/gpgme-1.1.6/gpgme/data-fd.c new file mode 100644 index 0000000..2c65be1 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/data-fd.c @@ -0,0 +1,78 @@ +/* data-fd.c - A file descripor based data object. + Copyright (C) 2002, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "data.h" + + +static ssize_t +fd_read (gpgme_data_t dh, void *buffer, size_t size) +{ + return read (dh->data.fd, buffer, size); +} + + +static ssize_t +fd_write (gpgme_data_t dh, const void *buffer, size_t size) +{ + return write (dh->data.fd, buffer, size); +} + + +static off_t +fd_seek (gpgme_data_t dh, off_t offset, int whence) +{ + return lseek (dh->data.fd, offset, whence); +} + + +static int +fd_get_fd (gpgme_data_t dh) +{ + return (dh->data.fd); +} + + +static struct _gpgme_data_cbs fd_cbs = + { + fd_read, + fd_write, + fd_seek, + NULL, + fd_get_fd + }; + + +gpgme_error_t +gpgme_data_new_from_fd (gpgme_data_t *dh, int fd) +{ + gpgme_error_t err = _gpgme_data_new (dh, &fd_cbs); + if (err) + return err; + + (*dh)->data.fd = fd; + return 0; +} diff --git a/tags/gpgme-1.1.6/gpgme/data-mem.c b/tags/gpgme-1.1.6/gpgme/data-mem.c new file mode 100644 index 0000000..b58a3c0 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/data-mem.c @@ -0,0 +1,280 @@ +/* data-mem.c - A memory based data object. + Copyright (C) 2002, 2003, 2004, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include "data.h" +#include "util.h" +#include "debug.h" + + +static ssize_t +mem_read (gpgme_data_t dh, void *buffer, size_t size) +{ + size_t amt = dh->data.mem.length - dh->data.mem.offset; + const char *src; + + if (!amt) + return 0; + + if (size < amt) + amt = size; + + src = dh->data.mem.buffer ? dh->data.mem.buffer : dh->data.mem.orig_buffer; + memcpy (buffer, src + dh->data.mem.offset, amt); + dh->data.mem.offset += amt; + return amt; +} + + +static ssize_t +mem_write (gpgme_data_t dh, const void *buffer, size_t size) +{ + size_t unused; + + if (!dh->data.mem.buffer && dh->data.mem.orig_buffer) + { + size_t new_size = dh->data.mem.size; + char *new_buffer; + + if (new_size < dh->data.mem.offset + size) + new_size = dh->data.mem.offset + size; + + new_buffer = malloc (new_size); + if (!new_buffer) + return -1; + memcpy (new_buffer, dh->data.mem.orig_buffer, dh->data.mem.length); + + dh->data.mem.buffer = new_buffer; + dh->data.mem.size = new_size; + } + + unused = dh->data.mem.size - dh->data.mem.offset; + if (unused < size) + { + /* Allocate a large enough buffer with exponential backoff. */ +#define INITIAL_ALLOC 512 + size_t new_size = dh->data.mem.size + ? (2 * dh->data.mem.size) : INITIAL_ALLOC; + char *new_buffer; + + if (new_size < dh->data.mem.offset + size) + new_size = dh->data.mem.offset + size; + + new_buffer = realloc (dh->data.mem.buffer, new_size); + if (!new_buffer && new_size > dh->data.mem.offset + size) + { + /* Maybe we were too greedy, try again. */ + new_size = dh->data.mem.offset + size; + new_buffer = realloc (dh->data.mem.buffer, new_size); + } + if (!new_buffer) + return -1; + dh->data.mem.buffer = new_buffer; + dh->data.mem.size = new_size; + } + + memcpy (dh->data.mem.buffer + dh->data.mem.offset, buffer, size); + dh->data.mem.offset += size; + if (dh->data.mem.length < dh->data.mem.offset) + dh->data.mem.length = dh->data.mem.offset; + return size; +} + + +static off_t +mem_seek (gpgme_data_t dh, off_t offset, int whence) +{ + switch (whence) + { + case SEEK_SET: + if (offset < 0 || offset > dh->data.mem.length) + { + errno = EINVAL; + return -1; + } + dh->data.mem.offset = offset; + break; + case SEEK_CUR: + if ((offset > 0 && dh->data.mem.length - dh->data.mem.offset < offset) + || (offset < 0 && dh->data.mem.offset < -offset)) + { + errno = EINVAL; + return -1; + } + dh->data.mem.offset += offset; + break; + case SEEK_END: + if (offset > 0 || -offset > dh->data.mem.length) + { + errno = EINVAL; + return -1; + } + dh->data.mem.offset = dh->data.mem.length - offset; + break; + default: + errno = EINVAL; + return -1; + } + return dh->data.mem.offset; +} + + +static void +mem_release (gpgme_data_t dh) +{ + if (dh->data.mem.buffer) + free (dh->data.mem.buffer); +} + + +static struct _gpgme_data_cbs mem_cbs = + { + mem_read, + mem_write, + mem_seek, + mem_release, + NULL + }; + + +/* Create a new data buffer and return it in R_DH. */ +gpgme_error_t +gpgme_data_new (gpgme_data_t *r_dh) +{ + gpgme_error_t err; + TRACE_BEG (DEBUG_DATA, "gpgme_data_new", r_dh); + + err = _gpgme_data_new (r_dh, &mem_cbs); + + if (err) + return TRACE_ERR (err); + + return TRACE_SUC1 ("r_dh=%p", *r_dh); +} + + +/* Create a new data buffer filled with SIZE bytes starting from + BUFFER. If COPY is zero, copying is delayed until necessary, and + the data is taken from the original location when needed. */ +gpgme_error_t +gpgme_data_new_from_mem (gpgme_data_t *r_dh, const char *buffer, + size_t size, int copy) +{ + gpgme_error_t err; + TRACE_BEG4 (DEBUG_DATA, "gpgme_data_new_from_mem", r_dh, + "buffer=%p, size=%u, copy=%i (%s)", buffer, size, + copy, copy ? "yes" : "no"); + + err = _gpgme_data_new (r_dh, &mem_cbs); + if (err) + return TRACE_ERR (err); + + if (copy) + { + char *bufcpy = malloc (size); + if (!bufcpy) + { + int saved_errno = errno; + _gpgme_data_release (*r_dh); + return TRACE_ERR (gpg_error_from_errno (saved_errno)); + } + memcpy (bufcpy, buffer, size); + (*r_dh)->data.mem.buffer = bufcpy; + } + else + (*r_dh)->data.mem.orig_buffer = buffer; + + (*r_dh)->data.mem.size = size; + (*r_dh)->data.mem.length = size; + return TRACE_SUC1 ("dh=%p", *r_dh); +} + + +/* Destroy the data buffer DH and return a pointer to its content. + The memory has be to released with gpgme_free() by the user. It's + size is returned in R_LEN. */ +char * +gpgme_data_release_and_get_mem (gpgme_data_t dh, size_t *r_len) +{ + char *str = NULL; + + TRACE_BEG1 (DEBUG_DATA, "gpgme_data_release_and_get_mem", dh, + "r_len=%p", r_len); + + if (!dh || dh->cbs != &mem_cbs) + { + gpgme_data_release (dh); + TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); + return NULL; + } + + str = dh->data.mem.buffer; + if (!str && dh->data.mem.orig_buffer) + { + str = malloc (dh->data.mem.length); + if (!str) + { + int saved_errno = errno; + gpgme_data_release (dh); + TRACE_ERR (gpg_error_from_errno (saved_errno)); + return NULL; + } + memcpy (str, dh->data.mem.orig_buffer, dh->data.mem.length); + } + else + /* Prevent mem_release from releasing the buffer memory. We must + not fail from this point. */ + dh->data.mem.buffer = NULL; + + if (r_len) + *r_len = dh->data.mem.length; + + gpgme_data_release (dh); + + if (r_len) + { + TRACE_SUC2 ("buffer=%p, len=%u", str, *r_len); + } + else + { + TRACE_SUC1 ("buffer=%p", str); + } + return str; +} + + +/* Release the memory returned by gpgme_data_release_and_get_mem(). */ +void +gpgme_free (void *buffer) +{ + TRACE (DEBUG_DATA, "gpgme_free", buffer); + + if (buffer) + free (buffer); +} diff --git a/tags/gpgme-1.1.6/gpgme/data-stream.c b/tags/gpgme-1.1.6/gpgme/data-stream.c new file mode 100644 index 0000000..629fb36 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/data-stream.c @@ -0,0 +1,101 @@ +/* data-stream.c - A stream based data object. + Copyright (C) 2002, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "data.h" + + +static ssize_t +stream_read (gpgme_data_t dh, void *buffer, size_t size) +{ + size_t amt = fread (buffer, 1, size, dh->data.stream); + if (amt > 0) + return amt; + return ferror (dh->data.stream) ? -1 : 0; +} + + +static ssize_t +stream_write (gpgme_data_t dh, const void *buffer, size_t size) +{ + size_t amt = fwrite (buffer, 1, size, dh->data.stream); + if (amt > 0) + return amt; + return ferror (dh->data.stream) ? -1 : 0; +} + + +static off_t +stream_seek (gpgme_data_t dh, off_t offset, int whence) +{ + int err; + +#ifdef HAVE_FSEEKO + err = fseeko (dh->data.stream, offset, whence); +#else + /* FIXME: Check for overflow, or at least bail at compilation. */ + err = fseek (dh->data.stream, offset, whence); +#endif + + if (err) + return -1; + +#ifdef HAVE_FSEEKO + return ftello (dh->data.stream); +#else + return ftell (dh->data.stream); +#endif +} + + +static int +stream_get_fd (gpgme_data_t dh) +{ + fflush (dh->data.stream); + return fileno (dh->data.stream); +} + + +static struct _gpgme_data_cbs stream_cbs = + { + stream_read, + stream_write, + stream_seek, + NULL, + stream_get_fd + }; + + +gpgme_error_t +gpgme_data_new_from_stream (gpgme_data_t *dh, FILE *stream) +{ + gpgme_error_t err = _gpgme_data_new (dh, &stream_cbs); + if (err) + return err; + + (*dh)->data.stream = stream; + return 0; +} diff --git a/tags/gpgme-1.1.6/gpgme/data-user.c b/tags/gpgme-1.1.6/gpgme/data-user.c new file mode 100644 index 0000000..ca9e9b1 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/data-user.c @@ -0,0 +1,98 @@ +/* data-user.c - A user callback based data object. + Copyright (C) 2002, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "data.h" + + +static ssize_t +user_read (gpgme_data_t dh, void *buffer, size_t size) +{ + if (!dh->data.user.cbs->read) + { + errno = EBADF; + return -1; + } + + return (*dh->data.user.cbs->read) (dh->data.user.handle, buffer, size); +} + + +static ssize_t +user_write (gpgme_data_t dh, const void *buffer, size_t size) +{ + if (!dh->data.user.cbs->write) + { + errno = EBADF; + return -1; + } + + return (*dh->data.user.cbs->write) (dh->data.user.handle, buffer, size); +} + + +static off_t +user_seek (gpgme_data_t dh, off_t offset, int whence) +{ + if (!dh->data.user.cbs->seek) + { + errno = EBADF; + return -1; + } + + return (*dh->data.user.cbs->seek) (dh->data.user.handle, offset, whence); +} + + +static void +user_release (gpgme_data_t dh) +{ + if (dh->data.user.cbs->release) + (*dh->data.user.cbs->release) (dh->data.user.handle); +} + + +static struct _gpgme_data_cbs user_cbs = + { + user_read, + user_write, + user_seek, + user_release, + NULL + }; + + +gpgme_error_t +gpgme_data_new_from_cbs (gpgme_data_t *dh, gpgme_data_cbs_t cbs, void *handle) +{ + gpgme_error_t err = _gpgme_data_new (dh, &user_cbs); + if (err) + return err; + + (*dh)->data.user.cbs = cbs; + (*dh)->data.user.handle = handle; + return 0; +} diff --git a/tags/gpgme-1.1.6/gpgme/data.c b/tags/gpgme-1.1.6/gpgme/data.c new file mode 100644 index 0000000..aa3eeb3 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/data.c @@ -0,0 +1,326 @@ +/* data.c - An abstraction for data objects. + Copyright (C) 2002, 2003, 2004, 2005, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include "gpgme.h" +#include "data.h" +#include "util.h" +#include "ops.h" +#include "priv-io.h" +#include "debug.h" + + +gpgme_error_t +_gpgme_data_new (gpgme_data_t *r_dh, struct _gpgme_data_cbs *cbs) +{ + gpgme_data_t dh; + + if (!r_dh) + return gpg_error (GPG_ERR_INV_VALUE); + + *r_dh = NULL; + dh = calloc (1, sizeof (*dh)); + if (!dh) + return gpg_error_from_errno (errno); + + dh->cbs = cbs; + + *r_dh = dh; + return 0; +} + + +void +_gpgme_data_release (gpgme_data_t dh) +{ + if (!dh) + return; + + if (dh->file_name) + free (dh->file_name); + free (dh); +} + + +/* Read up to SIZE bytes into buffer BUFFER from the data object with + the handle DH. Return the number of characters read, 0 on EOF and + -1 on error. If an error occurs, errno is set. */ +ssize_t +gpgme_data_read (gpgme_data_t dh, void *buffer, size_t size) +{ + ssize_t res; + TRACE_BEG2 (DEBUG_DATA, "gpgme_data_read", dh, + "buffer=%p, size=%u", buffer, size); + + if (!dh) + { + errno = EINVAL; + return TRACE_SYSRES (-1); + } + if (!dh->cbs->read) + { + errno = ENOSYS; + return TRACE_SYSRES (-1); + } + res = (*dh->cbs->read) (dh, buffer, size); + return TRACE_SYSRES (res); +} + + +/* Write up to SIZE bytes from buffer BUFFER to the data object with + the handle DH. Return the number of characters written, or -1 on + error. If an error occurs, errno is set. */ +ssize_t +gpgme_data_write (gpgme_data_t dh, const void *buffer, size_t size) +{ + ssize_t res; + TRACE_BEG2 (DEBUG_DATA, "gpgme_data_write", dh, + "buffer=%p, size=%u", buffer, size); + + if (!dh) + { + errno = EINVAL; + return TRACE_SYSRES (-1); + } + if (!dh->cbs->write) + { + errno = ENOSYS; + return TRACE_SYSRES (-1); + } + res = (*dh->cbs->write) (dh, buffer, size); + return TRACE_SYSRES (res); +} + + +/* Set the current position from where the next read or write starts + in the data object with the handle DH to OFFSET, relativ to + WHENCE. */ +off_t +gpgme_data_seek (gpgme_data_t dh, off_t offset, int whence) +{ + TRACE_BEG2 (DEBUG_DATA, "gpgme_data_seek", dh, + "offset=%lli, whence=%i", offset, whence); + + if (!dh) + { + errno = EINVAL; + return TRACE_SYSRES (-1); + } + if (!dh->cbs->seek) + { + errno = ENOSYS; + return TRACE_SYSRES (-1); + } + + /* For relative movement, we must take into account the actual + position of the read counter. */ + if (whence == SEEK_CUR) + offset -= dh->pending_len; + + offset = (*dh->cbs->seek) (dh, offset, whence); + if (offset >= 0) + dh->pending_len = 0; + + return TRACE_SYSRES (offset); +} + + +/* Release the data object with the handle DH. */ +void +gpgme_data_release (gpgme_data_t dh) +{ + TRACE (DEBUG_DATA, "gpgme_data_release", dh); + + if (!dh) + return; + + if (dh->cbs->release) + (*dh->cbs->release) (dh); + _gpgme_data_release (dh); +} + + +/* Get the current encoding meta information for the data object with + handle DH. */ +gpgme_data_encoding_t +gpgme_data_get_encoding (gpgme_data_t dh) +{ + TRACE1 (DEBUG_DATA, "gpgme_data_get_encoding", dh, + "dh->encoding=%i", dh ? dh->encoding : GPGME_DATA_ENCODING_NONE); + return dh ? dh->encoding : GPGME_DATA_ENCODING_NONE; +} + + +/* Set the encoding meta information for the data object with handle + DH to ENC. */ +gpgme_error_t +gpgme_data_set_encoding (gpgme_data_t dh, gpgme_data_encoding_t enc) +{ + TRACE_BEG1 (DEBUG_DATA, "gpgme_data_set_encoding", dh, + "encoding=%i", enc); + if (!dh) + return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); + if (enc < 0 || enc > GPGME_DATA_ENCODING_ARMOR) + return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); + dh->encoding = enc; + return TRACE_ERR (0); +} + + +/* Set the file name associated with the data object with handle DH to + FILE_NAME. */ +gpgme_error_t +gpgme_data_set_file_name (gpgme_data_t dh, const char *file_name) +{ + TRACE_BEG1 (DEBUG_DATA, "gpgme_data_set_file_name", dh, + "file_name=%s", file_name); + + if (!dh) + return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); + + if (dh->file_name) + free (dh->file_name); + + if (file_name) + { + dh->file_name = strdup (file_name); + if (!dh->file_name) + return TRACE_ERR (gpg_error_from_errno (errno)); + } + else + dh->file_name = 0; + + return TRACE_ERR (0); +} + + +/* Get the file name associated with the data object with handle DH, + or NULL if there is none. */ +char * +gpgme_data_get_file_name (gpgme_data_t dh) +{ + if (!dh) + { + TRACE (DEBUG_DATA, "gpgme_data_get_file_name", dh); + return NULL; + } + + TRACE1 (DEBUG_DATA, "gpgme_data_get_file_name", dh, + "dh->file_name=%s", dh->file_name); + return dh->file_name; +} + + +/* Functions to support the wait interface. */ + +gpgme_error_t +_gpgme_data_inbound_handler (void *opaque, int fd) +{ + gpgme_data_t dh = (gpgme_data_t) opaque; + char buffer[BUFFER_SIZE]; + char *bufp = buffer; + ssize_t buflen; + TRACE_BEG1 (DEBUG_CTX, "_gpgme_data_inbound_handler", dh, + "fd=0x%x", fd); + + buflen = _gpgme_io_read (fd, buffer, BUFFER_SIZE); + if (buflen < 0) + return gpg_error_from_errno (errno); + if (buflen == 0) + { + _gpgme_io_close (fd); + return TRACE_ERR (0); + } + + do + { + ssize_t amt = gpgme_data_write (dh, bufp, buflen); + if (amt == 0 || (amt < 0 && errno != EINTR)) + return TRACE_ERR (gpg_error_from_errno (errno)); + bufp += amt; + buflen -= amt; + } + while (buflen > 0); + return TRACE_ERR (0); +} + + +gpgme_error_t +_gpgme_data_outbound_handler (void *opaque, int fd) +{ + gpgme_data_t dh = (gpgme_data_t) opaque; + ssize_t nwritten; + TRACE_BEG1 (DEBUG_CTX, "_gpgme_data_outbound_handler", dh, + "fd=0x%x", fd); + + if (!dh->pending_len) + { + ssize_t amt = gpgme_data_read (dh, dh->pending, BUFFER_SIZE); + if (amt < 0) + return TRACE_ERR (gpg_error_from_errno (errno)); + if (amt == 0) + { + _gpgme_io_close (fd); + return TRACE_ERR (0); + } + dh->pending_len = amt; + } + + nwritten = _gpgme_io_write (fd, dh->pending, dh->pending_len); + if (nwritten == -1 && errno == EAGAIN) + return TRACE_ERR (0); + + if (nwritten == -1 && errno == EPIPE) + { + /* Not much we can do. The other end closed the pipe, but we + still have data. This should only ever happen if the other + end is going to tell us what happened on some other channel. + Silently close our end. */ + _gpgme_io_close (fd); + return TRACE_ERR (0); + } + + if (nwritten <= 0) + return TRACE_ERR (gpg_error_from_errno (errno)); + + if (nwritten < dh->pending_len) + memmove (dh->pending, dh->pending + nwritten, dh->pending_len - nwritten); + dh->pending_len -= nwritten; + return TRACE_ERR (0); +} + + +/* Get the file descriptor associated with DH, if possible. Otherwise + return -1. */ +int +_gpgme_data_get_fd (gpgme_data_t dh) +{ + if (!dh || !dh->cbs->get_fd) + return -1; + return (*dh->cbs->get_fd) (dh); +} diff --git a/tags/gpgme-1.1.6/gpgme/data.h b/tags/gpgme-1.1.6/gpgme/data.h new file mode 100644 index 0000000..370751d --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/data.h @@ -0,0 +1,132 @@ +/* data.h - Internal data object abstraction interface. + Copyright (C) 2002, 2004, 2005 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 DATA_H +#define DATA_H + +#if HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "gpgme.h" + + +/* Read up to SIZE bytes into buffer BUFFER from the data object with + the handle DH. Return the number of characters read, 0 on EOF and + -1 on error. If an error occurs, errno is set. */ +typedef ssize_t (*gpgme_data_read_cb) (gpgme_data_t dh, void *buffer, + size_t size); + +/* Write up to SIZE bytes from buffer BUFFER to the data object with + the handle DH. Return the number of characters written, or -1 on + error. If an error occurs, errno is set. */ +typedef ssize_t (*gpgme_data_write_cb) (gpgme_data_t dh, const void *buffer, + size_t size); + +/* Set the current position from where the next read or write starts + in the data object with the handle DH to OFFSET, relativ to + WHENCE. */ +typedef off_t (*gpgme_data_seek_cb) (gpgme_data_t dh, off_t offset, + int whence); + +/* Release the data object with the handle DH. */ +typedef void (*gpgme_data_release_cb) (gpgme_data_t dh); + +/* Get the FD associated with the handle DH, or -1. */ +typedef int (*gpgme_data_get_fd_cb) (gpgme_data_t dh); + +struct _gpgme_data_cbs +{ + gpgme_data_read_cb read; + gpgme_data_write_cb write; + gpgme_data_seek_cb seek; + gpgme_data_release_cb release; + gpgme_data_get_fd_cb get_fd; +}; + +struct gpgme_data +{ + struct _gpgme_data_cbs *cbs; + gpgme_data_encoding_t encoding; + +#ifdef PIPE_BUF +#define BUFFER_SIZE PIPE_BUF +#else +#ifdef _POSIX_PIPE_BUF +#define BUFFER_SIZE _POSIX_PIPE_BUF +#else +#define BUFFER_SIZE 512 +#endif +#endif + char pending[BUFFER_SIZE]; + int pending_len; + + /* File name of the data object. */ + char *file_name; + + union + { + /* For gpgme_data_new_from_fd. */ + int fd; + + /* For gpgme_data_new_from_stream. */ + FILE *stream; + + /* For gpgme_data_new_from_cbs. */ + struct + { + gpgme_data_cbs_t cbs; + void *handle; + } user; + + /* For gpgme_data_new_from_mem. */ + struct + { + char *buffer; + const char *orig_buffer; + /* Allocated size of BUFFER. */ + size_t size; + size_t length; + off_t offset; + } mem; + + /* For gpgme_data_new_from_read_cb. */ + struct + { + int (*cb) (void *, char *, size_t, size_t *); + void *handle; + } old_user; + } data; +}; + + +gpgme_error_t _gpgme_data_new (gpgme_data_t *r_dh, + struct _gpgme_data_cbs *cbs); + +void _gpgme_data_release (gpgme_data_t dh); + +/* Get the file descriptor associated with DH, if possible. Otherwise + return -1. */ +int _gpgme_data_get_fd (gpgme_data_t dh); + +#endif /* DATA_H */ diff --git a/tags/gpgme-1.1.6/gpgme/debug.c b/tags/gpgme-1.1.6/gpgme/debug.c new file mode 100644 index 0000000..bf1ca18 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/debug.c @@ -0,0 +1,295 @@ +/* debug.c - helpful output in desperate situations + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#if HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#ifndef HAVE_DOSISH_SYSTEM +# include +# include +# include +#endif +#include + +#ifdef HAVE_ASSUAN_H +#include "assuan.h" +#endif + +#include "util.h" +#include "sema.h" +#include "debug.h" + + +/* Lock to serialize initialization of the debug output subsystem and + output of actual debug messages. */ +DEFINE_STATIC_LOCK (debug_lock); + +/* The amount of detail requested by the user, per environment + variable GPGME_DEBUG. */ +static int debug_level; + +/* The output stream for the debug messages. */ +static FILE *errfp; + + +/* Remove leading and trailing white spaces. */ +static char * +trim_spaces (char *str) +{ + char *string, *p, *mark; + + string = str; + /* Find first non space character. */ + for (p = string; *p && isspace (*(unsigned char *) p); p++) + ; + /* Move characters. */ + for (mark = NULL; (*string = *p); string++, p++) + if (isspace (*(unsigned char *) p)) + { + if (!mark) + mark = string; + } + else + mark = NULL; + if (mark) + *mark = '\0'; /* Remove trailing spaces. */ + + return str; +} + + +static void +debug_init (void) +{ + static int initialized; + + LOCK (debug_lock); + if (!initialized) + { + gpgme_error_t err; + char *e; + const char *s1, *s2;; + + err = _gpgme_getenv ("GPGME_DEBUG", &e); + if (err) + { + UNLOCK (debug_lock); + return; + } + + initialized = 1; + errfp = stderr; + if (e) + { + debug_level = atoi (e); + s1 = strchr (e, PATHSEP_C); + if (s1) + { +#ifndef HAVE_DOSISH_SYSTEM + if (getuid () == geteuid ()) + { +#endif + char *p; + FILE *fp; + + s1++; + if (!(s2 = strchr (s1, PATHSEP_C))) + s2 = s1 + strlen (s1); + p = malloc (s2 - s1 + 1); + if (p) + { + memcpy (p, s1, s2 - s1); + p[s2-s1] = 0; + trim_spaces (p); + fp = fopen (p,"a"); + if (fp) + { + setvbuf (fp, NULL, _IOLBF, 0); + errfp = fp; + } + free (p); + } +#ifndef HAVE_DOSISH_SYSTEM + } +#endif + } + free (e); + } + + if (debug_level > 0) + fprintf (errfp, "gpgme_debug: level=%d\n", debug_level); +#ifdef HAVE_ASSUAN_H + assuan_set_assuan_log_prefix ("gpgme-assuan"); + assuan_set_assuan_log_stream (errfp); + assuan_set_assuan_log_level (debug_level >= 0? debug_level:0); +#endif /* HAVE_ASSUAN_H*/ + } + UNLOCK (debug_lock); +} + + + +/* This should be called as soon as the locks are intialized. It is + required so that the assuan logging gets conncted to the gpgme log + stream as early as possible. */ +void +_gpgme_debug_subsystem_init (void) +{ + debug_init (); +} + + + + +/* Log the formatted string FORMAT at debug level LEVEL or higher. */ +void +_gpgme_debug (int level, const char *format, ...) +{ + va_list arg_ptr; + int saved_errno; + + saved_errno = errno; + + debug_init (); + if (debug_level < level) + return; + + va_start (arg_ptr, format); + LOCK (debug_lock); + vfprintf (errfp, format, arg_ptr); + va_end (arg_ptr); + if(format && *format && format[strlen (format) - 1] != '\n') + putc ('\n', errfp); + UNLOCK (debug_lock); + fflush (errfp); + + errno = saved_errno; +} + + +/* Start a new debug line in *LINE, logged at level LEVEL or higher, + and starting with the formatted string FORMAT. */ +void +_gpgme_debug_begin (void **line, int level, const char *format, ...) +{ + va_list arg_ptr; + + debug_init (); + if (debug_level < level) + { + /* Disable logging of this line. */ + *line = NULL; + return; + } + + va_start (arg_ptr, format); + vasprintf ((char **) line, format, arg_ptr); + va_end (arg_ptr); +} + + +/* Add the formatted string FORMAT to the debug line *LINE. */ +void +_gpgme_debug_add (void **line, const char *format, ...) +{ + va_list arg_ptr; + char *toadd; + char *result; + + if (!*line) + return; + + va_start (arg_ptr, format); + vasprintf (&toadd, format, arg_ptr); + va_end (arg_ptr); + asprintf (&result, "%s%s", *(char **) line, toadd); + free (*line); + free (toadd); + *line = result; +} + + +/* Finish construction of *LINE and send it to the debug output + stream. */ +void +_gpgme_debug_end (void **line) +{ + if (!*line) + return; + + /* The smallest possible level is 1, so force logging here by + using that. */ + _gpgme_debug (1, "%s", *line); + free (*line); + *line = NULL; +} + + +#define TOHEX(val) (((val) < 10) ? ((val) + '0') : ((val) - 10 + 'a')) + +void +_gpgme_debug_buffer (int lvl, const char *const fmt, + const char *const func, const char *const tagname, + void *tag, const char *const buffer, size_t len) +{ + int idx = 0; + int j; + + if (!_gpgme_debug_trace ()) + return; + + while (idx < len) + { + char str[51]; + char *strp = str; + char *strp2 = &str[34]; + + for (j = 0; j < 16; j++) + { + unsigned char val; + if (idx < len) + { + val = buffer[idx++]; + *(strp++) = TOHEX (val >> 4); + *(strp++) = TOHEX (val % 16); + *(strp2++) = isprint (val) ? val : '.'; + } + else + { + *(strp++) = ' '; + *(strp++) = ' '; + } + if (j == 7) + *(strp++) = ' '; + } + *(strp++) = ' '; + *(strp2) = '\0'; + + _gpgme_debug (lvl, fmt, func, tagname, tag, str); + } +} diff --git a/tags/gpgme-1.1.6/gpgme/debug.h b/tags/gpgme-1.1.6/gpgme/debug.h new file mode 100644 index 0000000..1083c66 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/debug.h @@ -0,0 +1,226 @@ +/* debug.h - interface to debugging functions + Copyright (C) 2002, 2004, 2005, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 DEBUG_H +#define DEBUG_H + +#include + +/* Indirect stringification, requires __STDC__ to work. */ +#define STRINGIFY(v) #v +#define XSTRINGIFY(v) STRINGIFY(v) + + +/* The debug levels. */ + +#define DEBUG_INIT 1 +#define DEBUG_CTX 2 +#define DEBUG_ENGINE 3 +#define DEBUG_DATA 4 +#define DEBUG_ASSUAN 5 +#define DEBUG_SYSIO 6 + + +/* Remove path components from filenames (i.e. __FILE__) for cleaner + logs. */ +static inline const char *_gpgme_debug_srcname (const char *file) + GPGME_GCC_A_PURE; + +static inline const char * +_gpgme_debug_srcname (const char *file) +{ + const char *s = strrchr (file, '/'); + return s? s+1:file; +} + +/* Called early to initialize the logging. */ +void _gpgme_debug_subsystem_init (void); + +/* Log the formatted string FORMAT at debug level LEVEL or higher. */ +void _gpgme_debug (int level, const char *format, ...); + +/* Start a new debug line in *LINE, logged at level LEVEL or higher, + and starting with the formatted string FORMAT. */ +void _gpgme_debug_begin (void **helper, int level, const char *format, ...); + +/* Add the formatted string FORMAT to the debug line *LINE. */ +void _gpgme_debug_add (void **helper, const char *format, ...); + +/* Finish construction of *LINE and send it to the debug output + stream. */ +void _gpgme_debug_end (void **helper); + +void _gpgme_debug_buffer (int lvl, const char *const fmt, + const char *const func, const char *const tagname, + void *tag, const char *const buffer, size_t len); + + +/* Trace support. */ + +/* FIXME: For now. */ +#define _gpgme_debug_trace() 1 + +#define _TRACE(lvl, name, tag) \ + int _gpgme_trace_level = lvl; \ + const char *const _gpgme_trace_func = name; \ + const char *const _gpgme_trace_tagname = STRINGIFY (tag); \ + void *_gpgme_trace_tag = (void *) tag + +#define TRACE_BEG(lvl, name, tag) \ + _TRACE (lvl, name, tag); \ + _gpgme_debug (_gpgme_trace_level, "%s (%s=0x%x): enter\n", \ + _gpgme_trace_func, _gpgme_trace_tagname, \ + _gpgme_trace_tag), 0 +#define TRACE_BEG0(lvl, name, tag, fmt) \ + _TRACE (lvl, name, tag); \ + _gpgme_debug (_gpgme_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ + _gpgme_trace_func, _gpgme_trace_tagname, \ + _gpgme_trace_tag), 0 +#define TRACE_BEG1(lvl, name, tag, fmt, arg1) \ + _TRACE (lvl, name, tag); \ + _gpgme_debug (_gpgme_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ + _gpgme_trace_func, _gpgme_trace_tagname, \ + _gpgme_trace_tag, arg1), 0 +#define TRACE_BEG2(lvl, name, tag, fmt, arg1, arg2) \ + _TRACE (lvl, name, tag); \ + _gpgme_debug (_gpgme_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ + _gpgme_trace_func, _gpgme_trace_tagname, \ + _gpgme_trace_tag, arg1, arg2), 0 +#define TRACE_BEG3(lvl, name, tag, fmt, arg1, arg2, arg3) \ + _TRACE (lvl, name, tag); \ + _gpgme_debug (_gpgme_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ + _gpgme_trace_func, _gpgme_trace_tagname, \ + _gpgme_trace_tag, arg1, arg2, arg3), 0 +#define TRACE_BEG4(lvl, name, tag, fmt, arg1, arg2, arg3, arg4) \ + _TRACE (lvl, name, tag); \ + _gpgme_debug (_gpgme_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ + _gpgme_trace_func, _gpgme_trace_tagname, \ + _gpgme_trace_tag, arg1, arg2, arg3, arg4), 0 + +#define TRACE(lvl, name, tag) \ + _gpgme_debug (lvl, "%s (%s=0x%x): call\n", \ + name, STRINGIFY (tag), (void *) tag), 0 +#define TRACE0(lvl, name, tag, fmt) \ + _gpgme_debug (lvl, "%s (%s=0x%x): call: " fmt "\n", \ + name, STRINGIFY (tag), (void *) tag), 0 +#define TRACE1(lvl, name, tag, fmt, arg1) \ + _gpgme_debug (lvl, "%s (%s=0x%x): call: " fmt "\n", \ + name, STRINGIFY (tag), (void *) tag, arg1), 0 +#define TRACE2(lvl, name, tag, fmt, arg1, arg2) \ + _gpgme_debug (lvl, "%s (%s=0x%x): call: " fmt "\n", \ + name, STRINGIFY (tag), (void *) tag, arg1, arg2), 0 +#define TRACE3(lvl, name, tag, fmt, arg1, arg2, arg3) \ + _gpgme_debug (lvl, "%s (%s=0x%x): call: " fmt "\n", \ + name, STRINGIFY (tag), (void *) tag, arg1, arg2, \ + arg3), 0 +#define TRACE6(lvl, name, tag, fmt, arg1, arg2, arg3, arg4, arg5, arg6) \ + _gpgme_debug (lvl, "%s (%s=0x%x): call: " fmt "\n", \ + name, STRINGIFY (tag), (void *) tag, arg1, arg2, arg3, \ + arg4, arg5, arg6), 0 + +#define TRACE_ERR(err) \ + err == 0 ? (TRACE_SUC ()) : \ + (_gpgme_debug (_gpgme_trace_level, "%s (%s=0x%x): error: %s <%s>\n", \ + _gpgme_trace_func, _gpgme_trace_tagname, \ + _gpgme_trace_tag, gpgme_strerror (err), \ + gpgme_strsource (err)), (err)) +/* The cast to void suppresses GCC warnings. */ +#define TRACE_SYSRES(res) \ + res >= 0 ? ((void) (TRACE_SUC1 ("result=%i", res)), (res)) : \ + (_gpgme_debug (_gpgme_trace_level, "%s (%s=0x%x): error: %s\n", \ + _gpgme_trace_func, _gpgme_trace_tagname, \ + _gpgme_trace_tag, strerror (errno)), (res)) +#define TRACE_SYSERR(res) \ + res == 0 ? ((void) (TRACE_SUC1 ("result=%i", res)), (res)) : \ + (_gpgme_debug (_gpgme_trace_level, "%s (%s=0x%x): error: %s\n", \ + _gpgme_trace_func, _gpgme_trace_tagname, \ + _gpgme_trace_tag, strerror (res)), (res)) + +#define TRACE_SUC() \ + _gpgme_debug (_gpgme_trace_level, "%s (%s=0x%x): leave\n", \ + _gpgme_trace_func, _gpgme_trace_tagname, \ + _gpgme_trace_tag), 0 +#define TRACE_SUC0(fmt) \ + _gpgme_debug (_gpgme_trace_level, "%s (%s=0x%x): leave: " fmt "\n", \ + _gpgme_trace_func, _gpgme_trace_tagname, \ + _gpgme_trace_tag), 0 +#define TRACE_SUC1(fmt, arg1) \ + _gpgme_debug (_gpgme_trace_level, "%s (%s=0x%x): leave: " fmt "\n", \ + _gpgme_trace_func, _gpgme_trace_tagname, \ + _gpgme_trace_tag, arg1), 0 +#define TRACE_SUC2(fmt, arg1, arg2) \ + _gpgme_debug (_gpgme_trace_level, "%s (%s=0x%x): leave: " fmt "\n", \ + _gpgme_trace_func, _gpgme_trace_tagname, \ + _gpgme_trace_tag, arg1, arg2), 0 +#define TRACE_SUC5(fmt, arg1, arg2, arg3, arg4, arg5) \ + _gpgme_debug (_gpgme_trace_level, "%s (%s=0x%x): leave: " fmt "\n", \ + _gpgme_trace_func, _gpgme_trace_tagname, \ + _gpgme_trace_tag, arg1, arg2, arg3, arg4, arg5), 0 + +#define TRACE_LOG(fmt) \ + _gpgme_debug (_gpgme_trace_level, "%s (%s=0x%x): check: " fmt "\n", \ + _gpgme_trace_func, _gpgme_trace_tagname, \ + _gpgme_trace_tag), 0 +#define TRACE_LOG1(fmt, arg1) \ + _gpgme_debug (_gpgme_trace_level, "%s (%s=0x%x): check: " fmt "\n", \ + _gpgme_trace_func, _gpgme_trace_tagname, \ + _gpgme_trace_tag, arg1), 0 +#define TRACE_LOG2(fmt, arg1, arg2) \ + _gpgme_debug (_gpgme_trace_level, "%s (%s=0x%x): check: " fmt "\n", \ + _gpgme_trace_func, _gpgme_trace_tagname, \ + _gpgme_trace_tag, arg1, arg2), 0 +#define TRACE_LOG3(fmt, arg1, arg2, arg3) \ + _gpgme_debug (_gpgme_trace_level, "%s (%s=0x%x): check: " fmt "\n", \ + _gpgme_trace_func, _gpgme_trace_tagname, \ + _gpgme_trace_tag, arg1, arg2, arg3), 0 +#define TRACE_LOG4(fmt, arg1, arg2, arg3, arg4) \ + _gpgme_debug (_gpgme_trace_level, "%s (%s=0x%x): check: " fmt "\n", \ + _gpgme_trace_func, _gpgme_trace_tagname, \ + _gpgme_trace_tag, arg1, arg2, arg3, arg4), 0 +#define TRACE_LOG6(fmt, arg1, arg2, arg3, arg4, arg5, arg6) \ + _gpgme_debug (_gpgme_trace_level, "%s (%s=0x%x): check: " fmt "\n", \ + _gpgme_trace_func, _gpgme_trace_tagname, \ + _gpgme_trace_tag, arg1, arg2, arg3, arg4, arg5, \ + arg6), 0 + +#define TRACE_LOGBUF(buf, len) \ + _gpgme_debug_buffer (_gpgme_trace_level, "%s (%s=0x%x): check: %s", \ + _gpgme_trace_func, _gpgme_trace_tagname, \ + _gpgme_trace_tag, buf, len) + +#define TRACE_SEQ(hlp,fmt) \ + _gpgme_debug_begin (&(hlp), _gpgme_trace_level, \ + "%s (%s=0x%x): check: " fmt, \ + _gpgme_trace_func, _gpgme_trace_tagname, \ + _gpgme_trace_tag) +#define TRACE_ADD0(hlp,fmt) \ + _gpgme_debug_add (&(hlp), fmt) +#define TRACE_ADD1(hlp,fmt,a) \ + _gpgme_debug_add (&(hlp), fmt, (a)) +#define TRACE_ADD2(hlp,fmt,a,b) \ + _gpgme_debug_add (&(hlp), fmt, (a), (b)) +#define TRACE_ADD3(hlp,fmt,a,b,c) \ + _gpgme_debug_add (&(hlp), fmt, (a), (b), (c)) +#define TRACE_END(hlp,fmt) \ + _gpgme_debug_add (&(hlp), fmt); \ + _gpgme_debug_end (&(hlp)) +#define TRACE_ENABLED(hlp) (!!(hlp)) + +#endif /* DEBUG_H */ diff --git a/tags/gpgme-1.1.6/gpgme/decrypt-verify.c b/tags/gpgme-1.1.6/gpgme/decrypt-verify.c new file mode 100644 index 0000000..2fa3bb2 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/decrypt-verify.c @@ -0,0 +1,103 @@ +/* decrypt-verify.c - Decrypt and verify function. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif + +#include "gpgme.h" +#include "ops.h" + + +static gpgme_error_t +decrypt_verify_status_handler (void *priv, gpgme_status_code_t code, + char *args) +{ + gpgme_error_t err; + + err = _gpgme_progress_status_handler (priv, code, args); + if (!err) + err = _gpgme_decrypt_status_handler (priv, code, args); + if (!err) + err = _gpgme_verify_status_handler (priv, code, args); + return err; +} + + +static gpgme_error_t +decrypt_verify_start (gpgme_ctx_t ctx, int synchronous, + gpgme_data_t cipher, gpgme_data_t plain) +{ + gpgme_error_t err; + + err = _gpgme_op_reset (ctx, synchronous); + if (err) + return err; + + err = _gpgme_op_decrypt_init_result (ctx); + if (err) + return err; + + err = _gpgme_op_verify_init_result (ctx); + if (err) + return err; + + if (!cipher) + return gpg_error (GPG_ERR_NO_DATA); + if (!plain) + return gpg_error (GPG_ERR_INV_VALUE); + + if (ctx->passphrase_cb) + { + err = _gpgme_engine_set_command_handler + (ctx->engine, _gpgme_passphrase_command_handler, ctx, NULL); + if (err) + return err; + } + + _gpgme_engine_set_status_handler (ctx->engine, + decrypt_verify_status_handler, ctx); + + return _gpgme_engine_op_decrypt (ctx->engine, cipher, plain); +} + + +/* Decrypt ciphertext CIPHER and make a signature verification within + CTX and store the resulting plaintext in PLAIN. */ +gpgme_error_t +gpgme_op_decrypt_verify_start (gpgme_ctx_t ctx, gpgme_data_t cipher, + gpgme_data_t plain) +{ + return decrypt_verify_start (ctx, 0, cipher, plain); +} + + +/* Decrypt ciphertext CIPHER and make a signature verification within + CTX and store the resulting plaintext in PLAIN. */ +gpgme_error_t +gpgme_op_decrypt_verify (gpgme_ctx_t ctx, gpgme_data_t cipher, + gpgme_data_t plain) +{ + gpgme_error_t err = decrypt_verify_start (ctx, 1, cipher, plain); + if (!err) + err = _gpgme_wait_one (ctx); + return err; +} diff --git a/tags/gpgme-1.1.6/gpgme/decrypt.c b/tags/gpgme-1.1.6/gpgme/decrypt.c new file mode 100644 index 0000000..5ce21ba --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/decrypt.c @@ -0,0 +1,340 @@ +/* decrypt.c - Decrypt function. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif +#include +#include +#include + +#include "gpgme.h" +#include "util.h" +#include "context.h" +#include "ops.h" + + +typedef struct +{ + struct _gpgme_op_decrypt_result result; + + int okay; + int failed; + + /* A pointer to the next pointer of the last recipient in the list. + This makes appending new invalid signers painless while + preserving the order. */ + gpgme_recipient_t *last_recipient_p; +} *op_data_t; + + +static void +release_op_data (void *hook) +{ + op_data_t opd = (op_data_t) hook; + + if (opd->result.unsupported_algorithm) + free (opd->result.unsupported_algorithm); + + if (opd->result.file_name) + free (opd->result.file_name); +} + + +gpgme_decrypt_result_t +gpgme_op_decrypt_result (gpgme_ctx_t ctx) +{ + void *hook; + op_data_t opd; + gpgme_error_t err; + + err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook, -1, NULL); + opd = hook; + if (err || !opd) + return NULL; + + return &opd->result; +} + + +static gpgme_error_t +parse_enc_to (char *args, gpgme_recipient_t *recp) +{ + gpgme_recipient_t rec; + char *tail; + int i; + + rec = malloc (sizeof (*rec)); + if (!rec) + return gpg_error_from_errno (errno); + + rec->next = NULL; + rec->keyid = rec->_keyid; + rec->status = 0; + + for (i = 0; i < sizeof (rec->_keyid) - 1; i++) + { + if (args[i] == '\0' || args[i] == ' ') + break; + + rec->_keyid[i] = args[i]; + } + rec->_keyid[i] = '\0'; + + args = &args[i]; + if (*args != '\0' && *args != ' ') + { + free (rec); + return gpg_error (GPG_ERR_INV_ENGINE); + } + + while (*args == ' ') + args++; + + if (*args) + { + errno = 0; + rec->pubkey_algo = strtol (args, &tail, 0); + if (errno || args == tail || *tail != ' ') + { + /* The crypto backend does not behave. */ + free (rec); + return gpg_error (GPG_ERR_INV_ENGINE); + } + } + + /* FIXME: The key length is always 0 right now, so no need to parse + it. */ + + *recp = rec; + return 0; +} + + +gpgme_error_t +_gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code, + char *args) +{ + gpgme_ctx_t ctx = (gpgme_ctx_t) priv; + gpgme_error_t err; + void *hook; + op_data_t opd; + + err = _gpgme_passphrase_status_handler (priv, code, args); + if (err) + return err; + + err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook, -1, NULL); + opd = hook; + if (err) + return err; + + switch (code) + { + case GPGME_STATUS_EOF: + /* FIXME: These error values should probably be attributed to + the underlying crypto engine (as error source). */ + if (opd->failed) + return gpg_error (GPG_ERR_DECRYPT_FAILED); + else if (!opd->okay) + return gpg_error (GPG_ERR_NO_DATA); + break; + + case GPGME_STATUS_DECRYPTION_OKAY: + opd->okay = 1; + break; + + case GPGME_STATUS_DECRYPTION_FAILED: + opd->failed = 1; + break; + + case GPGME_STATUS_ERROR: + /* Note that this is an informational status code which should + not lead to an error return unless it is something not + related to the backend. */ + { + const char d_alg[] = "decrypt.algorithm"; + const char u_alg[] = "Unsupported_Algorithm"; + const char k_alg[] = "decrypt.keyusage"; + + if (!strncmp (args, d_alg, sizeof (d_alg) - 1)) + { + args += sizeof (d_alg) - 1; + while (*args == ' ') + args++; + + if (!strncmp (args, u_alg, sizeof (u_alg) - 1)) + { + char *end; + + args += sizeof (u_alg) - 1; + while (*args == ' ') + args++; + + end = strchr (args, ' '); + if (end) + *end = '\0'; + + if (!(*args == '?' && *(args + 1) == '\0')) + { + opd->result.unsupported_algorithm = strdup (args); + if (!opd->result.unsupported_algorithm) + return gpg_error_from_errno (errno); + } + } + } + else if (!strncmp (args, k_alg, sizeof (k_alg) - 1)) + { + args += sizeof (k_alg) - 1; + while (*args == ' ') + args++; + + err = _gpgme_map_gnupg_error (args); + if (gpg_err_code (err) == GPG_ERR_WRONG_KEY_USAGE) + opd->result.wrong_key_usage = 1; + } + } + break; + + case GPGME_STATUS_ENC_TO: + err = parse_enc_to (args, opd->last_recipient_p); + if (err) + return err; + + opd->last_recipient_p = &(*opd->last_recipient_p)->next; + break; + + case GPGME_STATUS_NO_SECKEY: + { + gpgme_recipient_t rec = opd->result.recipients; + + while (rec) + { + if (!strcmp (rec->keyid, args)) + { + rec->status = gpg_error (GPG_ERR_NO_SECKEY); + break; + } + rec = rec->next; + } + /* FIXME: Is this ok? */ + if (!rec) + return gpg_error (GPG_ERR_INV_ENGINE); + } + break; + + case GPGME_STATUS_PLAINTEXT: + err = _gpgme_parse_plaintext (args, &opd->result.file_name); + if (err) + return err; + + default: + break; + } + + return 0; +} + + +static gpgme_error_t +decrypt_status_handler (void *priv, gpgme_status_code_t code, char *args) +{ + gpgme_error_t err; + + err = _gpgme_progress_status_handler (priv, code, args); + if (!err) + err = _gpgme_decrypt_status_handler (priv, code, args); + return err; +} + + +gpgme_error_t +_gpgme_op_decrypt_init_result (gpgme_ctx_t ctx) +{ + gpgme_error_t err; + void *hook; + op_data_t opd; + + err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook, + sizeof (*opd), release_op_data); + opd = hook; + if (err) + return err; + + opd->last_recipient_p = &opd->result.recipients; + return 0; +} + + +static gpgme_error_t +decrypt_start (gpgme_ctx_t ctx, int synchronous, + gpgme_data_t cipher, gpgme_data_t plain) +{ + gpgme_error_t err; + + err = _gpgme_op_reset (ctx, synchronous); + if (err) + return err; + + err = _gpgme_op_decrypt_init_result (ctx); + if (err) + return err; + + if (!cipher) + return gpg_error (GPG_ERR_NO_DATA); + if (!plain) + return gpg_error (GPG_ERR_INV_VALUE); + + if (err) + return err; + + if (ctx->passphrase_cb) + { + err = _gpgme_engine_set_command_handler + (ctx->engine, _gpgme_passphrase_command_handler, ctx, NULL); + if (err) + return err; + } + + _gpgme_engine_set_status_handler (ctx->engine, decrypt_status_handler, ctx); + + return _gpgme_engine_op_decrypt (ctx->engine, cipher, plain); +} + + +gpgme_error_t +gpgme_op_decrypt_start (gpgme_ctx_t ctx, gpgme_data_t cipher, + gpgme_data_t plain) +{ + return decrypt_start (ctx, 0, cipher, plain); +} + + +/* Decrypt ciphertext CIPHER within CTX and store the resulting + plaintext in PLAIN. */ +gpgme_error_t +gpgme_op_decrypt (gpgme_ctx_t ctx, gpgme_data_t cipher, gpgme_data_t plain) +{ + gpgme_error_t err = decrypt_start (ctx, 1, cipher, plain); + if (!err) + err = _gpgme_wait_one (ctx); + return err; +} diff --git a/tags/gpgme-1.1.6/gpgme/delete.c b/tags/gpgme-1.1.6/gpgme/delete.c new file mode 100644 index 0000000..38f2fdd --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/delete.c @@ -0,0 +1,109 @@ +/* delete.c - Delete a key. + Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif +#include +#include + +#include "gpgme.h" +#include "context.h" +#include "ops.h" + + +static gpgme_error_t +delete_status_handler (void *priv, gpgme_status_code_t code, char *args) +{ + if (code == GPGME_STATUS_DELETE_PROBLEM) + { + enum delete_problem + { + DELETE_No_Problem = 0, + DELETE_No_Such_Key = 1, + DELETE_Must_Delete_Secret_Key = 2, + DELETE_Ambiguous_Specification = 3 + }; + long problem; + char *tail; + + errno = 0; + problem = strtol (args, &tail, 0); + if (errno || (*tail && *tail != ' ')) + return gpg_error (GPG_ERR_INV_ENGINE); + + switch (problem) + { + case DELETE_No_Problem: + break; + + case DELETE_No_Such_Key: + return gpg_error (GPG_ERR_NO_PUBKEY); + + case DELETE_Must_Delete_Secret_Key: + return gpg_error (GPG_ERR_CONFLICT); + + case DELETE_Ambiguous_Specification: + return gpg_error (GPG_ERR_AMBIGUOUS_NAME); + + default: + return gpg_error (GPG_ERR_GENERAL); + } + } + return 0; +} + + +static gpgme_error_t +delete_start (gpgme_ctx_t ctx, int synchronous, const gpgme_key_t key, + int allow_secret) +{ + gpgme_error_t err; + + err = _gpgme_op_reset (ctx, synchronous); + if (err) + return err; + + _gpgme_engine_set_status_handler (ctx->engine, delete_status_handler, ctx); + + return _gpgme_engine_op_delete (ctx->engine, key, allow_secret); +} + + +/* Delete KEY from the keyring. If ALLOW_SECRET is non-zero, secret + keys are also deleted. */ +gpgme_error_t +gpgme_op_delete_start (gpgme_ctx_t ctx, const gpgme_key_t key, + int allow_secret) +{ + return delete_start (ctx, 0, key, allow_secret); +} + + +/* Delete KEY from the keyring. If ALLOW_SECRET is non-zero, secret + keys are also deleted. */ +gpgme_error_t +gpgme_op_delete (gpgme_ctx_t ctx, const gpgme_key_t key, int allow_secret) +{ + gpgme_error_t err = delete_start (ctx, 1, key, allow_secret); + if (!err) + err = _gpgme_wait_one (ctx); + return err; +} diff --git a/tags/gpgme-1.1.6/gpgme/edit.c b/tags/gpgme-1.1.6/gpgme/edit.c new file mode 100644 index 0000000..186d4f9 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/edit.c @@ -0,0 +1,177 @@ +/* edit.c - Key edit function. + Copyright (C) 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif +#include + +#include "gpgme.h" +#include "context.h" +#include "ops.h" + + +typedef struct +{ + /* The user callback function and its hook value. */ + gpgme_edit_cb_t fnc; + void *fnc_value; +} *op_data_t; + + +static gpgme_error_t +edit_status_handler (void *priv, gpgme_status_code_t status, char *args) +{ + gpgme_ctx_t ctx = (gpgme_ctx_t) priv; + gpgme_error_t err; + void *hook; + op_data_t opd; + + err = _gpgme_passphrase_status_handler (priv, status, args); + if (err) + return err; + + err = _gpgme_progress_status_handler (priv, status, args); + if (err) + return err; + + err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, -1, NULL); + opd = hook; + if (err) + return err; + + return (*opd->fnc) (opd->fnc_value, status, args, -1); +} + + +static gpgme_error_t +command_handler (void *priv, gpgme_status_code_t status, const char *args, + int fd, int *processed_r) +{ + gpgme_ctx_t ctx = (gpgme_ctx_t) priv; + gpgme_error_t err; + int processed = 0; + + if (ctx->passphrase_cb) + { + err = _gpgme_passphrase_command_handler (ctx, status, args, + fd, &processed); + if (err) + return err; + } + + if (!processed) + { + void *hook; + op_data_t opd; + + err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, -1, NULL); + opd = hook; + if (err) + return err; + + /* FIXME: We expect the user to handle _all_ status codes. + Later, we may fix the callback interface to allow the user + indicate if it processed the status code or not. */ + *processed_r = 1; + + return (*opd->fnc) (opd->fnc_value, status, args, fd); + } + + *processed_r = processed; + return 0; +} + + +static gpgme_error_t +edit_start (gpgme_ctx_t ctx, int synchronous, int type, gpgme_key_t key, + gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out) +{ + gpgme_error_t err; + void *hook; + op_data_t opd; + + err = _gpgme_op_reset (ctx, synchronous); + if (err) + return err; + + if (!fnc || !out) + return gpg_error (GPG_ERR_INV_VALUE); + + err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, sizeof (*opd), NULL); + opd = hook; + if (err) + return err; + + opd->fnc = fnc; + opd->fnc_value = fnc_value; + + err = _gpgme_engine_set_command_handler (ctx->engine, command_handler, + ctx, out); + if (err) + return err; + + _gpgme_engine_set_status_handler (ctx->engine, edit_status_handler, ctx); + + return _gpgme_engine_op_edit (ctx->engine, type, key, out, ctx); +} + + +gpgme_error_t +gpgme_op_edit_start (gpgme_ctx_t ctx, gpgme_key_t key, + gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out) +{ + return edit_start (ctx, 0, 0, key, fnc, fnc_value, out); +} + + +/* Edit the key KEY. Send status and command requests to FNC and + output of edit commands to OUT. */ +gpgme_error_t +gpgme_op_edit (gpgme_ctx_t ctx, gpgme_key_t key, + gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out) +{ + gpgme_error_t err = edit_start (ctx, 1, 0, key, fnc, fnc_value, out); + if (!err) + err = _gpgme_wait_one (ctx); + return err; +} + + +gpgme_error_t +gpgme_op_card_edit_start (gpgme_ctx_t ctx, gpgme_key_t key, + gpgme_edit_cb_t fnc, void *fnc_value, + gpgme_data_t out) +{ + return edit_start (ctx, 0, 1, key, fnc, fnc_value, out); +} + + +/* Edit the card for the key KEY. Send status and command requests to + FNC and output of edit commands to OUT. */ +gpgme_error_t +gpgme_op_card_edit (gpgme_ctx_t ctx, gpgme_key_t key, + gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out) +{ + gpgme_error_t err = edit_start (ctx, 1, 1, key, fnc, fnc_value, out); + if (!err) + err = _gpgme_wait_one (ctx); + return err; +} diff --git a/tags/gpgme-1.1.6/gpgme/encrypt-sign.c b/tags/gpgme-1.1.6/gpgme/encrypt-sign.c new file mode 100644 index 0000000..7e3d2ed --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/encrypt-sign.c @@ -0,0 +1,110 @@ +/* encrypt-sign.c - encrypt and verify functions + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif + +#include "gpgme.h" +#include "context.h" +#include "ops.h" + + +static gpgme_error_t +encrypt_sign_status_handler (void *priv, gpgme_status_code_t code, char *args) +{ + gpgme_error_t err; + + err = _gpgme_progress_status_handler (priv, code, args); + if (!err) + err = _gpgme_encrypt_status_handler (priv, code, args); + if (!err) + err = _gpgme_sign_status_handler (priv, code, args); + return err; +} + + +static gpgme_error_t +encrypt_sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[], + gpgme_encrypt_flags_t flags, + gpgme_data_t plain, gpgme_data_t cipher) +{ + gpgme_error_t err; + + err = _gpgme_op_reset (ctx, synchronous); + if (err) + return err; + + if (!plain) + return gpg_error (GPG_ERR_NO_DATA); + if (!cipher || !recp) + return gpg_error (GPG_ERR_INV_VALUE); + + err = _gpgme_op_encrypt_init_result (ctx); + if (err) + return err; + + err = _gpgme_op_sign_init_result (ctx); + if (err) + return err; + + if (ctx->passphrase_cb) + { + err = _gpgme_engine_set_command_handler + (ctx->engine, _gpgme_passphrase_command_handler, ctx, NULL); + if (err) + return err; + } + + _gpgme_engine_set_status_handler (ctx->engine, + encrypt_sign_status_handler, ctx); + + return _gpgme_engine_op_encrypt_sign (ctx->engine, recp, flags, plain, + cipher, ctx->use_armor, + ctx /* FIXME */); +} + + +/* Encrypt plaintext PLAIN within CTX for the recipients RECP and + store the resulting ciphertext in CIPHER. Also sign the ciphertext + with the signers in CTX. */ +gpgme_error_t +gpgme_op_encrypt_sign_start (gpgme_ctx_t ctx, gpgme_key_t recp[], + gpgme_encrypt_flags_t flags, + gpgme_data_t plain, gpgme_data_t cipher) +{ + return encrypt_sign_start (ctx, 0, recp, flags, plain, cipher); +} + + +/* Encrypt plaintext PLAIN within CTX for the recipients RECP and + store the resulting ciphertext in CIPHER. Also sign the ciphertext + with the signers in CTX. */ +gpgme_error_t +gpgme_op_encrypt_sign (gpgme_ctx_t ctx, gpgme_key_t recp[], + gpgme_encrypt_flags_t flags, + gpgme_data_t plain, gpgme_data_t cipher) +{ + gpgme_error_t err = encrypt_sign_start (ctx, 1, recp, flags, plain, cipher); + if (!err) + err = _gpgme_wait_one (ctx); + return err; +} diff --git a/tags/gpgme-1.1.6/gpgme/encrypt.c b/tags/gpgme-1.1.6/gpgme/encrypt.c new file mode 100644 index 0000000..a7a1f4d --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/encrypt.c @@ -0,0 +1,222 @@ +/* encrypt.c - Encrypt function. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif +#include +#include +#include + +#include "gpgme.h" +#include "context.h" +#include "ops.h" + + +typedef struct +{ + struct _gpgme_op_encrypt_result result; + + /* A pointer to the next pointer of the last invalid recipient in + the list. This makes appending new invalid recipients painless + while preserving the order. */ + gpgme_invalid_key_t *lastp; +} *op_data_t; + + +static void +release_op_data (void *hook) +{ + op_data_t opd = (op_data_t) hook; + gpgme_invalid_key_t invalid_recipient = opd->result.invalid_recipients; + + while (invalid_recipient) + { + gpgme_invalid_key_t next = invalid_recipient->next; + if (invalid_recipient->fpr) + free (invalid_recipient->fpr); + invalid_recipient = next; + } +} + + +gpgme_encrypt_result_t +gpgme_op_encrypt_result (gpgme_ctx_t ctx) +{ + void *hook; + op_data_t opd; + gpgme_error_t err; + + err = _gpgme_op_data_lookup (ctx, OPDATA_ENCRYPT, &hook, -1, NULL); + opd = hook; + + if (err || !opd) + return NULL; + + return &opd->result; +} + + +gpgme_error_t +_gpgme_encrypt_status_handler (void *priv, gpgme_status_code_t code, + char *args) +{ + gpgme_ctx_t ctx = (gpgme_ctx_t) priv; + gpgme_error_t err; + void *hook; + op_data_t opd; + + err = _gpgme_op_data_lookup (ctx, OPDATA_ENCRYPT, &hook, -1, NULL); + opd = hook; + if (err) + return err; + + switch (code) + { + case GPGME_STATUS_EOF: + if (opd->result.invalid_recipients) + return gpg_error (GPG_ERR_UNUSABLE_PUBKEY); + break; + + case GPGME_STATUS_INV_RECP: + err = _gpgme_parse_inv_recp (args, opd->lastp); + if (err) + return err; + + opd->lastp = &(*opd->lastp)->next; + break; + + case GPGME_STATUS_NO_RECP: + /* Should not happen, because we require at least one recipient. */ + return gpg_error (GPG_ERR_GENERAL); + + default: + break; + } + return 0; +} + + +static gpgme_error_t +encrypt_sym_status_handler (void *priv, gpgme_status_code_t code, char *args) +{ + gpgme_error_t err; + + err = _gpgme_progress_status_handler (priv, code, args); + if (!err) + err = _gpgme_passphrase_status_handler (priv, code, args); + return err; +} + + +static gpgme_error_t +encrypt_status_handler (void *priv, gpgme_status_code_t code, char *args) +{ + return _gpgme_progress_status_handler (priv, code, args) + || _gpgme_encrypt_status_handler (priv, code, args); +} + + +gpgme_error_t +_gpgme_op_encrypt_init_result (gpgme_ctx_t ctx) +{ + gpgme_error_t err; + void *hook; + op_data_t opd; + + err = _gpgme_op_data_lookup (ctx, OPDATA_ENCRYPT, &hook, sizeof (*opd), + release_op_data); + opd = hook; + if (err) + return err; + + opd->lastp = &opd->result.invalid_recipients; + return 0; +} + + +static gpgme_error_t +encrypt_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[], + gpgme_encrypt_flags_t flags, + gpgme_data_t plain, gpgme_data_t cipher) +{ + gpgme_error_t err; + int symmetric = 0; + + err = _gpgme_op_reset (ctx, synchronous); + if (err) + return err; + + err = _gpgme_op_encrypt_init_result (ctx); + if (err) + return err; + + if (!recp) + symmetric = 1; + + if (!plain) + return gpg_error (GPG_ERR_NO_DATA); + if (!cipher) + return gpg_error (GPG_ERR_INV_VALUE); + if (recp && ! *recp) + return gpg_error (GPG_ERR_INV_VALUE); + + if (symmetric && ctx->passphrase_cb) + { + /* Symmetric encryption requires a passphrase. */ + err = _gpgme_engine_set_command_handler + (ctx->engine, _gpgme_passphrase_command_handler, ctx, NULL); + if (err) + return err; + } + + _gpgme_engine_set_status_handler (ctx->engine, + symmetric + ? encrypt_sym_status_handler + : encrypt_status_handler, + ctx); + + return _gpgme_engine_op_encrypt (ctx->engine, recp, flags, plain, cipher, + ctx->use_armor); +} + + +gpgme_error_t +gpgme_op_encrypt_start (gpgme_ctx_t ctx, gpgme_key_t recp[], + gpgme_encrypt_flags_t flags, + gpgme_data_t plain, gpgme_data_t cipher) +{ + return encrypt_start (ctx, 0, recp, flags, plain, cipher); +} + + +/* Encrypt plaintext PLAIN within CTX for the recipients RECP and + store the resulting ciphertext in CIPHER. */ +gpgme_error_t +gpgme_op_encrypt (gpgme_ctx_t ctx, gpgme_key_t recp[], + gpgme_encrypt_flags_t flags, + gpgme_data_t plain, gpgme_data_t cipher) +{ + gpgme_error_t err = encrypt_start (ctx, 1, recp, flags, plain, cipher); + if (!err) + err = _gpgme_wait_one (ctx); + return err; +} diff --git a/tags/gpgme-1.1.6/gpgme/engine-backend.h b/tags/gpgme-1.1.6/gpgme/engine-backend.h new file mode 100644 index 0000000..2e2ef5e --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/engine-backend.h @@ -0,0 +1,118 @@ +/* engine-backend.h - A crypto backend for the engine interface. + Copyright (C) 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 ENGINE_BACKEND_H +#define ENGINE_BACKEND_H + +#include "engine.h" + +/* FIXME: Correct check? */ +#ifdef GPGSM_PATH +#define ENABLE_GPGSM 1 +#endif + +struct engine_ops +{ + /* Static functions. */ + + /* Return the default file name for the binary of this engine. */ + const char *(*get_file_name) (void); + + /* Returns a malloced string containing the version of the engine + with the given binary file name (or the default if FILE_NAME is + NULL. */ + char *(*get_version) (const char *file_name); + + /* Returns a statically allocated string containing the required + version. */ + const char *(*get_req_version) (void); + + gpgme_error_t (*new) (void **r_engine, + const char *file_name, const char *home_dir); + + /* Member functions. */ + void (*release) (void *engine); + gpgme_error_t (*reset) (void *engine); + void (*set_status_handler) (void *engine, engine_status_handler_t fnc, + void *fnc_value); + gpgme_error_t (*set_command_handler) (void *engine, + engine_command_handler_t fnc, + void *fnc_value, gpgme_data_t data); + gpgme_error_t (*set_colon_line_handler) (void *engine, + engine_colon_line_handler_t fnc, + void *fnc_value); + gpgme_error_t (*set_locale) (void *engine, int category, const char *value); + gpgme_error_t (*decrypt) (void *engine, gpgme_data_t ciph, + gpgme_data_t plain); + gpgme_error_t (*delete) (void *engine, gpgme_key_t key, int allow_secret); + gpgme_error_t (*edit) (void *engine, int type, gpgme_key_t key, + gpgme_data_t out, gpgme_ctx_t ctx /* FIXME */); + gpgme_error_t (*encrypt) (void *engine, gpgme_key_t recp[], + gpgme_encrypt_flags_t flags, + gpgme_data_t plain, gpgme_data_t ciph, + int use_armor); + gpgme_error_t (*encrypt_sign) (void *engine, gpgme_key_t recp[], + gpgme_encrypt_flags_t flags, + gpgme_data_t plain, gpgme_data_t ciph, + int use_armor, gpgme_ctx_t ctx /* FIXME */); + gpgme_error_t (*export) (void *engine, const char *pattern, + unsigned int reserved, gpgme_data_t keydata, + int use_armor); + gpgme_error_t (*export_ext) (void *engine, const char *pattern[], + unsigned int reserved, gpgme_data_t keydata, + int use_armor); + gpgme_error_t (*genkey) (void *engine, gpgme_data_t help_data, int use_armor, + gpgme_data_t pubkey, gpgme_data_t seckey); + gpgme_error_t (*import) (void *engine, gpgme_data_t keydata); + gpgme_error_t (*keylist) (void *engine, const char *pattern, + int secret_only, gpgme_keylist_mode_t mode); + gpgme_error_t (*keylist_ext) (void *engine, const char *pattern[], + int secret_only, int reserved, + gpgme_keylist_mode_t mode); + gpgme_error_t (*sign) (void *engine, gpgme_data_t in, gpgme_data_t out, + gpgme_sig_mode_t mode, int use_armor, + int use_textmode, + int include_certs, gpgme_ctx_t ctx /* FIXME */); + gpgme_error_t (*trustlist) (void *engine, const char *pattern); + gpgme_error_t (*verify) (void *engine, gpgme_data_t sig, + gpgme_data_t signed_text, + gpgme_data_t plaintext); + gpgme_error_t (*getauditlog) (void *engine, gpgme_data_t output, + unsigned int flags); + + gpgme_error_t (*conf_load) (void *engine, gpgme_conf_comp_t *conf_p); + gpgme_error_t (*conf_save) (void *engine, gpgme_conf_comp_t conf); + + void (*set_io_cbs) (void *engine, gpgme_io_cbs_t io_cbs); + void (*io_event) (void *engine, gpgme_event_io_t type, void *type_data); + + gpgme_error_t (*cancel) (void *engine); +}; + + +extern struct engine_ops _gpgme_engine_ops_gpg; /* OpenPGP. */ +#ifdef ENABLE_GPGSM +extern struct engine_ops _gpgme_engine_ops_gpgsm; /* CMS. */ +#endif +#ifdef ENABLE_GPGCONF +extern struct engine_ops _gpgme_engine_ops_gpgconf; /* gpg-conf. */ +#endif + +#endif /* ENGINE_BACKEND_H */ diff --git a/tags/gpgme-1.1.6/gpgme/engine-gpgconf.c b/tags/gpgme-1.1.6/gpgme/engine-gpgconf.c new file mode 100644 index 0000000..ee545f8 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/engine-gpgconf.c @@ -0,0 +1,877 @@ +// Check protocol. +// IMPLEMENT NO_ARG_DESC!!!! + +/* engine-gpgconf.c - gpg-conf engine. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include /* FIXME */ +#include + +#include "gpgme.h" +#include "util.h" +#include "ops.h" +#include "wait.h" +#include "priv-io.h" +#include "sema.h" + +#include "assuan.h" +#include "debug.h" + +#include "engine-backend.h" + + +struct engine_gpgconf +{ + char *file_name; + char *home_dir; +}; + +typedef struct engine_gpgconf *engine_gpgconf_t; + + +static char * +gpgconf_get_version (const char *file_name) +{ + return _gpgme_get_program_version (file_name ? file_name + : _gpgme_get_gpgconf_path ()); +} + + +static const char * +gpgconf_get_req_version (void) +{ + return NEED_GPGCONF_VERSION; +} + + +static void +gpgconf_release (void *engine) +{ + engine_gpgconf_t gpgconf = engine; + + if (!gpgconf) + return; + + if (gpgconf->file_name) + free (gpgconf->file_name); + if (gpgconf->home_dir) + free (gpgconf->home_dir); + + free (gpgconf); +} + + +static gpgme_error_t +gpgconf_new (void **engine, const char *file_name, const char *home_dir) +{ + gpgme_error_t err = 0; + engine_gpgconf_t gpgconf; + + gpgconf = calloc (1, sizeof *gpgconf); + if (!gpgconf) + return gpg_error_from_errno (errno); + + gpgconf->file_name = strdup (file_name ? file_name + : _gpgme_get_gpgconf_path ()); + if (!gpgconf->file_name) + err = gpg_error_from_syserror (); + + if (!err && home_dir) + { + gpgconf->home_dir = strdup (home_dir); + if (!gpgconf->home_dir) + err = gpg_error_from_syserror (); + } + + if (err) + gpgconf_release (gpgconf); + else + *engine = gpgconf; + + return err; +} + + +static void +release_arg (gpgme_conf_arg_t arg, gpgme_conf_type_t alt_type) +{ + while (arg) + { + gpgme_conf_arg_t next = arg->next; + + if (alt_type == GPGME_CONF_STRING) + free (arg->value.string); + free (arg); + arg = next; + } +} + + +static void +release_opt (gpgme_conf_opt_t opt) +{ + if (opt->name) + free (opt->name); + if (opt->description) + free (opt->description); + if (opt->argname) + free (opt->argname); + + release_arg (opt->default_value, opt->alt_type); + if (opt->default_description) + free (opt->default_description); + + release_arg (opt->no_arg_value, opt->alt_type); + release_arg (opt->value, opt->alt_type); + release_arg (opt->new_value, opt->alt_type); + + free (opt); +} + + +static void +release_comp (gpgme_conf_comp_t comp) +{ + gpgme_conf_opt_t opt; + + if (comp->name) + free (comp->name); + if (comp->description) + free (comp->description); + if (comp->program_name) + free (comp->program_name); + + opt = comp->options; + while (opt) + { + gpgme_conf_opt_t next = opt->next; + release_opt (opt); + opt = next; + } + + free (comp); +} + + +static void +gpgconf_config_release (gpgme_conf_comp_t conf) +{ + while (conf) + { + gpgme_conf_comp_t next = conf->next; + release_comp (conf); + conf = next; + } +} + + +static gpgme_error_t +gpgconf_read (void *engine, char *arg1, char *arg2, + gpgme_error_t (*cb) (void *hook, char *line), + void *hook) +{ + struct engine_gpgconf *gpgconf = engine; + gpgme_error_t err = 0; +#define LINELENGTH 1024 + char line[LINELENGTH] = ""; + int linelen = 0; + char *argv[] = { NULL /* file_name */, arg1, arg2, 0 }; + int rp[2]; + struct spawn_fd_item_s pfd[] = { {0, -1}, {-1, -1} }; + struct spawn_fd_item_s cfd[] = { {-1, 1 /* STDOUT_FILENO */}, {-1, -1} }; + int status; + int nread; + char *mark = NULL; + + /* FIXME: Deal with engine->home_dir. */ + + /* _gpgme_engine_new guarantees that this is not NULL. */ + argv[0] = gpgconf->file_name; + + if (_gpgme_io_pipe (rp, 1) < 0) + return gpg_error_from_syserror (); + + pfd[0].fd = rp[1]; + cfd[0].fd = rp[1]; + + status = _gpgme_io_spawn (gpgconf->file_name, argv, cfd, pfd); + if (status < 0) + { + _gpgme_io_close (rp[0]); + _gpgme_io_close (rp[1]); + return gpg_error_from_syserror (); + } + + do + { + nread = _gpgme_io_read (rp[0], &line[linelen], LINELENGTH - linelen - 1); + if (nread > 0) + { + line[linelen + nread] = '\0'; + linelen += nread; + + while ((mark = strchr (line, '\n'))) + { + char *eol = mark; + + if (eol > &line[0] && *eol == '\r') + eol--; + *eol = '\0'; + + /* Got a full line. */ + err = (*cb) (hook, line); + if (err) + break; + + linelen -= mark - line; + memmove (line, eol + 1, linelen); + } + } + } + while (nread > 0 && linelen < LINELENGTH - 1); + + if (!err && nread < 0) + err = gpg_error_from_syserror (); + if (!err && nread > 0) + err = gpg_error (GPG_ERR_LINE_TOO_LONG); + + _gpgme_io_close (rp[0]); + + return err; +} + + +static gpgme_error_t +gpgconf_config_load_cb (void *hook, char *line) +{ + gpgme_conf_comp_t *comp_p = hook; + gpgme_conf_comp_t comp = *comp_p; +#define NR_FIELDS 16 + char *field[NR_FIELDS]; + int fields = 0; + + while (line && fields < NR_FIELDS) + { + field[fields++] = line; + line = strchr (line, ':'); + if (line) + *(line++) = '\0'; + } + + /* We require at least the first 3 fields. */ + if (fields < 2) + return gpg_error (GPG_ERR_INV_ENGINE); + + /* Find the pointer to the new component in the list. */ + while (comp && comp->next) + comp = comp->next; + if (comp) + comp_p = &comp->next; + + comp = calloc (1, sizeof (*comp)); + if (!comp) + return gpg_error_from_syserror (); + /* Prepare return value. */ + comp->_last_opt_p = &comp->options; + *comp_p = comp; + + comp->name = strdup (field[0]); + if (!comp->name) + return gpg_error_from_syserror (); + + comp->description = strdup (field[1]); + if (!comp->description) + return gpg_error_from_syserror (); + + if (fields >= 3) + { + comp->description = strdup (field[2]); + if (!comp->description) + return gpg_error_from_syserror (); + } + + return 0; +} + + +static gpgme_error_t +gpgconf_parse_option (gpgme_conf_opt_t opt, + gpgme_conf_arg_t *arg_p, char *line) +{ + gpgme_error_t err; + char *mark; + + if (!line[0]) + return 0; + + mark = strchr (line, ','); + if (mark) + *mark = '\0'; + + while (line) + { + gpgme_conf_arg_t arg = calloc (1, sizeof (*arg)); + if (!arg) + return gpg_error_from_syserror (); + *arg_p = arg; + arg_p = &arg->next; + + if (*line == '\0') + arg->no_arg = 1; + else + { + switch (opt->alt_type) + { + /* arg->value.count is an alias for arg->value.uint32. */ + case GPGME_CONF_NONE: + case GPGME_CONF_UINT32: + arg->value.uint32 = strtoul (line, NULL, 0); + break; + + case GPGME_CONF_INT32: + arg->value.uint32 = strtol (line, NULL, 0); + break; + + case GPGME_CONF_STRING: + case GPGME_CONF_PATHNAME: + case GPGME_CONF_LDAP_SERVER: + /* Skip quote character. */ + line++; + + err = _gpgme_decode_percent_string (line, &arg->value.string, + 0, 0); + if (err) + return err; + break; + } + } + + /* Find beginning of next value. */ + if (mark++ && *mark) + line = mark; + else + line = NULL; + } + + return 0; +} + + +static gpgme_error_t +gpgconf_config_load_cb2 (void *hook, char *line) +{ + gpgme_error_t err; + gpgme_conf_comp_t comp = hook; + gpgme_conf_opt_t *opt_p = comp->_last_opt_p; + gpgme_conf_opt_t opt; +#define NR_FIELDS 16 + char *field[NR_FIELDS]; + int fields = 0; + + while (line && fields < NR_FIELDS) + { + field[fields++] = line; + line = strchr (line, ':'); + if (line) + *(line++) = '\0'; + } + + /* We require at least the first 10 fields. */ + if (fields < 10) + return gpg_error (GPG_ERR_INV_ENGINE); + + opt = calloc (1, sizeof (*opt)); + if (!opt) + return gpg_error_from_syserror (); + + comp->_last_opt_p = &opt->next; + *opt_p = opt; + + if (field[0][0]) + { + opt->name = strdup (field[0]); + if (!opt->name) + return gpg_error_from_syserror (); + } + + opt->flags = strtoul (field[1], NULL, 0); + + opt->level = strtoul (field[2], NULL, 0); + + if (field[3][0]) + { + opt->description = strdup (field[3]); + if (!opt->description) + return gpg_error_from_syserror (); + } + + opt->type = strtoul (field[4], NULL, 0); + + opt->alt_type = strtoul (field[5], NULL, 0); + + if (field[6][0]) + { + opt->argname = strdup (field[6]); + if (!opt->argname) + return gpg_error_from_syserror (); + } + + if (opt->flags & GPGME_CONF_DEFAULT) + { + err = gpgconf_parse_option (opt, &opt->default_value, field[7]); + if (err) + return err; + } + else if ((opt->flags & GPGME_CONF_DEFAULT_DESC) && field[7][0]) + { + opt->default_description = strdup (field[7]); + if (!opt->default_description) + return gpg_error_from_syserror (); + } + + err = gpgconf_parse_option (opt, &opt->no_arg_value, field[8]); + if (err) + return err; + + err = gpgconf_parse_option (opt, &opt->value, field[9]); + if (err) + return err; + + return 0; +} + + +static gpgme_error_t +gpgconf_conf_load (void *engine, gpgme_conf_comp_t *comp_p) +{ + gpgme_error_t err; + gpgme_conf_comp_t comp = NULL; + gpgme_conf_comp_t cur_comp; + + *comp_p = NULL; + + err = gpgconf_read (engine, "--list-components", NULL, + gpgconf_config_load_cb, &comp); + if (err) + { + gpgconf_release (comp); + return err; + } + + cur_comp = comp; + while (!err && cur_comp) + { + err = gpgconf_read (engine, "--list-options", cur_comp->name, + gpgconf_config_load_cb2, cur_comp); + cur_comp = cur_comp->next; + } + + if (err) + { + gpgconf_release (comp); + return err; + } + + *comp_p = comp; + return 0; +} + + + +gpgme_error_t +_gpgme_conf_arg_new (gpgme_conf_arg_t *arg_p, + gpgme_conf_type_t type, void *value) +{ + gpgme_conf_arg_t arg; + + arg = calloc (1, sizeof (*arg)); + if (!arg) + return gpg_error_from_syserror (); + + if (!value) + arg->no_arg = 1; + else + { + switch (type) + { + case GPGME_CONF_NONE: + case GPGME_CONF_UINT32: + arg->value.uint32 = *((unsigned int *) value); + break; + + case GPGME_CONF_INT32: + arg->value.int32 = *((int *) value); + break; + + case GPGME_CONF_STRING: + case GPGME_CONF_PATHNAME: + case GPGME_CONF_LDAP_SERVER: + arg->value.string = strdup (value); + if (!arg->value.string) + { + free (arg); + return gpg_error_from_syserror (); + } + break; + + default: + free (arg); + return gpg_error (GPG_ERR_INV_VALUE); + } + } + + *arg_p = arg; + return 0; +} + + +void +_gpgme_conf_arg_release (gpgme_conf_arg_t arg, gpgme_conf_type_t type) +{ + switch (type) + { + case GPGME_CONF_NONE: + case GPGME_CONF_UINT32: + case GPGME_CONF_INT32: + case GPGME_CONF_STRING: + default: + break; + + case GPGME_CONF_PATHNAME: + case GPGME_CONF_LDAP_SERVER: + type = GPGME_CONF_STRING; + break; + } + + release_arg (arg, type); +} + + +gpgme_error_t +_gpgme_conf_opt_change (gpgme_conf_opt_t opt, int reset, gpgme_conf_arg_t arg) +{ + if (opt->new_value) + release_arg (opt->new_value, opt->alt_type); + + if (reset) + { + opt->new_value = NULL; + opt->change_value = 0; + } + else + { + opt->new_value = arg; + opt->change_value = 1; + } + return 0; +} + + +/* FIXME: Major problem: We don't get errors from gpgconf. */ + +static gpgme_error_t +gpgconf_write (void *engine, char *arg1, char *arg2, gpgme_data_t conf) +{ + struct engine_gpgconf *gpgconf = engine; + gpgme_error_t err = 0; +#define BUFLEN 1024 + char buf[BUFLEN]; + int buflen = 0; + char *argv[] = { NULL /* file_name */, arg1, arg2, 0 }; + int rp[2]; + struct spawn_fd_item_s pfd[] = { {1, -1}, {-1, -1} }; + struct spawn_fd_item_s cfd[] = { {-1, 0 /* STDIN_FILENO */}, {-1, -1} }; + int status; + int nwrite; + + /* FIXME: Deal with engine->home_dir. */ + + /* _gpgme_engine_new guarantees that this is not NULL. */ + argv[0] = gpgconf->file_name; + argv[0] = "/home/marcus/g10/install/bin/gpgconf"; + + if (_gpgme_io_pipe (rp, 0) < 0) + return gpg_error_from_syserror (); + + pfd[0].fd = rp[0]; + cfd[0].fd = rp[0]; + + status = _gpgme_io_spawn (gpgconf->file_name, argv, cfd, pfd); + if (status < 0) + { + _gpgme_io_close (rp[0]); + _gpgme_io_close (rp[1]); + return gpg_error_from_syserror (); + } + + for (;;) + { + if (buflen == 0) + { + do + { + buflen = gpgme_data_read (conf, buf, BUFLEN); + } + while (buflen < 0 && errno == EAGAIN); + + if (buflen < 0) + { + err = gpg_error_from_syserror (); + _gpgme_io_close (rp[1]); + return err; + } + else if (buflen == 0) + { + /* All is written. */ + _gpgme_io_close (rp[1]); + return 0; + } + } + + do + { + nwrite = _gpgme_io_write (rp[1], buf, buflen); + } + while (nwrite < 0 && errno == EAGAIN); + + if (nwrite > 0) + { + buflen -= nwrite; + if (buflen > 0) + memmove (&buf[0], &buf[nwrite], buflen); + } + else if (nwrite < 0) + { + _gpgme_io_close (rp[1]); + return gpg_error_from_syserror (); + } + } + + return 0; +} + + +static gpgme_error_t +arg_to_data (gpgme_data_t conf, gpgme_conf_opt_t option, gpgme_conf_arg_t arg) +{ + gpgme_error_t err = 0; + int amt = 0; + char buf[16]; + + while (amt >= 0 && arg) + { + switch (option->alt_type) + { + case GPGME_CONF_NONE: + case GPGME_CONF_UINT32: + default: + snprintf (buf, sizeof (buf), "%u", arg->value.uint32); + buf[sizeof (buf) - 1] = '\0'; + amt = gpgme_data_write (conf, buf, strlen (buf)); + break; + + case GPGME_CONF_INT32: + snprintf (buf, sizeof (buf), "%i", arg->value.uint32); + buf[sizeof (buf) - 1] = '\0'; + amt = gpgme_data_write (conf, buf, strlen (buf)); + break; + + case GPGME_CONF_STRING: + case GPGME_CONF_PATHNAME: + case GPGME_CONF_LDAP_SERVER: + /* One quote character, and three times to allow + for percent escaping. */ + { + char *ptr = arg->value.string; + amt = gpgme_data_write (conf, "\"", 1); + if (amt < 0) + break; + + while (!err && *ptr) + { + switch (*ptr) + { + case '%': + amt = gpgme_data_write (conf, "%25", 3); + break; + + case ':': + amt = gpgme_data_write (conf, "%3a", 3); + break; + + case ',': + amt = gpgme_data_write (conf, "%2c", 3); + break; + + default: + amt = gpgme_data_write (conf, ptr, 1); + } + ptr++; + } + } + break; + } + + if (amt < 0) + break; + + arg = arg->next; + /* Comma separator. */ + if (arg) + amt = gpgme_data_write (conf, ",", 1); + } + + if (amt < 0) + return gpg_error_from_syserror (); + + return 0; +} + + +static gpgme_error_t +gpgconf_conf_save (void *engine, gpgme_conf_comp_t comp) +{ + gpgme_error_t err; + int amt = 0; + /* We use a data object to store the new configuration. */ + gpgme_data_t conf; + gpgme_conf_opt_t option; + int something_changed = 0; + + err = gpgme_data_new (&conf); + if (err) + return err; + + option = comp->options; + while (!err && amt >= 0 && option) + { + if (option->change_value) + { + unsigned int flags = 0; + char buf[16]; + + something_changed = 1; + + amt = gpgme_data_write (conf, option->name, strlen (option->name)); + if (amt >= 0) + amt = gpgme_data_write (conf, ":", 1); + if (amt < 0) + break; + + if (!option->new_value) + flags |= GPGME_CONF_DEFAULT; + snprintf (buf, sizeof (buf), "%u", flags); + buf[sizeof (buf) - 1] = '\0'; + + amt = gpgme_data_write (conf, buf, strlen (buf)); + if (amt >= 0) + amt = gpgme_data_write (conf, ":", 1); + if (amt < 0) + break; + + if (option->new_value) + { + err = arg_to_data (conf, option, option->new_value); + if (err) + break; + } + amt = gpgme_data_write (conf, "\n", 1); + } + option = option->next; + } + if (!err && amt < 0) + err = gpg_error_from_syserror (); + if (err || !something_changed) + goto bail; + + err = gpgme_data_seek (conf, 0, SEEK_SET); + if (err) + goto bail; + + err = gpgconf_write (engine, "--change-options", comp->name, conf); + bail: + gpgme_data_release (conf); + return err; +} + + +static void +gpgconf_set_io_cbs (void *engine, gpgme_io_cbs_t io_cbs) +{ + /* Nothing to do. */ +} + + +/* Currently, we do not use the engine interface for the various + operations. */ +void +_gpgme_conf_release (gpgme_conf_comp_t conf) +{ + gpgconf_config_release (conf); +} + + +struct engine_ops _gpgme_engine_ops_gpgconf = + { + /* Static functions. */ + _gpgme_get_gpgconf_path, + gpgconf_get_version, + gpgconf_get_req_version, + gpgconf_new, + + /* Member functions. */ + gpgconf_release, + NULL, /* reset */ + NULL, /* set_status_handler */ + NULL, /* set_command_handler */ + NULL, /* set_colon_line_handler */ + NULL, /* set_locale */ + NULL, /* decrypt */ + NULL, /* delete */ + NULL, /* edit */ + NULL, /* encrypt */ + NULL, /* encrypt_sign */ + NULL, /* export */ + NULL, /* export_ext */ + NULL, /* genkey */ + NULL, /* import */ + NULL, /* keylist */ + NULL, /* keylist_ext */ + NULL, /* sign */ + NULL, /* trustlist */ + NULL, /* verify */ + NULL, /* getauditlog */ + gpgconf_conf_load, + gpgconf_conf_save, + gpgconf_set_io_cbs, + NULL, /* io_event */ + NULL /* cancel */ + }; diff --git a/tags/gpgme-1.1.6/gpgme/engine-gpgsm.c b/tags/gpgme-1.1.6/gpgme/engine-gpgsm.c new file mode 100644 index 0000000..1e9ddd2 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/engine-gpgsm.c @@ -0,0 +1,1893 @@ +/* engine-gpgsm.c - GpgSM engine. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include /* FIXME */ +#include + +#include "gpgme.h" +#include "util.h" +#include "ops.h" +#include "wait.h" +#include "priv-io.h" +#include "sema.h" + +#include "assuan.h" +#include "status-table.h" +#include "debug.h" + +#include "engine-backend.h" + + +typedef struct +{ + int fd; /* FD we talk about. */ + int server_fd;/* Server FD for this connection. */ + int dir; /* Inbound/Outbound, maybe given implicit? */ + void *data; /* Handler-specific data. */ + void *tag; /* ID from the user for gpgme_remove_io_callback. */ + char server_fd_str[15]; /* Same as SERVER_FD but as a string. We + need this because _gpgme_io_fd2str can't + be used on a closed descriptor. */ +} iocb_data_t; + + +struct engine_gpgsm +{ + assuan_context_t assuan_ctx; + + int lc_ctype_set; + int lc_messages_set; + + iocb_data_t status_cb; + + /* Input, output etc are from the servers perspective. */ + iocb_data_t input_cb; + + iocb_data_t output_cb; + + iocb_data_t message_cb; + + struct + { + engine_status_handler_t fnc; + void *fnc_value; + } status; + + struct + { + engine_colon_line_handler_t fnc; + void *fnc_value; + struct + { + char *line; + int linesize; + int linelen; + } attic; + int any; /* any data line seen */ + } colon; + + gpgme_data_t inline_data; /* Used to collect D lines. */ + + struct gpgme_io_cbs io_cbs; +}; + +typedef struct engine_gpgsm *engine_gpgsm_t; + + +static void gpgsm_io_event (void *engine, + gpgme_event_io_t type, void *type_data); + + + +static char * +gpgsm_get_version (const char *file_name) +{ + return _gpgme_get_program_version (file_name ? file_name + : _gpgme_get_gpgsm_path ()); +} + + +static const char * +gpgsm_get_req_version (void) +{ + return NEED_GPGSM_VERSION; +} + + +static void +close_notify_handler (int fd, void *opaque) +{ + engine_gpgsm_t gpgsm = opaque; + + assert (fd != -1); + if (gpgsm->status_cb.fd == fd) + { + if (gpgsm->status_cb.tag) + (*gpgsm->io_cbs.remove) (gpgsm->status_cb.tag); + gpgsm->status_cb.fd = -1; + gpgsm->status_cb.tag = NULL; + } + else if (gpgsm->input_cb.fd == fd) + { + if (gpgsm->input_cb.tag) + (*gpgsm->io_cbs.remove) (gpgsm->input_cb.tag); + gpgsm->input_cb.fd = -1; + gpgsm->input_cb.tag = NULL; + } + else if (gpgsm->output_cb.fd == fd) + { + if (gpgsm->output_cb.tag) + (*gpgsm->io_cbs.remove) (gpgsm->output_cb.tag); + gpgsm->output_cb.fd = -1; + gpgsm->output_cb.tag = NULL; + } + else if (gpgsm->message_cb.fd == fd) + { + if (gpgsm->message_cb.tag) + (*gpgsm->io_cbs.remove) (gpgsm->message_cb.tag); + gpgsm->message_cb.fd = -1; + gpgsm->message_cb.tag = NULL; + } +} + + +static gpgme_error_t +map_assuan_error (gpg_error_t err) +{ + if (!err) + return 0; + + if (err == -1) + return gpg_error (GPG_ERR_INV_ENGINE); + + /* New code will use gpg_error_t values. */ + if (gpg_err_source (err)) + return (gpgme_error_t) err; + + /* Legacy code will use old values. */ + switch (err) + { + case ASSUAN_No_Error: + return gpg_error (GPG_ERR_NO_ERROR); + case ASSUAN_General_Error: + return gpg_error (GPG_ERR_GENERAL); + case ASSUAN_Out_Of_Core: + return gpg_error (GPG_ERR_ENOMEM); + case ASSUAN_Invalid_Value: + return gpg_error (GPG_ERR_INV_VALUE); + case ASSUAN_Timeout: + return gpg_error (GPG_ERR_ETIMEDOUT); + case ASSUAN_Read_Error: + return gpg_error (GPG_ERR_GENERAL); + case ASSUAN_Write_Error: + return gpg_error (GPG_ERR_GENERAL); + + case ASSUAN_Problem_Starting_Server: + case ASSUAN_Not_A_Server: + case ASSUAN_Not_A_Client: + case ASSUAN_Nested_Commands: + case ASSUAN_No_Data_Callback: + case ASSUAN_No_Inquire_Callback: + case ASSUAN_Connect_Failed: + case ASSUAN_Accept_Failed: + case ASSUAN_Invalid_Command: + case ASSUAN_Unknown_Command: + case ASSUAN_Syntax_Error: + case ASSUAN_Parameter_Error: + case ASSUAN_Parameter_Conflict: + case ASSUAN_No_Input: + case ASSUAN_No_Output: + case ASSUAN_No_Data_Available: + case ASSUAN_Too_Much_Data: + case ASSUAN_Inquire_Unknown: + case ASSUAN_Inquire_Error: + case ASSUAN_Invalid_Option: + case ASSUAN_Unexpected_Status: + case ASSUAN_Unexpected_Data: + case ASSUAN_Invalid_Status: + return gpg_error (GPG_ERR_ASSUAN); + + case ASSUAN_Invalid_Response: + return gpg_error (GPG_ERR_INV_RESPONSE); + + case ASSUAN_Not_Implemented: + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + case ASSUAN_Line_Too_Long: + return gpg_error (GPG_ERR_LINE_TOO_LONG); + case ASSUAN_Line_Not_Terminated: + return gpg_error (GPG_ERR_INCOMPLETE_LINE); + case ASSUAN_Canceled: + return gpg_error (GPG_ERR_CANCELED); + + case ASSUAN_Unsupported_Algorithm: + return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); + case ASSUAN_Server_Resource_Problem: + return gpg_error (GPG_ERR_RESOURCE_LIMIT); + case ASSUAN_Server_IO_Error: + return gpg_error (GPG_ERR_GENERAL); + case ASSUAN_Server_Bug: + return gpg_error (GPG_ERR_BUG); + case ASSUAN_Invalid_Data: + return gpg_error (GPG_ERR_INV_DATA); + case ASSUAN_Invalid_Index: + return gpg_error (GPG_ERR_INV_INDEX); + case ASSUAN_Not_Confirmed: + return gpg_error (GPG_ERR_NOT_CONFIRMED); + case ASSUAN_Bad_Certificate: + return gpg_error (GPG_ERR_BAD_CERT); + case ASSUAN_Bad_Certificate_Chain: + return gpg_error (GPG_ERR_BAD_CERT_CHAIN); + case ASSUAN_Missing_Certificate: + return gpg_error (GPG_ERR_MISSING_CERT); + case ASSUAN_Bad_Signature: + return gpg_error (GPG_ERR_BAD_SIGNATURE); + case ASSUAN_No_Agent: + return gpg_error (GPG_ERR_NO_AGENT); + case ASSUAN_Agent_Error: + return gpg_error (GPG_ERR_AGENT); + case ASSUAN_No_Public_Key: + return gpg_error (GPG_ERR_NO_PUBKEY); + case ASSUAN_No_Secret_Key: + return gpg_error (GPG_ERR_NO_SECKEY); + case ASSUAN_Invalid_Name: + return gpg_error (GPG_ERR_INV_NAME); + + case ASSUAN_Cert_Revoked: + return gpg_error (GPG_ERR_CERT_REVOKED); + case ASSUAN_No_CRL_For_Cert: + return gpg_error (GPG_ERR_NO_CRL_KNOWN); + case ASSUAN_CRL_Too_Old: + return gpg_error (GPG_ERR_CRL_TOO_OLD); + case ASSUAN_Not_Trusted: + return gpg_error (GPG_ERR_NOT_TRUSTED); + + case ASSUAN_Card_Error: + return gpg_error (GPG_ERR_CARD); + case ASSUAN_Invalid_Card: + return gpg_error (GPG_ERR_INV_CARD); + case ASSUAN_No_PKCS15_App: + return gpg_error (GPG_ERR_NO_PKCS15_APP); + case ASSUAN_Card_Not_Present: + return gpg_error (GPG_ERR_CARD_NOT_PRESENT); + case ASSUAN_Invalid_Id: + return gpg_error (GPG_ERR_INV_ID); + default: + return gpg_error (GPG_ERR_GENERAL); + } +} + + +static gpgme_error_t +gpgsm_cancel (void *engine) +{ + engine_gpgsm_t gpgsm = engine; + + if (!gpgsm) + return gpg_error (GPG_ERR_INV_VALUE); + + if (gpgsm->status_cb.fd != -1) + _gpgme_io_close (gpgsm->status_cb.fd); + if (gpgsm->input_cb.fd != -1) + _gpgme_io_close (gpgsm->input_cb.fd); + if (gpgsm->output_cb.fd != -1) + _gpgme_io_close (gpgsm->output_cb.fd); + if (gpgsm->message_cb.fd != -1) + _gpgme_io_close (gpgsm->message_cb.fd); + + if (gpgsm->assuan_ctx) + { + assuan_disconnect (gpgsm->assuan_ctx); + gpgsm->assuan_ctx = NULL; + } + + return 0; +} + + +static void +gpgsm_release (void *engine) +{ + engine_gpgsm_t gpgsm = engine; + + if (!gpgsm) + return; + + gpgsm_cancel (engine); + + free (gpgsm->colon.attic.line); + free (gpgsm); +} + + +static gpgme_error_t +gpgsm_new (void **engine, const char *file_name, const char *home_dir) +{ + gpgme_error_t err = 0; + engine_gpgsm_t gpgsm; + const char *argv[5]; + int argc; +#if !USE_DESCRIPTOR_PASSING + int fds[2]; + int child_fds[4]; +#endif + char *dft_display = NULL; + char dft_ttyname[64]; + char *dft_ttytype = NULL; + char *optstr; + + gpgsm = calloc (1, sizeof *gpgsm); + if (!gpgsm) + return gpg_error_from_errno (errno); + + gpgsm->status_cb.fd = -1; + gpgsm->status_cb.dir = 1; + gpgsm->status_cb.tag = 0; + gpgsm->status_cb.data = gpgsm; + + gpgsm->input_cb.fd = -1; + gpgsm->input_cb.dir = 0; + gpgsm->input_cb.tag = 0; + gpgsm->input_cb.server_fd = -1; + *gpgsm->input_cb.server_fd_str = 0; + gpgsm->output_cb.fd = -1; + gpgsm->output_cb.dir = 1; + gpgsm->output_cb.tag = 0; + gpgsm->output_cb.server_fd = -1; + *gpgsm->output_cb.server_fd_str = 0; + gpgsm->message_cb.fd = -1; + gpgsm->message_cb.dir = 0; + gpgsm->message_cb.tag = 0; + gpgsm->message_cb.server_fd = -1; + *gpgsm->message_cb.server_fd_str = 0; + + gpgsm->status.fnc = 0; + gpgsm->colon.fnc = 0; + gpgsm->colon.attic.line = 0; + gpgsm->colon.attic.linesize = 0; + gpgsm->colon.attic.linelen = 0; + gpgsm->colon.any = 0; + + gpgsm->inline_data = NULL; + + gpgsm->io_cbs.add = NULL; + gpgsm->io_cbs.add_priv = NULL; + gpgsm->io_cbs.remove = NULL; + gpgsm->io_cbs.event = NULL; + gpgsm->io_cbs.event_priv = NULL; + +#if !USE_DESCRIPTOR_PASSING + if (_gpgme_io_pipe (fds, 0) < 0) + { + err = gpg_error_from_errno (errno); + goto leave; + } + gpgsm->input_cb.fd = fds[1]; + gpgsm->input_cb.server_fd = fds[0]; + _gpgme_io_fd2str (gpgsm->input_cb.server_fd_str, + sizeof gpgsm->input_cb.server_fd_str, + gpgsm->input_cb.server_fd); + + if (_gpgme_io_pipe (fds, 1) < 0) + { + err = gpg_error_from_errno (errno); + goto leave; + } + gpgsm->output_cb.fd = fds[0]; + gpgsm->output_cb.server_fd = fds[1]; + _gpgme_io_fd2str (gpgsm->output_cb.server_fd_str, + sizeof gpgsm->output_cb.server_fd_str, + gpgsm->output_cb.server_fd); + + if (_gpgme_io_pipe (fds, 0) < 0) + { + err = gpg_error_from_errno (errno); + goto leave; + } + gpgsm->message_cb.fd = fds[1]; + gpgsm->message_cb.server_fd = fds[0]; + _gpgme_io_fd2str (gpgsm->message_cb.server_fd_str, + sizeof gpgsm->message_cb.server_fd_str, + gpgsm->message_cb.server_fd); + + child_fds[0] = gpgsm->input_cb.server_fd; + child_fds[1] = gpgsm->output_cb.server_fd; + child_fds[2] = gpgsm->message_cb.server_fd; + child_fds[3] = -1; +#endif + + argc = 0; + argv[argc++] = "gpgsm"; + if (home_dir) + { + argv[argc++] = "--homedir"; + argv[argc++] = home_dir; + } + argv[argc++] = "--server"; + argv[argc++] = NULL; + +#if USE_DESCRIPTOR_PASSING + err = assuan_pipe_connect_ext + (&gpgsm->assuan_ctx, file_name ? file_name : _gpgme_get_gpgsm_path (), + argv, NULL, NULL, NULL, 1); +#else + err = assuan_pipe_connect + (&gpgsm->assuan_ctx, file_name ? file_name : _gpgme_get_gpgsm_path (), + argv, child_fds); +#endif + if (err) + goto leave; + + err = _gpgme_getenv ("DISPLAY", &dft_display); + if (err) + goto leave; + if (dft_display) + { + if (asprintf (&optstr, "OPTION display=%s", dft_display) < 0) + { + free (dft_display); + err = gpg_error_from_errno (errno); + goto leave; + } + free (dft_display); + + err = assuan_transact (gpgsm->assuan_ctx, optstr, NULL, NULL, NULL, + NULL, NULL, NULL); + free (optstr); + if (err) + { + err = map_assuan_error (err); + goto leave; + } + } + + if (isatty (1)) + { + int rc; + + rc = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname)); + if (rc) + { + err = gpg_error_from_errno (rc); + goto leave; + } + else + { + if (asprintf (&optstr, "OPTION ttyname=%s", dft_ttyname) < 0) + { + err = gpg_error_from_errno (errno); + goto leave; + } + err = assuan_transact (gpgsm->assuan_ctx, optstr, NULL, NULL, NULL, + NULL, NULL, NULL); + free (optstr); + if (err) + { + err = map_assuan_error (err); + goto leave; + } + + err = _gpgme_getenv ("TERM", &dft_ttytype); + if (err) + goto leave; + if (dft_ttytype) + { + if (asprintf (&optstr, "OPTION ttytype=%s", dft_ttytype) < 0) + { + free (dft_ttytype); + err = gpg_error_from_errno (errno); + goto leave; + } + free (dft_ttytype); + + err = assuan_transact (gpgsm->assuan_ctx, optstr, NULL, NULL, + NULL, NULL, NULL, NULL); + free (optstr); + if (err) + { + err = map_assuan_error (err); + goto leave; + } + } + } + } + + /* Ask gpgsm to enable the audit log support. */ + if (!err) + { + err = assuan_transact (gpgsm->assuan_ctx, "OPTION enable-audit-log=1", + NULL, NULL, NULL, NULL, NULL, NULL); + if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION) + err = 0; /* This is an optional feature of gpgsm. */ + } + +#if !USE_DESCRIPTOR_PASSING + if (!err + && (_gpgme_io_set_close_notify (gpgsm->input_cb.fd, + close_notify_handler, gpgsm) + || _gpgme_io_set_close_notify (gpgsm->output_cb.fd, + close_notify_handler, gpgsm) + || _gpgme_io_set_close_notify (gpgsm->message_cb.fd, + close_notify_handler, gpgsm))) + { + err = gpg_error (GPG_ERR_GENERAL); + goto leave; + } +#endif + + leave: + /* Close the server ends of the pipes (because of this, we must use + the stored server_fd_str in the function start). Our ends are + closed in gpgsm_release(). */ +#if !USE_DESCRIPTOR_PASSING + if (gpgsm->input_cb.server_fd != -1) + _gpgme_io_close (gpgsm->input_cb.server_fd); + if (gpgsm->output_cb.server_fd != -1) + _gpgme_io_close (gpgsm->output_cb.server_fd); + if (gpgsm->message_cb.server_fd != -1) + _gpgme_io_close (gpgsm->message_cb.server_fd); +#endif + + if (err) + gpgsm_release (gpgsm); + else + *engine = gpgsm; + + return err; +} + + +static gpgme_error_t +gpgsm_set_locale (void *engine, int category, const char *value) +{ + engine_gpgsm_t gpgsm = engine; + gpgme_error_t err; + char *optstr; + char *catstr; + + /* FIXME: If value is NULL, we need to reset the option to default. + But we can't do this. So we error out here. GPGSM needs support + for this. */ + if (category == LC_CTYPE) + { + catstr = "lc-ctype"; + if (!value && gpgsm->lc_ctype_set) + return gpg_error (GPG_ERR_INV_VALUE); + if (value) + gpgsm->lc_ctype_set = 1; + } +#ifdef LC_MESSAGES + else if (category == LC_MESSAGES) + { + catstr = "lc-messages"; + if (!value && gpgsm->lc_messages_set) + return gpg_error (GPG_ERR_INV_VALUE); + if (value) + gpgsm->lc_messages_set = 1; + } +#endif /* LC_MESSAGES */ + else + return gpg_error (GPG_ERR_INV_VALUE); + + if (asprintf (&optstr, "OPTION %s=%s", catstr, value) < 0) + err = gpg_error_from_errno (errno); + else + { + err = assuan_transact (gpgsm->assuan_ctx, optstr, NULL, NULL, + NULL, NULL, NULL, NULL); + free (optstr); + if (err) + err = map_assuan_error (err); + } + return err; +} + + +/* Forward declaration. */ +static gpgme_status_code_t parse_status (const char *name); + +static gpgme_error_t +gpgsm_assuan_simple_command (assuan_context_t ctx, char *cmd, + engine_status_handler_t status_fnc, + void *status_fnc_value) +{ + gpg_error_t err; + char *line; + size_t linelen; + + err = assuan_write_line (ctx, cmd); + if (err) + return map_assuan_error (err); + + do + { + err = assuan_read_line (ctx, &line, &linelen); + if (err) + return map_assuan_error (err); + + if (*line == '#' || !linelen) + continue; + + if (linelen >= 2 + && line[0] == 'O' && line[1] == 'K' + && (line[2] == '\0' || line[2] == ' ')) + return 0; + else if (linelen >= 4 + && line[0] == 'E' && line[1] == 'R' && line[2] == 'R' + && line[3] == ' ') + err = map_assuan_error (atoi (&line[4])); + else if (linelen >= 2 + && line[0] == 'S' && line[1] == ' ') + { + char *rest; + gpgme_status_code_t r; + + rest = strchr (line + 2, ' '); + if (!rest) + rest = line + linelen; /* set to an empty string */ + else + *(rest++) = 0; + + r = parse_status (line + 2); + + if (r >= 0 && status_fnc) + err = status_fnc (status_fnc_value, r, rest); + else + err = gpg_error (GPG_ERR_GENERAL); + } + else + err = gpg_error (GPG_ERR_GENERAL); + } + while (!err); + + return err; +} + + +typedef enum { INPUT_FD, OUTPUT_FD, MESSAGE_FD } fd_type_t; + +static void +gpgsm_clear_fd (engine_gpgsm_t gpgsm, fd_type_t fd_type) +{ +#if !USE_DESCRIPTOR_PASSING + switch (fd_type) + { + case INPUT_FD: + _gpgme_io_close (gpgsm->input_cb.fd); + break; + case OUTPUT_FD: + _gpgme_io_close (gpgsm->output_cb.fd); + break; + case MESSAGE_FD: + _gpgme_io_close (gpgsm->message_cb.fd); + break; + } +#endif +} + +#define COMMANDLINELEN 40 +static gpgme_error_t +gpgsm_set_fd (engine_gpgsm_t gpgsm, fd_type_t fd_type, const char *opt) +{ + gpg_error_t err = 0; + char line[COMMANDLINELEN]; + char *which; + iocb_data_t *iocb_data; + int dir; + + switch (fd_type) + { + case INPUT_FD: + which = "INPUT"; + iocb_data = &gpgsm->input_cb; + break; + + case OUTPUT_FD: + which = "OUTPUT"; + iocb_data = &gpgsm->output_cb; + break; + + case MESSAGE_FD: + which = "MESSAGE"; + iocb_data = &gpgsm->message_cb; + break; + + default: + return gpg_error (GPG_ERR_INV_VALUE); + } + + dir = iocb_data->dir; + +#if USE_DESCRIPTOR_PASSING + /* We try to short-cut the communication by giving GPGSM direct + access to the file descriptor, rather than using a pipe. */ + iocb_data->server_fd = _gpgme_data_get_fd (iocb_data->data); + if (iocb_data->server_fd < 0) + { + int fds[2]; + + if (_gpgme_io_pipe (fds, 0) < 0) + return gpg_error_from_errno (errno); + + iocb_data->fd = dir ? fds[0] : fds[1]; + iocb_data->server_fd = dir ? fds[1] : fds[0]; + + if (_gpgme_io_set_close_notify (iocb_data->fd, + close_notify_handler, gpgsm)) + { + err = gpg_error (GPG_ERR_GENERAL); + goto leave_set_fd; + } + } + + err = assuan_sendfd (gpgsm->assuan_ctx, iocb_data->server_fd); + if (err) + goto leave_set_fd; + + _gpgme_io_close (iocb_data->server_fd); + iocb_data->server_fd = -1; + + if (opt) + snprintf (line, COMMANDLINELEN, "%s FD %s", which, opt); + else + snprintf (line, COMMANDLINELEN, "%s FD", which); +#else + if (opt) + snprintf (line, COMMANDLINELEN, "%s FD=%s %s", + which, iocb_data->server_fd_str, opt); + else + snprintf (line, COMMANDLINELEN, "%s FD=%s", + which, iocb_data->server_fd_str); +#endif + + err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx, line, NULL, NULL); + +#if USE_DESCRIPTOR_PASSING + leave_set_fd: + if (err) + { + _gpgme_io_close (iocb_data->fd); + iocb_data->fd = -1; + if (iocb_data->server_fd != -1) + { + _gpgme_io_close (iocb_data->server_fd); + iocb_data->server_fd = -1; + } + } +#endif + + return err; +} + + +static const char * +map_input_enc (gpgme_data_t d) +{ + switch (gpgme_data_get_encoding (d)) + { + case GPGME_DATA_ENCODING_NONE: + break; + case GPGME_DATA_ENCODING_BINARY: + return "--binary"; + case GPGME_DATA_ENCODING_BASE64: + return "--base64"; + case GPGME_DATA_ENCODING_ARMOR: + return "--armor"; + default: + break; + } + return NULL; +} + + +static int +status_cmp (const void *ap, const void *bp) +{ + const struct status_table_s *a = ap; + const struct status_table_s *b = bp; + + return strcmp (a->name, b->name); +} + + +static gpgme_status_code_t +parse_status (const char *name) +{ + struct status_table_s t, *r; + t.name = name; + r = bsearch (&t, status_table, DIM(status_table) - 1, + sizeof t, status_cmp); + return r ? r->code : -1; +} + + +static gpgme_error_t +status_handler (void *opaque, int fd) +{ + gpg_error_t assuan_err; + gpgme_error_t err = 0; + engine_gpgsm_t gpgsm = opaque; + char *line; + size_t linelen; + + do + { + assuan_err = assuan_read_line (gpgsm->assuan_ctx, &line, &linelen); + if (assuan_err) + { + /* Try our best to terminate the connection friendly. */ + /* assuan_write_line (gpgsm->assuan_ctx, "BYE"); */ + err = map_assuan_error (assuan_err); + TRACE3 (DEBUG_CTX, "gpgme:status_handler", gpgsm, + "fd 0x%x: error from assuan (%d) getting status line : %s", + fd, assuan_err, gpg_strerror (err)); + } + else if (linelen >= 3 + && line[0] == 'E' && line[1] == 'R' && line[2] == 'R' + && (line[3] == '\0' || line[3] == ' ')) + { + if (line[3] == ' ') + err = map_assuan_error (atoi (&line[4])); + else + err = gpg_error (GPG_ERR_GENERAL); + TRACE2 (DEBUG_CTX, "gpgme:status_handler", gpgsm, + "fd 0x%x: ERR line - mapped to: %s", + fd, err ? gpg_strerror (err) : "ok"); + /* Try our best to terminate the connection friendly. */ + // assuan_write_line (gpgsm->assuan_ctx, "BYE"); + } + else if (linelen >= 2 + && line[0] == 'O' && line[1] == 'K' + && (line[2] == '\0' || line[2] == ' ')) + { + if (gpgsm->status.fnc) + err = gpgsm->status.fnc (gpgsm->status.fnc_value, + GPGME_STATUS_EOF, ""); + + if (!err && gpgsm->colon.fnc && gpgsm->colon.any ) + { + /* We must tell a colon function about the EOF. We do + this only when we have seen any data lines. Note + that this inlined use of colon data lines will + eventually be changed into using a regular data + channel. */ + gpgsm->colon.any = 0; + err = gpgsm->colon.fnc (gpgsm->colon.fnc_value, NULL); + } + TRACE2 (DEBUG_CTX, "gpgme:status_handler", gpgsm, + "fd 0x%x: OK line - final status: %s", + fd, err ? gpg_strerror (err) : "ok"); + _gpgme_io_close (gpgsm->status_cb.fd); + return err; + } + else if (linelen > 2 + && line[0] == 'D' && line[1] == ' ' + && gpgsm->colon.fnc) + { + /* We are using the colon handler even for plain inline data + - strange name for that function but for historic reasons + we keep it. */ + /* FIXME We can't use this for binary data because we + assume this is a string. For the current usage of colon + output it is correct. */ + char *src = line + 2; + char *end = line + linelen; + char *dst; + char **aline = &gpgsm->colon.attic.line; + int *alinelen = &gpgsm->colon.attic.linelen; + + if (gpgsm->colon.attic.linesize < *alinelen + linelen + 1) + { + char *newline = realloc (*aline, *alinelen + linelen + 1); + if (!newline) + err = gpg_error_from_errno (errno); + else + { + *aline = newline; + gpgsm->colon.attic.linesize += linelen + 1; + } + } + if (!err) + { + dst = *aline + *alinelen; + + while (!err && src < end) + { + if (*src == '%' && src + 2 < end) + { + /* Handle escaped characters. */ + ++src; + *dst = _gpgme_hextobyte (src); + (*alinelen)++; + src += 2; + } + else + { + *dst = *src++; + (*alinelen)++; + } + + if (*dst == '\n') + { + /* Terminate the pending line, pass it to the colon + handler and reset it. */ + + gpgsm->colon.any = 1; + if (*alinelen > 1 && *(dst - 1) == '\r') + dst--; + *dst = '\0'; + + /* FIXME How should we handle the return code? */ + err = gpgsm->colon.fnc (gpgsm->colon.fnc_value, *aline); + if (!err) + { + dst = *aline; + *alinelen = 0; + } + } + else + dst++; + } + } + TRACE2 (DEBUG_CTX, "gpgme:status_handler", gpgsm, + "fd 0x%x: D line; final status: %s", + fd, err? gpg_strerror (err):"ok"); + } + else if (linelen > 2 + && line[0] == 'D' && line[1] == ' ' + && gpgsm->inline_data) + { + char *src = line + 2; + char *end = line + linelen; + char *dst = src; + ssize_t nwritten; + + linelen = 0; + while (src < end) + { + if (*src == '%' && src + 2 < end) + { + /* Handle escaped characters. */ + ++src; + *dst++ = _gpgme_hextobyte (src); + src += 2; + } + else + *dst++ = *src++; + + linelen++; + } + + src = line + 2; + while (linelen > 0) + { + nwritten = gpgme_data_write (gpgsm->inline_data, src, linelen); + if (!nwritten || (nwritten < 0 && errno != EINTR) + || nwritten > linelen) + { + err = gpg_error_from_errno (errno); + break; + } + src += nwritten; + linelen -= nwritten; + } + + TRACE2 (DEBUG_CTX, "gpgme:status_handler", gpgsm, + "fd 0x%x: D inlinedata; final status: %s", + fd, err? gpg_strerror (err):"ok"); + } + else if (linelen > 2 + && line[0] == 'S' && line[1] == ' ') + { + char *rest; + gpgme_status_code_t r; + + rest = strchr (line + 2, ' '); + if (!rest) + rest = line + linelen; /* set to an empty string */ + else + *(rest++) = 0; + + r = parse_status (line + 2); + + if (r >= 0) + { + if (gpgsm->status.fnc) + err = gpgsm->status.fnc (gpgsm->status.fnc_value, r, rest); + } + else + fprintf (stderr, "[UNKNOWN STATUS]%s %s", line + 2, rest); + TRACE3 (DEBUG_CTX, "gpgme:status_handler", gpgsm, + "fd 0x%x: S line (%s) - final status: %s", + fd, line+2, err? gpg_strerror (err):"ok"); + } + } + while (!err && assuan_pending_line (gpgsm->assuan_ctx)); + + return err; +} + + +static gpgme_error_t +add_io_cb (engine_gpgsm_t gpgsm, iocb_data_t *iocbd, gpgme_io_cb_t handler) +{ + gpgme_error_t err; + + TRACE_BEG2 (DEBUG_ENGINE, "engine-gpgsm:add_io_cb", gpgsm, + "fd %d, dir %d", iocbd->fd, iocbd->dir); + err = (*gpgsm->io_cbs.add) (gpgsm->io_cbs.add_priv, + iocbd->fd, iocbd->dir, + handler, iocbd->data, &iocbd->tag); + if (err) + return TRACE_ERR (err); + if (!iocbd->dir) + /* FIXME Kludge around poll() problem. */ + err = _gpgme_io_set_nonblocking (iocbd->fd); + return TRACE_ERR (err); +} + + +static gpgme_error_t +start (engine_gpgsm_t gpgsm, const char *command) +{ + gpgme_error_t err; + int fdlist[5]; + int nfds; + + /* We need to know the fd used by assuan for reads. We do this by + using the assumption that the first returned fd from + assuan_get_active_fds() is always this one. */ + nfds = assuan_get_active_fds (gpgsm->assuan_ctx, 0 /* read fds */, + fdlist, DIM (fdlist)); + if (nfds < 1) + return gpg_error (GPG_ERR_GENERAL); /* FIXME */ + + /* We "duplicate" the file descriptor, so we can close it here (we + can't close fdlist[0], as that is closed by libassuan, and + closing it here might cause libassuan to close some unrelated FD + later). Alternatively, we could special case status_fd and + register/unregister it manually as needed, but this increases + code duplication and is more complicated as we can not use the + close notifications etc. A third alternative would be to let + Assuan know that we closed the FD, but that complicates the + Assuan interface. */ + + gpgsm->status_cb.fd = _gpgme_io_dup (fdlist[0]); + if (gpgsm->status_cb.fd < 0) + return gpg_error_from_syserror (); + + if (_gpgme_io_set_close_notify (gpgsm->status_cb.fd, + close_notify_handler, gpgsm)) + { + _gpgme_io_close (gpgsm->status_cb.fd); + gpgsm->status_cb.fd = -1; + return gpg_error (GPG_ERR_GENERAL); + } + + err = add_io_cb (gpgsm, &gpgsm->status_cb, status_handler); + if (!err && gpgsm->input_cb.fd != -1) + err = add_io_cb (gpgsm, &gpgsm->input_cb, _gpgme_data_outbound_handler); + if (!err && gpgsm->output_cb.fd != -1) + err = add_io_cb (gpgsm, &gpgsm->output_cb, _gpgme_data_inbound_handler); + if (!err && gpgsm->message_cb.fd != -1) + err = add_io_cb (gpgsm, &gpgsm->message_cb, _gpgme_data_outbound_handler); + + if (!err) + err = map_assuan_error (assuan_write_line (gpgsm->assuan_ctx, command)); + + if (!err) + gpgsm_io_event (gpgsm, GPGME_EVENT_START, NULL); + + return err; +} + + +#if USE_DESCRIPTOR_PASSING +static gpgme_error_t +gpgsm_reset (void *engine) +{ + engine_gpgsm_t gpgsm = engine; + + /* We must send a reset because we need to reset the list of + signers. Note that RESET does not reset OPTION commands. */ + return gpgsm_assuan_simple_command (gpgsm->assuan_ctx, "RESET", NULL, NULL); +} +#endif + + +static gpgme_error_t +gpgsm_decrypt (void *engine, gpgme_data_t ciph, gpgme_data_t plain) +{ + engine_gpgsm_t gpgsm = engine; + gpgme_error_t err; + + if (!gpgsm) + return gpg_error (GPG_ERR_INV_VALUE); + + gpgsm->input_cb.data = ciph; + err = gpgsm_set_fd (gpgsm, INPUT_FD, map_input_enc (gpgsm->input_cb.data)); + if (err) + return gpg_error (GPG_ERR_GENERAL); /* FIXME */ + gpgsm->output_cb.data = plain; + err = gpgsm_set_fd (gpgsm, OUTPUT_FD, 0); + if (err) + return gpg_error (GPG_ERR_GENERAL); /* FIXME */ + gpgsm_clear_fd (gpgsm, MESSAGE_FD); + gpgsm->inline_data = NULL; + + err = start (engine, "DECRYPT"); + return err; +} + + +static gpgme_error_t +gpgsm_delete (void *engine, gpgme_key_t key, int allow_secret) +{ + engine_gpgsm_t gpgsm = engine; + gpgme_error_t err; + char *fpr = key->subkeys ? key->subkeys->fpr : NULL; + char *linep = fpr; + char *line; + int length = 8; /* "DELKEYS " */ + + if (!fpr) + return gpg_error (GPG_ERR_INV_VALUE); + + while (*linep) + { + length++; + if (*linep == '%' || *linep == ' ' || *linep == '+') + length += 2; + linep++; + } + length++; + + line = malloc (length); + if (!line) + return gpg_error_from_errno (errno); + + strcpy (line, "DELKEYS "); + linep = &line[8]; + + while (*fpr) + { + switch (*fpr) + { + case '%': + *(linep++) = '%'; + *(linep++) = '2'; + *(linep++) = '5'; + break; + case ' ': + *(linep++) = '%'; + *(linep++) = '2'; + *(linep++) = '0'; + break; + case '+': + *(linep++) = '%'; + *(linep++) = '2'; + *(linep++) = 'B'; + break; + default: + *(linep++) = *fpr; + break; + } + fpr++; + } + *linep = '\0'; + + gpgsm_clear_fd (gpgsm, OUTPUT_FD); + gpgsm_clear_fd (gpgsm, INPUT_FD); + gpgsm_clear_fd (gpgsm, MESSAGE_FD); + gpgsm->inline_data = NULL; + + err = start (gpgsm, line); + free (line); + + return err; +} + + +static gpgme_error_t +set_recipients (engine_gpgsm_t gpgsm, gpgme_key_t recp[]) +{ + gpgme_error_t err = 0; + assuan_context_t ctx = gpgsm->assuan_ctx; + char *line; + int linelen; + int invalid_recipients = 0; + int i = 0; + + linelen = 10 + 40 + 1; /* "RECIPIENT " + guess + '\0'. */ + line = malloc (10 + 40 + 1); + if (!line) + return gpg_error_from_errno (errno); + strcpy (line, "RECIPIENT "); + while (!err && recp[i]) + { + char *fpr; + int newlen; + + if (!recp[i]->subkeys || !recp[i]->subkeys->fpr) + { + invalid_recipients++; + continue; + } + fpr = recp[i]->subkeys->fpr; + + newlen = 11 + strlen (fpr); + if (linelen < newlen) + { + char *newline = realloc (line, newlen); + if (! newline) + { + int saved_errno = errno; + free (line); + return gpg_error_from_errno (saved_errno); + } + line = newline; + linelen = newlen; + } + strcpy (&line[10], fpr); + + err = gpgsm_assuan_simple_command (ctx, line, gpgsm->status.fnc, + gpgsm->status.fnc_value); + /* FIXME: This requires more work. */ + if (gpg_err_code (err) == GPG_ERR_NO_PUBKEY) + invalid_recipients++; + else if (err) + { + free (line); + return err; + } + i++; + } + free (line); + return gpg_error (invalid_recipients + ? GPG_ERR_UNUSABLE_PUBKEY : GPG_ERR_NO_ERROR); +} + + +static gpgme_error_t +gpgsm_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, + gpgme_data_t plain, gpgme_data_t ciph, int use_armor) +{ + engine_gpgsm_t gpgsm = engine; + gpgme_error_t err; + + if (!gpgsm) + return gpg_error (GPG_ERR_INV_VALUE); + if (!recp) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + gpgsm->input_cb.data = plain; + err = gpgsm_set_fd (gpgsm, INPUT_FD, map_input_enc (gpgsm->input_cb.data)); + if (err) + return err; + gpgsm->output_cb.data = ciph; + err = gpgsm_set_fd (gpgsm, OUTPUT_FD, use_armor ? "--armor" : 0); + if (err) + return err; + gpgsm_clear_fd (gpgsm, MESSAGE_FD); + gpgsm->inline_data = NULL; + + err = set_recipients (gpgsm, recp); + + if (!err) + err = start (gpgsm, "ENCRYPT"); + + return err; +} + + +static gpgme_error_t +gpgsm_export (void *engine, const char *pattern, unsigned int reserved, + gpgme_data_t keydata, int use_armor) +{ + engine_gpgsm_t gpgsm = engine; + gpgme_error_t err = 0; + char *cmd; + + if (!gpgsm || reserved) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!pattern) + pattern = ""; + + cmd = malloc (7 + strlen (pattern) + 1); + if (!cmd) + return gpg_error_from_errno (errno); + strcpy (cmd, "EXPORT "); + strcpy (&cmd[7], pattern); + + gpgsm->output_cb.data = keydata; + err = gpgsm_set_fd (gpgsm, OUTPUT_FD, use_armor ? "--armor" : 0); + if (err) + return err; + gpgsm_clear_fd (gpgsm, INPUT_FD); + gpgsm_clear_fd (gpgsm, MESSAGE_FD); + gpgsm->inline_data = NULL; + + err = start (gpgsm, cmd); + free (cmd); + return err; +} + + +static gpgme_error_t +gpgsm_export_ext (void *engine, const char *pattern[], unsigned int reserved, + gpgme_data_t keydata, int use_armor) +{ + engine_gpgsm_t gpgsm = engine; + gpgme_error_t err = 0; + char *line; + /* Length is "EXPORT " + p + '\0'. */ + int length = 7 + 1; + char *linep; + + if (!gpgsm || reserved) + return gpg_error (GPG_ERR_INV_VALUE); + + if (pattern && *pattern) + { + const char **pat = pattern; + + while (*pat) + { + const char *patlet = *pat; + + while (*patlet) + { + length++; + if (*patlet == '%' || *patlet == ' ' || *patlet == '+') + length += 2; + patlet++; + } + pat++; + length++; + } + } + line = malloc (length); + if (!line) + return gpg_error_from_errno (errno); + + strcpy (line, "EXPORT "); + linep = &line[7]; + + if (pattern && *pattern) + { + while (*pattern) + { + const char *patlet = *pattern; + + while (*patlet) + { + switch (*patlet) + { + case '%': + *(linep++) = '%'; + *(linep++) = '2'; + *(linep++) = '5'; + break; + case ' ': + *(linep++) = '%'; + *(linep++) = '2'; + *(linep++) = '0'; + break; + case '+': + *(linep++) = '%'; + *(linep++) = '2'; + *(linep++) = 'B'; + break; + default: + *(linep++) = *patlet; + break; + } + patlet++; + } + pattern++; + if (*pattern) + *linep++ = ' '; + } + } + *linep = '\0'; + + gpgsm->output_cb.data = keydata; + err = gpgsm_set_fd (gpgsm, OUTPUT_FD, use_armor ? "--armor" : 0); + if (err) + return err; + gpgsm_clear_fd (gpgsm, INPUT_FD); + gpgsm_clear_fd (gpgsm, MESSAGE_FD); + gpgsm->inline_data = NULL; + + err = start (gpgsm, line); + free (line); + return err; +} + + +static gpgme_error_t +gpgsm_genkey (void *engine, gpgme_data_t help_data, int use_armor, + gpgme_data_t pubkey, gpgme_data_t seckey) +{ + engine_gpgsm_t gpgsm = engine; + gpgme_error_t err; + + if (!gpgsm || !pubkey || seckey) + return gpg_error (GPG_ERR_INV_VALUE); + + gpgsm->input_cb.data = help_data; + err = gpgsm_set_fd (gpgsm, INPUT_FD, map_input_enc (gpgsm->input_cb.data)); + if (err) + return err; + gpgsm->output_cb.data = pubkey; + err = gpgsm_set_fd (gpgsm, OUTPUT_FD, use_armor ? "--armor" : 0); + if (err) + return err; + gpgsm_clear_fd (gpgsm, MESSAGE_FD); + gpgsm->inline_data = NULL; + + err = start (gpgsm, "GENKEY"); + return err; +} + + +static gpgme_error_t +gpgsm_import (void *engine, gpgme_data_t keydata) +{ + engine_gpgsm_t gpgsm = engine; + gpgme_error_t err; + + if (!gpgsm) + return gpg_error (GPG_ERR_INV_VALUE); + + gpgsm->input_cb.data = keydata; + err = gpgsm_set_fd (gpgsm, INPUT_FD, map_input_enc (gpgsm->input_cb.data)); + if (err) + return err; + gpgsm_clear_fd (gpgsm, OUTPUT_FD); + gpgsm_clear_fd (gpgsm, MESSAGE_FD); + gpgsm->inline_data = NULL; + + err = start (gpgsm, "IMPORT"); + return err; +} + + +static gpgme_error_t +gpgsm_keylist (void *engine, const char *pattern, int secret_only, + gpgme_keylist_mode_t mode) +{ + engine_gpgsm_t gpgsm = engine; + char *line; + gpgme_error_t err; + int list_mode = 0; + + if (mode & GPGME_KEYLIST_MODE_LOCAL) + list_mode |= 1; + if (mode & GPGME_KEYLIST_MODE_EXTERN) + list_mode |= 2; + + if (!pattern) + pattern = ""; + + /* Always send list-mode option because RESET does not reset it. */ + if (asprintf (&line, "OPTION list-mode=%d", (list_mode & 3)) < 0) + return gpg_error_from_errno (errno); + err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx, line, NULL, NULL); + free (line); + if (err) + return err; + + + /* Always send key validation because RESET does not reset it. */ + + /* Use the validation mode if required. We don't check for an error + yet because this is a pretty fresh gpgsm features. */ + gpgsm_assuan_simple_command (gpgsm->assuan_ctx, + (mode & GPGME_KEYLIST_MODE_VALIDATE)? + "OPTION with-validation=1": + "OPTION with-validation=0" , + NULL, NULL); + + + /* Length is "LISTSECRETKEYS " + p + '\0'. */ + line = malloc (15 + strlen (pattern) + 1); + if (!line) + return gpg_error_from_errno (errno); + if (secret_only) + { + strcpy (line, "LISTSECRETKEYS "); + strcpy (&line[15], pattern); + } + else + { + strcpy (line, "LISTKEYS "); + strcpy (&line[9], pattern); + } + + gpgsm_clear_fd (gpgsm, INPUT_FD); + gpgsm_clear_fd (gpgsm, OUTPUT_FD); + gpgsm_clear_fd (gpgsm, MESSAGE_FD); + gpgsm->inline_data = NULL; + + err = start (gpgsm, line); + free (line); + return err; +} + + +static gpgme_error_t +gpgsm_keylist_ext (void *engine, const char *pattern[], int secret_only, + int reserved, gpgme_keylist_mode_t mode) +{ + engine_gpgsm_t gpgsm = engine; + char *line; + gpgme_error_t err; + /* Length is "LISTSECRETKEYS " + p + '\0'. */ + int length = 15 + 1; + char *linep; + int any_pattern = 0; + int list_mode = 0; + + if (reserved) + return gpg_error (GPG_ERR_INV_VALUE); + + if (mode & GPGME_KEYLIST_MODE_LOCAL) + list_mode |= 1; + if (mode & GPGME_KEYLIST_MODE_EXTERN) + list_mode |= 2; + + /* Always send list-mode option because RESET does not reset it. */ + if (asprintf (&line, "OPTION list-mode=%d", (list_mode & 3)) < 0) + return gpg_error_from_errno (errno); + err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx, line, NULL, NULL); + free (line); + if (err) + return err; + + /* Always send key validation because RESET does not reset it. */ + /* Use the validation mode if required. We don't check for an error + yet because this is a pretty fresh gpgsm features. */ + gpgsm_assuan_simple_command (gpgsm->assuan_ctx, + (mode & GPGME_KEYLIST_MODE_VALIDATE)? + "OPTION with-validation=1": + "OPTION with-validation=0" , + NULL, NULL); + + + if (pattern && *pattern) + { + const char **pat = pattern; + + while (*pat) + { + const char *patlet = *pat; + + while (*patlet) + { + length++; + if (*patlet == '%' || *patlet == ' ' || *patlet == '+') + length += 2; + patlet++; + } + pat++; + length++; + } + } + line = malloc (length); + if (!line) + return gpg_error_from_errno (errno); + if (secret_only) + { + strcpy (line, "LISTSECRETKEYS "); + linep = &line[15]; + } + else + { + strcpy (line, "LISTKEYS "); + linep = &line[9]; + } + + if (pattern && *pattern) + { + while (*pattern) + { + const char *patlet = *pattern; + + while (*patlet) + { + switch (*patlet) + { + case '%': + *(linep++) = '%'; + *(linep++) = '2'; + *(linep++) = '5'; + break; + case ' ': + *(linep++) = '%'; + *(linep++) = '2'; + *(linep++) = '0'; + break; + case '+': + *(linep++) = '%'; + *(linep++) = '2'; + *(linep++) = 'B'; + break; + default: + *(linep++) = *patlet; + break; + } + patlet++; + } + any_pattern = 1; + *linep++ = ' '; + pattern++; + } + } + if (any_pattern) + linep--; + *linep = '\0'; + + gpgsm_clear_fd (gpgsm, INPUT_FD); + gpgsm_clear_fd (gpgsm, OUTPUT_FD); + gpgsm_clear_fd (gpgsm, MESSAGE_FD); + gpgsm->inline_data = NULL; + + err = start (gpgsm, line); + free (line); + return err; +} + + +static gpgme_error_t +gpgsm_sign (void *engine, gpgme_data_t in, gpgme_data_t out, + gpgme_sig_mode_t mode, int use_armor, int use_textmode, + int include_certs, gpgme_ctx_t ctx /* FIXME */) +{ + engine_gpgsm_t gpgsm = engine; + gpgme_error_t err; + char *assuan_cmd; + int i; + gpgme_key_t key; + + if (!gpgsm) + return gpg_error (GPG_ERR_INV_VALUE); + + /* FIXME: This does not work as RESET does not reset it so we can't + revert back to default. */ + if (include_certs != GPGME_INCLUDE_CERTS_DEFAULT) + { + /* FIXME: Make sure that if we run multiple operations, that we + can reset any previously set value in case the default is + requested. */ + + if (asprintf (&assuan_cmd, "OPTION include-certs %i", include_certs) < 0) + return gpg_error_from_errno (errno); + err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx, assuan_cmd, + NULL, NULL); + free (assuan_cmd); + if (err) + return err; + } + + for (i = 0; (key = gpgme_signers_enum (ctx, i)); i++) + { + const char *s = key->subkeys ? key->subkeys->fpr : NULL; + if (s && strlen (s) < 80) + { + char buf[100]; + + strcpy (stpcpy (buf, "SIGNER "), s); + err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx, buf, + NULL, NULL); + } + else + err = gpg_error (GPG_ERR_INV_VALUE); + gpgme_key_unref (key); + if (err) + return err; + } + + gpgsm->input_cb.data = in; + err = gpgsm_set_fd (gpgsm, INPUT_FD, map_input_enc (gpgsm->input_cb.data)); + if (err) + return err; + gpgsm->output_cb.data = out; + err = gpgsm_set_fd (gpgsm, OUTPUT_FD, use_armor ? "--armor" : 0); + if (err) + return err; + gpgsm_clear_fd (gpgsm, MESSAGE_FD); + gpgsm->inline_data = NULL; + + err = start (gpgsm, mode == GPGME_SIG_MODE_DETACH + ? "SIGN --detached" : "SIGN"); + return err; +} + + +static gpgme_error_t +gpgsm_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text, + gpgme_data_t plaintext) +{ + engine_gpgsm_t gpgsm = engine; + gpgme_error_t err; + + if (!gpgsm) + return gpg_error (GPG_ERR_INV_VALUE); + + gpgsm->input_cb.data = sig; + err = gpgsm_set_fd (gpgsm, INPUT_FD, map_input_enc (gpgsm->input_cb.data)); + if (err) + return err; + if (plaintext) + { + /* Normal or cleartext signature. */ + gpgsm->output_cb.data = plaintext; + err = gpgsm_set_fd (gpgsm, OUTPUT_FD, 0); + gpgsm_clear_fd (gpgsm, MESSAGE_FD); + } + else + { + /* Detached signature. */ + gpgsm->message_cb.data = signed_text; + err = gpgsm_set_fd (gpgsm, MESSAGE_FD, 0); + gpgsm_clear_fd (gpgsm, OUTPUT_FD); + } + gpgsm->inline_data = NULL; + + if (!err) + err = start (gpgsm, "VERIFY"); + + return err; +} + + +/* Send the GETAUDITLOG command. The result is saved to a gpgme data + object. */ +static gpgme_error_t +gpgsm_getauditlog (void *engine, gpgme_data_t output, unsigned int flags) +{ + engine_gpgsm_t gpgsm = engine; + gpgme_error_t err = 0; + + if (!gpgsm || !output) + return gpg_error (GPG_ERR_INV_VALUE); + +#if USE_DESCRIPTOR_PASSING + gpgsm->output_cb.data = output; + err = gpgsm_set_fd (gpgsm, OUTPUT_FD, 0); + if (err) + return err; + + gpgsm_clear_fd (gpgsm, INPUT_FD); + gpgsm_clear_fd (gpgsm, MESSAGE_FD); + gpgsm->inline_data = NULL; +# define CMD "GETAUDITLOG" +#else + gpgsm_clear_fd (gpgsm, OUTPUT_FD); + gpgsm_clear_fd (gpgsm, INPUT_FD); + gpgsm_clear_fd (gpgsm, MESSAGE_FD); + gpgsm->inline_data = output; +# define CMD "GETAUDITLOG --data" +#endif + + err = start (gpgsm, (flags & GPGME_AUDITLOG_HTML)? CMD " --html" : CMD); + + return err; +} + + + +static void +gpgsm_set_status_handler (void *engine, engine_status_handler_t fnc, + void *fnc_value) +{ + engine_gpgsm_t gpgsm = engine; + + gpgsm->status.fnc = fnc; + gpgsm->status.fnc_value = fnc_value; +} + + +static gpgme_error_t +gpgsm_set_colon_line_handler (void *engine, engine_colon_line_handler_t fnc, + void *fnc_value) +{ + engine_gpgsm_t gpgsm = engine; + + gpgsm->colon.fnc = fnc; + gpgsm->colon.fnc_value = fnc_value; + gpgsm->colon.any = 0; + return 0; +} + + +static void +gpgsm_set_io_cbs (void *engine, gpgme_io_cbs_t io_cbs) +{ + engine_gpgsm_t gpgsm = engine; + gpgsm->io_cbs = *io_cbs; +} + + +static void +gpgsm_io_event (void *engine, gpgme_event_io_t type, void *type_data) +{ + engine_gpgsm_t gpgsm = engine; + + TRACE3 (DEBUG_ENGINE, "gpgme:gpgsm_io_event", gpgsm, + "event %p, type %d, type_data %p", + gpgsm->io_cbs.event, type, type_data); + if (gpgsm->io_cbs.event) + (*gpgsm->io_cbs.event) (gpgsm->io_cbs.event_priv, type, type_data); +} + + +struct engine_ops _gpgme_engine_ops_gpgsm = + { + /* Static functions. */ + _gpgme_get_gpgsm_path, + gpgsm_get_version, + gpgsm_get_req_version, + gpgsm_new, + + /* Member functions. */ + gpgsm_release, +#if USE_DESCRIPTOR_PASSING + gpgsm_reset, +#else + NULL, /* reset */ +#endif + gpgsm_set_status_handler, + NULL, /* set_command_handler */ + gpgsm_set_colon_line_handler, + gpgsm_set_locale, + gpgsm_decrypt, + gpgsm_delete, + NULL, /* edit */ + gpgsm_encrypt, + NULL, /* encrypt_sign */ + gpgsm_export, + gpgsm_export_ext, + gpgsm_genkey, + gpgsm_import, + gpgsm_keylist, + gpgsm_keylist_ext, + gpgsm_sign, + NULL, /* trustlist */ + gpgsm_verify, + gpgsm_getauditlog, + NULL, /* conf_load */ + NULL, /* conf_save */ + gpgsm_set_io_cbs, + gpgsm_io_event, + gpgsm_cancel + }; diff --git a/tags/gpgme-1.1.6/gpgme/engine.c b/tags/gpgme-1.1.6/gpgme/engine.c new file mode 100644 index 0000000..cf3fe9f --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/engine.c @@ -0,0 +1,790 @@ +/* engine.c - GPGME engine support. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004, 2006 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include + +#include "gpgme.h" +#include "util.h" +#include "sema.h" +#include "ops.h" + +#include "engine.h" +#include "engine-backend.h" + + +struct engine +{ + struct engine_ops *ops; + void *engine; +}; + + +static struct engine_ops *engine_ops[] = + { + &_gpgme_engine_ops_gpg, /* OpenPGP. */ +#ifdef ENABLE_GPGSM + &_gpgme_engine_ops_gpgsm, /* CMS. */ +#else + NULL, +#endif +#ifdef ENABLE_GPGCONF + &_gpgme_engine_ops_gpgconf /* gpg-conf. */ +#else + NULL +#endif + }; + + +/* The engine info. */ +static gpgme_engine_info_t engine_info; +DEFINE_STATIC_LOCK (engine_info_lock); + + +/* Get the file name of the engine for PROTOCOL. */ +static const char * +engine_get_file_name (gpgme_protocol_t proto) +{ + if (proto > DIM (engine_ops)) + return NULL; + + if (engine_ops[proto] && engine_ops[proto]->get_file_name) + return (*engine_ops[proto]->get_file_name) (); + else + return NULL; +} + + +/* Get a malloced string containing the version number of the engine + for PROTOCOL. */ +static char * +engine_get_version (gpgme_protocol_t proto, const char *file_name) +{ + if (proto > DIM (engine_ops)) + return NULL; + + if (engine_ops[proto] && engine_ops[proto]->get_version) + return (*engine_ops[proto]->get_version) (file_name); + else + return NULL; +} + + +/* Get the required version number of the engine for PROTOCOL. */ +static const char * +engine_get_req_version (gpgme_protocol_t proto) +{ + if (proto > DIM (engine_ops)) + return NULL; + + if (engine_ops[proto] && engine_ops[proto]->get_req_version) + return (*engine_ops[proto]->get_req_version) (); + else + return NULL; +} + + +/* Verify the version requirement for the engine for PROTOCOL. */ +gpgme_error_t +gpgme_engine_check_version (gpgme_protocol_t proto) +{ + gpgme_error_t err; + gpgme_engine_info_t info; + int result; + + LOCK (engine_info_lock); + info = engine_info; + if (!info) + { + /* Make sure it is initialized. */ + UNLOCK (engine_info_lock); + err = gpgme_get_engine_info (&info); + if (err) + return err; + + LOCK (engine_info_lock); + } + + while (info && info->protocol != proto) + info = info->next; + + if (!info) + result = 0; + else + result = _gpgme_compare_versions (info->version, + info->req_version); + + UNLOCK (engine_info_lock); + return result ? 0 : gpg_error (GPG_ERR_INV_ENGINE); +} + + +/* Release the engine info INFO. */ +void +_gpgme_engine_info_release (gpgme_engine_info_t info) +{ + while (info) + { + gpgme_engine_info_t next_info = info->next; + + assert (info->file_name); + free (info->file_name); + if (info->home_dir) + free (info->home_dir); + if (info->version) + free (info->version); + free (info); + info = next_info; + } +} + + +/* Get the information about the configured and installed engines. A + pointer to the first engine in the statically allocated linked list + is returned in *INFO. If an error occurs, it is returned. The + returned data is valid until the next gpgme_set_engine_info. */ +gpgme_error_t +gpgme_get_engine_info (gpgme_engine_info_t *info) +{ + LOCK (engine_info_lock); + if (!engine_info) + { + gpgme_engine_info_t *lastp = &engine_info; + gpgme_protocol_t proto_list[] = { GPGME_PROTOCOL_OpenPGP, + GPGME_PROTOCOL_CMS, + GPGME_PROTOCOL_GPGCONF }; + unsigned int proto; + + for (proto = 0; proto < DIM (proto_list); proto++) + { + const char *ofile_name = engine_get_file_name (proto_list[proto]); + char *file_name; + + if (!ofile_name) + continue; + + file_name = strdup (ofile_name); + + *lastp = malloc (sizeof (*engine_info)); + if (!*lastp || !file_name) + { + int saved_errno = errno; + + _gpgme_engine_info_release (engine_info); + engine_info = NULL; + + if (file_name) + free (file_name); + + UNLOCK (engine_info_lock); + return gpg_error_from_errno (saved_errno); + } + + (*lastp)->protocol = proto_list[proto]; + (*lastp)->file_name = file_name; + (*lastp)->home_dir = NULL; + (*lastp)->version = engine_get_version (proto_list[proto], NULL); + (*lastp)->req_version = engine_get_req_version (proto_list[proto]); + (*lastp)->next = NULL; + lastp = &(*lastp)->next; + } + } + + *info = engine_info; + UNLOCK (engine_info_lock); + return 0; +} + + +/* Get a deep copy of the engine info and return it in INFO. */ +gpgme_error_t +_gpgme_engine_info_copy (gpgme_engine_info_t *r_info) +{ + gpgme_error_t err = 0; + gpgme_engine_info_t info; + gpgme_engine_info_t new_info; + gpgme_engine_info_t *lastp; + + LOCK (engine_info_lock); + info = engine_info; + if (!info) + { + /* Make sure it is initialized. */ + UNLOCK (engine_info_lock); + err = gpgme_get_engine_info (&info); + if (err) + return err; + + LOCK (engine_info_lock); + } + + new_info = NULL; + lastp = &new_info; + + while (info) + { + char *file_name; + char *home_dir; + char *version; + + assert (info->file_name); + file_name = strdup (info->file_name); + + if (info->home_dir) + { + home_dir = strdup (info->home_dir); + if (!home_dir) + err = gpg_error_from_errno (errno); + } + else + home_dir = NULL; + + if (info->version) + { + version = strdup (info->version); + if (!version) + err = gpg_error_from_errno (errno); + } + else + version = NULL; + + *lastp = malloc (sizeof (*engine_info)); + if (!*lastp || !file_name || err) + { + int saved_errno = errno; + + _gpgme_engine_info_release (new_info); + + if (file_name) + free (file_name); + if (home_dir) + free (home_dir); + if (version) + free (version); + + UNLOCK (engine_info_lock); + return gpg_error_from_errno (saved_errno); + } + + (*lastp)->protocol = info->protocol; + (*lastp)->file_name = file_name; + (*lastp)->home_dir = home_dir; + (*lastp)->version = version; + (*lastp)->req_version = info->req_version; + (*lastp)->next = NULL; + lastp = &(*lastp)->next; + + info = info->next; + } + + *r_info = new_info; + UNLOCK (engine_info_lock); + return 0; +} + + +/* Set the engine info for the info list INFO, protocol PROTO, to the + file name FILE_NAME and the home directory HOME_DIR. */ +gpgme_error_t +_gpgme_set_engine_info (gpgme_engine_info_t info, gpgme_protocol_t proto, + const char *file_name, const char *home_dir) +{ + char *new_file_name; + char *new_home_dir; + + /* FIXME: Use some PROTO_MAX definition. */ + if (proto > DIM (engine_ops)) + return gpg_error (GPG_ERR_INV_VALUE); + + while (info && info->protocol != proto) + info = info->next; + + if (!info) + return gpg_error (GPG_ERR_INV_ENGINE); + + /* Prepare new members. */ + if (file_name) + new_file_name = strdup (file_name); + else + { + const char *ofile_name = engine_get_file_name (proto); + assert (ofile_name); + new_file_name = strdup (ofile_name); + } + if (!new_file_name) + return gpg_error_from_errno (errno); + + if (home_dir) + { + new_home_dir = strdup (home_dir); + if (!new_home_dir) + { + free (new_file_name); + return gpg_error_from_errno (errno); + } + } + else + new_home_dir = NULL; + + /* Remove the old members. */ + assert (info->file_name); + free (info->file_name); + if (info->home_dir) + free (info->home_dir); + if (info->version) + free (info->version); + + /* Install the new members. */ + info->file_name = new_file_name; + info->home_dir = new_home_dir; + info->version = engine_get_version (proto, new_file_name); + + return 0; +} + + +/* Set the default engine info for the protocol PROTO to the file name + FILE_NAME and the home directory HOME_DIR. */ +gpgme_error_t +gpgme_set_engine_info (gpgme_protocol_t proto, + const char *file_name, const char *home_dir) +{ + gpgme_error_t err; + gpgme_engine_info_t info; + + LOCK (engine_info_lock); + info = engine_info; + if (!info) + { + /* Make sure it is initialized. */ + UNLOCK (engine_info_lock); + err = gpgme_get_engine_info (&info); + if (err) + return err; + + LOCK (engine_info_lock); + } + + err = _gpgme_set_engine_info (info, proto, file_name, home_dir); + UNLOCK (engine_info_lock); + return err; +} + + +gpgme_error_t +_gpgme_engine_new (gpgme_engine_info_t info, engine_t *r_engine) +{ + engine_t engine; + + if (!info->file_name || !info->version) + return gpg_error (GPG_ERR_INV_ENGINE); + + engine = calloc (1, sizeof *engine); + if (!engine) + return gpg_error_from_errno (errno); + + engine->ops = engine_ops[info->protocol]; + if (engine->ops->new) + { + gpgme_error_t err; + err = (*engine->ops->new) (&engine->engine, + info->file_name, info->home_dir); + if (err) + { + free (engine); + return err; + } + } + else + engine->engine = NULL; + + *r_engine = engine; + return 0; +} + + +gpgme_error_t +_gpgme_engine_reset (engine_t engine) +{ + if (!engine) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!engine->ops->reset) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + return (*engine->ops->reset) (engine->engine); +} + + +void +_gpgme_engine_release (engine_t engine) +{ + if (!engine) + return; + + if (engine->ops->release) + (*engine->ops->release) (engine->engine); + free (engine); +} + + +void +_gpgme_engine_set_status_handler (engine_t engine, + engine_status_handler_t fnc, void *fnc_value) +{ + if (!engine) + return; + + if (engine->ops->set_status_handler) + (*engine->ops->set_status_handler) (engine->engine, fnc, fnc_value); +} + + +gpgme_error_t +_gpgme_engine_set_command_handler (engine_t engine, + engine_command_handler_t fnc, + void *fnc_value, + gpgme_data_t linked_data) +{ + if (!engine) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!engine->ops->set_command_handler) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + return (*engine->ops->set_command_handler) (engine->engine, + fnc, fnc_value, linked_data); +} + +gpgme_error_t +_gpgme_engine_set_colon_line_handler (engine_t engine, + engine_colon_line_handler_t fnc, + void *fnc_value) +{ + if (!engine) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!engine->ops->set_colon_line_handler) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + return (*engine->ops->set_colon_line_handler) (engine->engine, + fnc, fnc_value); +} + +gpgme_error_t +_gpgme_engine_set_locale (engine_t engine, int category, + const char *value) +{ + if (!engine) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!engine->ops->set_locale) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + return (*engine->ops->set_locale) (engine->engine, category, value); +} + +gpgme_error_t +_gpgme_engine_op_decrypt (engine_t engine, gpgme_data_t ciph, + gpgme_data_t plain) +{ + if (!engine) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!engine->ops->decrypt) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + return (*engine->ops->decrypt) (engine->engine, ciph, plain); +} + +gpgme_error_t +_gpgme_engine_op_delete (engine_t engine, gpgme_key_t key, + int allow_secret) +{ + if (!engine) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!engine->ops->delete) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + return (*engine->ops->delete) (engine->engine, key, allow_secret); +} + + +gpgme_error_t +_gpgme_engine_op_edit (engine_t engine, int type, gpgme_key_t key, + gpgme_data_t out, gpgme_ctx_t ctx /* FIXME */) +{ + if (!engine) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!engine->ops->edit) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + return (*engine->ops->edit) (engine->engine, type, key, out, ctx); +} + + +gpgme_error_t +_gpgme_engine_op_encrypt (engine_t engine, gpgme_key_t recp[], + gpgme_encrypt_flags_t flags, + gpgme_data_t plain, gpgme_data_t ciph, int use_armor) +{ + if (!engine) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!engine->ops->encrypt) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + return (*engine->ops->encrypt) (engine->engine, recp, flags, plain, ciph, + use_armor); +} + + +gpgme_error_t +_gpgme_engine_op_encrypt_sign (engine_t engine, gpgme_key_t recp[], + gpgme_encrypt_flags_t flags, + gpgme_data_t plain, gpgme_data_t ciph, + int use_armor, gpgme_ctx_t ctx /* FIXME */) +{ + if (!engine) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!engine->ops->encrypt_sign) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + return (*engine->ops->encrypt_sign) (engine->engine, recp, flags, + plain, ciph, use_armor, ctx); +} + + +gpgme_error_t +_gpgme_engine_op_export (engine_t engine, const char *pattern, + unsigned int reserved, gpgme_data_t keydata, + int use_armor) +{ + if (!engine) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!engine->ops->export) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + return (*engine->ops->export) (engine->engine, pattern, reserved, + keydata, use_armor); +} + + +gpgme_error_t +_gpgme_engine_op_export_ext (engine_t engine, const char *pattern[], + unsigned int reserved, gpgme_data_t keydata, + int use_armor) +{ + if (!engine) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!engine->ops->export_ext) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + return (*engine->ops->export_ext) (engine->engine, pattern, reserved, + keydata, use_armor); +} + + +gpgme_error_t +_gpgme_engine_op_genkey (engine_t engine, gpgme_data_t help_data, + int use_armor, gpgme_data_t pubkey, + gpgme_data_t seckey) +{ + if (!engine) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!engine->ops->genkey) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + return (*engine->ops->genkey) (engine->engine, help_data, use_armor, + pubkey, seckey); +} + + +gpgme_error_t +_gpgme_engine_op_import (engine_t engine, gpgme_data_t keydata) +{ + if (!engine) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!engine->ops->import) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + return (*engine->ops->import) (engine->engine, keydata); +} + + +gpgme_error_t +_gpgme_engine_op_keylist (engine_t engine, const char *pattern, + int secret_only, gpgme_keylist_mode_t mode) +{ + if (!engine) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!engine->ops->keylist) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + return (*engine->ops->keylist) (engine->engine, pattern, secret_only, mode); +} + + +gpgme_error_t +_gpgme_engine_op_keylist_ext (engine_t engine, const char *pattern[], + int secret_only, int reserved, + gpgme_keylist_mode_t mode) +{ + if (!engine) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!engine->ops->keylist_ext) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + return (*engine->ops->keylist_ext) (engine->engine, pattern, secret_only, + reserved, mode); +} + + +gpgme_error_t +_gpgme_engine_op_sign (engine_t engine, gpgme_data_t in, gpgme_data_t out, + gpgme_sig_mode_t mode, int use_armor, + int use_textmode, int include_certs, + gpgme_ctx_t ctx /* FIXME */) +{ + if (!engine) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!engine->ops->sign) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + return (*engine->ops->sign) (engine->engine, in, out, mode, use_armor, + use_textmode, include_certs, ctx); +} + + +gpgme_error_t +_gpgme_engine_op_trustlist (engine_t engine, const char *pattern) +{ + if (!engine) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!engine->ops->trustlist) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + return (*engine->ops->trustlist) (engine->engine, pattern); +} + + +gpgme_error_t +_gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig, + gpgme_data_t signed_text, gpgme_data_t plaintext) +{ + if (!engine) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!engine->ops->verify) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + return (*engine->ops->verify) (engine->engine, sig, signed_text, plaintext); +} + + +gpgme_error_t +_gpgme_engine_op_getauditlog (engine_t engine, gpgme_data_t output, + unsigned int flags) +{ + if (!engine) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!engine->ops->getauditlog) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + return (*engine->ops->getauditlog) (engine->engine, output, flags); +} + + +gpgme_error_t +_gpgme_engine_op_conf_load (engine_t engine, gpgme_conf_comp_t *conf_p) +{ + if (!engine) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!engine->ops->conf_load) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + return (*engine->ops->conf_load) (engine->engine, conf_p); +} + + +gpgme_error_t +_gpgme_engine_op_conf_save (engine_t engine, gpgme_conf_comp_t conf) +{ + if (!engine) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!engine->ops->conf_save) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + return (*engine->ops->conf_save) (engine->engine, conf); +} + + +void +_gpgme_engine_set_io_cbs (engine_t engine, gpgme_io_cbs_t io_cbs) +{ + if (!engine) + return; + + (*engine->ops->set_io_cbs) (engine->engine, io_cbs); +} + + +void +_gpgme_engine_io_event (engine_t engine, + gpgme_event_io_t type, void *type_data) +{ + if (!engine) + return; + + (*engine->ops->io_event) (engine->engine, type, type_data); +} + + +gpgme_error_t +_gpgme_engine_cancel (engine_t engine) +{ + if (!engine) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!engine->ops->cancel) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + return (*engine->ops->cancel) (engine->engine); +} diff --git a/tags/gpgme-1.1.6/gpgme/engine.h b/tags/gpgme-1.1.6/gpgme/engine.h new file mode 100644 index 0000000..e67399e --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/engine.h @@ -0,0 +1,142 @@ +/* engine.h - GPGME engine interface. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 ENGINE_H +#define ENGINE_H + +#include "gpgme.h" + +struct engine; +typedef struct engine *engine_t; + +typedef gpgme_error_t (*engine_status_handler_t) (void *priv, + gpgme_status_code_t code, + char *args); +typedef gpgme_error_t (*engine_colon_line_handler_t) (void *priv, char *line); +typedef gpgme_error_t (*engine_command_handler_t) (void *priv, + gpgme_status_code_t code, + const char *keyword, + int fd, int *processed); + +/* Get a deep copy of the engine info and return it in INFO. */ +gpgme_error_t _gpgme_engine_info_copy (gpgme_engine_info_t *r_info); + +/* Release the engine info INFO. */ +void _gpgme_engine_info_release (gpgme_engine_info_t info); + +/* Set the engine info for the info list INFO, protocol PROTO, to the + file name FILE_NAME and the home directory HOME_DIR. */ +gpgme_error_t _gpgme_set_engine_info (gpgme_engine_info_t info, + gpgme_protocol_t praoto, + const char *file_name, + const char *home_dir); + + +gpgme_error_t _gpgme_engine_new (gpgme_engine_info_t info, + engine_t *r_engine); +gpgme_error_t _gpgme_engine_reset (engine_t engine); + +gpgme_error_t _gpgme_engine_set_locale (engine_t engine, int category, + const char *value); + +void _gpgme_engine_release (engine_t engine); +void _gpgme_engine_set_status_handler (engine_t engine, + engine_status_handler_t fnc, + void *fnc_value); +gpgme_error_t _gpgme_engine_set_command_handler (engine_t engine, + engine_command_handler_t fnc, + void *fnc_value, + gpgme_data_t data); +gpgme_error_t +_gpgme_engine_set_colon_line_handler (engine_t engine, + engine_colon_line_handler_t fnc, + void *fnc_value); +gpgme_error_t _gpgme_engine_op_decrypt (engine_t engine, + gpgme_data_t ciph, + gpgme_data_t plain); +gpgme_error_t _gpgme_engine_op_delete (engine_t engine, gpgme_key_t key, + int allow_secret); +gpgme_error_t _gpgme_engine_op_edit (engine_t engine, int type, + gpgme_key_t key, gpgme_data_t out, + gpgme_ctx_t ctx /* FIXME */); +gpgme_error_t _gpgme_engine_op_encrypt (engine_t engine, + gpgme_key_t recp[], + gpgme_encrypt_flags_t flags, + gpgme_data_t plain, gpgme_data_t ciph, + int use_armor); +gpgme_error_t _gpgme_engine_op_encrypt_sign (engine_t engine, + gpgme_key_t recp[], + gpgme_encrypt_flags_t flags, + gpgme_data_t plain, + gpgme_data_t ciph, + int use_armor, + gpgme_ctx_t ctx /* FIXME */); +gpgme_error_t _gpgme_engine_op_export (engine_t engine, const char *pattern, + unsigned int reserved, + gpgme_data_t keydata, int use_armor); +gpgme_error_t _gpgme_engine_op_export_ext (engine_t engine, + const char *pattern[], + unsigned int reserved, + gpgme_data_t keydata, + int use_armor); +gpgme_error_t _gpgme_engine_op_genkey (engine_t engine, + gpgme_data_t help_data, + int use_armor, gpgme_data_t pubkey, + gpgme_data_t seckey); +gpgme_error_t _gpgme_engine_op_import (engine_t engine, + gpgme_data_t keydata); +gpgme_error_t _gpgme_engine_op_keylist (engine_t engine, + const char *pattern, + int secret_only, + gpgme_keylist_mode_t mode); +gpgme_error_t _gpgme_engine_op_keylist_ext (engine_t engine, + const char *pattern[], + int secret_only, + int reserved, + gpgme_keylist_mode_t mode); +gpgme_error_t _gpgme_engine_op_sign (engine_t engine, gpgme_data_t in, + gpgme_data_t out, gpgme_sig_mode_t mode, + int use_armor, int use_textmode, + int include_certs, + gpgme_ctx_t ctx /* FIXME */); +gpgme_error_t _gpgme_engine_op_trustlist (engine_t engine, + const char *pattern); +gpgme_error_t _gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig, + gpgme_data_t signed_text, + gpgme_data_t plaintext); + +gpgme_error_t _gpgme_engine_op_getauditlog (engine_t engine, + gpgme_data_t output, + unsigned int flags); + +gpgme_error_t _gpgme_engine_op_conf_load (engine_t engine, + gpgme_conf_comp_t *conf_p); +gpgme_error_t _gpgme_engine_op_conf_save (engine_t engine, + gpgme_conf_comp_t conf); + +void _gpgme_engine_set_io_cbs (engine_t engine, + gpgme_io_cbs_t io_cbs); +void _gpgme_engine_io_event (engine_t engine, + gpgme_event_io_t type, void *type_data); + +gpgme_error_t _gpgme_engine_cancel (engine_t engine); + +#endif /* ENGINE_H */ diff --git a/tags/gpgme-1.1.6/gpgme/error.c b/tags/gpgme-1.1.6/gpgme/error.c new file mode 100644 index 0000000..6f37ef7 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/error.c @@ -0,0 +1,92 @@ +/* error.c - Error handling for GPGME. + Copyright (C) 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif + +#include + +/* Return a pointer to a string containing a description of the error + code in the error value ERR. */ +const char * +gpgme_strerror (gpgme_error_t err) +{ + return gpg_strerror (err); +} + + +/* Return the error string for ERR in the user-supplied buffer BUF of + size BUFLEN. This function is, in contrast to gpg_strerror, + thread-safe if a thread-safe strerror_r() function is provided by + the system. If the function succeeds, 0 is returned and BUF + contains the string describing the error. If the buffer was not + large enough, ERANGE is returned and BUF contains as much of the + beginning of the error string as fits into the buffer. */ +int +gpgme_strerror_r (gpg_error_t err, char *buf, size_t buflen) +{ + return gpg_strerror_r (err, buf, buflen); +} + + +/* Return a pointer to a string containing a description of the error + source in the error value ERR. */ +const char * +gpgme_strsource (gpgme_error_t err) +{ + return gpg_strsource (err); +} + + +/* Retrieve the error code for the system error ERR. This returns + GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped (report + this). */ +gpgme_err_code_t +gpgme_err_code_from_errno (int err) +{ + return gpg_err_code_from_errno (err); +} + + +/* Retrieve the system error for the error code CODE. This returns 0 + if CODE is not a system error code. */ +int +gpgme_err_code_to_errno (gpgme_err_code_t code) +{ + return gpg_err_code_from_errno (code); +} + + +/* Return an error value with the error source SOURCE and the system + error ERR. */ +gpgme_error_t +gpgme_err_make_from_errno (gpg_err_source_t source, int err) +{ + return gpg_err_make_from_errno (source, err); +} + + +/* Return an error value with the system error ERR. */ +gpgme_err_code_t +gpgme_error_from_errno (int err) +{ + return gpgme_error (gpg_err_code_from_errno (err)); +} diff --git a/tags/gpgme-1.1.6/gpgme/export.c b/tags/gpgme-1.1.6/gpgme/export.c new file mode 100644 index 0000000..079a7e0 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/export.c @@ -0,0 +1,117 @@ +/* export.c - Export a key. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif + +#include "gpgme.h" +#include "context.h" +#include "ops.h" + + +static gpgme_error_t +export_status_handler (void *priv, gpgme_status_code_t code, char *args) +{ + return 0; +} + + +static gpgme_error_t +export_start (gpgme_ctx_t ctx, int synchronous, const char *pattern, + unsigned int reserved, gpgme_data_t keydata) +{ + gpgme_error_t err; + + if (!keydata) + return gpg_error (GPG_ERR_INV_VALUE); + + err = _gpgme_op_reset (ctx, synchronous); + if (err) + return err; + + _gpgme_engine_set_status_handler (ctx->engine, export_status_handler, ctx); + + return _gpgme_engine_op_export (ctx->engine, pattern, reserved, keydata, + ctx->use_armor); +} + + +/* Export the keys listed in RECP into KEYDATA. */ +gpgme_error_t +gpgme_op_export_start (gpgme_ctx_t ctx, const char *pattern, + unsigned int reserved, gpgme_data_t keydata) +{ + return export_start (ctx, 0, pattern, reserved, keydata); +} + + +/* Export the keys listed in RECP into KEYDATA. */ +gpgme_error_t +gpgme_op_export (gpgme_ctx_t ctx, const char *pattern, unsigned int reserved, + gpgme_data_t keydata) +{ + gpgme_error_t err = export_start (ctx, 1, pattern, reserved, keydata); + if (!err) + err = _gpgme_wait_one (ctx); + return err; +} + + +static gpgme_error_t +export_ext_start (gpgme_ctx_t ctx, int synchronous, const char *pattern[], + unsigned int reserved, gpgme_data_t keydata) +{ + gpgme_error_t err; + + if (!keydata) + return gpg_error (GPG_ERR_INV_VALUE); + + err = _gpgme_op_reset (ctx, synchronous); + if (err) + return err; + + _gpgme_engine_set_status_handler (ctx->engine, export_status_handler, ctx); + + return _gpgme_engine_op_export_ext (ctx->engine, pattern, reserved, keydata, + ctx->use_armor); +} + + +/* Export the keys listed in RECP into KEYDATA. */ +gpgme_error_t +gpgme_op_export_ext_start (gpgme_ctx_t ctx, const char *pattern[], + unsigned int reserved, gpgme_data_t keydata) +{ + return export_ext_start (ctx, 0, pattern, reserved, keydata); +} + + +/* Export the keys listed in RECP into KEYDATA. */ +gpgme_error_t +gpgme_op_export_ext (gpgme_ctx_t ctx, const char *pattern[], + unsigned int reserved, gpgme_data_t keydata) +{ + gpgme_error_t err = export_ext_start (ctx, 1, pattern, reserved, keydata); + if (!err) + err = _gpgme_wait_one (ctx); + return err; +} diff --git a/tags/gpgme-1.1.6/gpgme/funopen.c b/tags/gpgme-1.1.6/gpgme/funopen.c new file mode 100644 index 0000000..a20dd8a --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/funopen.c @@ -0,0 +1,63 @@ +/* funopen.c - Replacement for funopen. + Copyright (C) 2004 g10 Code GmbH + + This file is part of GPGME + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + + +/* Replacement for the *BSD function: + + FILE *funopen (void *cookie, + int (*readfn)(void *, char *, int), + int (*writefn)(void *, const char *, int), + fpos_t (*seekfn)(void *, fpos_t, int), + int (*closefn)(void *)); + + The functions to provide my either be NULL if not required or + similar to the unistd function with the exception of using the + cookie instead of the fiel descripor. +*/ + + +#ifdef HAVE_FOPENCOOKIE +FILE * +_gpgme_funopen(void *cookie, + cookie_read_function_t *readfn, + cookie_write_function_t *writefn, + cookie_seek_function_t *seekfn, + cookie_close_function_t *closefn) +{ + cookie_io_functions_t io = { NULL }; + + io.read = readfn; + io.write = writefn; + io.seek = seekfn; + io.close = closefn; + + return fopencookie (cookie, + readfn ? ( writefn ? "rw" : "r" ) + : ( writefn ? "w" : ""), io); +} +#else +#error No known way to implement funopen. +#endif diff --git a/tags/gpgme-1.1.6/gpgme/genkey.c b/tags/gpgme-1.1.6/gpgme/genkey.c new file mode 100644 index 0000000..afebb7c --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/genkey.c @@ -0,0 +1,206 @@ +/* genkey.c - Key generation. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif +#include +#include +#include + +#include "gpgme.h" +#include "context.h" +#include "ops.h" + + +typedef struct +{ + struct _gpgme_op_genkey_result result; + + /* The key parameters passed to the crypto engine. */ + gpgme_data_t key_parameter; +} *op_data_t; + + +static void +release_op_data (void *hook) +{ + op_data_t opd = (op_data_t) hook; + + if (opd->result.fpr) + free (opd->result.fpr); + if (opd->key_parameter) + gpgme_data_release (opd->key_parameter); +} + + +gpgme_genkey_result_t +gpgme_op_genkey_result (gpgme_ctx_t ctx) +{ + void *hook; + op_data_t opd; + gpgme_error_t err; + + err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, &hook, -1, NULL); + opd = hook; + if (err || !opd) + return NULL; + + return &opd->result; +} + + +static gpgme_error_t +genkey_status_handler (void *priv, gpgme_status_code_t code, char *args) +{ + gpgme_ctx_t ctx = (gpgme_ctx_t) priv; + gpgme_error_t err; + void *hook; + op_data_t opd; + + /* Pipe the status code through the progress status handler. */ + err = _gpgme_progress_status_handler (ctx, code, args); + if (err) + return err; + + err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, &hook, -1, NULL); + opd = hook; + if (err) + return err; + + switch (code) + { + case GPGME_STATUS_KEY_CREATED: + if (args && *args) + { + if (*args == 'B' || *args == 'P') + opd->result.primary = 1; + if (*args == 'B' || *args == 'S') + opd->result.sub = 1; + if (args[1] == ' ') + { + if (opd->result.fpr) + free (opd->result.fpr); + opd->result.fpr = strdup (&args[2]); + if (!opd->result.fpr) + return gpg_error_from_errno (errno); + } + } + break; + + case GPGME_STATUS_EOF: + /* FIXME: Should return some more useful error value. */ + if (!opd->result.primary && !opd->result.sub) + return gpg_error (GPG_ERR_GENERAL); + break; + + default: + break; + } + return 0; +} + + +static gpgme_error_t +get_key_parameter (const char *parms, gpgme_data_t *key_parameter) +{ + const char *content; + const char *attrib; + const char *endtag; + + /* Extract the key parameter from the XML structure. */ + parms = strstr (parms, "'); + if (!content) + return gpg_error (GPG_ERR_INV_VALUE); + content++; + + attrib = strstr (parms, "format=\"internal\""); + if (!attrib || attrib >= content) + return gpg_error (GPG_ERR_INV_VALUE); + + endtag = strstr (content, ""); + /* FIXME: Check that there are no control statements inside. */ + while (content[0] == '\n' + || (content[0] == '\r' && content[1] == '\n')) + content++; + + return gpgme_data_new_from_mem (key_parameter, content, + endtag - content, 1); +} + + +static gpgme_error_t +genkey_start (gpgme_ctx_t ctx, int synchronous, const char *parms, + gpgme_data_t pubkey, gpgme_data_t seckey) +{ + gpgme_error_t err; + void *hook; + op_data_t opd; + err = _gpgme_op_reset (ctx, synchronous); + if (err) + return err; + + err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, &hook, + sizeof (*opd), release_op_data); + opd = hook; + if (err) + return err; + + err = get_key_parameter (parms, &opd->key_parameter); + if (err) + return err; + + _gpgme_engine_set_status_handler (ctx->engine, genkey_status_handler, ctx); + + return _gpgme_engine_op_genkey (ctx->engine, opd->key_parameter, + ctx->use_armor, pubkey, seckey); +} + + +/* Generate a new keypair and add it to the keyring. PUBKEY and + SECKEY should be null for now. PARMS specifies what keys should be + generated. */ +gpgme_error_t +gpgme_op_genkey_start (gpgme_ctx_t ctx, const char *parms, + gpgme_data_t pubkey, gpgme_data_t seckey) +{ + return genkey_start (ctx, 0, parms, pubkey, seckey); +} + + +/* Generate a new keypair and add it to the keyring. PUBKEY and + SECKEY should be null for now. PARMS specifies what keys should be + generated. */ +gpgme_error_t +gpgme_op_genkey (gpgme_ctx_t ctx, const char *parms, gpgme_data_t pubkey, + gpgme_data_t seckey) +{ + gpgme_error_t err; + + err = genkey_start (ctx, 1, parms, pubkey, seckey); + if (!err) + err = _gpgme_wait_one (ctx); + return err; +} diff --git a/tags/gpgme-1.1.6/gpgme/get-env.c b/tags/gpgme-1.1.6/gpgme/get-env.c new file mode 100644 index 0000000..bea8949 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/get-env.c @@ -0,0 +1,59 @@ +/* get_env.c - A getenv() replacement. + Copyright (C) 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif +#include +#include +#include + +#include "util.h" + + +#if defined(HAVE_THREAD_SAFE_GETENV) || !defined (HAVE_GETENV_R) +/* We prefer using getenv() if it is thread-safe. */ + +/* Retrieve the environment variable NAME and return a copy of it in a + malloc()'ed buffer in *VALUE. If the environment variable is not + set, return NULL in *VALUE. */ +gpgme_error_t +_gpgme_getenv (const char *name, char **value) +{ + char *env_value; + + env_value = getenv (name); + if (!env_value) + *value = NULL; + else + { + *value = strdup (env_value); + if (!*value) + return gpg_error_from_errno (errno); + } + return 0; +} + +#else + +/* FIXME: Implement this when we have the specification for it. */ +#error Use of getenv_r not implemented. + +#endif diff --git a/tags/gpgme-1.1.6/gpgme/getauditlog.c b/tags/gpgme-1.1.6/gpgme/getauditlog.c new file mode 100644 index 0000000..9f02b09 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/getauditlog.c @@ -0,0 +1,81 @@ +/* getauditlog.c - Retrieve the audit log. + Copyright (C) 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, see . + */ + +#if HAVE_CONFIG_H +#include +#endif + +#include "gpgme.h" +#include "context.h" +#include "ops.h" + + +static gpgme_error_t +getauditlog_status_handler (void *priv, gpgme_status_code_t code, char *args) +{ + return 0; +} + + +static gpgme_error_t +getauditlog_start (gpgme_ctx_t ctx, int synchronous, + gpgme_data_t output, unsigned int flags) +{ + gpgme_error_t err; + + if (!output) + return gpg_error (GPG_ERR_INV_VALUE); + + err = _gpgme_op_reset (ctx, ((synchronous&255) | 256) ); + if (err) + return err; + + _gpgme_engine_set_status_handler (ctx->engine, + getauditlog_status_handler, ctx); + + return _gpgme_engine_op_getauditlog (ctx->engine, output, flags); +} + + + +/* Return the auditlog for the current session. This may be called + after a successful or failed operation. If no audit log is + available GPG_ERR_NO_DATA is returned. This is the asynchronous + variant. */ +gpgme_error_t +gpgme_op_getauditlog_start (gpgme_ctx_t ctx, + gpgme_data_t output, unsigned int flags) +{ + return getauditlog_start (ctx, 0, output, flags); +} + + +/* Return the auditlog for the current session. This may be called + after a successful or failed operation. If no audit log is + available GPG_ERR_NO_DATA is returned. This is the synchronous + variant. */ +gpgme_error_t +gpgme_op_getauditlog (gpgme_ctx_t ctx, gpgme_data_t output, unsigned int flags) +{ + gpgme_error_t err = getauditlog_start (ctx, 1, output, flags); + if (!err) + err = _gpgme_wait_one (ctx); + return err; +} + diff --git a/tags/gpgme-1.1.6/gpgme/gpgconf.c b/tags/gpgme-1.1.6/gpgme/gpgconf.c new file mode 100644 index 0000000..9fa2ce9 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/gpgconf.c @@ -0,0 +1,134 @@ +/* gpgconf.c - GnuPG Made Easy. + Copyright (C) 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif + +#include "gpgme.h" + +#include "ops.h" +#include "engine.h" + +#ifdef ENABLE_GPGCONF +/* engine-gpgconf.c. */ +gpgme_error_t _gpgme_conf_arg_new (gpgme_conf_arg_t *arg_p, + gpgme_conf_type_t type, void *value); +void _gpgme_conf_arg_release (gpgme_conf_arg_t arg, gpgme_conf_type_t type); +gpgme_error_t _gpgme_conf_opt_change (gpgme_conf_opt_t opt, int reset, + gpgme_conf_arg_t arg); +void _gpgme_conf_release (gpgme_conf_comp_t conf); +gpgme_error_t _gpgme_conf_load (void *engine, gpgme_conf_comp_t *conf_p); +gpgme_error_t gpgme_op_conf_save (gpgme_ctx_t ctx, gpgme_conf_comp_t comp); + +#endif + + +/* Allocate a new gpgme_conf_arg_t. */ +gpgme_error_t +gpgme_conf_arg_new (gpgme_conf_arg_t *arg_p, + gpgme_conf_type_t type, void *value) +{ +#ifdef ENABLE_GPGCONF + return _gpgme_conf_arg_new (arg_p, type, value); +#else + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); +#endif +} + + +/* This also releases all chained argument structures! */ +void +gpgme_conf_arg_release (gpgme_conf_arg_t arg, gpgme_conf_type_t type) +{ +#ifdef ENABLE_GPGCONF + return _gpgme_conf_arg_release (arg, type); +#endif +} + + +/* Register a change for the value of OPT to ARG. */ +gpgme_error_t +gpgme_conf_opt_change (gpgme_conf_opt_t opt, int reset, gpgme_conf_arg_t arg) +{ +#ifdef ENABLE_GPGCONF + return _gpgme_conf_opt_change (opt, reset, arg); +#else + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); +#endif +} + + + +/* Public function to release a gpgme_conf_comp list. */ +void +gpgme_conf_release (gpgme_conf_comp_t conf) +{ +#ifdef ENABLE_GPGCONF + _gpgme_conf_release (conf); +#endif +} + + +/* Public function to release load a configuration list. No + asynchronous interface for now. */ +gpgme_error_t +gpgme_op_conf_load (gpgme_ctx_t ctx, gpgme_conf_comp_t *conf_p) +{ +#ifdef ENABLE_GPGCONF + gpgme_error_t err; + gpgme_protocol_t proto = ctx->protocol; + + ctx->protocol = GPGME_PROTOCOL_GPGCONF; + err = _gpgme_op_reset (ctx, 1); + if (err) + return err; + + err = _gpgme_engine_op_conf_load (ctx->engine, conf_p); + ctx->protocol = proto; + return err; +#else + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); +#endif +} + + +/* This function does not follow chained components! */ +gpgme_error_t +gpgme_op_conf_save (gpgme_ctx_t ctx, gpgme_conf_comp_t comp) +{ +#ifdef ENABLE_GPGCONF + gpgme_error_t err; + gpgme_protocol_t proto = ctx->protocol; + + ctx->protocol = GPGME_PROTOCOL_GPGCONF; + err = _gpgme_op_reset (ctx, 1); + if (err) + return err; + + err = _gpgme_engine_op_conf_save (ctx->engine, comp); + ctx->protocol = proto; + return err; +#else + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); +#endif +} + + diff --git a/tags/gpgme-1.1.6/gpgme/gpgme-config.in b/tags/gpgme-1.1.6/gpgme/gpgme-config.in new file mode 100644 index 0000000..4a67b3f --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/gpgme-config.in @@ -0,0 +1,162 @@ +#!/bin/sh +# Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc. +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This file is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +includedir=@includedir@ +libdir=@libdir@ + +# Network libraries. +netlibs="@NETLIBS@" + +# Configure libgpg-error. +gpg_error_cflags="@GPG_ERROR_CFLAGS@" +gpg_error_libs="@GPG_ERROR_LIBS@" + +# Configure thread packages. +thread_modules="" + +@HAVE_PTH_TRUE@thread_modules="$thread_modules pth" +libs_pth="@PTH_LDFLAGS@ @PTH_LIBS@" +cflags_pth="@PTH_CFLAGS@" + +@HAVE_PTHREAD_TRUE@thread_modules="$thread_modules pthread" +libs_pthread="-lpthread" +cflags_pthread="" + +# Configure glib. +libs_glib="@GLIB_LIBS@" +cflags_glib="@GLIB_CFLAGS@" +with_glib= + +output="" + +usage() +{ + cat <&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=*) + # For compatibility reasons with old M4 macros, we ignore + # setting of prefix. + ;; + --prefix) + output="$output $prefix" + ;; + --exec-prefix=*) + ;; + --exec-prefix) + output="$output $exec_prefix" + ;; + --glib) + with_glib=yes + ;; + --version) + echo "@VERSION@" + exit 0 + ;; + --api-version) + echo "@GPGME_CONFIG_API_VERSION@" + exit 0 + ;; + --cflags) + if test "x$includedir" != "x/usr/include" -a "x$includedir" != "x/include"; then + output="$output -I$includedir" + fi + case "$thread_module" in + pthread) + output="$output $cflags_pthread" + ;; + pth) + output="$output $cflags_pth" + ;; + esac + output="$output $gpg_error_cflags" + if test "x$with_glib" = "xyes"; then + output="$output $glib_cflags" + fi + ;; + --libs) + if test "x$libdir" != "x/usr/lib" -a "x$libdir" != "x/lib"; then + output="$output -L$libdir" + fi + case "$thread_module" in + pthread) + output="$output -lgpgme-pthread $libs_pthread" + ;; + pth) + output="$output -lgpgme-pth $libs_pth" + ;; + *) + if test "x$with_glib" = "xyes"; then + output="$output -lgpgme-glib" + else + output="$output -lgpgme" + fi + ;; + esac + output="$output $gpg_error_libs $netlibs" + if test "x$with_glib" = "xyes"; then + output="$output $glib_cflags" + fi + ;; + --thread=*) + for thread_mod in $thread_modules; do + if test "$thread_mod" = "$optarg"; then + thread_module="$optarg"; + fi + done + if test "x$thread_module" = "x"; then + usage 1 1>&2 + fi + ;; + --get-gpg) + output="$output @GPG@" + ;; + --get-gpgsm) + output="$output @GPGSM@" + ;; + *) + usage 1 1>&2 + ;; + esac + shift +done + +echo $output diff --git a/tags/gpgme-1.1.6/gpgme/gpgme.c b/tags/gpgme-1.1.6/gpgme/gpgme.c new file mode 100644 index 0000000..a96db53 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/gpgme.c @@ -0,0 +1,667 @@ +/* gpgme.c - GnuPG Made Easy. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "context.h" +#include "ops.h" +#include "wait.h" +#include "debug.h" + + +/* The default locale. */ +DEFINE_STATIC_LOCK (def_lc_lock); +static char *def_lc_ctype; +static char *def_lc_messages; + + +/* Create a new context as an environment for GPGME crypto + operations. */ +gpgme_error_t +gpgme_new (gpgme_ctx_t *r_ctx) +{ + gpgme_ctx_t ctx; + TRACE_BEG (DEBUG_CTX, "gpgme_new", r_ctx); + + ctx = calloc (1, sizeof *ctx); + if (!ctx) + return TRACE_ERR (gpg_error_from_errno (errno)); + + _gpgme_engine_info_copy (&ctx->engine_info); + if (!ctx->engine_info) + { + free (ctx); + return TRACE_ERR (gpg_error_from_errno (errno)); + } + + ctx->keylist_mode = GPGME_KEYLIST_MODE_LOCAL; + ctx->include_certs = GPGME_INCLUDE_CERTS_DEFAULT; + ctx->protocol = GPGME_PROTOCOL_OpenPGP; + _gpgme_fd_table_init (&ctx->fdt); + + LOCK (def_lc_lock); + if (def_lc_ctype) + { + ctx->lc_ctype = strdup (def_lc_ctype); + if (!ctx->lc_ctype) + { + UNLOCK (def_lc_lock); + _gpgme_engine_info_release (ctx->engine_info); + free (ctx); + return TRACE_ERR (gpg_error_from_errno (errno)); + } + } + else + def_lc_ctype = NULL; + + if (def_lc_messages) + { + ctx->lc_messages = strdup (def_lc_messages); + if (!ctx->lc_messages) + { + UNLOCK (def_lc_lock); + if (ctx->lc_ctype) + free (ctx->lc_ctype); + _gpgme_engine_info_release (ctx->engine_info); + free (ctx); + return TRACE_ERR (gpg_error_from_errno (errno)); + } + } + else + def_lc_messages = NULL; + UNLOCK (def_lc_lock); + + *r_ctx = ctx; + + return TRACE_SUC1 ("ctx=%p", ctx); +} + + +/* Cancel a pending asynchronous operation. */ +gpgme_error_t +gpgme_cancel (gpgme_ctx_t ctx) +{ + gpgme_error_t err; + TRACE_BEG (DEBUG_CTX, "gpgme_cancel", ctx); + + err = _gpgme_engine_cancel (ctx->engine); + if (err) + return TRACE_ERR (err); + + err = gpg_error (GPG_ERR_CANCELED); + _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &err); + + return TRACE_ERR (0); +} + +/* Release all resources associated with the given context. */ +void +gpgme_release (gpgme_ctx_t ctx) +{ + TRACE (DEBUG_CTX, "gpgme_release", ctx); + + _gpgme_engine_release (ctx->engine); + _gpgme_fd_table_deinit (&ctx->fdt); + _gpgme_release_result (ctx); + gpgme_signers_clear (ctx); + gpgme_sig_notation_clear (ctx); + if (ctx->signers) + free (ctx->signers); + if (ctx->lc_ctype) + free (ctx->lc_ctype); + if (ctx->lc_messages) + free (ctx->lc_messages); + _gpgme_engine_info_release (ctx->engine_info); + free (ctx); +} + + +void +_gpgme_release_result (gpgme_ctx_t ctx) +{ + struct ctx_op_data *data = ctx->op_data; + + while (data) + { + struct ctx_op_data *next_data = data->next; + if (data->cleanup) + (*data->cleanup) (data->hook); + free (data); + data = next_data; + } + ctx->op_data = NULL; +} + + +gpgme_error_t +gpgme_set_protocol (gpgme_ctx_t ctx, gpgme_protocol_t protocol) +{ + TRACE_BEG2 (DEBUG_CTX, "gpgme_set_protocol", ctx, "protocol=%i (%s)", + protocol, gpgme_get_protocol_name (protocol) + ? gpgme_get_protocol_name (protocol) : "unknown"); + + if (protocol != GPGME_PROTOCOL_OpenPGP && protocol != GPGME_PROTOCOL_CMS) + return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); + + if (ctx->protocol != protocol) + { + /* Shut down the engine when switching protocols. */ + if (ctx->engine) + { + TRACE_LOG1 ("releasing ctx->engine=%p", ctx->engine); + _gpgme_engine_release (ctx->engine); + ctx->engine = NULL; + } + + ctx->protocol = protocol; + } + return TRACE_ERR (0); +} + + +gpgme_protocol_t +gpgme_get_protocol (gpgme_ctx_t ctx) +{ + TRACE2 (DEBUG_CTX, "gpgme_get_protocol", ctx, + "ctx->protocol=%i (%s)", ctx->protocol, + gpgme_get_protocol_name (ctx->protocol) + ? gpgme_get_protocol_name (ctx->protocol) : "unknown"); + return ctx->protocol; +} + + +const char * +gpgme_get_protocol_name (gpgme_protocol_t protocol) +{ + switch (protocol) + { + case GPGME_PROTOCOL_OpenPGP: + return "OpenPGP"; + + case GPGME_PROTOCOL_CMS: + return "CMS"; + + case GPGME_PROTOCOL_UNKNOWN: + return "unknown"; + + default: + return NULL; + } +} + +/* Enable or disable the use of an ascii armor for all output. */ +void +gpgme_set_armor (gpgme_ctx_t ctx, int use_armor) +{ + TRACE2 (DEBUG_CTX, "gpgme_set_armor", ctx, "use_armor=%i (%s)", + use_armor, use_armor ? "yes" : "no"); + ctx->use_armor = use_armor; +} + + +/* Return the state of the armor flag. */ +int +gpgme_get_armor (gpgme_ctx_t ctx) +{ + TRACE2 (DEBUG_CTX, "gpgme_get_armor", ctx, "ctx->use_armor=%i (%s)", + ctx->use_armor, ctx->use_armor ? "yes" : "no"); + return ctx->use_armor; +} + + +/* Enable or disable the use of the special textmode. Textmode is for + example used for the RFC2015 signatures; note that the updated RFC + 3156 mandates that the MUA does some preparations so that textmode + is not needed anymore. */ +void +gpgme_set_textmode (gpgme_ctx_t ctx, int use_textmode) +{ + TRACE2 (DEBUG_CTX, "gpgme_set_textmode", ctx, "use_textmode=%i (%s)", + use_textmode, use_textmode ? "yes" : "no"); + ctx->use_textmode = use_textmode; +} + +/* Return the state of the textmode flag. */ +int +gpgme_get_textmode (gpgme_ctx_t ctx) +{ + TRACE2 (DEBUG_CTX, "gpgme_get_textmode", ctx, "ctx->use_textmode=%i (%s)", + ctx->use_textmode, ctx->use_textmode ? "yes" : "no"); + return ctx->use_textmode; +} + + +/* Set the number of certifications to include in an S/MIME message. + The default is GPGME_INCLUDE_CERTS_DEFAULT. -1 means all certs, + and -2 means all certs except the root cert. */ +void +gpgme_set_include_certs (gpgme_ctx_t ctx, int nr_of_certs) +{ + if (nr_of_certs == GPGME_INCLUDE_CERTS_DEFAULT) + ctx->include_certs = GPGME_INCLUDE_CERTS_DEFAULT; + else if (nr_of_certs < -2) + ctx->include_certs = -2; + else + ctx->include_certs = nr_of_certs; + + TRACE2 (DEBUG_CTX, "gpgme_set_include_certs", ctx, "nr_of_certs=%i%s", + nr_of_certs, nr_of_certs == ctx->include_certs ? "" : " (-2)"); +} + + +/* Get the number of certifications to include in an S/MIME + message. */ +int +gpgme_get_include_certs (gpgme_ctx_t ctx) +{ + TRACE1 (DEBUG_CTX, "gpgme_get_include_certs", ctx, "ctx->include_certs=%i", + ctx->include_certs); + return ctx->include_certs; +} + + +/* This function changes the default behaviour of the keylisting + functions. MODE is a bitwise-OR of the GPGME_KEYLIST_* flags. The + default mode is GPGME_KEYLIST_MODE_LOCAL. */ +gpgme_error_t +gpgme_set_keylist_mode (gpgme_ctx_t ctx, gpgme_keylist_mode_t mode) +{ + TRACE1 (DEBUG_CTX, "gpgme_set_keylist_mode", ctx, "keylist_mode=0x%x", + mode); + + ctx->keylist_mode = mode; + return 0; +} + +/* This function returns the default behaviour of the keylisting + functions. */ +gpgme_keylist_mode_t +gpgme_get_keylist_mode (gpgme_ctx_t ctx) +{ + TRACE1 (DEBUG_CTX, "gpgme_get_keylist_mode", ctx, + "ctx->keylist_mode=0x%x", ctx->keylist_mode); + return ctx->keylist_mode; +} + + +/* This function sets a callback function to be used to pass a + passphrase to gpg. */ +void +gpgme_set_passphrase_cb (gpgme_ctx_t ctx, gpgme_passphrase_cb_t cb, + void *cb_value) +{ + TRACE2 (DEBUG_CTX, "gpgme_set_passphrase_cb", ctx, + "passphrase_cb=%p/%p", cb, cb_value); + ctx->passphrase_cb = cb; + ctx->passphrase_cb_value = cb_value; +} + + +/* This function returns the callback function to be used to pass a + passphrase to the crypto engine. */ +void +gpgme_get_passphrase_cb (gpgme_ctx_t ctx, gpgme_passphrase_cb_t *r_cb, + void **r_cb_value) +{ + TRACE2 (DEBUG_CTX, "gpgme_get_passphrase_cb", ctx, + "ctx->passphrase_cb=%p/%p", + ctx->passphrase_cb, ctx->passphrase_cb_value); + if (r_cb) + *r_cb = ctx->passphrase_cb; + if (r_cb_value) + *r_cb_value = ctx->passphrase_cb_value; +} + + +/* This function sets a callback function to be used as a progress + indicator. */ +void +gpgme_set_progress_cb (gpgme_ctx_t ctx, gpgme_progress_cb_t cb, void *cb_value) +{ + TRACE2 (DEBUG_CTX, "gpgme_set_progress_cb", ctx, "progress_cb=%p/%p", + cb, cb_value); + ctx->progress_cb = cb; + ctx->progress_cb_value = cb_value; +} + + +/* This function returns the callback function to be used as a + progress indicator. */ +void +gpgme_get_progress_cb (gpgme_ctx_t ctx, gpgme_progress_cb_t *r_cb, + void **r_cb_value) +{ + TRACE2 (DEBUG_CTX, "gpgme_get_progress_cb", ctx, "ctx->progress_cb=%p/%p", + ctx->progress_cb, ctx->progress_cb_value); + if (r_cb) + *r_cb = ctx->progress_cb; + if (r_cb_value) + *r_cb_value = ctx->progress_cb_value; +} + + +/* Set the I/O callback functions for CTX to IO_CBS. */ +void +gpgme_set_io_cbs (gpgme_ctx_t ctx, gpgme_io_cbs_t io_cbs) +{ + if (io_cbs) + { + TRACE6 (DEBUG_CTX, "gpgme_set_io_cbs", ctx, + "io_cbs=%p (add=%p/%p, remove=%p, event=%p/%p", + io_cbs, io_cbs->add, io_cbs->add_priv, io_cbs->remove, + io_cbs->event, io_cbs->event_priv); + ctx->io_cbs = *io_cbs; + } + else + { + TRACE1 (DEBUG_CTX, "gpgme_set_io_cbs", ctx, + "io_cbs=%p (default)", io_cbs); + ctx->io_cbs.add = NULL; + ctx->io_cbs.add_priv = NULL; + ctx->io_cbs.remove = NULL; + ctx->io_cbs.event = NULL; + ctx->io_cbs.event_priv = NULL; + } +} + + +/* This function returns the callback function for I/O. */ +void +gpgme_get_io_cbs (gpgme_ctx_t ctx, gpgme_io_cbs_t io_cbs) +{ + TRACE6 (DEBUG_CTX, "gpgme_get_io_cbs", ctx, + "io_cbs=%p, ctx->io_cbs.add=%p/%p, .remove=%p, .event=%p/%p", + io_cbs, io_cbs->add, io_cbs->add_priv, io_cbs->remove, + io_cbs->event, io_cbs->event_priv); + + *io_cbs = ctx->io_cbs; +} + + +/* This function sets the locale for the context CTX, or the default + locale if CTX is a null pointer. */ +gpgme_error_t +gpgme_set_locale (gpgme_ctx_t ctx, int category, const char *value) +{ + int failed = 0; + char *new_lc_ctype = NULL; + char *new_lc_messages = NULL; + + TRACE_BEG2 (DEBUG_CTX, "gpgme_set_locale", ctx, + "category=%i, value=%s", category, value ? value : "(null)"); + +#define PREPARE_ONE_LOCALE(lcat, ucat) \ + if (!failed && value \ + && (category == LC_ALL || category == LC_ ## ucat)) \ + { \ + new_lc_ ## lcat = strdup (value); \ + if (!new_lc_ ## lcat) \ + failed = 1; \ + } + + PREPARE_ONE_LOCALE (ctype, CTYPE); +#ifdef LC_MESSAGES + PREPARE_ONE_LOCALE (messages, MESSAGES); +#endif + + if (failed) + { + int saved_errno = errno; + + if (new_lc_ctype) + free (new_lc_ctype); + if (new_lc_messages) + free (new_lc_messages); + + return TRACE_ERR (gpg_error_from_errno (saved_errno)); + } + +#define SET_ONE_LOCALE(lcat, ucat) \ + if (category == LC_ALL || category == LC_ ## ucat) \ + { \ + if (ctx) \ + { \ + if (ctx->lc_ ## lcat) \ + free (ctx->lc_ ## lcat); \ + ctx->lc_ ## lcat = new_lc_ ## lcat; \ + } \ + else \ + { \ + if (def_lc_ ## lcat) \ + free (def_lc_ ## lcat); \ + def_lc_ ## lcat = new_lc_ ## lcat; \ + } \ + } + + if (!ctx) + LOCK (def_lc_lock); + SET_ONE_LOCALE (ctype, CTYPE); +#ifdef LC_MESSAGES + SET_ONE_LOCALE (messages, MESSAGES); +#endif + if (!ctx) + UNLOCK (def_lc_lock); + + return TRACE_ERR (0); +} + + +/* Get the information about the configured engines. A pointer to the + first engine in the statically allocated linked list is returned. + The returned data is valid until the next gpgme_ctx_set_engine_info. */ +gpgme_engine_info_t +gpgme_ctx_get_engine_info (gpgme_ctx_t ctx) +{ + TRACE1 (DEBUG_CTX, "gpgme_ctx_get_engine_info", ctx, + "ctx->engine_info=%p", ctx->engine_info); + return ctx->engine_info; +} + + +/* Set the engine info for the context CTX, protocol PROTO, to the + file name FILE_NAME and the home directory HOME_DIR. */ +gpgme_error_t +gpgme_ctx_set_engine_info (gpgme_ctx_t ctx, gpgme_protocol_t proto, + const char *file_name, const char *home_dir) +{ + gpgme_error_t err; + TRACE_BEG4 (DEBUG_CTX, "gpgme_ctx_set_engine_info", ctx, + "protocol=%i (%s), file_name=%s, home_dir=%s", + proto, gpgme_get_protocol_name (proto) + ? gpgme_get_protocol_name (proto) : "unknown", + file_name ? file_name : "(default)", + home_dir ? home_dir : "(default)"); + + /* Shut down the engine when changing engine info. */ + if (ctx->engine) + { + TRACE_LOG1 ("releasing ctx->engine=%p", ctx->engine); + _gpgme_engine_release (ctx->engine); + ctx->engine = NULL; + } + err = _gpgme_set_engine_info (ctx->engine_info, proto, + file_name, home_dir); + return TRACE_ERR (err); +} + + +/* Clear all notation data from the context. */ +void +gpgme_sig_notation_clear (gpgme_ctx_t ctx) +{ + gpgme_sig_notation_t notation; + TRACE (DEBUG_CTX, "gpgme_sig_notation_clear", ctx); + + if (!ctx) + return; + + notation = ctx->sig_notations; + while (notation) + { + gpgme_sig_notation_t next_notation = notation->next; + _gpgme_sig_notation_free (notation); + notation = next_notation; + } +} + + +/* Add the human-readable notation data with name NAME and value VALUE + to the context CTX, using the flags FLAGS. If NAME is NULL, then + VALUE should be a policy URL. The flag + GPGME_SIG_NOTATION_HUMAN_READABLE is forced to be true for notation + data, and false for policy URLs. */ +gpgme_error_t +gpgme_sig_notation_add (gpgme_ctx_t ctx, const char *name, + const char *value, gpgme_sig_notation_flags_t flags) +{ + gpgme_error_t err; + gpgme_sig_notation_t notation; + gpgme_sig_notation_t *lastp; + + TRACE_BEG3 (DEBUG_CTX, "gpgme_sig_notation_add", ctx, + "name=%s, value=%s, flags=0x%x", + name ? name : "(null)", value ? value : "(null)", + flags); + + if (!ctx) + return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); + + if (name) + flags |= GPGME_SIG_NOTATION_HUMAN_READABLE; + else + flags &= ~GPGME_SIG_NOTATION_HUMAN_READABLE; + + err = _gpgme_sig_notation_create (¬ation, name, name ? strlen (name) : 0, + value, value ? strlen (value) : 0, flags); + if (err) + return TRACE_ERR (err); + + lastp = &ctx->sig_notations; + while (*lastp) + lastp = &(*lastp)->next; + + *lastp = notation; + return TRACE_ERR (0); +} + + +/* Get the sig notations for this context. */ +gpgme_sig_notation_t +gpgme_sig_notation_get (gpgme_ctx_t ctx) +{ + if (!ctx) + { + TRACE (DEBUG_CTX, "gpgme_sig_notation_get", ctx); + return NULL; + } + TRACE1 (DEBUG_CTX, "gpgme_sig_notation_get", ctx, + "ctx->sig_notations=%p", ctx->sig_notations); + + return ctx->sig_notations; +} + + +const char * +gpgme_pubkey_algo_name (gpgme_pubkey_algo_t algo) +{ + switch (algo) + { + case GPGME_PK_RSA: + return "RSA"; + + case GPGME_PK_RSA_E: + return "RSA-E"; + + case GPGME_PK_RSA_S: + return "RSA-S"; + + case GPGME_PK_ELG_E: + return "ELG-E"; + + case GPGME_PK_DSA: + return "DSA"; + + case GPGME_PK_ELG: + return "ELG"; + + default: + return NULL; + } +} + + +const char * +gpgme_hash_algo_name (gpgme_hash_algo_t algo) +{ + switch (algo) + { + case GPGME_MD_MD5: + return "MD5"; + + case GPGME_MD_SHA1: + return "SHA1"; + + case GPGME_MD_RMD160: + return "RIPEMD160"; + + case GPGME_MD_MD2: + return "MD2"; + + case GPGME_MD_TIGER: + return "TIGER192"; + + case GPGME_MD_HAVAL: + return "HAVAL"; + + case GPGME_MD_SHA256: + return "SHA256"; + + case GPGME_MD_SHA384: + return "SHA384"; + + case GPGME_MD_SHA512: + return "SHA512"; + + case GPGME_MD_MD4: + return "MD4"; + + case GPGME_MD_CRC32: + return "CRC32"; + + case GPGME_MD_CRC32_RFC1510: + return "CRC32RFC1510"; + + case GPGME_MD_CRC24_RFC2440: + return "CRC24RFC2440"; + + default: + return NULL; + } +} diff --git a/tags/gpgme-1.1.6/gpgme/gpgme.def b/tags/gpgme-1.1.6/gpgme/gpgme.def new file mode 100644 index 0000000..3c5e335 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/gpgme.def @@ -0,0 +1,170 @@ +; gpgme.def - List of symbols to export. +; Copyright (C) 2005 g10 Code GmbH +; +; This file is part of GPGME. +; +; GPGME is free software; you can redistribute it and/or modify +; it under the terms of the GNU Lesser general Public License as +; published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. +; +; You should have received a copy of the GNU Lesser 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 + + +EXPORTS + gpgme_check_version @1 + gpgme_get_engine_info @2 + gpgme_engine_check_version @3 + + gpgme_err_code_from_errno @4 + gpgme_err_code_to_errno @5 + gpgme_err_make_from_errno @6 + gpgme_error_from_errno @7 + gpgme_strerror @8 + gpgme_strerror_r @9 + gpgme_strsource @10 + + gpgme_data_get_encoding @11 + gpgme_data_new @12 + gpgme_data_new_from_cbs @13 + gpgme_data_new_from_fd @14 + gpgme_data_new_from_file @15 + gpgme_data_new_from_filepart @16 + gpgme_data_new_from_mem @17 + gpgme_data_new_from_stream @18 + gpgme_data_read @19 + gpgme_data_release @20 + gpgme_data_release_and_get_mem @21 + gpgme_data_seek @22 + gpgme_data_set_encoding @23 + gpgme_data_write @24 + + gpgme_get_protocol_name @25 + gpgme_hash_algo_name @26 + gpgme_pubkey_algo_name @27 + + gpgme_new @28 + gpgme_get_armor @29 + gpgme_get_include_certs @30 + gpgme_get_io_cbs @31 + gpgme_get_keylist_mode @32 + gpgme_get_passphrase_cb @33 + gpgme_get_progress_cb @34 + gpgme_get_protocol @35 + gpgme_get_textmode @36 + gpgme_release @37 + gpgme_set_armor @38 + gpgme_set_include_certs @39 + gpgme_set_io_cbs @40 + gpgme_set_keylist_mode @41 + gpgme_set_locale @42 + gpgme_set_passphrase_cb @43 + gpgme_set_progress_cb @44 + gpgme_set_protocol @45 + gpgme_set_textmode @46 + gpgme_signers_add @47 + gpgme_signers_clear @48 + gpgme_signers_enum @49 + + gpgme_key_ref @50 + gpgme_key_unref @51 + gpgme_key_release @52 + + gpgme_trust_item_ref @53 + gpgme_trust_item_unref @54 + + gpgme_cancel @55 + gpgme_op_card_edit @56 + gpgme_op_card_edit_start @57 + gpgme_op_decrypt @58 + gpgme_op_decrypt_result @59 + gpgme_op_decrypt_start @60 + gpgme_op_decrypt_verify @61 + gpgme_op_decrypt_verify_start @62 + gpgme_op_delete @63 + gpgme_op_delete_start @64 + gpgme_op_edit @65 + gpgme_op_edit_start @66 + gpgme_op_encrypt @67 + gpgme_op_encrypt_result @68 + gpgme_op_encrypt_sign @69 + gpgme_op_encrypt_sign_start @70 + gpgme_op_encrypt_start @71 + gpgme_op_export @72 + gpgme_op_export_ext @73 + gpgme_op_export_ext_start @74 + gpgme_op_export_start @75 + gpgme_op_genkey @76 + gpgme_op_genkey_result @77 + gpgme_op_genkey_start @78 + gpgme_get_key @79 + gpgme_op_import @80 + gpgme_op_import_result @81 + gpgme_op_import_start @82 + gpgme_op_keylist_end @83 + gpgme_op_keylist_ext_start @84 + gpgme_op_keylist_next @85 + gpgme_op_keylist_result @86 + gpgme_op_keylist_start @87 + gpgme_op_sign @88 + gpgme_op_sign_result @89 + gpgme_op_sign_start @90 + gpgme_op_trustlist_end @91 + gpgme_op_trustlist_next @92 + gpgme_op_trustlist_start @93 + gpgme_op_verify @94 + gpgme_op_verify_result @95 + gpgme_op_verify_start @96 + gpgme_wait @97 + + gpgme_data_new_with_read_cb @98 + gpgme_data_rewind @99 + gpgme_get_sig_status @100 + gpgme_get_sig_string_attr @101 + gpgme_get_sig_ulong_attr @102 + gpgme_get_sig_key @103 + gpgme_key_get_string_attr @104 + gpgme_key_get_ulong_attr @105 + gpgme_key_sig_get_string_attr @106 + gpgme_key_sig_get_ulong_attr @107 + gpgme_op_import_ext @108 + gpgme_trust_item_get_int_attr @109 + gpgme_trust_item_get_string_attr @110 + gpgme_trust_item_release @111 + + gpgme_set_engine_info @112 + + gpgme_ctx_get_engine_info @113 + gpgme_ctx_set_engine_info @114 + + gpgme_data_set_file_name @115 + gpgme_data_get_file_name @116 + + gpgme_sig_notation_clear @117 + gpgme_sig_notation_add @118 + gpgme_sig_notation_get @119 + + gpgme_free @120 + + gpgme_get_giochannel @121 + gpgme_get_fdptr @122 + + gpgme_op_getauditlog_start @123 + gpgme_op_getauditlog @124 + + gpgme_conf_release @125 + gpgme_conf_arg_new @126 + gpgme_conf_arg_release @127 + gpgme_conf_opt_change @128 + gpgme_op_conf_load @129 + gpgme_op_conf_save @130 + +; END + diff --git a/tags/gpgme-1.1.6/gpgme/gpgme.h b/tags/gpgme-1.1.6/gpgme/gpgme.h new file mode 100644 index 0000000..bf42035 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/gpgme.h @@ -0,0 +1,1883 @@ +/* gpgme.h - Public interface to GnuPG Made Easy. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, see . + */ + +#ifndef GPGME_H +#define GPGME_H + +#ifdef __GNUC__ +#define _GPGME_INLINE __inline__ +#elif __STDC_VERSION__ >= 199901L +#define _GPGME_INLINE inline +#else +#define _GPGME_INLINE +#endif + +/* Include stdio.h for the FILE type definition. */ +#include + +#ifdef _MSC_VER + typedef long off_t; + typedef long ssize_t; +#else +# include +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#if 0 /* just to make Emacs auto-indent happy */ +} +#endif +#endif /* __cplusplus */ + + + +/* Check for compiler features. */ +#if __GNUC__ +#define _GPGME_GCC_VERSION (__GNUC__ * 10000 \ + + __GNUC_MINOR__ * 100 \ + + __GNUC_PATCHLEVEL__) + +#if _GPGME_GCC_VERSION > 30100 +#define _GPGME_DEPRECATED __attribute__ ((__deprecated__)) +#endif +#endif + +#ifndef _GPGME_DEPRECATED +#define _GPGME_DEPRECATED +#endif + + +/* The version of this header should match the one of the library. Do + not use this symbol in your application, use gpgme_check_version + instead. 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 "1.1.6-svn1282" + + + +/* Some opaque data types used by GPGME. */ + +/* The context holds some global state and configration options, as + well as the results of a crypto operation. */ +struct gpgme_context; +typedef struct gpgme_context *gpgme_ctx_t; + +/* The data object is used by GPGME to exchange arbitrary data. */ +struct gpgme_data; +typedef struct gpgme_data *gpgme_data_t; + + +/* Wrappers for the libgpg-error library. */ + +typedef gpg_error_t gpgme_error_t; +typedef gpg_err_code_t gpgme_err_code_t; +typedef gpg_err_source_t gpgme_err_source_t; + + +static _GPGME_INLINE gpgme_error_t +gpgme_err_make (gpgme_err_source_t source, gpgme_err_code_t code) +{ + return gpg_err_make (source, code); +} + + +/* The user can define GPGME_ERR_SOURCE_DEFAULT before including this + file to specify a default source for gpgme_error. */ +#ifndef GPGME_ERR_SOURCE_DEFAULT +#define GPGME_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_USER_1 +#endif + +static _GPGME_INLINE gpgme_error_t +gpgme_error (gpgme_err_code_t code) +{ + return gpgme_err_make (GPGME_ERR_SOURCE_DEFAULT, code); +} + + +static _GPGME_INLINE gpgme_err_code_t +gpgme_err_code (gpgme_error_t err) +{ + return gpg_err_code (err); +} + + +static _GPGME_INLINE gpgme_err_source_t +gpgme_err_source (gpgme_error_t err) +{ + return gpg_err_source (err); +} + + +/* Return a pointer to a string containing a description of the error + code in the error value ERR. This function is not thread safe. */ +const char *gpgme_strerror (gpgme_error_t err); + +/* Return the error string for ERR in the user-supplied buffer BUF of + size BUFLEN. This function is, in contrast to gpg_strerror, + thread-safe if a thread-safe strerror_r() function is provided by + the system. If the function succeeds, 0 is returned and BUF + contains the string describing the error. If the buffer was not + large enough, ERANGE is returned and BUF contains as much of the + beginning of the error string as fits into the buffer. */ +int gpgme_strerror_r (gpg_error_t err, char *buf, size_t buflen); + + +/* Return a pointer to a string containing a description of the error + source in the error value ERR. */ +const char *gpgme_strsource (gpgme_error_t err); + + +/* Retrieve the error code for the system error ERR. This returns + GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped (report + this). */ +gpgme_err_code_t gpgme_err_code_from_errno (int err); + + +/* Retrieve the system error for the error code CODE. This returns 0 + if CODE is not a system error code. */ +int gpgme_err_code_to_errno (gpgme_err_code_t code); + + +/* Return an error value with the error source SOURCE and the system + error ERR. */ +gpgme_error_t gpgme_err_make_from_errno (gpgme_err_source_t source, int err); + + +/* Return an error value with the system error ERR. */ +gpgme_err_code_t gpgme_error_from_errno (int err); + + +/* The possible encoding mode of gpgme_data_t objects. */ +typedef enum + { + GPGME_DATA_ENCODING_NONE = 0, /* Not specified. */ + GPGME_DATA_ENCODING_BINARY = 1, + GPGME_DATA_ENCODING_BASE64 = 2, + GPGME_DATA_ENCODING_ARMOR = 3 /* Either PEM or OpenPGP Armor. */ + } +gpgme_data_encoding_t; + + +/* Public key algorithms from libgcrypt. */ +typedef enum + { + GPGME_PK_RSA = 1, + GPGME_PK_RSA_E = 2, + GPGME_PK_RSA_S = 3, + GPGME_PK_ELG_E = 16, + GPGME_PK_DSA = 17, + GPGME_PK_ELG = 20 + } +gpgme_pubkey_algo_t; + + +/* Hash algorithms from libgcrypt. */ +typedef enum + { + GPGME_MD_NONE = 0, + GPGME_MD_MD5 = 1, + GPGME_MD_SHA1 = 2, + GPGME_MD_RMD160 = 3, + GPGME_MD_MD2 = 5, + GPGME_MD_TIGER = 6, /* TIGER/192. */ + GPGME_MD_HAVAL = 7, /* HAVAL, 5 pass, 160 bit. */ + GPGME_MD_SHA256 = 8, + GPGME_MD_SHA384 = 9, + GPGME_MD_SHA512 = 10, + GPGME_MD_MD4 = 301, + GPGME_MD_CRC32 = 302, + GPGME_MD_CRC32_RFC1510 = 303, + GPGME_MD_CRC24_RFC2440 = 304 + } +gpgme_hash_algo_t; + + +/* The possible signature stati. Deprecated, use error value in sig + status. */ +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, + GPGME_SIG_STAT_DIFF = 6, + GPGME_SIG_STAT_GOOD_EXP = 7, + GPGME_SIG_STAT_GOOD_EXPKEY = 8 + } +_gpgme_sig_stat_t; +typedef _gpgme_sig_stat_t gpgme_sig_stat_t _GPGME_DEPRECATED; + + +/* The available signature modes. */ +typedef enum + { + GPGME_SIG_MODE_NORMAL = 0, + GPGME_SIG_MODE_DETACH = 1, + GPGME_SIG_MODE_CLEAR = 2 + } +gpgme_sig_mode_t; + + +/* The available key and signature attributes. Deprecated, use the + individual result structures instead. */ +typedef enum + { + GPGME_ATTR_KEYID = 1, + GPGME_ATTR_FPR = 2, + GPGME_ATTR_ALGO = 3, + GPGME_ATTR_LEN = 4, + GPGME_ATTR_CREATED = 5, + GPGME_ATTR_EXPIRE = 6, + GPGME_ATTR_OTRUST = 7, + GPGME_ATTR_USERID = 8, + GPGME_ATTR_NAME = 9, + GPGME_ATTR_EMAIL = 10, + GPGME_ATTR_COMMENT = 11, + GPGME_ATTR_VALIDITY = 12, + GPGME_ATTR_LEVEL = 13, + GPGME_ATTR_TYPE = 14, + GPGME_ATTR_IS_SECRET = 15, + GPGME_ATTR_KEY_REVOKED = 16, + GPGME_ATTR_KEY_INVALID = 17, + GPGME_ATTR_UID_REVOKED = 18, + GPGME_ATTR_UID_INVALID = 19, + GPGME_ATTR_KEY_CAPS = 20, + GPGME_ATTR_CAN_ENCRYPT = 21, + GPGME_ATTR_CAN_SIGN = 22, + GPGME_ATTR_CAN_CERTIFY = 23, + GPGME_ATTR_KEY_EXPIRED = 24, + GPGME_ATTR_KEY_DISABLED = 25, + GPGME_ATTR_SERIAL = 26, + GPGME_ATTR_ISSUER = 27, + GPGME_ATTR_CHAINID = 28, + GPGME_ATTR_SIG_STATUS = 29, + GPGME_ATTR_ERRTOK = 30, + GPGME_ATTR_SIG_SUMMARY = 31, + GPGME_ATTR_SIG_CLASS = 32 + } +_gpgme_attr_t; +typedef _gpgme_attr_t gpgme_attr_t _GPGME_DEPRECATED; + + +/* The available validities for a trust item or key. */ +typedef enum + { + GPGME_VALIDITY_UNKNOWN = 0, + GPGME_VALIDITY_UNDEFINED = 1, + GPGME_VALIDITY_NEVER = 2, + GPGME_VALIDITY_MARGINAL = 3, + GPGME_VALIDITY_FULL = 4, + GPGME_VALIDITY_ULTIMATE = 5 + } +gpgme_validity_t; + + +/* The available protocols. */ +typedef enum + { + GPGME_PROTOCOL_OpenPGP = 0, /* The default mode. */ + GPGME_PROTOCOL_CMS = 1, + GPGME_PROTOCOL_GPGCONF = 2, /* Special code for gpgconf. */ + GPGME_PROTOCOL_UNKNOWN = 255 + } +gpgme_protocol_t; + + +/* The available keylist mode flags. */ +#define GPGME_KEYLIST_MODE_LOCAL 1 +#define GPGME_KEYLIST_MODE_EXTERN 2 +#define GPGME_KEYLIST_MODE_SIGS 4 +#define GPGME_KEYLIST_MODE_SIG_NOTATIONS 8 +#define GPGME_KEYLIST_MODE_VALIDATE 256 + +typedef unsigned int gpgme_keylist_mode_t; + + +/* Flags for the audit log functions. */ +#define GPGME_AUDITLOG_HTML 1 +#define GPGME_AUDITLOG_WITH_HELP 128 + + +/* Signature notations. */ + +/* The available signature notation flags. */ +#define GPGME_SIG_NOTATION_HUMAN_READABLE 1 +#define GPGME_SIG_NOTATION_CRITICAL 2 + +typedef unsigned int gpgme_sig_notation_flags_t; + +struct _gpgme_sig_notation +{ + struct _gpgme_sig_notation *next; + + /* If NAME is a null pointer, then VALUE contains a policy URL + rather than a notation. */ + char *name; + + /* The value of the notation data. */ + char *value; + + /* The length of the name of the notation data. */ + int name_len; + + /* The length of the value of the notation data. */ + int value_len; + + /* The accumulated flags. */ + gpgme_sig_notation_flags_t flags; + + /* Notation data is human-readable. */ + unsigned int human_readable : 1; + + /* Notation data is critical. */ + unsigned int critical : 1; + + /* Internal to GPGME, do not use. */ + int _unused : 30; +}; +typedef struct _gpgme_sig_notation *gpgme_sig_notation_t; + + +/* The possible stati for the edit operation. */ +typedef enum + { + GPGME_STATUS_EOF, + /* mkstatus processing starts here */ + GPGME_STATUS_ENTER, + GPGME_STATUS_LEAVE, + GPGME_STATUS_ABORT, + + GPGME_STATUS_GOODSIG, + GPGME_STATUS_BADSIG, + GPGME_STATUS_ERRSIG, + + GPGME_STATUS_BADARMOR, + + GPGME_STATUS_RSA_OR_IDEA, + GPGME_STATUS_KEYEXPIRED, + GPGME_STATUS_KEYREVOKED, + + GPGME_STATUS_TRUST_UNDEFINED, + GPGME_STATUS_TRUST_NEVER, + GPGME_STATUS_TRUST_MARGINAL, + GPGME_STATUS_TRUST_FULLY, + GPGME_STATUS_TRUST_ULTIMATE, + + GPGME_STATUS_SHM_INFO, + GPGME_STATUS_SHM_GET, + GPGME_STATUS_SHM_GET_BOOL, + GPGME_STATUS_SHM_GET_HIDDEN, + + GPGME_STATUS_NEED_PASSPHRASE, + GPGME_STATUS_VALIDSIG, + GPGME_STATUS_SIG_ID, + GPGME_STATUS_ENC_TO, + GPGME_STATUS_NODATA, + GPGME_STATUS_BAD_PASSPHRASE, + GPGME_STATUS_NO_PUBKEY, + GPGME_STATUS_NO_SECKEY, + GPGME_STATUS_NEED_PASSPHRASE_SYM, + GPGME_STATUS_DECRYPTION_FAILED, + GPGME_STATUS_DECRYPTION_OKAY, + GPGME_STATUS_MISSING_PASSPHRASE, + GPGME_STATUS_GOOD_PASSPHRASE, + GPGME_STATUS_GOODMDC, + GPGME_STATUS_BADMDC, + GPGME_STATUS_ERRMDC, + GPGME_STATUS_IMPORTED, + GPGME_STATUS_IMPORT_OK, + GPGME_STATUS_IMPORT_PROBLEM, + GPGME_STATUS_IMPORT_RES, + GPGME_STATUS_FILE_START, + GPGME_STATUS_FILE_DONE, + GPGME_STATUS_FILE_ERROR, + + GPGME_STATUS_BEGIN_DECRYPTION, + GPGME_STATUS_END_DECRYPTION, + GPGME_STATUS_BEGIN_ENCRYPTION, + GPGME_STATUS_END_ENCRYPTION, + + GPGME_STATUS_DELETE_PROBLEM, + GPGME_STATUS_GET_BOOL, + GPGME_STATUS_GET_LINE, + GPGME_STATUS_GET_HIDDEN, + GPGME_STATUS_GOT_IT, + GPGME_STATUS_PROGRESS, + GPGME_STATUS_SIG_CREATED, + GPGME_STATUS_SESSION_KEY, + GPGME_STATUS_NOTATION_NAME, + GPGME_STATUS_NOTATION_DATA, + GPGME_STATUS_POLICY_URL, + GPGME_STATUS_BEGIN_STREAM, + GPGME_STATUS_END_STREAM, + GPGME_STATUS_KEY_CREATED, + GPGME_STATUS_USERID_HINT, + GPGME_STATUS_UNEXPECTED, + GPGME_STATUS_INV_RECP, + GPGME_STATUS_NO_RECP, + GPGME_STATUS_ALREADY_SIGNED, + GPGME_STATUS_SIGEXPIRED, + GPGME_STATUS_EXPSIG, + GPGME_STATUS_EXPKEYSIG, + GPGME_STATUS_TRUNCATED, + GPGME_STATUS_ERROR, + GPGME_STATUS_NEWSIG, + GPGME_STATUS_REVKEYSIG, + GPGME_STATUS_SIG_SUBPACKET, + GPGME_STATUS_NEED_PASSPHRASE_PIN, + GPGME_STATUS_SC_OP_FAILURE, + GPGME_STATUS_SC_OP_SUCCESS, + GPGME_STATUS_CARDCTRL, + GPGME_STATUS_BACKUP_KEY_CREATED, + GPGME_STATUS_PKA_TRUST_BAD, + GPGME_STATUS_PKA_TRUST_GOOD, + + GPGME_STATUS_PLAINTEXT + } +gpgme_status_code_t; + + +/* The engine information structure. */ +struct _gpgme_engine_info +{ + struct _gpgme_engine_info *next; + + /* The protocol ID. */ + gpgme_protocol_t protocol; + + /* The file name of the engine binary. */ + char *file_name; + + /* The version string of the installed engine. */ + char *version; + + /* The minimum version required for GPGME. */ + const char *req_version; + + /* The home directory used, or NULL if default. */ + char *home_dir; +}; +typedef struct _gpgme_engine_info *gpgme_engine_info_t; + + +/* A subkey from a key. */ +struct _gpgme_subkey +{ + struct _gpgme_subkey *next; + + /* True if subkey is revoked. */ + unsigned int revoked : 1; + + /* True if subkey is expired. */ + unsigned int expired : 1; + + /* True if subkey is disabled. */ + unsigned int disabled : 1; + + /* True if subkey is invalid. */ + unsigned int invalid : 1; + + /* True if subkey can be used for encryption. */ + unsigned int can_encrypt : 1; + + /* True if subkey can be used for signing. */ + unsigned int can_sign : 1; + + /* True if subkey can be used for certification. */ + unsigned int can_certify : 1; + + /* True if subkey is secret. */ + unsigned int secret : 1; + + /* True if subkey can be used for authentication. */ + unsigned int can_authenticate : 1; + + /* True if subkey is qualified for signatures according to German law. */ + unsigned int is_qualified : 1; + + /* Internal to GPGME, do not use. */ + unsigned int _unused : 22; + + /* Public key algorithm supported by this subkey. */ + gpgme_pubkey_algo_t pubkey_algo; + + /* Length of the subkey. */ + unsigned int length; + + /* The key ID of the subkey. */ + char *keyid; + + /* Internal to GPGME, do not use. */ + char _keyid[16 + 1]; + + /* The fingerprint of the subkey in hex digit form. */ + char *fpr; + + /* The creation timestamp, -1 if invalid, 0 if not available. */ + long int timestamp; + + /* The expiration timestamp, 0 if the subkey does not expire. */ + long int expires; +}; +typedef struct _gpgme_subkey *gpgme_subkey_t; + + +/* A signature on a user ID. */ +struct _gpgme_key_sig +{ + struct _gpgme_key_sig *next; + + /* True if the signature is a revocation signature. */ + unsigned int revoked : 1; + + /* True if the signature is expired. */ + unsigned int expired : 1; + + /* True if the signature is invalid. */ + unsigned int invalid : 1; + + /* True if the signature should be exported. */ + unsigned int exportable : 1; + + /* Internal to GPGME, do not use. */ + unsigned int _unused : 28; + + /* The public key algorithm used to create the signature. */ + gpgme_pubkey_algo_t pubkey_algo; + + /* The key ID of key used to create the signature. */ + char *keyid; + + /* Internal to GPGME, do not use. */ + char _keyid[16 + 1]; + + /* The creation timestamp, -1 if invalid, 0 if not available. */ + long int timestamp; + + /* The expiration timestamp, 0 if the subkey does not expire. */ + long int expires; + + /* Same as in gpgme_signature_t. */ + gpgme_error_t status; + +#ifdef __cplusplus + unsigned int _obsolete_class _GPGME_DEPRECATED; +#else + /* Must be set to SIG_CLASS below. */ + unsigned int class _GPGME_DEPRECATED; +#endif + + /* The user ID string. */ + char *uid; + + /* The name part of the user ID. */ + char *name; + + /* The email part of the user ID. */ + char *email; + + /* The comment part of the user ID. */ + char *comment; + + /* Crypto backend specific signature class. */ + unsigned int sig_class; + + /* Notation data and policy URLs. */ + gpgme_sig_notation_t notations; + + /* Internal to GPGME, do not use. */ + gpgme_sig_notation_t _last_notation; +}; +typedef struct _gpgme_key_sig *gpgme_key_sig_t; + + +/* An user ID from a key. */ +struct _gpgme_user_id +{ + struct _gpgme_user_id *next; + + /* True if the user ID is revoked. */ + unsigned int revoked : 1; + + /* True if the user ID is invalid. */ + unsigned int invalid : 1; + + /* Internal to GPGME, do not use. */ + unsigned int _unused : 30; + + /* The validity of the user ID. */ + gpgme_validity_t validity; + + /* The user ID string. */ + char *uid; + + /* The name part of the user ID. */ + char *name; + + /* The email part of the user ID. */ + char *email; + + /* The comment part of the user ID. */ + char *comment; + + /* The signatures of the user ID. */ + gpgme_key_sig_t signatures; + + /* Internal to GPGME, do not use. */ + gpgme_key_sig_t _last_keysig; +}; +typedef struct _gpgme_user_id *gpgme_user_id_t; + + +/* A key from the keyring. */ +struct _gpgme_key +{ + /* Internal to GPGME, do not use. */ + unsigned int _refs; + + /* True if key is revoked. */ + unsigned int revoked : 1; + + /* True if key is expired. */ + unsigned int expired : 1; + + /* True if key is disabled. */ + unsigned int disabled : 1; + + /* True if key is invalid. */ + unsigned int invalid : 1; + + /* True if key can be used for encryption. */ + unsigned int can_encrypt : 1; + + /* True if key can be used for signing. */ + unsigned int can_sign : 1; + + /* True if key can be used for certification. */ + unsigned int can_certify : 1; + + /* True if key is secret. */ + unsigned int secret : 1; + + /* True if key can be used for authentication. */ + unsigned int can_authenticate : 1; + + /* True if subkey is qualified for signatures according to German law. */ + unsigned int is_qualified : 1; + + /* Internal to GPGME, do not use. */ + unsigned int _unused : 22; + + /* This is the protocol supported by this key. */ + gpgme_protocol_t protocol; + + /* If protocol is GPGME_PROTOCOL_CMS, this string contains the + issuer serial. */ + char *issuer_serial; + + /* If protocol is GPGME_PROTOCOL_CMS, this string contains the + issuer name. */ + char *issuer_name; + + /* If protocol is GPGME_PROTOCOL_CMS, this string contains the chain + ID. */ + char *chain_id; + + /* If protocol is GPGME_PROTOCOL_OpenPGP, this field contains the + owner trust. */ + gpgme_validity_t owner_trust; + + /* The subkeys of the key. */ + gpgme_subkey_t subkeys; + + /* The user IDs of the key. */ + gpgme_user_id_t uids; + + /* Internal to GPGME, do not use. */ + gpgme_subkey_t _last_subkey; + + /* Internal to GPGME, do not use. */ + gpgme_user_id_t _last_uid; + + /* The keylist mode that was active when listing the key. */ + gpgme_keylist_mode_t keylist_mode; +}; +typedef struct _gpgme_key *gpgme_key_t; + + + +/* Types for callback functions. */ + +/* Request a passphrase from the user. */ +typedef gpgme_error_t (*gpgme_passphrase_cb_t) (void *hook, + const char *uid_hint, + const char *passphrase_info, + int prev_was_bad, int fd); + +/* Inform the user about progress made. */ +typedef void (*gpgme_progress_cb_t) (void *opaque, const char *what, + int type, int current, int total); + +/* Interact with the user about an edit operation. */ +typedef gpgme_error_t (*gpgme_edit_cb_t) (void *opaque, + gpgme_status_code_t status, + const char *args, int fd); + + +/* Context management functions. */ + +/* Create a new context and return it in CTX. */ +gpgme_error_t gpgme_new (gpgme_ctx_t *ctx); + +/* Release the context CTX. */ +void gpgme_release (gpgme_ctx_t ctx); + +/* Set the protocol to be used by CTX to PROTO. */ +gpgme_error_t gpgme_set_protocol (gpgme_ctx_t ctx, gpgme_protocol_t proto); + +/* Get the protocol used with CTX */ +gpgme_protocol_t gpgme_get_protocol (gpgme_ctx_t ctx); + +/* Get the string describing protocol PROTO, or NULL if invalid. */ +const char *gpgme_get_protocol_name (gpgme_protocol_t proto); + +/* If YES is non-zero, enable armor mode in CTX, disable it otherwise. */ +void gpgme_set_armor (gpgme_ctx_t ctx, int yes); + +/* Return non-zero if armor mode is set in CTX. */ +int gpgme_get_armor (gpgme_ctx_t ctx); + +/* If YES is non-zero, enable text mode in CTX, disable it otherwise. */ +void gpgme_set_textmode (gpgme_ctx_t ctx, int yes); + +/* Return non-zero if text mode is set in CTX. */ +int gpgme_get_textmode (gpgme_ctx_t ctx); + +/* Use whatever the default of the backend crypto engine is. */ +#define GPGME_INCLUDE_CERTS_DEFAULT -256 + +/* Include up to NR_OF_CERTS certificates in an S/MIME message. */ +void gpgme_set_include_certs (gpgme_ctx_t ctx, int nr_of_certs); + +/* Return the number of certs to include in an S/MIME message. */ +int gpgme_get_include_certs (gpgme_ctx_t ctx); + +/* Set keylist mode in CTX to MODE. */ +gpgme_error_t gpgme_set_keylist_mode (gpgme_ctx_t ctx, + gpgme_keylist_mode_t mode); + +/* Get keylist mode in CTX. */ +gpgme_keylist_mode_t gpgme_get_keylist_mode (gpgme_ctx_t ctx); + +/* Set the passphrase callback function in CTX to CB. HOOK_VALUE is + passed as first argument to the passphrase callback function. */ +void gpgme_set_passphrase_cb (gpgme_ctx_t ctx, + gpgme_passphrase_cb_t cb, void *hook_value); + +/* Get the current passphrase callback function in *CB and the current + hook value in *HOOK_VALUE. */ +void gpgme_get_passphrase_cb (gpgme_ctx_t ctx, gpgme_passphrase_cb_t *cb, + void **hook_value); + +/* Set the progress callback function in CTX to CB. HOOK_VALUE is + passed as first argument to the progress callback function. */ +void gpgme_set_progress_cb (gpgme_ctx_t c, gpgme_progress_cb_t cb, + void *hook_value); + +/* Get the current progress callback function in *CB and the current + hook value in *HOOK_VALUE. */ +void gpgme_get_progress_cb (gpgme_ctx_t ctx, gpgme_progress_cb_t *cb, + void **hook_value); + +/* This function sets the locale for the context CTX, or the default + locale if CTX is a null pointer. */ +gpgme_error_t gpgme_set_locale (gpgme_ctx_t ctx, int category, + const char *value); + +/* Get the information about the configured engines. A pointer to the + first engine in the statically allocated linked list is returned. + The returned data is valid until the next gpgme_ctx_set_engine_info. */ +gpgme_engine_info_t gpgme_ctx_get_engine_info (gpgme_ctx_t ctx); + +/* Set the engine info for the context CTX, protocol PROTO, to the + file name FILE_NAME and the home directory HOME_DIR. */ +gpgme_error_t gpgme_ctx_set_engine_info (gpgme_ctx_t ctx, + gpgme_protocol_t proto, + const char *file_name, + const char *home_dir); + + +/* Return a statically allocated string with the name of the public + key algorithm ALGO, or NULL if that name is not known. */ +const char *gpgme_pubkey_algo_name (gpgme_pubkey_algo_t algo); + +/* Return a statically allocated string with the name of the hash + algorithm ALGO, or NULL if that name is not known. */ +const char *gpgme_hash_algo_name (gpgme_hash_algo_t algo); + + +/* Delete all signers from CTX. */ +void gpgme_signers_clear (gpgme_ctx_t ctx); + +/* Add KEY to list of signers in CTX. */ +gpgme_error_t gpgme_signers_add (gpgme_ctx_t ctx, const gpgme_key_t key); + +/* Return the SEQth signer's key in CTX. */ +gpgme_key_t gpgme_signers_enum (const gpgme_ctx_t ctx, int seq); + +/* Retrieve the signature status of signature IDX in CTX after a + successful verify operation in R_STAT (if non-null). The creation + time stamp of the signature is returned in R_CREATED (if non-null). + The function returns a string containing the fingerprint. + Deprecated, use verify result directly. */ +const char *gpgme_get_sig_status (gpgme_ctx_t ctx, int idx, + _gpgme_sig_stat_t *r_stat, + time_t *r_created) _GPGME_DEPRECATED; + +/* Retrieve certain attributes of a signature. IDX is the index + number of the signature after a successful verify operation. WHAT + is an attribute where GPGME_ATTR_EXPIRE is probably the most useful + one. WHATIDX is to be passed as 0 for most attributes . */ +unsigned long gpgme_get_sig_ulong_attr (gpgme_ctx_t c, int idx, + _gpgme_attr_t what, int whatidx) + _GPGME_DEPRECATED; +const char *gpgme_get_sig_string_attr (gpgme_ctx_t c, int idx, + _gpgme_attr_t what, int whatidx) + _GPGME_DEPRECATED; + + +/* Get the key used to create signature IDX in CTX and return it in + R_KEY. */ +gpgme_error_t gpgme_get_sig_key (gpgme_ctx_t ctx, int idx, gpgme_key_t *r_key) + _GPGME_DEPRECATED; + + +/* Clear all notation data from the context. */ +void gpgme_sig_notation_clear (gpgme_ctx_t ctx); + +/* Add the human-readable notation data with name NAME and value VALUE + to the context CTX, using the flags FLAGS. If NAME is NULL, then + VALUE should be a policy URL. The flag + GPGME_SIG_NOTATION_HUMAN_READABLE is forced to be true for notation + data, and false for policy URLs. */ +gpgme_error_t gpgme_sig_notation_add (gpgme_ctx_t ctx, const char *name, + const char *value, + gpgme_sig_notation_flags_t flags); + +/* Get the sig notations for this context. */ +gpgme_sig_notation_t gpgme_sig_notation_get (gpgme_ctx_t ctx); + + +/* Run control. */ + +/* The type of an I/O callback function. */ +typedef gpgme_error_t (*gpgme_io_cb_t) (void *data, int fd); + +/* The type of a function that can register FNC as the I/O callback + function for the file descriptor FD with direction dir (0: for writing, + 1: for reading). FNC_DATA should be passed as DATA to FNC. The + function should return a TAG suitable for the corresponding + gpgme_remove_io_cb_t, and an error value. */ +typedef gpgme_error_t (*gpgme_register_io_cb_t) (void *data, int fd, int dir, + gpgme_io_cb_t fnc, + void *fnc_data, void **tag); + +/* The type of a function that can remove a previously registered I/O + callback function given TAG as returned by the register + function. */ +typedef void (*gpgme_remove_io_cb_t) (void *tag); + +typedef enum + { + GPGME_EVENT_START, + GPGME_EVENT_DONE, + GPGME_EVENT_NEXT_KEY, + GPGME_EVENT_NEXT_TRUSTITEM + } +gpgme_event_io_t; + +/* The type of a function that is called when a context finished an + operation. */ +typedef void (*gpgme_event_io_cb_t) (void *data, gpgme_event_io_t type, + void *type_data); + +struct gpgme_io_cbs +{ + gpgme_register_io_cb_t add; + void *add_priv; + gpgme_remove_io_cb_t remove; + gpgme_event_io_cb_t event; + void *event_priv; +}; +typedef struct gpgme_io_cbs *gpgme_io_cbs_t; + +/* Set the I/O callback functions in CTX to IO_CBS. */ +void gpgme_set_io_cbs (gpgme_ctx_t ctx, gpgme_io_cbs_t io_cbs); + +/* Get the current I/O callback functions. */ +void gpgme_get_io_cbs (gpgme_ctx_t ctx, gpgme_io_cbs_t io_cbs); + +/* Process the pending operation and, if HANG is non-zero, wait for + the pending operation to finish. */ +gpgme_ctx_t gpgme_wait (gpgme_ctx_t ctx, gpgme_error_t *status, int hang); + + +/* Functions to handle data objects. */ + +/* Read up to SIZE bytes into buffer BUFFER from the data object with + the handle HANDLE. Return the number of characters read, 0 on EOF + and -1 on error. If an error occurs, errno is set. */ +typedef ssize_t (*gpgme_data_read_cb_t) (void *handle, void *buffer, + size_t size); + +/* Write up to SIZE bytes from buffer BUFFER to the data object with + the handle HANDLE. Return the number of characters written, or -1 + on error. If an error occurs, errno is set. */ +typedef ssize_t (*gpgme_data_write_cb_t) (void *handle, const void *buffer, + size_t size); + +/* Set the current position from where the next read or write starts + in the data object with the handle HANDLE to OFFSET, relativ to + WHENCE. */ +typedef off_t (*gpgme_data_seek_cb_t) (void *handle, off_t offset, int whence); + +/* Close the data object with the handle DL. */ +typedef void (*gpgme_data_release_cb_t) (void *handle); + +struct gpgme_data_cbs +{ + gpgme_data_read_cb_t read; + gpgme_data_write_cb_t write; + gpgme_data_seek_cb_t seek; + gpgme_data_release_cb_t release; +}; +typedef struct gpgme_data_cbs *gpgme_data_cbs_t; + +/* Read up to SIZE bytes into buffer BUFFER from the data object with + the handle DH. Return the number of characters read, 0 on EOF and + -1 on error. If an error occurs, errno is set. */ +ssize_t gpgme_data_read (gpgme_data_t dh, void *buffer, size_t size); + +/* Write up to SIZE bytes from buffer BUFFER to the data object with + the handle DH. Return the number of characters written, or -1 on + error. If an error occurs, errno is set. */ +ssize_t gpgme_data_write (gpgme_data_t dh, const void *buffer, size_t size); + +/* Set the current position from where the next read or write starts + in the data object with the handle DH to OFFSET, relativ to + WHENCE. */ +off_t gpgme_data_seek (gpgme_data_t dh, off_t offset, int whence); + +/* Create a new data buffer and return it in R_DH. */ +gpgme_error_t gpgme_data_new (gpgme_data_t *r_dh); + +/* Destroy the data buffer DH. */ +void gpgme_data_release (gpgme_data_t dh); + +/* Create a new data buffer filled with SIZE bytes starting from + BUFFER. If COPY is zero, copying is delayed until necessary, and + the data is taken from the original location when needed. */ +gpgme_error_t gpgme_data_new_from_mem (gpgme_data_t *r_dh, + const char *buffer, size_t size, + int copy); + +/* Destroy the data buffer DH and return a pointer to its content. + The memory has be to released with gpgme_free() by the user. It's + size is returned in R_LEN. */ +char *gpgme_data_release_and_get_mem (gpgme_data_t dh, size_t *r_len); + +/* Release the memory returned by gpgme_data_release_and_get_mem(). */ +void gpgme_free (void *buffer); + +gpgme_error_t gpgme_data_new_from_cbs (gpgme_data_t *dh, + gpgme_data_cbs_t cbs, + void *handle); + +gpgme_error_t gpgme_data_new_from_fd (gpgme_data_t *dh, int fd); + +gpgme_error_t gpgme_data_new_from_stream (gpgme_data_t *dh, FILE *stream); + +/* Return the encoding attribute of the data buffer DH */ +gpgme_data_encoding_t gpgme_data_get_encoding (gpgme_data_t dh); + +/* Set the encoding attribute of data buffer DH to ENC */ +gpgme_error_t gpgme_data_set_encoding (gpgme_data_t dh, + gpgme_data_encoding_t enc); + +/* Get the file name associated with the data object with handle DH, or + NULL if there is none. */ +char *gpgme_data_get_file_name (gpgme_data_t dh); + +/* Set the file name associated with the data object with handle DH to + FILE_NAME. */ +gpgme_error_t gpgme_data_set_file_name (gpgme_data_t dh, + const char *file_name); + + +/* Create a new data buffer which retrieves the data from the callback + function READ_CB. Deprecated, please use gpgme_data_new_from_cbs + instead. */ +gpgme_error_t gpgme_data_new_with_read_cb (gpgme_data_t *r_dh, + int (*read_cb) (void*,char *, + size_t,size_t*), + void *read_cb_value) + _GPGME_DEPRECATED; + +/* Create a new data buffer filled with the content of file FNAME. + COPY must be non-zero. For delayed read, please use + gpgme_data_new_from_fd or gpgme_data_new_from stream instead. */ +gpgme_error_t gpgme_data_new_from_file (gpgme_data_t *r_dh, + const char *fname, + int copy); + +/* Create a new data buffer filled with LENGTH bytes starting from + OFFSET within the file FNAME or stream FP (exactly one must be + non-zero). */ +gpgme_error_t gpgme_data_new_from_filepart (gpgme_data_t *r_dh, + const char *fname, FILE *fp, + off_t offset, size_t length); + +/* Reset the read pointer in DH. Deprecated, please use + gpgme_data_seek instead. */ +gpgme_error_t gpgme_data_rewind (gpgme_data_t dh) _GPGME_DEPRECATED; + + +/* Key and trust functions. */ + +/* Get the key with the fingerprint FPR from the crypto backend. If + SECRET is true, get the secret key. */ +gpgme_error_t gpgme_get_key (gpgme_ctx_t ctx, const char *fpr, + gpgme_key_t *r_key, int secret); + +/* Acquire a reference to KEY. */ +void gpgme_key_ref (gpgme_key_t key); + +/* Release a reference to KEY. If this was the last one the key is + destroyed. */ +void gpgme_key_unref (gpgme_key_t key); +void gpgme_key_release (gpgme_key_t key); + +/* Return the value of the attribute WHAT of KEY, which has to be + representable by a string. IDX specifies the sub key or user ID + for attributes related to sub keys or user IDs. Deprecated, use + key structure directly instead. */ +const char *gpgme_key_get_string_attr (gpgme_key_t key, _gpgme_attr_t what, + const void *reserved, int idx) + _GPGME_DEPRECATED; + +/* Return the value of the attribute WHAT of KEY, which has to be + representable by an unsigned integer. IDX specifies the sub key or + user ID for attributes related to sub keys or user IDs. + Deprecated, use key structure directly instead. */ +unsigned long gpgme_key_get_ulong_attr (gpgme_key_t key, _gpgme_attr_t what, + const void *reserved, int idx) + _GPGME_DEPRECATED; + +/* Return the value of the attribute WHAT of a signature on user ID + UID_IDX in KEY, which has to be representable by a string. IDX + specifies the signature. Deprecated, use key structure directly + instead. */ +const char *gpgme_key_sig_get_string_attr (gpgme_key_t key, int uid_idx, + _gpgme_attr_t what, + const void *reserved, int idx) + _GPGME_DEPRECATED; + +/* Return the value of the attribute WHAT of a signature on user ID + UID_IDX in KEY, which has to be representable by an unsigned + integer string. IDX specifies the signature. Deprecated, use key + structure directly instead. */ +unsigned long gpgme_key_sig_get_ulong_attr (gpgme_key_t key, int uid_idx, + _gpgme_attr_t what, + const void *reserved, int idx) + _GPGME_DEPRECATED; + + +/* Crypto Operations. */ + +/* Cancel a pending asynchronous operation. */ +gpgme_error_t gpgme_cancel (gpgme_ctx_t ctx); + + +struct _gpgme_invalid_key +{ + struct _gpgme_invalid_key *next; + char *fpr; + gpgme_error_t reason; +}; +typedef struct _gpgme_invalid_key *gpgme_invalid_key_t; + + +/* Encryption. */ +struct _gpgme_op_encrypt_result +{ + /* The list of invalid recipients. */ + gpgme_invalid_key_t invalid_recipients; +}; +typedef struct _gpgme_op_encrypt_result *gpgme_encrypt_result_t; + +/* Retrieve a pointer to the result of the encrypt operation. */ +gpgme_encrypt_result_t gpgme_op_encrypt_result (gpgme_ctx_t ctx); + +/* The valid encryption flags. */ +typedef enum + { + GPGME_ENCRYPT_ALWAYS_TRUST = 1 + } +gpgme_encrypt_flags_t; + +/* Encrypt plaintext PLAIN within CTX for the recipients RECP and + store the resulting ciphertext in CIPHER. */ +gpgme_error_t gpgme_op_encrypt_start (gpgme_ctx_t ctx, gpgme_key_t recp[], + gpgme_encrypt_flags_t flags, + gpgme_data_t plain, gpgme_data_t cipher); +gpgme_error_t gpgme_op_encrypt (gpgme_ctx_t ctx, gpgme_key_t recp[], + gpgme_encrypt_flags_t flags, + gpgme_data_t plain, gpgme_data_t cipher); + +/* Encrypt plaintext PLAIN within CTX for the recipients RECP and + store the resulting ciphertext in CIPHER. Also sign the ciphertext + with the signers in CTX. */ +gpgme_error_t gpgme_op_encrypt_sign_start (gpgme_ctx_t ctx, + gpgme_key_t recp[], + gpgme_encrypt_flags_t flags, + gpgme_data_t plain, + gpgme_data_t cipher); +gpgme_error_t gpgme_op_encrypt_sign (gpgme_ctx_t ctx, gpgme_key_t recp[], + gpgme_encrypt_flags_t flags, + gpgme_data_t plain, gpgme_data_t cipher); + + +/* Decryption. */ + +struct _gpgme_recipient +{ + struct _gpgme_recipient *next; + + /* The key ID of key for which the text was encrypted. */ + char *keyid; + + /* Internal to GPGME, do not use. */ + char _keyid[16 + 1]; + + /* The public key algorithm of the recipient key. */ + gpgme_pubkey_algo_t pubkey_algo; + + /* The status of the recipient. */ + gpgme_error_t status; +}; +typedef struct _gpgme_recipient *gpgme_recipient_t; + +struct _gpgme_op_decrypt_result +{ + char *unsupported_algorithm; + + /* Key should not have been used for encryption. */ + unsigned int wrong_key_usage : 1; + + /* Internal to GPGME, do not use. */ + int _unused : 31; + + gpgme_recipient_t recipients; + + /* The original file name of the plaintext message, if + available. */ + char *file_name; +}; +typedef struct _gpgme_op_decrypt_result *gpgme_decrypt_result_t; + +/* Retrieve a pointer to the result of the decrypt operation. */ +gpgme_decrypt_result_t gpgme_op_decrypt_result (gpgme_ctx_t ctx); + +/* Decrypt ciphertext CIPHER within CTX and store the resulting + plaintext in PLAIN. */ +gpgme_error_t gpgme_op_decrypt_start (gpgme_ctx_t ctx, gpgme_data_t cipher, + gpgme_data_t plain); +gpgme_error_t gpgme_op_decrypt (gpgme_ctx_t ctx, + gpgme_data_t cipher, gpgme_data_t plain); + +/* Decrypt ciphertext CIPHER and make a signature verification within + CTX and store the resulting plaintext in PLAIN. */ +gpgme_error_t gpgme_op_decrypt_verify_start (gpgme_ctx_t ctx, + gpgme_data_t cipher, + gpgme_data_t plain); +gpgme_error_t gpgme_op_decrypt_verify (gpgme_ctx_t ctx, gpgme_data_t cipher, + gpgme_data_t plain); + + +/* Signing. */ +struct _gpgme_new_signature +{ + struct _gpgme_new_signature *next; + + /* The type of the signature. */ + gpgme_sig_mode_t type; + + /* The public key algorithm used to create the signature. */ + gpgme_pubkey_algo_t pubkey_algo; + + /* The hash algorithm used to create the signature. */ + gpgme_hash_algo_t hash_algo; + + /* Internal to GPGME, do not use. Must be set to the same value as + CLASS below. */ + unsigned long _obsolete_class; + + /* Signature creation time. */ + long int timestamp; + + /* The fingerprint of the signature. */ + char *fpr; + +#ifdef __cplusplus + unsigned int _obsolete_class_2; +#else + /* Must be set to SIG_CLASS below. */ + unsigned int class _GPGME_DEPRECATED; +#endif + + /* Crypto backend specific signature class. */ + unsigned int sig_class; +}; +typedef struct _gpgme_new_signature *gpgme_new_signature_t; + +struct _gpgme_op_sign_result +{ + /* The list of invalid signers. */ + gpgme_invalid_key_t invalid_signers; + gpgme_new_signature_t signatures; +}; +typedef struct _gpgme_op_sign_result *gpgme_sign_result_t; + +/* Retrieve a pointer to the result of the signing operation. */ +gpgme_sign_result_t gpgme_op_sign_result (gpgme_ctx_t ctx); + +/* Sign the plaintext PLAIN and store the signature in SIG. */ +gpgme_error_t gpgme_op_sign_start (gpgme_ctx_t ctx, + gpgme_data_t plain, gpgme_data_t sig, + gpgme_sig_mode_t mode); +gpgme_error_t gpgme_op_sign (gpgme_ctx_t ctx, + gpgme_data_t plain, gpgme_data_t sig, + gpgme_sig_mode_t mode); + + +/* Verify. */ + +/* Flags used for the SUMMARY field in a gpgme_signature_t. */ +typedef enum + { + GPGME_SIGSUM_VALID = 0x0001, /* The signature is fully valid. */ + GPGME_SIGSUM_GREEN = 0x0002, /* The signature is good. */ + GPGME_SIGSUM_RED = 0x0004, /* The signature is bad. */ + GPGME_SIGSUM_KEY_REVOKED = 0x0010, /* One key has been revoked. */ + GPGME_SIGSUM_KEY_EXPIRED = 0x0020, /* One key has expired. */ + GPGME_SIGSUM_SIG_EXPIRED = 0x0040, /* The signature has expired. */ + GPGME_SIGSUM_KEY_MISSING = 0x0080, /* Can't verify: key missing. */ + GPGME_SIGSUM_CRL_MISSING = 0x0100, /* CRL not available. */ + GPGME_SIGSUM_CRL_TOO_OLD = 0x0200, /* Available CRL is too old. */ + GPGME_SIGSUM_BAD_POLICY = 0x0400, /* A policy was not met. */ + GPGME_SIGSUM_SYS_ERROR = 0x0800 /* A system error occured. */ + } +gpgme_sigsum_t; + +struct _gpgme_signature +{ + struct _gpgme_signature *next; + + /* A summary of the signature status. */ + gpgme_sigsum_t summary; + + /* The fingerprint or key ID of the signature. */ + char *fpr; + + /* The status of the signature. */ + gpgme_error_t status; + + /* Notation data and policy URLs. */ + gpgme_sig_notation_t notations; + + /* Signature creation time. */ + unsigned long timestamp; + + /* Signature exipration time or 0. */ + unsigned long exp_timestamp; + + /* Key should not have been used for signing. */ + unsigned int wrong_key_usage : 1; + + /* PKA status: 0 = not available, 1 = bad, 2 = okay, 3 = RFU. */ + unsigned int pka_trust : 2; + + /* Validity has been verified using the chain model. */ + unsigned int chain_model : 1; + + /* Internal to GPGME, do not use. */ + int _unused : 28; + + gpgme_validity_t validity; + gpgme_error_t validity_reason; + + /* The public key algorithm used to create the signature. */ + gpgme_pubkey_algo_t pubkey_algo; + + /* The hash algorithm used to create the signature. */ + gpgme_hash_algo_t hash_algo; + + /* The mailbox from the PKA information or NULL. */ + char *pka_address; +}; +typedef struct _gpgme_signature *gpgme_signature_t; + +struct _gpgme_op_verify_result +{ + gpgme_signature_t signatures; + + /* The original file name of the plaintext message, if + available. */ + char *file_name; +}; +typedef struct _gpgme_op_verify_result *gpgme_verify_result_t; + +/* Retrieve a pointer to the result of the verify operation. */ +gpgme_verify_result_t gpgme_op_verify_result (gpgme_ctx_t ctx); + +/* Verify within CTX that SIG is a valid signature for TEXT. */ +gpgme_error_t gpgme_op_verify_start (gpgme_ctx_t ctx, gpgme_data_t sig, + gpgme_data_t signed_text, + gpgme_data_t plaintext); +gpgme_error_t gpgme_op_verify (gpgme_ctx_t ctx, gpgme_data_t sig, + gpgme_data_t signed_text, + gpgme_data_t plaintext); + + +/* Import. */ + +/* The key was new. */ +#define GPGME_IMPORT_NEW 1 + +/* The key contained new user IDs. */ +#define GPGME_IMPORT_UID 2 + +/* The key contained new signatures. */ +#define GPGME_IMPORT_SIG 4 + +/* The key contained new sub keys. */ +#define GPGME_IMPORT_SUBKEY 8 + +/* The key contained a secret key. */ +#define GPGME_IMPORT_SECRET 16 + + +struct _gpgme_import_status +{ + struct _gpgme_import_status *next; + + /* Fingerprint. */ + char *fpr; + + /* If a problem occured, the reason why the key could not be + imported. Otherwise GPGME_No_Error. */ + gpgme_error_t result; + + /* The result of the import, the GPGME_IMPORT_* values bit-wise + ORed. 0 means the key was already known and no new components + have been added. */ + unsigned int status; +}; +typedef struct _gpgme_import_status *gpgme_import_status_t; + +/* Import. */ +struct _gpgme_op_import_result +{ + /* Number of considered keys. */ + int considered; + + /* Keys without user ID. */ + int no_user_id; + + /* Imported keys. */ + int imported; + + /* Imported RSA keys. */ + int imported_rsa; + + /* Unchanged keys. */ + int unchanged; + + /* Number of new user ids. */ + int new_user_ids; + + /* Number of new sub keys. */ + int new_sub_keys; + + /* Number of new signatures. */ + int new_signatures; + + /* Number of new revocations. */ + int new_revocations; + + /* Number of secret keys read. */ + int secret_read; + + /* Number of secret keys imported. */ + int secret_imported; + + /* Number of secret keys unchanged. */ + int secret_unchanged; + + /* Number of new keys skipped. */ + int skipped_new_keys; + + /* Number of keys not imported. */ + int not_imported; + + /* List of keys for which an import was attempted. */ + gpgme_import_status_t imports; +}; +typedef struct _gpgme_op_import_result *gpgme_import_result_t; + +/* Retrieve a pointer to the result of the import operation. */ +gpgme_import_result_t gpgme_op_import_result (gpgme_ctx_t ctx); + +/* Import the key in KEYDATA into the keyring. */ +gpgme_error_t gpgme_op_import_start (gpgme_ctx_t ctx, gpgme_data_t keydata); +gpgme_error_t gpgme_op_import (gpgme_ctx_t ctx, gpgme_data_t keydata); +gpgme_error_t gpgme_op_import_ext (gpgme_ctx_t ctx, gpgme_data_t keydata, + int *nr) _GPGME_DEPRECATED; + + +/* Export the keys found by PATTERN into KEYDATA. */ +gpgme_error_t gpgme_op_export_start (gpgme_ctx_t ctx, const char *pattern, + unsigned int reserved, + gpgme_data_t keydata); +gpgme_error_t gpgme_op_export (gpgme_ctx_t ctx, const char *pattern, + unsigned int reserved, gpgme_data_t keydata); + +gpgme_error_t gpgme_op_export_ext_start (gpgme_ctx_t ctx, + const char *pattern[], + unsigned int reserved, + gpgme_data_t keydata); +gpgme_error_t gpgme_op_export_ext (gpgme_ctx_t ctx, const char *pattern[], + unsigned int reserved, + gpgme_data_t keydata); + + +/* Key generation. */ +struct _gpgme_op_genkey_result +{ + /* A primary key was generated. */ + unsigned int primary : 1; + + /* A sub key was generated. */ + unsigned int sub : 1; + + /* Internal to GPGME, do not use. */ + unsigned int _unused : 30; + + /* The fingerprint of the generated key. */ + char *fpr; +}; +typedef struct _gpgme_op_genkey_result *gpgme_genkey_result_t; + +/* Generate a new keypair and add it to the keyring. PUBKEY and + SECKEY should be null for now. PARMS specifies what keys should be + generated. */ +gpgme_error_t gpgme_op_genkey_start (gpgme_ctx_t ctx, const char *parms, + gpgme_data_t pubkey, gpgme_data_t seckey); +gpgme_error_t gpgme_op_genkey (gpgme_ctx_t ctx, const char *parms, + gpgme_data_t pubkey, gpgme_data_t seckey); + +/* Retrieve a pointer to the result of the genkey operation. */ +gpgme_genkey_result_t gpgme_op_genkey_result (gpgme_ctx_t ctx); + + +/* Delete KEY from the keyring. If ALLOW_SECRET is non-zero, secret + keys are also deleted. */ +gpgme_error_t gpgme_op_delete_start (gpgme_ctx_t ctx, const gpgme_key_t key, + int allow_secret); +gpgme_error_t gpgme_op_delete (gpgme_ctx_t ctx, const gpgme_key_t key, + int allow_secret); + + +/* Edit the key KEY. Send status and command requests to FNC and + output of edit commands to OUT. */ +gpgme_error_t gpgme_op_edit_start (gpgme_ctx_t ctx, gpgme_key_t key, + gpgme_edit_cb_t fnc, void *fnc_value, + gpgme_data_t out); +gpgme_error_t gpgme_op_edit (gpgme_ctx_t ctx, gpgme_key_t key, + gpgme_edit_cb_t fnc, void *fnc_value, + gpgme_data_t out); + +/* Edit the card for the key KEY. Send status and command requests to + FNC and output of edit commands to OUT. */ +gpgme_error_t gpgme_op_card_edit_start (gpgme_ctx_t ctx, gpgme_key_t key, + gpgme_edit_cb_t fnc, void *fnc_value, + gpgme_data_t out); +gpgme_error_t gpgme_op_card_edit (gpgme_ctx_t ctx, gpgme_key_t key, + gpgme_edit_cb_t fnc, void *fnc_value, + gpgme_data_t out); + + +/* Key management functions. */ +struct _gpgme_op_keylist_result +{ + unsigned int truncated : 1; + + /* Internal to GPGME, do not use. */ + unsigned int _unused : 31; +}; +typedef struct _gpgme_op_keylist_result *gpgme_keylist_result_t; + +/* Retrieve a pointer to the result of the key listing operation. */ +gpgme_keylist_result_t gpgme_op_keylist_result (gpgme_ctx_t ctx); + +/* Start a keylist operation within CTX, searching for keys which + match PATTERN. If SECRET_ONLY is true, only secret keys are + returned. */ +gpgme_error_t gpgme_op_keylist_start (gpgme_ctx_t ctx, const char *pattern, + int secret_only); +gpgme_error_t gpgme_op_keylist_ext_start (gpgme_ctx_t ctx, + const char *pattern[], + int secret_only, int reserved); + +/* Return the next key from the keylist in R_KEY. */ +gpgme_error_t gpgme_op_keylist_next (gpgme_ctx_t ctx, gpgme_key_t *r_key); + +/* Terminate a pending keylist operation within CTX. */ +gpgme_error_t gpgme_op_keylist_end (gpgme_ctx_t ctx); + + +/* Trust items and operations. */ + +struct _gpgme_trust_item +{ + /* Internal to GPGME, do not use. */ + unsigned int _refs; + + /* The key ID to which the trust item belongs. */ + char *keyid; + + /* Internal to GPGME, do not use. */ + char _keyid[16 + 1]; + + /* The type of the trust item, 1 refers to a key, 2 to a user ID. */ + int type; + + /* The trust level. */ + int level; + + /* The owner trust if TYPE is 1. */ + char *owner_trust; + + /* Internal to GPGME, do not use. */ + char _owner_trust[2]; + + /* The calculated validity. */ + char *validity; + + /* Internal to GPGME, do not use. */ + char _validity[2]; + + /* The user name if TYPE is 2. */ + char *name; +}; +typedef struct _gpgme_trust_item *gpgme_trust_item_t; + +/* Start a trustlist operation within CTX, searching for trust items + which match PATTERN. */ +gpgme_error_t gpgme_op_trustlist_start (gpgme_ctx_t ctx, + const char *pattern, int max_level); + +/* Return the next trust item from the trustlist in R_ITEM. */ +gpgme_error_t gpgme_op_trustlist_next (gpgme_ctx_t ctx, + gpgme_trust_item_t *r_item); + +/* Terminate a pending trustlist operation within CTX. */ +gpgme_error_t gpgme_op_trustlist_end (gpgme_ctx_t ctx); + +/* Acquire a reference to ITEM. */ +void gpgme_trust_item_ref (gpgme_trust_item_t item); + +/* Release a reference to ITEM. If this was the last one the trust + item is destroyed. */ +void gpgme_trust_item_unref (gpgme_trust_item_t item); + +/* Release the trust item ITEM. Deprecated, use + gpgme_trust_item_unref. */ +void gpgme_trust_item_release (gpgme_trust_item_t item) _GPGME_DEPRECATED; + +/* Return the value of the attribute WHAT of ITEM, which has to be + representable by a string. Deprecated, use trust item structure + directly. */ +const char *gpgme_trust_item_get_string_attr (gpgme_trust_item_t item, + _gpgme_attr_t what, + const void *reserved, int idx) + _GPGME_DEPRECATED; + +/* Return the value of the attribute WHAT of KEY, which has to be + representable by an integer. IDX specifies a running index if the + attribute appears more than once in the key. Deprecated, use trust + item structure directly. */ +int gpgme_trust_item_get_int_attr (gpgme_trust_item_t item, _gpgme_attr_t what, + const void *reserved, int idx) + _GPGME_DEPRECATED; + + +/* Return the auditlog for the current session. This may be called + after a successful or failed operation. If no audit log is + available GPG_ERR_NO_DATA is returned. */ +gpgme_error_t gpgme_op_getauditlog_start (gpgme_ctx_t ctx, gpgme_data_t output, + unsigned int flags); +gpgme_error_t gpgme_op_getauditlog (gpgme_ctx_t ctx, gpgme_data_t output, + unsigned int flags); + + +/* Interface to gpg-conf. */ + +/* The expert level at which a configuration option or group of + options should be displayed. See the gpg-conf documentation for + more details. */ +typedef enum + { + GPGME_CONF_BASIC = 0, + GPGME_CONF_ADVANCED = 1, + GPGME_CONF_EXPERT = 2, + GPGME_CONF_INVISIBLE = 3, + GPGME_CONF_INTERNAL = 4 + } +gpgme_conf_level_t; + + +/* The data type of a configuration option argument. See the gpg-conf + documentation for more details. */ +typedef enum + { + /* Basic types. */ + GPGME_CONF_NONE = 0, + GPGME_CONF_STRING = 1, + GPGME_CONF_INT32 = 2, + GPGME_CONF_UINT32 = 3, + + /* Complex types. */ + GPGME_CONF_PATHNAME = 32, + GPGME_CONF_LDAP_SERVER = 33 + } +gpgme_conf_type_t; + + +/* This represents a single argument for a configuration option. + Which of the members of value is used depends on the ALT_TYPE. */ +typedef struct gpgme_conf_arg +{ + struct gpgme_conf_arg *next; + /* True if the option appears without an (optional) argument. */ + unsigned int no_arg; + union + { + unsigned int count; + unsigned int uint32; + int int32; + char *string; + } value; +} *gpgme_conf_arg_t; + + +/* The flags of a configuration option. See the gpg-conf + documentation for details. */ +#define GPGME_CONF_GROUP (1 << 0) +#define GPGME_CONF_OPTIONAL (1 << 1) +#define GPGME_CONF_LIST (1 << 2) +#define GPGME_CONF_RUNTIME (1 << 3) +#define GPGME_CONF_DEFAULT (1 << 4) +#define GPGME_CONF_DEFAULT_DESC (1 << 5) +#define GPGME_CONF_NO_ARG_DESC (1 << 6) +#define GPGME_CONF_NO_CHANGE (1 << 7) + + +/* The representation of a single configuration option. See the + gpg-conf documentation for details. */ +typedef struct gpgme_conf_opt +{ + struct gpgme_conf_opt *next; + + /* The option name. */ + char *name; + + /* The flags for this option. */ + unsigned int flags; + + /* The level of this option. */ + gpgme_conf_level_t level; + + /* The localized description of this option. */ + char *description; + + /* The type and alternate type of this option. */ + gpgme_conf_type_t type; + gpgme_conf_type_t alt_type; + + /* The localized (short) name of the argument, if any. */ + char *argname; + + /* The default value. */ + gpgme_conf_arg_t default_value; + char *default_description; + + /* The default value if the option is not set. */ + gpgme_conf_arg_t no_arg_value; + char *no_arg_description; + + /* The current value if the option is set. */ + gpgme_conf_arg_t value; + + /* The new value, if any. NULL means reset to default. */ + int change_value; + gpgme_conf_arg_t new_value; + + /* Free for application use. */ + void *user_data; +} *gpgme_conf_opt_t; + + +/* The representation of a component that can be configured. See the + gpg-conf documentation for details. */ +typedef struct gpgme_conf_comp +{ + struct gpgme_conf_comp *next; + + /* Internal to GPGME, do not use! */ + gpgme_conf_opt_t *_last_opt_p; + + /* The component name. */ + char *name; + + /* A human-readable description for the component. */ + char *description; + + /* The program name (an absolute path to the program). */ + char *program_name; + + /* A linked list of options for this component. */ + struct gpgme_conf_opt *options; +} *gpgme_conf_comp_t; + + +/* Allocate a new gpgme_conf_arg_t. If VALUE is NULL, a "no arg + default" is prepared. If type is a string type, VALUE should point + to the string. Else, it should point to an unsigned or signed + integer respectively. */ +gpgme_error_t gpgme_conf_arg_new (gpgme_conf_arg_t *arg_p, + gpgme_conf_type_t type, void *value); + +/* This also releases all chained argument structures! */ +void gpgme_conf_arg_release (gpgme_conf_arg_t arg, gpgme_conf_type_t type); + +/* Register a change for the value of OPT to ARG. If RESET is 1 (do + not use any values but 0 or 1), ARG is ignored and the option is + not changed (reverting a previous change). Otherwise, if ARG is + NULL, the option is cleared or reset to its default. */ +gpgme_error_t gpgme_conf_opt_change (gpgme_conf_opt_t opt, int reset, + gpgme_conf_arg_t arg); + +/* Release a set of configurations. */ +void gpgme_conf_release (gpgme_conf_comp_t conf); + +/* Retrieve the current configurations. */ +gpgme_error_t gpgme_op_conf_load (gpgme_ctx_t ctx, gpgme_conf_comp_t *conf_p); + +/* Save the configuration of component comp. This function does not + follow chained components! */ +gpgme_error_t gpgme_op_conf_save (gpgme_ctx_t ctx, gpgme_conf_comp_t comp); + + +/* Various functions. */ + +/* Check that the library fulfills the version requirement. */ +const char *gpgme_check_version (const char *req_version); + +/* Get the information about the configured and installed engines. A + pointer to the first engine in the statically allocated linked list + is returned in *INFO. If an error occurs, it is returned. The + returned data is valid until the next gpgme_set_engine_info. */ +gpgme_error_t gpgme_get_engine_info (gpgme_engine_info_t *engine_info); + +/* Set the default engine info for the protocol PROTO to the file name + FILE_NAME and the home directory HOME_DIR. */ +gpgme_error_t gpgme_set_engine_info (gpgme_protocol_t proto, + const char *file_name, + const char *home_dir); + + +/* Engine support functions. */ + +/* Verify that the engine implementing PROTO is installed and + available. */ +gpgme_error_t gpgme_engine_check_version (gpgme_protocol_t proto); + + +/* Deprecated types. */ +typedef gpgme_ctx_t GpgmeCtx _GPGME_DEPRECATED; +typedef gpgme_data_t GpgmeData _GPGME_DEPRECATED; +typedef gpgme_error_t GpgmeError _GPGME_DEPRECATED; +typedef gpgme_data_encoding_t GpgmeDataEncoding _GPGME_DEPRECATED; +typedef gpgme_pubkey_algo_t GpgmePubKeyAlgo _GPGME_DEPRECATED; +typedef gpgme_hash_algo_t GpgmeHashAlgo _GPGME_DEPRECATED; +typedef gpgme_sig_stat_t GpgmeSigStat _GPGME_DEPRECATED; +typedef gpgme_sig_mode_t GpgmeSigMode _GPGME_DEPRECATED; +typedef gpgme_attr_t GpgmeAttr _GPGME_DEPRECATED; +typedef gpgme_validity_t GpgmeValidity _GPGME_DEPRECATED; +typedef gpgme_protocol_t GpgmeProtocol _GPGME_DEPRECATED; +typedef gpgme_engine_info_t GpgmeEngineInfo _GPGME_DEPRECATED; +typedef gpgme_subkey_t GpgmeSubkey _GPGME_DEPRECATED; +typedef gpgme_key_sig_t GpgmeKeySig _GPGME_DEPRECATED; +typedef gpgme_user_id_t GpgmeUserID _GPGME_DEPRECATED; +typedef gpgme_key_t GpgmeKey _GPGME_DEPRECATED; +typedef gpgme_passphrase_cb_t GpgmePassphraseCb _GPGME_DEPRECATED; +typedef gpgme_progress_cb_t GpgmeProgressCb _GPGME_DEPRECATED; +typedef gpgme_io_cb_t GpgmeIOCb _GPGME_DEPRECATED; +typedef gpgme_register_io_cb_t GpgmeRegisterIOCb _GPGME_DEPRECATED; +typedef gpgme_remove_io_cb_t GpgmeRemoveIOCb _GPGME_DEPRECATED; +typedef gpgme_event_io_t GpgmeEventIO _GPGME_DEPRECATED; +typedef gpgme_event_io_cb_t GpgmeEventIOCb _GPGME_DEPRECATED; +#define GpgmeIOCbs gpgme_io_cbs +typedef gpgme_data_read_cb_t GpgmeDataReadCb _GPGME_DEPRECATED; +typedef gpgme_data_write_cb_t GpgmeDataWriteCb _GPGME_DEPRECATED; +typedef gpgme_data_seek_cb_t GpgmeDataSeekCb _GPGME_DEPRECATED; +typedef gpgme_data_release_cb_t GpgmeDataReleaseCb _GPGME_DEPRECATED; +#define GpgmeDataCbs gpgme_data_cbs +typedef gpgme_encrypt_result_t GpgmeEncryptResult _GPGME_DEPRECATED; +typedef gpgme_sig_notation_t GpgmeSigNotation _GPGME_DEPRECATED; +typedef gpgme_signature_t GpgmeSignature _GPGME_DEPRECATED; +typedef gpgme_verify_result_t GpgmeVerifyResult _GPGME_DEPRECATED; +typedef gpgme_import_status_t GpgmeImportStatus _GPGME_DEPRECATED; +typedef gpgme_import_result_t GpgmeImportResult _GPGME_DEPRECATED; +typedef gpgme_genkey_result_t GpgmeGenKeyResult _GPGME_DEPRECATED; +typedef gpgme_trust_item_t GpgmeTrustItem _GPGME_DEPRECATED; +typedef gpgme_status_code_t GpgmeStatusCode _GPGME_DEPRECATED; + +#ifdef __cplusplus +} +#endif +#endif /* GPGME_H */ diff --git a/tags/gpgme-1.1.6/gpgme/gpgme.m4 b/tags/gpgme-1.1.6/gpgme/gpgme.m4 new file mode 100644 index 0000000..44bf43c --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/gpgme.m4 @@ -0,0 +1,307 @@ +# gpgme.m4 - autoconf macro to detect GPGME. +# Copyright (C) 2002, 2003, 2004 g10 Code GmbH +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This file is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + +AC_DEFUN([_AM_PATH_GPGME_CONFIG], +[ AC_ARG_WITH(gpgme-prefix, + AC_HELP_STRING([--with-gpgme-prefix=PFX], + [prefix where GPGME is installed (optional)]), + gpgme_config_prefix="$withval", gpgme_config_prefix="") + if test "x$gpgme_config_prefix" != x ; then + GPGME_CONFIG="$gpgme_config_prefix/bin/gpgme-config" + fi + AC_PATH_PROG(GPGME_CONFIG, gpgme-config, no) + + if test "$GPGME_CONFIG" != "no" ; then + gpgme_version=`$GPGME_CONFIG --version` + fi + gpgme_version_major=`echo $gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` + gpgme_version_minor=`echo $gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` + gpgme_version_micro=`echo $gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'` +]) + +dnl AM_PATH_GPGME([MINIMUM-VERSION, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl Test for libgpgme and define GPGME_CFLAGS and GPGME_LIBS. +dnl +AC_DEFUN([AM_PATH_GPGME], +[ AC_REQUIRE([_AM_PATH_GPGME_CONFIG])dnl + tmp=ifelse([$1], ,1:0.4.2,$1) + if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then + req_gpgme_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` + min_gpgme_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` + else + req_gpgme_api=0 + min_gpgme_version="$tmp" + fi + + AC_MSG_CHECKING(for GPGME - version >= $min_gpgme_version) + ok=no + if test "$GPGME_CONFIG" != "no" ; then + req_major=`echo $min_gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` + req_minor=`echo $min_gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` + req_micro=`echo $min_gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` + if test "$gpgme_version_major" -gt "$req_major"; then + ok=yes + else + if test "$gpgme_version_major" -eq "$req_major"; then + if test "$gpgme_version_minor" -gt "$req_minor"; then + ok=yes + else + if test "$gpgme_version_minor" -eq "$req_minor"; then + if test "$gpgme_version_micro" -ge "$req_micro"; then + ok=yes + fi + fi + fi + fi + fi + fi + if test $ok = yes; then + # If we have a recent GPGME, we should also check that the + # API is compatible. + if test "$req_gpgme_api" -gt 0 ; then + tmp=`$GPGME_CONFIG --api-version 2>/dev/null || echo 0` + if test "$tmp" -gt 0 ; then + if test "$req_gpgme_api" -ne "$tmp" ; then + ok=no + fi + fi + fi + fi + if test $ok = yes; then + GPGME_CFLAGS=`$GPGME_CONFIG --cflags` + GPGME_LIBS=`$GPGME_CONFIG --libs` + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + GPGME_CFLAGS="" + GPGME_LIBS="" + AC_MSG_RESULT(no) + ifelse([$3], , :, [$3]) + fi + AC_SUBST(GPGME_CFLAGS) + AC_SUBST(GPGME_LIBS) +]) + +dnl AM_PATH_GPGME_PTH([MINIMUM-VERSION, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl Test for libgpgme and define GPGME_PTH_CFLAGS and GPGME_PTH_LIBS. +dnl +AC_DEFUN([AM_PATH_GPGME_PTH], +[ AC_REQUIRE([_AM_PATH_GPGME_CONFIG])dnl + tmp=ifelse([$1], ,1:0.4.2,$1) + if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then + req_gpgme_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` + min_gpgme_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` + else + req_gpgme_api=0 + min_gpgme_version="$tmp" + fi + + AC_MSG_CHECKING(for GPGME Pth - version >= $min_gpgme_version) + ok=no + if test "$GPGME_CONFIG" != "no" ; then + if `$GPGME_CONFIG --thread=pth 2> /dev/null` ; then + req_major=`echo $min_gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` + req_minor=`echo $min_gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` + req_micro=`echo $min_gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` + if test "$gpgme_version_major" -gt "$req_major"; then + ok=yes + else + if test "$gpgme_version_major" -eq "$req_major"; then + if test "$gpgme_version_minor" -gt "$req_minor"; then + ok=yes + else + if test "$gpgme_version_minor" -eq "$req_minor"; then + if test "$gpgme_version_micro" -ge "$req_micro"; then + ok=yes + fi + fi + fi + fi + fi + fi + fi + if test $ok = yes; then + # If we have a recent GPGME, we should also check that the + # API is compatible. + if test "$req_gpgme_api" -gt 0 ; then + tmp=`$GPGME_CONFIG --api-version 2>/dev/null || echo 0` + if test "$tmp" -gt 0 ; then + if test "$req_gpgme_api" -ne "$tmp" ; then + ok=no + fi + fi + fi + fi + if test $ok = yes; then + GPGME_PTH_CFLAGS=`$GPGME_CONFIG --thread=pth --cflags` + GPGME_PTH_LIBS=`$GPGME_CONFIG --thread=pth --libs` + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + GPGME_PTH_CFLAGS="" + GPGME_PTH_LIBS="" + AC_MSG_RESULT(no) + ifelse([$3], , :, [$3]) + fi + AC_SUBST(GPGME_PTH_CFLAGS) + AC_SUBST(GPGME_PTH_LIBS) +]) + +dnl AM_PATH_GPGME_PTHREAD([MINIMUM-VERSION, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl Test for libgpgme and define GPGME_PTHREAD_CFLAGS +dnl and GPGME_PTHREAD_LIBS. +dnl +AC_DEFUN([AM_PATH_GPGME_PTHREAD], +[ AC_REQUIRE([_AM_PATH_GPGME_CONFIG])dnl + tmp=ifelse([$1], ,1:0.4.2,$1) + if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then + req_gpgme_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` + min_gpgme_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` + else + req_gpgme_api=0 + min_gpgme_version="$tmp" + fi + + AC_MSG_CHECKING(for GPGME pthread - version >= $min_gpgme_version) + ok=no + if test "$GPGME_CONFIG" != "no" ; then + if `$GPGME_CONFIG --thread=pthread 2> /dev/null` ; then + req_major=`echo $min_gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` + req_minor=`echo $min_gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` + req_micro=`echo $min_gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` + if test "$gpgme_version_major" -gt "$req_major"; then + ok=yes + else + if test "$gpgme_version_major" -eq "$req_major"; then + if test "$gpgme_version_minor" -gt "$req_minor"; then + ok=yes + else + if test "$gpgme_version_minor" -eq "$req_minor"; then + if test "$gpgme_version_micro" -ge "$req_micro"; then + ok=yes + fi + fi + fi + fi + fi + fi + fi + if test $ok = yes; then + # If we have a recent GPGME, we should also check that the + # API is compatible. + if test "$req_gpgme_api" -gt 0 ; then + tmp=`$GPGME_CONFIG --api-version 2>/dev/null || echo 0` + if test "$tmp" -gt 0 ; then + if test "$req_gpgme_api" -ne "$tmp" ; then + ok=no + fi + fi + fi + fi + if test $ok = yes; then + GPGME_PTHREAD_CFLAGS=`$GPGME_CONFIG --thread=pthread --cflags` + GPGME_PTHREAD_LIBS=`$GPGME_CONFIG --thread=pthread --libs` + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + GPGME_PTHREAD_CFLAGS="" + GPGME_PTHREAD_LIBS="" + AC_MSG_RESULT(no) + ifelse([$3], , :, [$3]) + fi + AC_SUBST(GPGME_PTHREAD_CFLAGS) + AC_SUBST(GPGME_PTHREAD_LIBS) +]) + + +dnl AM_PATH_GPGME_GLIB([MINIMUM-VERSION, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl Test for libgpgme-glib and define GPGME_GLIB_CFLAGS and GPGME_GLIB_LIBS. +dnl +AC_DEFUN([AM_PATH_GPGME_GLIB], +[ AC_REQUIRE([_AM_PATH_GPGME_CONFIG])dnl + tmp=ifelse([$1], ,1:0.4.2,$1) + if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then + req_gpgme_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` + min_gpgme_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` + else + req_gpgme_api=0 + min_gpgme_version="$tmp" + fi + + AC_MSG_CHECKING(for GPGME - version >= $min_gpgme_version) + ok=no + if test "$GPGME_CONFIG" != "no" ; then + req_major=`echo $min_gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` + req_minor=`echo $min_gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` + req_micro=`echo $min_gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` + if test "$gpgme_version_major" -gt "$req_major"; then + ok=yes + else + if test "$gpgme_version_major" -eq "$req_major"; then + if test "$gpgme_version_minor" -gt "$req_minor"; then + ok=yes + else + if test "$gpgme_version_minor" -eq "$req_minor"; then + if test "$gpgme_version_micro" -ge "$req_micro"; then + ok=yes + fi + fi + fi + fi + fi + fi + if test $ok = yes; then + # If we have a recent GPGME, we should also check that the + # API is compatible. + if test "$req_gpgme_api" -gt 0 ; then + tmp=`$GPGME_CONFIG --api-version 2>/dev/null || echo 0` + if test "$tmp" -gt 0 ; then + if test "$req_gpgme_api" -ne "$tmp" ; then + ok=no + fi + fi + fi + fi + if test $ok = yes; then + GPGME_GLIB_CFLAGS=`$GPGME_CONFIG --glib --cflags` + GPGME_GLIB_LIBS=`$GPGME_CONFIG --glib --libs` + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + GPGME_GLIB_CFLAGS="" + GPGME_GLIB_LIBS="" + AC_MSG_RESULT(no) + ifelse([$3], , :, [$3]) + fi + AC_SUBST(GPGME_GLIB_CFLAGS) + AC_SUBST(GPGME_GLIB_LIBS) +]) + diff --git a/tags/gpgme-1.1.6/gpgme/import.c b/tags/gpgme-1.1.6/gpgme/import.c new file mode 100644 index 0000000..ad6b776 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/import.c @@ -0,0 +1,273 @@ +/* import.c - Import a key. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif +#include +#include +#include + +#include "gpgme.h" +#include "context.h" +#include "ops.h" + + +typedef struct +{ + struct _gpgme_op_import_result result; + + /* A pointer to the next pointer of the last import status in the + list. This makes appending new imports painless while preserving + the order. */ + gpgme_import_status_t *lastp; +} *op_data_t; + + +static void +release_op_data (void *hook) +{ + op_data_t opd = (op_data_t) hook; + gpgme_import_status_t import = opd->result.imports; + + while (import) + { + gpgme_import_status_t next = import->next; + free (import->fpr); + free (import); + import = next; + } +} + + +gpgme_import_result_t +gpgme_op_import_result (gpgme_ctx_t ctx) +{ + void *hook; + op_data_t opd; + gpgme_error_t err; + + err = _gpgme_op_data_lookup (ctx, OPDATA_IMPORT, &hook, -1, NULL); + opd = hook; + if (err || !opd) + return NULL; + + return &opd->result; +} + + +static gpgme_error_t +parse_import (char *args, gpgme_import_status_t *import_status, int problem) +{ + gpgme_import_status_t import; + char *tail; + long int nr; + + import = malloc (sizeof (*import)); + if (!import) + return gpg_error_from_errno (errno); + import->next = NULL; + + errno = 0; + nr = strtol (args, &tail, 0); + if (errno || args == tail || *tail != ' ') + { + /* The crypto backend does not behave. */ + free (import); + return gpg_error (GPG_ERR_INV_ENGINE); + } + args = tail; + + if (problem) + { + switch (nr) + { + case 0: + case 4: + default: + import->result = gpg_error (GPG_ERR_GENERAL); + break; + + case 1: + import->result = gpg_error (GPG_ERR_BAD_CERT); + break; + + case 2: + import->result = gpg_error (GPG_ERR_MISSING_CERT); + break; + + case 3: + import->result = gpg_error (GPG_ERR_BAD_CERT_CHAIN); + break; + } + import->status = 0; + } + else + { + import->result = gpg_error (GPG_ERR_NO_ERROR); + import->status = nr; + } + + while (*args == ' ') + args++; + tail = strchr (args, ' '); + if (tail) + *tail = '\0'; + + import->fpr = strdup (args); + if (!import->fpr) + { + int saved_errno = errno; + free (import); + return gpg_error_from_errno (saved_errno); + } + + *import_status = import; + return 0; +} + + + +gpgme_error_t +parse_import_res (char *args, gpgme_import_result_t result) +{ + char *tail; + + errno = 0; + +#define PARSE_NEXT(x) \ + (x) = strtol (args, &tail, 0); \ + if (errno || args == tail || *tail != ' ') \ + /* The crypto backend does not behave. */ \ + return gpg_error (GPG_ERR_INV_ENGINE); \ + args = tail; + + PARSE_NEXT (result->considered); + PARSE_NEXT (result->no_user_id); + PARSE_NEXT (result->imported); + PARSE_NEXT (result->imported_rsa); + PARSE_NEXT (result->unchanged); + PARSE_NEXT (result->new_user_ids); + PARSE_NEXT (result->new_sub_keys); + PARSE_NEXT (result->new_signatures); + PARSE_NEXT (result->new_revocations); + PARSE_NEXT (result->secret_read); + PARSE_NEXT (result->secret_imported); + PARSE_NEXT (result->secret_unchanged); + PARSE_NEXT (result->skipped_new_keys); + PARSE_NEXT (result->not_imported); + + return 0; +} + + +static gpgme_error_t +import_status_handler (void *priv, gpgme_status_code_t code, char *args) +{ + gpgme_ctx_t ctx = (gpgme_ctx_t) priv; + gpgme_error_t err; + void *hook; + op_data_t opd; + + err = _gpgme_op_data_lookup (ctx, OPDATA_IMPORT, &hook, -1, NULL); + opd = hook; + if (err) + return err; + + switch (code) + { + case GPGME_STATUS_IMPORT_OK: + case GPGME_STATUS_IMPORT_PROBLEM: + err = parse_import (args, opd->lastp, + code == GPGME_STATUS_IMPORT_OK ? 0 : 1); + if (err) + return err; + + opd->lastp = &(*opd->lastp)->next; + break; + + case GPGME_STATUS_IMPORT_RES: + err = parse_import_res (args, &opd->result); + break; + + default: + break; + } + return 0; +} + + +static gpgme_error_t +_gpgme_op_import_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t keydata) +{ + gpgme_error_t err; + void *hook; + op_data_t opd; + + err = _gpgme_op_reset (ctx, synchronous); + if (err) + return err; + + err = _gpgme_op_data_lookup (ctx, OPDATA_IMPORT, &hook, + sizeof (*opd), release_op_data); + opd = hook; + if (err) + return err; + opd->lastp = &opd->result.imports; + + if (!keydata) + return gpg_error (GPG_ERR_NO_DATA); + + _gpgme_engine_set_status_handler (ctx->engine, import_status_handler, ctx); + + return _gpgme_engine_op_import (ctx->engine, keydata); +} + + +gpgme_error_t +gpgme_op_import_start (gpgme_ctx_t ctx, gpgme_data_t keydata) +{ + return _gpgme_op_import_start (ctx, 0, keydata); +} + + +/* Import the key in KEYDATA into the keyring. */ +gpgme_error_t +gpgme_op_import (gpgme_ctx_t ctx, gpgme_data_t keydata) +{ + gpgme_error_t err = _gpgme_op_import_start (ctx, 1, keydata); + if (!err) + err = _gpgme_wait_one (ctx); + return err; +} + + +gpgme_error_t +gpgme_op_import_ext (gpgme_ctx_t ctx, gpgme_data_t keydata, int *nr) +{ + gpgme_error_t err = gpgme_op_import (ctx, keydata); + if (!err && nr) + { + gpgme_import_result_t result = gpgme_op_import_result (ctx); + *nr = result->considered; + } + return err; +} diff --git a/tags/gpgme-1.1.6/gpgme/isascii.c b/tags/gpgme-1.1.6/gpgme/isascii.c new file mode 100644 index 0000000..924ced0 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/isascii.c @@ -0,0 +1,28 @@ +/* Copyright (C) 1991,92,93,95,96,97,98,99,2001,2002,2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +int +isascii (int c) +{ + return (((c) & ~0x7f) == 0); +} diff --git a/tags/gpgme-1.1.6/gpgme/kdpipeiodevice.cpp b/tags/gpgme-1.1.6/gpgme/kdpipeiodevice.cpp new file mode 100644 index 0000000..9e0179c --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/kdpipeiodevice.cpp @@ -0,0 +1,940 @@ +/* + Copyright (C) 2007 Klarälvdalens Datakonsult AB + + KDPipeIODevice is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + KDPipeIODevice 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with KDPipeIODevice; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kdpipeiodevice.h" + +#include + +#include +#include +#include + +#ifdef Q_OS_WIN32 +# ifndef NOMINMAX +# define NOMINMAX +# endif +# include +# include +#else +# include +# include +#endif + +using namespace _gpgme_; + +#ifndef KDAB_CHECK_THIS +# define KDAB_CHECK_CTOR (void)1 +# define KDAB_CHECK_DTOR KDAB_CHECK_CTOR +# define KDAB_CHECK_THIS KDAB_CHECK_CTOR +#endif + +#define LOCKED( d ) const QMutexLocker locker( &d->mutex ) +#define synchronized( d ) if ( int i = 0 ) {} else for ( const QMutexLocker locker( &d->mutex ) ; !i ; ++i ) + +const unsigned int BUFFER_SIZE = 4096; +const bool ALLOW_QIODEVICE_BUFFERING = true; + +// comment to get trace output: +//#define qDebug if(1){}else qDebug + +namespace { +class Reader : public QThread { + Q_OBJECT +public: + Reader( int fd, Qt::HANDLE handle ); + ~Reader(); + + qint64 readData( char * data, qint64 maxSize ); + + unsigned int bytesInBuffer() const { + return ( wptr + sizeof buffer - rptr ) % sizeof buffer ; + } + + bool bufferFull() const { + return bytesInBuffer() == sizeof buffer - 1; + } + + bool bufferEmpty() const { + return bytesInBuffer() == 0; + } + + bool bufferContains( char ch ) { + const unsigned int bib = bytesInBuffer(); + for ( unsigned int i = rptr ; i < rptr + bib ; ++i ) + if ( buffer[i%sizeof buffer] == ch ) + return true; + return false; + } + + void notifyReadyRead(); + +Q_SIGNALS: + void readyRead(); + +protected: + /* reimp */ void run(); + +private: + int fd; + Qt::HANDLE handle; +public: + QMutex mutex; + QWaitCondition waitForCancelCondition; + QWaitCondition bufferNotFullCondition; + QWaitCondition bufferNotEmptyCondition; + QWaitCondition hasStarted; + QWaitCondition readyReadSentCondition; + QWaitCondition blockedConsumerIsDoneCondition; + bool cancel; + bool eof; + bool error; + bool eofShortCut; + int errorCode; + bool consumerBlocksOnUs; + +private: + unsigned int rptr, wptr; + char buffer[BUFFER_SIZE+1]; // need to keep one byte free to detect empty state +}; + + +Reader::Reader( int fd_, Qt::HANDLE handle_ ) + : QThread(), + fd( fd_ ), + handle( handle_ ), + mutex(), + bufferNotFullCondition(), + bufferNotEmptyCondition(), + hasStarted(), + cancel( false ), + eof( false ), + error( false ), + eofShortCut( false ), + errorCode( 0 ), + consumerBlocksOnUs( false ), + rptr( 0 ), wptr( 0 ) +{ + +} + +Reader::~Reader() {} + + +class Writer : public QThread { + Q_OBJECT +public: + Writer( int fd, Qt::HANDLE handle ); + ~Writer(); + + qint64 writeData( const char * data, qint64 size ); + + unsigned int bytesInBuffer() const { return numBytesInBuffer; } + + bool bufferFull() const { + return numBytesInBuffer == sizeof buffer; + } + + bool bufferEmpty() const { + return numBytesInBuffer == 0; + } + +Q_SIGNALS: + void bytesWritten( qint64 ); + +protected: + /* reimp */ void run(); + +private: + int fd; + Qt::HANDLE handle; +public: + QMutex mutex; + QWaitCondition bufferEmptyCondition; + QWaitCondition bufferNotEmptyCondition; + QWaitCondition hasStarted; + bool cancel; + bool error; + int errorCode; +private: + unsigned int numBytesInBuffer; + char buffer[BUFFER_SIZE]; +}; +} + +Writer::Writer( int fd_, Qt::HANDLE handle_ ) + : QThread(), + fd( fd_ ), + handle( handle_ ), + mutex(), + bufferEmptyCondition(), + bufferNotEmptyCondition(), + hasStarted(), + cancel( false ), + error( false ), + errorCode( 0 ), + numBytesInBuffer( 0 ) +{ + +} + +Writer::~Writer() {} + + +class KDPipeIODevice::Private : public QObject { +Q_OBJECT + friend class ::KDPipeIODevice; + KDPipeIODevice * const q; +public: + explicit Private( KDPipeIODevice * qq ); + ~Private(); + + bool doOpen( int, Qt::HANDLE, OpenMode ); + bool startReaderThread(); + bool startWriterThread(); + void stopThreads(); + +public Q_SLOTS: + void emitReadyRead(); + +private: + int fd; + Qt::HANDLE handle; + Reader * reader; + Writer * writer; + bool triedToStartReader; + bool triedToStartWriter; +}; + +KDPipeIODevice::Private::Private( KDPipeIODevice * qq ) + : QObject( qq ), q( qq ), + fd( -1 ), + handle( 0 ), + reader( 0 ), + writer( 0 ), + triedToStartReader( false ), triedToStartWriter( false ) +{ + +} + +KDPipeIODevice::Private::~Private() { + qDebug( "KDPipeIODevice::~Private(): Destroying %p", q ); +} + +KDPipeIODevice::KDPipeIODevice( QObject * p ) + : QIODevice( p ), d( new Private( this ) ) +{ + KDAB_CHECK_CTOR; +} + +KDPipeIODevice::KDPipeIODevice( int fd, OpenMode mode, QObject * p ) + : QIODevice( p ), d( new Private( this ) ) +{ + KDAB_CHECK_CTOR; + open( fd, mode ); +} + +KDPipeIODevice::KDPipeIODevice( Qt::HANDLE handle, OpenMode mode, QObject * p ) + : QIODevice( p ), d( new Private( this ) ) +{ + KDAB_CHECK_CTOR; + open( handle, mode ); +} + +KDPipeIODevice::~KDPipeIODevice() { KDAB_CHECK_DTOR; + if ( isOpen() ) + close(); + delete d; d = 0; +} + + +bool KDPipeIODevice::open( int fd, OpenMode mode ) { KDAB_CHECK_THIS; + +#ifdef Q_OS_WIN32 + return d->doOpen( fd, (HANDLE)_get_osfhandle( fd ), mode ); +#else + return d->doOpen( fd, 0, mode ); +#endif + +} + +bool KDPipeIODevice::open( Qt::HANDLE h, OpenMode mode ) { KDAB_CHECK_THIS; + +#ifdef Q_OS_WIN32 + return d->doOpen( -1, h, mode ); +#else + Q_UNUSED( h ); + Q_UNUSED( mode ); + assert( !"KDPipeIODevice::open( Qt::HANDLE, OpenMode ) should never be called except on Windows." ); +#endif + +} + +bool KDPipeIODevice::Private::startReaderThread() +{ + if ( triedToStartReader ) + return true; + triedToStartReader = true; + if ( reader && !reader->isRunning() && !reader->isFinished() ) { + qDebug("KDPipeIODevice::Private::startReaderThread(): locking reader (CONSUMER THREAD)" ); + LOCKED( reader ); + qDebug("KDPipeIODevice::Private::startReaderThread(): locked reader (CONSUMER THREAD)" ); + reader->start( QThread::HighestPriority ); + qDebug("KDPipeIODevice::Private::startReaderThread(): waiting for hasStarted (CONSUMER THREAD)" ); + const bool hasStarted = reader->hasStarted.wait( &reader->mutex, 1000 ); + qDebug("KDPipeIODevice::Private::startReaderThread(): returned from hasStarted (CONSUMER THREAD)" ); + + return hasStarted; + } + return true; +} + +bool KDPipeIODevice::Private::startWriterThread() +{ + if ( triedToStartWriter ) + return true; + triedToStartWriter = true; + if ( writer && !writer->isRunning() && !writer->isFinished() ) { + LOCKED( writer ); + + writer->start( QThread::HighestPriority ); + if ( !writer->hasStarted.wait( &writer->mutex, 1000 ) ) + return false; + } + return true; +} + +void KDPipeIODevice::Private::emitReadyRead() +{ + static int s_counter = 0; + const int counter = s_counter++; + QPointer thisPointer( this ); + qDebug( "KDPipeIODevice::Private::emitReadyRead %p, %d", this, counter ); + + emit q->readyRead(); + + if ( !thisPointer ) + return; + qDebug( "KDPipeIODevice::Private::emitReadyRead %p, %d: locking reader (CONSUMER THREAD)", this, counter ); + synchronized( reader ) { + qDebug( "KDPipeIODevice::Private::emitReadyRead %p, %d: locked reader (CONSUMER THREAD)", this, counter ); + reader->readyReadSentCondition.wakeAll(); + } + qDebug( "KDPipeIODevice::Private::emitReadyRead %p leaving %d", this, counter ); + +} + +bool KDPipeIODevice::Private::doOpen( int fd_, Qt::HANDLE handle_, OpenMode mode_ ) { + + if ( q->isOpen() ) + return false; + +#ifdef Q_OS_WIN32 + if ( !handle_ ) + return false; +#else + if ( fd_ < 0 ) + return false; +#endif + + if ( !(mode_ & ReadWrite) ) + return false; // need to have at least read -or- write + + + std::auto_ptr reader_; + std::auto_ptr writer_; + + if ( mode_ & ReadOnly ) { + reader_.reset( new Reader( fd_, handle_ ) ); + qDebug( "KDPipeIODevice::doOpen (%p): created reader (%p) for fd %d", this, reader_.get(), fd_ ); + connect( reader_.get(), SIGNAL(readyRead()), this, SLOT(emitReadyRead()), +Qt::QueuedConnection ); + } + if ( mode_ & WriteOnly ) { + writer_.reset( new Writer( fd_, handle_ ) ); + qDebug( "KDPipeIODevice::doOpen (%p): created writer (%p) for fd %d", this, writer_.get(), fd_ ); + connect( writer_.get(), SIGNAL(bytesWritten(qint64)), q, SIGNAL(bytesWritten(qint64)), +Qt::QueuedConnection ); + } + + // commit to *this: + fd = fd_; + handle = handle_; + reader = reader_.release(); + writer = writer_.release(); + + q->setOpenMode( mode_|Unbuffered ); + return true; +} + +int KDPipeIODevice::descriptor() const { KDAB_CHECK_THIS; + return d->fd; +} + + +Qt::HANDLE KDPipeIODevice::handle() const { KDAB_CHECK_THIS; + return d->handle; +} + +qint64 KDPipeIODevice::bytesAvailable() const { KDAB_CHECK_THIS; + const qint64 base = QIODevice::bytesAvailable(); + if ( !d->triedToStartReader ) { + d->startReaderThread(); + return base; + } + if ( d->reader ) + synchronized( d->reader ) { + const qint64 inBuffer = d->reader->bytesInBuffer(); + return base + inBuffer; + } + return base; +} + +qint64 KDPipeIODevice::bytesToWrite() const { KDAB_CHECK_THIS; + d->startWriterThread(); + const qint64 base = QIODevice::bytesToWrite(); + if ( d->writer ) + synchronized( d->writer ) return base + d->writer->bytesInBuffer(); + return base; +} + +bool KDPipeIODevice::canReadLine() const { KDAB_CHECK_THIS; + d->startReaderThread(); + if ( QIODevice::canReadLine() ) + return true; + if ( d->reader ) + synchronized( d->reader ) return d->reader->bufferContains( '\n' ); + return true; +} + +bool KDPipeIODevice::isSequential() const { + return true; +} + +bool KDPipeIODevice::atEnd() const { KDAB_CHECK_THIS; + d->startReaderThread(); + if ( !QIODevice::atEnd() ) { + qDebug( "%p: KDPipeIODevice::atEnd returns false since QIODevice::atEnd does (with bytesAvailable=%ld)", this, static_cast(bytesAvailable()) ); + return false; + } + if ( !isOpen() ) + return true; + if ( d->reader->eofShortCut ) + return true; + LOCKED( d->reader ); + const bool eof = ( d->reader->error || d->reader->eof ) && d->reader->bufferEmpty(); + if ( !eof ) { + if ( !d->reader->error && !d->reader->eof ) + qDebug( "%p: KDPipeIODevice::atEnd returns false since !reader->error && !reader->eof", this ); + if ( !d->reader->bufferEmpty() ) + qDebug( "%p: KDPipeIODevice::atEnd returns false since !reader->bufferEmpty()", this ); + } + return eof; +} + +bool KDPipeIODevice::waitForBytesWritten( int msecs ) { KDAB_CHECK_THIS; + d->startWriterThread(); + Writer * const w = d->writer; + if ( !w ) + return true; + LOCKED( w ); + qDebug( "KDPipeIODevice::waitForBytesWritten (%p,w=%p): entered locked area", this, w +); + return w->bufferEmpty() || w->error || w->bufferEmptyCondition.wait( &w->mutex, msecs ) ; +} + +bool KDPipeIODevice::waitForReadyRead( int msecs ) { KDAB_CHECK_THIS; + qDebug( "KDPipeIODEvice::waitForReadyRead()(%p)", this); + d->startReaderThread(); + if ( ALLOW_QIODEVICE_BUFFERING ) { + if ( bytesAvailable() > 0 ) + return true; + } + Reader * const r = d->reader; + if ( !r || r->eofShortCut ) + return true; + LOCKED( r ); + if ( r->bytesInBuffer() != 0 || r->eof || r->error ) + return true; + assert( false ); + return r->bufferNotEmptyCondition.wait( &r->mutex, msecs ) ; +} + +template +class TemporaryValue { +public: + TemporaryValue( T& var_, const T& tv ) : var( var_ ), oldValue( var_ ) { var = tv; } + ~TemporaryValue() { var = oldValue; } +private: + T& var; + const T oldValue; +}; + + +bool KDPipeIODevice::readWouldBlock() const +{ + d->startReaderThread(); + LOCKED( d->reader ); + return d->reader->bufferEmpty() && !d->reader->eof && !d->reader->error; +} + +bool KDPipeIODevice::writeWouldBlock() const +{ + d->startWriterThread(); + LOCKED( d->writer ); + return !d->writer->bufferEmpty() && !d->writer->error; +} + + +qint64 KDPipeIODevice::readData( char * data, qint64 maxSize ) { KDAB_CHECK_THIS; + qDebug( "%p: KDPipeIODevice::readData: data=%p, maxSize=%lld", this, data, maxSize ); + d->startReaderThread(); + Reader * const r = d->reader; + + assert( r ); + + + //assert( r->isRunning() ); // wrong (might be eof, error) + assert( data || maxSize == 0 ); + assert( maxSize >= 0 ); + + if ( r->eofShortCut ) { + qDebug( "%p: KDPipeIODevice::readData: hit eofShortCut, returning 0", this ); + return 0; + } + + if ( maxSize < 0 ) + maxSize = 0; + + if ( ALLOW_QIODEVICE_BUFFERING ) { + if ( bytesAvailable() > 0 ) + maxSize = std::min( maxSize, bytesAvailable() ); // don't block + } + qDebug( "%p: KDPipeIODevice::readData: try to lock reader (CONSUMER THREAD)", this ); + LOCKED( r ); + qDebug( "%p: KDPipeIODevice::readData: locked reader (CONSUMER THREAD)", this ); + + r->readyReadSentCondition.wakeAll(); + if ( /* maxSize > 0 && */ r->bufferEmpty() && !r->error && !r->eof ) { // ### block on maxSize == 0? + qDebug( "%p: KDPipeIODevice::readData: waiting for bufferNotEmptyCondition (CONSUMER THREAD)", this ); + const TemporaryValue tmp( d->reader->consumerBlocksOnUs, true ); + r->bufferNotEmptyCondition.wait( &r->mutex ); + r->blockedConsumerIsDoneCondition.wakeAll(); + qDebug( "%p: KDPipeIODevice::readData: woke up from bufferNotEmptyCondition (CONSUMER THREAD)", this ); + } + + if ( r->bufferEmpty() ) { + qDebug( "%p: KDPipeIODevice::readData: got empty buffer, signal eof", this ); + // woken with an empty buffer must mean either EOF or error: + assert( r->eof || r->error ); + r->eofShortCut = true; + return r->eof ? 0 : -1 ; + } + + qDebug( "%p: KDPipeIODevice::readData: got bufferNotEmptyCondition, trying to read %lld bytes", this, maxSize ); + const qint64 bytesRead = r->readData( data, maxSize ); + qDebug( "%p: KDPipeIODevice::readData: read %lld bytes", this, bytesRead ); + qDebug( "%p (fd=%d): KDPipeIODevice::readData: %s", this, d->fd, data ); + + return bytesRead; +} + +qint64 Reader::readData( char * data, qint64 maxSize ) { + qint64 numRead = rptr < wptr ? wptr - rptr : sizeof buffer - rptr ; + if ( numRead > maxSize ) + numRead = maxSize; + + qDebug( "%p: KDPipeIODevice::readData: data=%p, maxSize=%lld; rptr=%u, wptr=%u (bytesInBuffer=%u); -> numRead=%lld", this, + data, maxSize, rptr, wptr, bytesInBuffer(), numRead ); + + std::memcpy( data, buffer + rptr, numRead ); + + rptr = ( rptr + numRead ) % sizeof buffer ; + + if ( !bufferFull() ) { + qDebug( "%p: KDPipeIODevice::readData: signal bufferNotFullCondition", this ); + bufferNotFullCondition.wakeAll(); + } + + return numRead; +} + +qint64 KDPipeIODevice::writeData( const char * data, qint64 size ) { KDAB_CHECK_THIS; + d->startWriterThread(); + Writer * const w = d->writer; + + assert( w ); + assert( w->error || w->isRunning() ); + assert( data || size == 0 ); + assert( size >= 0 ); + + LOCKED( w ); + + while ( !w->error && !w->bufferEmpty() ) { + qDebug( "%p: KDPipeIODevice::writeData: wait for empty buffer", this ); + w->bufferEmptyCondition.wait( &w->mutex ); + qDebug( "%p: KDPipeIODevice::writeData: empty buffer signaled", this ); + + } + if ( w->error ) + return -1; + + assert( w->bufferEmpty() ); + + return w->writeData( data, size ); +} + +qint64 Writer::writeData( const char * data, qint64 size ) { + assert( bufferEmpty() ); + + if ( size > static_cast( sizeof buffer ) ) + size = sizeof buffer; + + std::memcpy( buffer, data, size ); + + numBytesInBuffer = size; + + if ( !bufferEmpty() ) { + bufferNotEmptyCondition.wakeAll(); + } + return size; +} + +void KDPipeIODevice::Private::stopThreads() +{ + if ( triedToStartWriter ) + { + if ( writer && q->bytesToWrite() > 0 ) + q->waitForBytesWritten( -1 ); + + assert( q->bytesToWrite() == 0 ); + } + if ( Reader * & r = reader ) { + disconnect( r, SIGNAL( readyRead() ), this, SLOT( emitReadyRead() ) ); + synchronized( r ) { + // tell thread to cancel: + r->cancel = true; + // and wake it, so it can terminate: + r->waitForCancelCondition.wakeAll(); + r->bufferNotFullCondition.wakeAll(); + r->readyReadSentCondition.wakeAll(); + } + } + if ( Writer * & w = writer ) { + synchronized( w ) { + // tell thread to cancel: + w->cancel = true; + // and wake it, so it can terminate: + w->bufferNotEmptyCondition.wakeAll(); + } + } +} + +void KDPipeIODevice::close() { KDAB_CHECK_THIS; + qDebug( "KDPipeIODevice::close(%p)", this ); + if ( !isOpen() ) + return; + + // tell clients we're about to close: + emit aboutToClose(); + d->stopThreads(); + +#define waitAndDelete( t ) if ( t ) { t->wait(); QThread* const t2 = t; t = 0; delete t2; } + qDebug( "KPipeIODevice::close(%p): wait and closing writer %p", this, d->writer ); + waitAndDelete( d->writer ); + qDebug( "KPipeIODevice::close(%p): wait and closing reader %p", this, d->reader ); + if ( d->reader ) { + LOCKED( d->reader ); + d->reader->readyReadSentCondition.wakeAll(); + } + waitAndDelete( d->reader ); +#undef waitAndDelete +#ifdef Q_OS_WIN32 + if ( d->fd != -1 ) + _close( d->fd ); + else + CloseHandle( d->handle ); +#else + ::close( d->fd ); +#endif + + setOpenMode( NotOpen ); + d->fd = -1; + d->handle = 0; +} + +void Reader::run() { + + LOCKED( this ); + + // too bad QThread doesn't have that itself; a signal isn't enough + hasStarted.wakeAll(); + + qDebug( "%p: Reader::run: started", this ); + + while ( true ) { + if ( !cancel && ( eof || error ) ) { + //notify the client until the buffer is empty and then once + //again so he receives eof/error. After that, wait for him + //to cancel + const bool wasEmpty = bufferEmpty(); + qDebug( "%p: Reader::run: received eof(%d) or error(%d), waking everyone", this, eof, error ); + notifyReadyRead(); + if ( !cancel && wasEmpty ) + waitForCancelCondition.wait( &mutex ); + } else if ( !cancel && !bufferFull() && !bufferEmpty() ) { + qDebug( "%p: Reader::run: buffer no longer empty, waking everyone", this ); + notifyReadyRead(); + } + + while ( !cancel && !error && bufferFull() ) { + notifyReadyRead(); + if ( bufferFull() ) { + qDebug( "%p: Reader::run: buffer is full, going to sleep", this ); + bufferNotFullCondition.wait( &mutex ); + } + } + + if ( cancel ) { + qDebug( "%p: Reader::run: detected cancel", this ); + goto leave; + } + + if ( !eof && !error ) { + if ( rptr == wptr ) // optimize for larger chunks in case the buffer is empty + rptr = wptr = 0; + + unsigned int numBytes = ( rptr + sizeof buffer - wptr - 1 ) % sizeof buffer; + if ( numBytes > sizeof buffer - wptr ) + numBytes = sizeof buffer - wptr; + + qDebug( "%p: Reader::run: rptr=%d, wptr=%d -> numBytes=%d", this, rptr, wptr, numBytes ); + + assert( numBytes > 0 ); + + qDebug( "%p: Reader::run: trying to read %d bytes", this, numBytes ); +#ifdef Q_OS_WIN32 + mutex.unlock(); + DWORD numRead; + const bool ok = ReadFile( handle, buffer + wptr, numBytes, &numRead, 0 ); + mutex.lock(); + if ( ok ) { + if ( numRead == 0 ) { + qDebug( "%p: Reader::run: got eof (numRead==0)", this ); + eof = true; + } + } else { // !ok + errorCode = static_cast( GetLastError() ); + if ( errorCode == ERROR_BROKEN_PIPE ) { + assert( numRead == 0 ); + qDebug( "%p: Reader::run: got eof (broken pipe)", this ); + eof = true; + } else { + assert( numRead == 0 ); + qDebug( "%p: Reader::run: got error: %s (%d)", this, strerror( errorCode ), errorCode ); + error = true; + } + } +#else + qint64 numRead; + mutex.unlock(); + do { + numRead = ::read( fd, buffer + wptr, numBytes ); + } while ( numRead == -1 && errno == EINTR ); + mutex.lock(); + + if ( numRead < 0 ) { + errorCode = errno; + error = true; + qDebug( "%p: Reader::run: got error: %d", this, errorCode ); + } else if ( numRead == 0 ) { + qDebug( "%p: Reader::run: eof detected", this ); + eof = true; + } +#endif + qDebug( "%p: Reader::run: read %ld bytes", this, static_cast(numRead) ); + qDebug( "%p: Reader::run(fd=%d): %s", this, fd, buffer ); + + if ( numRead > 0 ) { + qDebug( "%p: Reader::run: buffer before: rptr=%4d, wptr=%4d", this, rptr, wptr ); + wptr = ( wptr + numRead ) % sizeof buffer; + qDebug( "%p: Reader::run: buffer after: rptr=%4d, wptr=%4d", this, rptr, wptr ); + } + } + } + leave: + qDebug( "%p: Reader::run: terminated", this ); +} + +void Reader::notifyReadyRead() +{ + qDebug( "notifyReadyRead: %d bytes available", bytesInBuffer() ); + assert( !cancel ); + + if ( consumerBlocksOnUs ) { + bufferNotEmptyCondition.wakeAll(); + blockedConsumerIsDoneCondition.wait( &mutex ); + return; + } + qDebug( "notifyReadyRead: emit signal" ); + emit readyRead(); + readyReadSentCondition.wait( &mutex ); + qDebug( "notifyReadyRead: returning from waiting, leave" ); +} + +void Writer::run() { + + LOCKED( this ); + + // too bad QThread doesn't have that itself; a signal isn't enough + hasStarted.wakeAll(); + + qDebug( "%p: Writer::run: started", this ); + + while ( true ) { + + while ( !cancel && bufferEmpty() ) { + qDebug( "%p: Writer::run: buffer is empty, wake bufferEmptyCond listeners", this ); + bufferEmptyCondition.wakeAll(); + emit bytesWritten( 0 ); + qDebug( "%p: Writer::run: buffer is empty, going to sleep", this ); + bufferNotEmptyCondition.wait( &mutex ); + qDebug( "%p: Writer::run: woke up", this ); + } + + if ( cancel ) { + qDebug( "%p: Writer::run: detected cancel", this ); + goto leave; + } + + assert( numBytesInBuffer > 0 ); + + qDebug( "%p: Writer::run: Trying to write %u bytes", this, numBytesInBuffer ); + qint64 totalWritten = 0; + do { + mutex.unlock(); +#ifdef Q_OS_WIN32 + DWORD numWritten; + qDebug( "%p (fd=%d): Writer::run: buffer before WriteFile (numBytes=%lld): %s:", this, fd, numBytesInBuffer, buffer ); + qDebug( "%p (fd=%d): Writer::run: Going into WriteFile", this, fd ); + if ( !WriteFile( handle, buffer + totalWritten, numBytesInBuffer - totalWritten, &numWritten, 0 ) ) { + mutex.lock(); + errorCode = static_cast( GetLastError() ); + qDebug( "%p: Writer::run: got error code: %d", this, errorCode ); + error = true; + goto leave; + } +#else + qint64 numWritten; + do { + numWritten = ::write( fd, buffer + totalWritten, numBytesInBuffer - totalWritten ); + } while ( numWritten == -1 && errno == EINTR ); + + if ( numWritten < 0 ) { + mutex.lock(); + errorCode = errno; + qDebug( "%p: Writer::run: got error code: %d", this, errorCode ); + error = true; + goto leave; + } +#endif + qDebug( "%p (fd=%d): Writer::run: buffer after WriteFile (numBytes=%u): %s:", this, fd, numBytesInBuffer, buffer ); + totalWritten += numWritten; + mutex.lock(); + } while ( totalWritten < numBytesInBuffer ); + + qDebug( "%p: Writer::run: wrote %lld bytes", this, totalWritten ); + + numBytesInBuffer = 0; + + qDebug( "%p: Writer::run: buffer is empty, wake bufferEmptyCond listeners", this ); + bufferEmptyCondition.wakeAll(); + emit bytesWritten( totalWritten ); + } + leave: + qDebug( "%p: Writer::run: terminating", this ); + numBytesInBuffer = 0; + qDebug( "%p: Writer::run: buffer is empty, wake bufferEmptyCond listeners", this ); + bufferEmptyCondition.wakeAll(); + emit bytesWritten( 0 ); +} + +// static +std::pair KDPipeIODevice::makePairOfConnectedPipes() { + KDPipeIODevice * read = 0; + KDPipeIODevice * write = 0; +#ifdef Q_OS_WIN32 + HANDLE rh; + HANDLE wh; + SECURITY_ATTRIBUTES sa; + memset( &sa, 0, sizeof(sa) ); + sa.nLength = sizeof(sa); + sa.bInheritHandle = TRUE; + if ( CreatePipe( &rh, &wh, &sa, BUFFER_SIZE ) ) { + read = new KDPipeIODevice; + read->open( rh, ReadOnly ); + write = new KDPipeIODevice; + write->open( wh, WriteOnly ); + } +#else + int fds[2]; + if ( pipe( fds ) == 0 ) { + read = new KDPipeIODevice; + read->open( fds[0], ReadOnly ); + write = new KDPipeIODevice; + write->open( fds[1], WriteOnly ); + } +#endif + return std::make_pair( read, write ); +} + +#ifdef KDAB_DEFINE_CHECKS +KDAB_DEFINE_CHECKS( KDPipeIODevice ) { + if ( !isOpen() ) { + assert( openMode() == NotOpen ); + assert( !d->reader ); + assert( !d->writer ); +#ifdef Q_OS_WIN32 + assert( !d->handle ); +#else + assert( d->fd < 0 ); +#endif + } else { + assert( openMode() != NotOpen ); + assert( openMode() & ReadWrite ); + if ( openMode() & ReadOnly ) { + assert( d->reader ); + synchronized( d->reader ) + assert( d->reader->eof || d->reader->error || d->reader->isRunning() ); + } + if ( openMode() & WriteOnly ) { + assert( d->writer ); + synchronized( d->writer ) + assert( d->writer->error || d->writer->isRunning() ); + } +#ifdef Q_OS_WIN32 + assert( d->handle ); +#else + assert( d->fd >= 0 ); +#endif + } +} +#endif // KDAB_DEFINE_CHECKS + +#include "moc_kdpipeiodevice.cpp" +#include "kdpipeiodevice.moc" diff --git a/tags/gpgme-1.1.6/gpgme/kdpipeiodevice.h b/tags/gpgme-1.1.6/gpgme/kdpipeiodevice.h new file mode 100644 index 0000000..8da6af6 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/kdpipeiodevice.h @@ -0,0 +1,73 @@ +/* + Copyright (C) 2007 Klarälvdalens Datakonsult AB + + KDPipeIODevice is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + KDPipeIODevice 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with KDPipeIODevice; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __KDTOOLSCORE_KDPIPEIODEVICE_H__ +#define __KDTOOLSCORE_KDPIPEIODEVICE_H__ + +#include + +#include + +//#include "checker.h" + +namespace _gpgme_ { + +class KDPipeIODevice : public QIODevice { + Q_OBJECT + //KDAB_MAKE_CHECKABLE( KDPipeIODevice ) +public: + explicit KDPipeIODevice( QObject * parent=0 ); + explicit KDPipeIODevice( int fd, OpenMode=ReadOnly, QObject * parent=0 ); + explicit KDPipeIODevice( Qt::HANDLE handle, OpenMode=ReadOnly, QObject * parent=0 ); + ~KDPipeIODevice(); + + static std::pair makePairOfConnectedPipes(); + + bool open( int fd, OpenMode mode=ReadOnly ); + bool open( Qt::HANDLE handle, OpenMode mode=ReadOnly ); + + Qt::HANDLE handle() const; + int descriptor() const; + + bool readWouldBlock() const; + bool writeWouldBlock() const; + + /* reimp */ qint64 bytesAvailable() const; + /* reimp */ qint64 bytesToWrite() const; + /* reimp */ bool canReadLine() const; + /* reimp */ void close(); + /* reimp */ bool isSequential() const; + /* reimp */ bool atEnd() const; + + /* reimp */ bool waitForBytesWritten( int msecs ); + /* reimp */ bool waitForReadyRead( int msecs ); + +protected: + /* reimp */ qint64 readData( char * data, qint64 maxSize ); + /* reimp */ qint64 writeData( const char * data, qint64 maxSize ); + +private: + class Private; + Private * d; +}; + +} /* namespace _gpgme_ */ + +#endif /* __KDTOOLSCORE_KDPIPEIODEVICE_H__ */ + diff --git a/tags/gpgme-1.1.6/gpgme/kdpipeiodevice.moc b/tags/gpgme-1.1.6/gpgme/kdpipeiodevice.moc new file mode 100644 index 0000000..457f371 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/kdpipeiodevice.moc @@ -0,0 +1,183 @@ +/**************************************************************************** +** Meta object code from reading C++ file 'kdpipeiodevice.cpp' +** +** Created: Tue Oct 2 19:30:13 2007 +** by: The Qt Meta Object Compiler version 59 (Qt 4.3.1) +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +#if !defined(Q_MOC_OUTPUT_REVISION) +#error "The header file 'kdpipeiodevice.cpp' doesn't include ." +#elif Q_MOC_OUTPUT_REVISION != 59 +#error "This file was generated using the moc from 4.3.1. It" +#error "cannot be used with the include files from this version of Qt." +#error "(The moc has changed too much.)" +#endif + +static const uint qt_meta_data_Reader[] = { + + // content: + 1, // revision + 0, // classname + 0, 0, // classinfo + 1, 10, // methods + 0, 0, // properties + 0, 0, // enums/sets + + // signals: signature, parameters, type, tag, flags + 8, 7, 7, 7, 0x05, + + 0 // eod +}; + +static const char qt_meta_stringdata_Reader[] = { + "Reader\0\0readyRead()\0" +}; + +const QMetaObject Reader::staticMetaObject = { + { &QThread::staticMetaObject, qt_meta_stringdata_Reader, + qt_meta_data_Reader, 0 } +}; + +const QMetaObject *Reader::metaObject() const +{ + return &staticMetaObject; +} + +void *Reader::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_Reader)) + return static_cast(const_cast< Reader*>(this)); + return QThread::qt_metacast(_clname); +} + +int Reader::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QThread::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: readyRead(); break; + } + _id -= 1; + } + return _id; +} + +// SIGNAL 0 +void Reader::readyRead() +{ + QMetaObject::activate(this, &staticMetaObject, 0, 0); +} +static const uint qt_meta_data_Writer[] = { + + // content: + 1, // revision + 0, // classname + 0, 0, // classinfo + 1, 10, // methods + 0, 0, // properties + 0, 0, // enums/sets + + // signals: signature, parameters, type, tag, flags + 8, 7, 7, 7, 0x05, + + 0 // eod +}; + +static const char qt_meta_stringdata_Writer[] = { + "Writer\0\0bytesWritten(qint64)\0" +}; + +const QMetaObject Writer::staticMetaObject = { + { &QThread::staticMetaObject, qt_meta_stringdata_Writer, + qt_meta_data_Writer, 0 } +}; + +const QMetaObject *Writer::metaObject() const +{ + return &staticMetaObject; +} + +void *Writer::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_Writer)) + return static_cast(const_cast< Writer*>(this)); + return QThread::qt_metacast(_clname); +} + +int Writer::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QThread::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: bytesWritten((*reinterpret_cast< qint64(*)>(_a[1]))); break; + } + _id -= 1; + } + return _id; +} + +// SIGNAL 0 +void Writer::bytesWritten(qint64 _t1) +{ + void *_a[] = { 0, const_cast(reinterpret_cast(&_t1)) }; + QMetaObject::activate(this, &staticMetaObject, 0, _a); +} +static const uint qt_meta_data_KDPipeIODevice__Private[] = { + + // content: + 1, // revision + 0, // classname + 0, 0, // classinfo + 1, 10, // methods + 0, 0, // properties + 0, 0, // enums/sets + + // slots: signature, parameters, type, tag, flags + 25, 24, 24, 24, 0x0a, + + 0 // eod +}; + +static const char qt_meta_stringdata_KDPipeIODevice__Private[] = { + "KDPipeIODevice::Private\0\0emitReadyRead()\0" +}; + +const QMetaObject KDPipeIODevice::Private::staticMetaObject = { + { &QObject::staticMetaObject, qt_meta_stringdata_KDPipeIODevice__Private, + qt_meta_data_KDPipeIODevice__Private, 0 } +}; + +const QMetaObject *KDPipeIODevice::Private::metaObject() const +{ + return &staticMetaObject; +} + +void *KDPipeIODevice::Private::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_KDPipeIODevice__Private)) + return static_cast(const_cast< Private*>(this)); + return QObject::qt_metacast(_clname); +} + +int KDPipeIODevice::Private::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QObject::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: emitReadyRead(); break; + } + _id -= 1; + } + return _id; +} diff --git a/tags/gpgme-1.1.6/gpgme/key.c b/tags/gpgme-1.1.6/gpgme/key.c new file mode 100644 index 0000000..3dde670 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/key.c @@ -0,0 +1,722 @@ +/* key.c - Key objects. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include + +#include "util.h" +#include "ops.h" +#include "sema.h" + + +/* Protects all reference counters in keys. All other accesses to a + key are read only. */ +DEFINE_STATIC_LOCK (key_ref_lock); + + +/* Create a new key. */ +gpgme_error_t +_gpgme_key_new (gpgme_key_t *r_key) +{ + gpgme_key_t key; + + key = calloc (1, sizeof *key); + if (!key) + return gpg_error_from_errno (errno); + key->_refs = 1; + + *r_key = key; + return 0; +} + + +gpgme_error_t +_gpgme_key_add_subkey (gpgme_key_t key, gpgme_subkey_t *r_subkey) +{ + gpgme_subkey_t subkey; + + subkey = calloc (1, sizeof *subkey); + if (!subkey) + return gpg_error_from_errno (errno); + subkey->keyid = subkey->_keyid; + subkey->_keyid[16] = '\0'; + + if (!key->subkeys) + key->subkeys = subkey; + if (key->_last_subkey) + key->_last_subkey->next = subkey; + key->_last_subkey = subkey; + + *r_subkey = subkey; + return 0; +} + + +static char * +set_user_id_part (char *tail, const char *buf, size_t len) +{ + while (len && (buf[len - 1] == ' ' || buf[len - 1] == '\t')) + len--; + for (; len; len--) + *tail++ = *buf++; + *tail++ = 0; + return tail; +} + + +static void +parse_user_id (char *src, char **name, char **email, + char **comment, char *tail) +{ + const char *start = NULL; + int in_name = 0; + int in_email = 0; + int in_comment = 0; + + while (*src) + { + if (in_email) + { + if (*src == '<') + /* Not legal but anyway. */ + in_email++; + else if (*src == '>') + { + if (!--in_email && !*email) + { + *email = tail; + tail = set_user_id_part (tail, start, src - start); + } + } + } + else if (in_comment) + { + if (*src == '(') + in_comment++; + else if (*src == ')') + { + if (!--in_comment && !*comment) + { + *comment = tail; + tail = set_user_id_part (tail, start, src - start); + } + } + } + else if (*src == '<') + { + if (in_name) + { + if (!*name) + { + *name = tail; + tail = set_user_id_part (tail, start, src - start); + } + in_name = 0; + } + in_email = 1; + start = src + 1; + } + else if (*src == '(') + { + if (in_name) + { + if (!*name) + { + *name = tail; + tail = set_user_id_part (tail, start, src - start); + } + in_name = 0; + } + in_comment = 1; + start = src + 1; + } + else if (!in_name && *src != ' ' && *src != '\t') + { + in_name = 1; + start = src; + } + src++; + } + + if (in_name) + { + if (!*name) + { + *name = tail; + tail = set_user_id_part (tail, start, src - start); + } + } + + /* Let unused parts point to an EOS. */ + tail--; + if (!*name) + *name = tail; + if (!*email) + *email = tail; + if (!*comment) + *comment = tail; +} + + +static void +parse_x509_user_id (char *src, char **name, char **email, + char **comment, char *tail) +{ + if (*src == '<' && src[strlen (src) - 1] == '>') + *email = src; + + /* Let unused parts point to an EOS. */ + tail--; + if (!*name) + *name = tail; + if (!*email) + *email = tail; + if (!*comment) + *comment = tail; +} + + +/* Take a name from the --with-colon listing, remove certain escape + sequences sequences and put it into the list of UIDs. */ +gpgme_error_t +_gpgme_key_append_name (gpgme_key_t key, char *src) +{ + gpgme_user_id_t uid; + char *dst; + int src_len = strlen (src); + + assert (key); + /* We can malloc a buffer of the same length, because the converted + string will never be larger. Actually we allocate it twice the + size, so that we are able to store the parsed stuff there too. */ + uid = malloc (sizeof (*uid) + 2 * src_len + 3); + if (!uid) + return gpg_error_from_errno (errno); + memset (uid, 0, sizeof *uid); + + uid->uid = ((char *) uid) + sizeof (*uid); + dst = uid->uid; + _gpgme_decode_c_string (src, &dst, src_len + 1); + + dst += strlen (dst) + 1; + if (key->protocol == GPGME_PROTOCOL_CMS) + parse_x509_user_id (uid->uid, &uid->name, &uid->email, + &uid->comment, dst); + else + parse_user_id (uid->uid, &uid->name, &uid->email, + &uid->comment, dst); + + if (!key->uids) + key->uids = uid; + if (key->_last_uid) + key->_last_uid->next = uid; + key->_last_uid = uid; + + return 0; +} + + +gpgme_key_sig_t +_gpgme_key_add_sig (gpgme_key_t key, char *src) +{ + int src_len = src ? strlen (src) : 0; + gpgme_user_id_t uid; + gpgme_key_sig_t sig; + + assert (key); /* XXX */ + + uid = key->_last_uid; + assert (uid); /* XXX */ + + /* We can malloc a buffer of the same length, because the converted + string will never be larger. Actually we allocate it twice the + size, so that we are able to store the parsed stuff there too. */ + sig = malloc (sizeof (*sig) + 2 * src_len + 3); + if (!sig) + return NULL; + memset (sig, 0, sizeof *sig); + + sig->keyid = sig->_keyid; + sig->_keyid[16] = '\0'; + sig->uid = ((char *) sig) + sizeof (*sig); + + if (src) + { + char *dst = sig->uid; + _gpgme_decode_c_string (src, &dst, src_len + 1); + dst += strlen (dst) + 1; + if (key->protocol == GPGME_PROTOCOL_CMS) + parse_x509_user_id (sig->uid, &sig->name, &sig->email, + &sig->comment, dst); + else + parse_user_id (sig->uid, &sig->name, &sig->email, + &sig->comment, dst); + } + + if (!uid->signatures) + uid->signatures = sig; + if (uid->_last_keysig) + uid->_last_keysig->next = sig; + uid->_last_keysig = sig; + + return sig; +} + + +/* Acquire a reference to KEY. */ +void +gpgme_key_ref (gpgme_key_t key) +{ + LOCK (key_ref_lock); + key->_refs++; + UNLOCK (key_ref_lock); +} + + +/* gpgme_key_unref releases the key object. Note, that this function + may not do an actual release if there are other shallow copies of + the objects. You have to call this function for every newly + created key object as well as for every gpgme_key_ref() done on the + key object. */ +void +gpgme_key_unref (gpgme_key_t key) +{ + gpgme_user_id_t uid; + gpgme_subkey_t subkey; + + if (!key) + return; + + LOCK (key_ref_lock); + assert (key->_refs > 0); + if (--key->_refs) + { + UNLOCK (key_ref_lock); + return; + } + UNLOCK (key_ref_lock); + + subkey = key->subkeys; + while (subkey) + { + gpgme_subkey_t next = subkey->next; + if (subkey->fpr) + free (subkey->fpr); + free (subkey); + subkey = next; + } + + uid = key->uids; + while (uid) + { + gpgme_user_id_t next_uid = uid->next; + gpgme_key_sig_t keysig = uid->signatures; + + while (keysig) + { + gpgme_key_sig_t next_keysig = keysig->next; + gpgme_sig_notation_t notation = keysig->notations; + + while (notation) + { + gpgme_sig_notation_t next_notation = notation->next; + + _gpgme_sig_notation_free (notation); + notation = next_notation; + } + + free (keysig); + keysig = next_keysig; + } + free (uid); + uid = next_uid; + } + + if (key->issuer_serial) + free (key->issuer_serial); + if (key->issuer_name) + free (key->issuer_name); + + if (key->chain_id) + free (key->chain_id); + + free (key); +} + + +/* Compatibility interfaces. */ + +void +gpgme_key_release (gpgme_key_t key) +{ + gpgme_key_unref (key); +} + + +static const char * +otrust_to_string (int otrust) +{ + switch (otrust) + { + case GPGME_VALIDITY_NEVER: + return "n"; + + case GPGME_VALIDITY_MARGINAL: + return "m"; + + case GPGME_VALIDITY_FULL: + return "f"; + + case GPGME_VALIDITY_ULTIMATE: + return "u"; + + default: + return "?"; + } +} + + +static const char * +validity_to_string (int validity) +{ + switch (validity) + { + case GPGME_VALIDITY_UNDEFINED: + return "q"; + + case GPGME_VALIDITY_NEVER: + return "n"; + + case GPGME_VALIDITY_MARGINAL: + return "m"; + + case GPGME_VALIDITY_FULL: + return "f"; + + case GPGME_VALIDITY_ULTIMATE: + return "u"; + + case GPGME_VALIDITY_UNKNOWN: + default: + return "?"; + } +} + + +static const char * +capabilities_to_string (gpgme_subkey_t subkey) +{ + static const char *const strings[8] = + { + "", + "c", + "s", + "sc", + "e", + "ec", + "es", + "esc" + }; + return strings[(!!subkey->can_encrypt << 2) + | (!!subkey->can_sign << 1) + | (!!subkey->can_certify)]; +} + + +/* Return the value of the attribute WHAT of ITEM, which has to be + representable by a string. */ +const char * +gpgme_key_get_string_attr (gpgme_key_t key, _gpgme_attr_t what, + const void *reserved, int idx) +{ + gpgme_subkey_t subkey; + gpgme_user_id_t uid; + int i; + + if (!key || reserved || idx < 0) + return NULL; + + /* Select IDXth subkey. */ + subkey = key->subkeys; + for (i = 0; i < idx; i++) + { + subkey = subkey->next; + if (!subkey) + break; + } + + /* Select the IDXth user ID. */ + uid = key->uids; + for (i = 0; i < idx; i++) + { + uid = uid->next; + if (!uid) + break; + } + + switch (what) + { + case GPGME_ATTR_KEYID: + return subkey ? subkey->keyid : NULL; + + case GPGME_ATTR_FPR: + return subkey ? subkey->fpr : NULL; + + case GPGME_ATTR_ALGO: + return subkey ? gpgme_pubkey_algo_name (subkey->pubkey_algo) : NULL; + + case GPGME_ATTR_TYPE: + return key->protocol == GPGME_PROTOCOL_CMS ? "X.509" : "PGP"; + + case GPGME_ATTR_OTRUST: + return otrust_to_string (key->owner_trust); + + case GPGME_ATTR_USERID: + return uid ? uid->uid : NULL; + + case GPGME_ATTR_NAME: + return uid ? uid->name : NULL; + + case GPGME_ATTR_EMAIL: + return uid ? uid->email : NULL; + + case GPGME_ATTR_COMMENT: + return uid ? uid->comment : NULL; + + case GPGME_ATTR_VALIDITY: + return uid ? validity_to_string (uid->validity) : NULL; + + case GPGME_ATTR_KEY_CAPS: + return subkey ? capabilities_to_string (subkey) : NULL; + + case GPGME_ATTR_SERIAL: + return key->issuer_serial; + + case GPGME_ATTR_ISSUER: + return idx ? NULL : key->issuer_name; + + case GPGME_ATTR_CHAINID: + return key->chain_id; + + default: + return NULL; + } +} + + +unsigned long +gpgme_key_get_ulong_attr (gpgme_key_t key, _gpgme_attr_t what, + const void *reserved, int idx) +{ + gpgme_subkey_t subkey; + gpgme_user_id_t uid; + int i; + + if (!key || reserved || idx < 0) + return 0; + + /* Select IDXth subkey. */ + subkey = key->subkeys; + for (i = 0; i < idx; i++) + { + subkey = subkey->next; + if (!subkey) + break; + } + + /* Select the IDXth user ID. */ + uid = key->uids; + for (i = 0; i < idx; i++) + { + uid = uid->next; + if (!uid) + break; + } + + switch (what) + { + case GPGME_ATTR_ALGO: + return subkey ? (unsigned long) subkey->pubkey_algo : 0; + + case GPGME_ATTR_LEN: + return subkey ? (unsigned long) subkey->length : 0; + + case GPGME_ATTR_TYPE: + return key->protocol == GPGME_PROTOCOL_CMS ? 1 : 0; + + case GPGME_ATTR_CREATED: + return (subkey && subkey->timestamp >= 0) + ? (unsigned long) subkey->timestamp : 0; + + case GPGME_ATTR_EXPIRE: + return (subkey && subkey->expires >= 0) + ? (unsigned long) subkey->expires : 0; + + case GPGME_ATTR_VALIDITY: + return uid ? uid->validity : 0; + + case GPGME_ATTR_OTRUST: + return key->owner_trust; + + case GPGME_ATTR_IS_SECRET: + return !!key->secret; + + case GPGME_ATTR_KEY_REVOKED: + return subkey ? subkey->revoked : 0; + + case GPGME_ATTR_KEY_INVALID: + return subkey ? subkey->invalid : 0; + + case GPGME_ATTR_KEY_EXPIRED: + return subkey ? subkey->expired : 0; + + case GPGME_ATTR_KEY_DISABLED: + return subkey ? subkey->disabled : 0; + + case GPGME_ATTR_UID_REVOKED: + return uid ? uid->revoked : 0; + + case GPGME_ATTR_UID_INVALID: + return uid ? uid->invalid : 0; + + case GPGME_ATTR_CAN_ENCRYPT: + return key->can_encrypt; + + case GPGME_ATTR_CAN_SIGN: + return key->can_sign; + + case GPGME_ATTR_CAN_CERTIFY: + return key->can_certify; + + default: + return 0; + } +} + + +static gpgme_key_sig_t +get_keysig (gpgme_key_t key, int uid_idx, int idx) +{ + gpgme_user_id_t uid; + gpgme_key_sig_t sig; + + if (!key || uid_idx < 0 || idx < 0) + return NULL; + + uid = key->uids; + while (uid && uid_idx > 0) + { + uid = uid->next; + uid_idx--; + } + if (!uid) + return NULL; + + sig = uid->signatures; + while (sig && idx > 0) + { + sig = sig->next; + idx--; + } + return sig; +} + + +const char * +gpgme_key_sig_get_string_attr (gpgme_key_t key, int uid_idx, + _gpgme_attr_t what, + const void *reserved, int idx) +{ + gpgme_key_sig_t certsig = get_keysig (key, uid_idx, idx); + + if (!certsig || reserved) + return NULL; + + switch (what) + { + case GPGME_ATTR_KEYID: + return certsig->keyid; + + case GPGME_ATTR_ALGO: + return gpgme_pubkey_algo_name (certsig->pubkey_algo); + + case GPGME_ATTR_USERID: + return certsig->uid; + + case GPGME_ATTR_NAME: + return certsig->name; + + case GPGME_ATTR_EMAIL: + return certsig->email; + + case GPGME_ATTR_COMMENT: + return certsig->comment; + + default: + return NULL; + } +} + + +unsigned long +gpgme_key_sig_get_ulong_attr (gpgme_key_t key, int uid_idx, _gpgme_attr_t what, + const void *reserved, int idx) +{ + gpgme_key_sig_t certsig = get_keysig (key, uid_idx, idx); + + if (!certsig || reserved) + return 0; + + switch (what) + { + case GPGME_ATTR_ALGO: + return (unsigned long) certsig->pubkey_algo; + + case GPGME_ATTR_CREATED: + return certsig->timestamp < 0 ? 0L : (unsigned long) certsig->timestamp; + + case GPGME_ATTR_EXPIRE: + return certsig->expires < 0 ? 0L : (unsigned long) certsig->expires; + + case GPGME_ATTR_KEY_REVOKED: + return certsig->revoked; + + case GPGME_ATTR_KEY_INVALID: + return certsig->invalid; + + case GPGME_ATTR_KEY_EXPIRED: + return certsig->expired; + + case GPGME_ATTR_SIG_CLASS: + return certsig->sig_class; + + case GPGME_ATTR_SIG_STATUS: + return certsig->status; + + default: + return 0; + } +} diff --git a/tags/gpgme-1.1.6/gpgme/keylist.c b/tags/gpgme-1.1.6/gpgme/keylist.c new file mode 100644 index 0000000..0f88cf7 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/keylist.c @@ -0,0 +1,982 @@ +/* keylist.c - Listing keys. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004, 2006, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif +#include +#include +#include +/* Solaris 8 needs sys/types.h before time.h. */ +#include +#include +#include +#include +#include + +#include "gpgme.h" +#include "util.h" +#include "context.h" +#include "ops.h" +#include "debug.h" + + +struct key_queue_item_s +{ + struct key_queue_item_s *next; + gpgme_key_t key; +}; + +typedef struct +{ + struct _gpgme_op_keylist_result result; + + gpgme_key_t tmp_key; + + /* This points to the last uid in tmp_key. */ + gpgme_user_id_t tmp_uid; + + /* This points to the last sig in tmp_uid. */ + gpgme_key_sig_t tmp_keysig; + + /* Something new is available. */ + int key_cond; + struct key_queue_item_s *key_queue; +} *op_data_t; + + +static void +release_op_data (void *hook) +{ + op_data_t opd = (op_data_t) hook; + struct key_queue_item_s *key = opd->key_queue; + + if (opd->tmp_key) + gpgme_key_unref (opd->tmp_key); + + /* opd->tmp_uid and opd->tmp_keysig are actually part of opd->tmp_key, + so we do not need to release them here. */ + + while (key) + { + struct key_queue_item_s *next = key->next; + + gpgme_key_unref (key->key); + key = next; + } +} + + +gpgme_keylist_result_t +gpgme_op_keylist_result (gpgme_ctx_t ctx) +{ + void *hook; + op_data_t opd; + gpgme_error_t err; + + err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL); + opd = hook; + if (err || !opd) + return NULL; + + return &opd->result; +} + + +static gpgme_error_t +keylist_status_handler (void *priv, gpgme_status_code_t code, char *args) +{ + gpgme_ctx_t ctx = (gpgme_ctx_t) priv; + gpgme_error_t err; + void *hook; + op_data_t opd; + + err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL); + opd = hook; + if (err) + return err; + + switch (code) + { + case GPGME_STATUS_TRUNCATED: + opd->result.truncated = 1; + break; + + default: + break; + } + return 0; +} + + +static void +set_subkey_trust_info (gpgme_subkey_t subkey, const char *src) +{ + while (*src && !isdigit (*src)) + { + switch (*src) + { + case 'e': + subkey->expired = 1; + break; + + case 'r': + subkey->revoked = 1; + break; + + case 'd': + /* Note that gpg 1.3 won't print that anymore but only uses + the capabilities field. */ + subkey->disabled = 1; + break; + + case 'i': + subkey->invalid = 1; + break; + } + src++; + } +} + + +static void +set_mainkey_trust_info (gpgme_key_t key, const char *src) +{ + /* First set the trust info of the main key (the first subkey). */ + set_subkey_trust_info (key->subkeys, src); + + /* Now set the summarized trust info. */ + while (*src && !isdigit (*src)) + { + switch (*src) + { + case 'e': + key->expired = 1; + break; + + case 'r': + key->revoked = 1; + break; + + case 'd': + /* Note that gpg 1.3 won't print that anymore but only uses + the capabilities field. However, it is still used for + external key listings. */ + key->disabled = 1; + break; + + case 'i': + key->invalid = 1; + break; + } + src++; + } +} + + +static void +set_userid_flags (gpgme_key_t key, const char *src) +{ + gpgme_user_id_t uid = key->_last_uid; + + assert (uid); + /* Look at letters and stop at the first digit. */ + while (*src && !isdigit (*src)) + { + switch (*src) + { + case 'r': + uid->revoked = 1; + break; + + case 'i': + uid->invalid = 1; + break; + + case 'n': + uid->validity = GPGME_VALIDITY_NEVER; + break; + + case 'm': + uid->validity = GPGME_VALIDITY_MARGINAL; + break; + + case 'f': + uid->validity = GPGME_VALIDITY_FULL; + break; + + case 'u': + uid->validity = GPGME_VALIDITY_ULTIMATE; + break; + } + src++; + } +} + + +static void +set_subkey_capability (gpgme_subkey_t subkey, const char *src) +{ + while (*src) + { + switch (*src) + { + case 'e': + subkey->can_encrypt = 1; + break; + + case 's': + subkey->can_sign = 1; + break; + + case 'c': + subkey->can_certify = 1; + break; + + case 'a': + subkey->can_authenticate = 1; + break; + + case 'q': + subkey->is_qualified = 1; + break; + + case 'd': + subkey->disabled = 1; + break; + } + src++; + } +} + + +static void +set_mainkey_capability (gpgme_key_t key, const char *src) +{ + /* First set the capabilities of the main key (the first subkey). */ + set_subkey_capability (key->subkeys, src); + + while (*src) + { + switch (*src) + { + case 'd': + case 'D': + /* Note, that this flag is also set using the key validity + field for backward compatibility with gpg 1.2. We use d + and D, so that a future gpg version will be able to + disable certain subkeys. Currently it is expected that + gpg sets this for the primary key. */ + key->disabled = 1; + break; + + case 'e': + case 'E': + key->can_encrypt = 1; + break; + + case 's': + case 'S': + key->can_sign = 1; + break; + + case 'c': + case 'C': + key->can_certify = 1; + break; + + case 'a': + case 'A': + key->can_authenticate = 1; + break; + + case 'q': + case 'Q': + key->is_qualified = 1; + break; + } + src++; + } +} + + +static void +set_ownertrust (gpgme_key_t key, const char *src) +{ + /* Look at letters and stop at the first digit. */ + while (*src && !isdigit (*src)) + { + switch (*src) + { + case 'n': + key->owner_trust = GPGME_VALIDITY_NEVER; + break; + + case 'm': + key->owner_trust = GPGME_VALIDITY_MARGINAL; + break; + + case 'f': + key->owner_trust = GPGME_VALIDITY_FULL; + break; + + case 'u': + key->owner_trust = GPGME_VALIDITY_ULTIMATE; + break; + + default: + key->owner_trust = GPGME_VALIDITY_UNKNOWN; + break; + } + src++; + } +} + + +/* We have read an entire key into tmp_key and should now finish it. + It is assumed that this releases tmp_key. */ +static void +finish_key (gpgme_ctx_t ctx, op_data_t opd) +{ + gpgme_key_t key = opd->tmp_key; + + opd->tmp_key = NULL; + opd->tmp_uid = NULL; + opd->tmp_keysig = NULL; + + if (key) + _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_NEXT_KEY, key); +} + + +/* Note: We are allowed to modify LINE. */ +static gpgme_error_t +keylist_colon_handler (void *priv, char *line) +{ + gpgme_ctx_t ctx = (gpgme_ctx_t) priv; + enum + { + RT_NONE, RT_SIG, RT_UID, RT_SUB, RT_PUB, RT_FPR, + RT_SSB, RT_SEC, RT_CRT, RT_CRS, RT_REV, RT_SPK + } + rectype = RT_NONE; +#define NR_FIELDS 16 + char *field[NR_FIELDS]; + int fields = 0; + void *hook; + op_data_t opd; + gpgme_error_t err; + gpgme_key_t key; + gpgme_subkey_t subkey = NULL; + gpgme_key_sig_t keysig = NULL; + + err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL); + opd = hook; + if (err) + return err; + + key = opd->tmp_key; + + TRACE2 (DEBUG_CTX, "gpgme:keylist_colon_handler", ctx, + "key = %p, line = %s", key, line ? line : "(null)"); + + if (!line) + { + /* End Of File. */ + finish_key (ctx, opd); + return 0; + } + + while (line && fields < NR_FIELDS) + { + field[fields++] = line; + line = strchr (line, ':'); + if (line) + *(line++) = '\0'; + } + + if (!strcmp (field[0], "sig")) + rectype = RT_SIG; + else if (!strcmp (field[0], "rev")) + rectype = RT_REV; + else if (!strcmp (field[0], "pub")) + rectype = RT_PUB; + else if (!strcmp (field[0], "sec")) + rectype = RT_SEC; + else if (!strcmp (field[0], "crt")) + rectype = RT_CRT; + else if (!strcmp (field[0], "crs")) + rectype = RT_CRS; + else if (!strcmp (field[0], "fpr") && key) + rectype = RT_FPR; + else if (!strcmp (field[0], "uid") && key) + rectype = RT_UID; + else if (!strcmp (field[0], "sub") && key) + rectype = RT_SUB; + else if (!strcmp (field[0], "ssb") && key) + rectype = RT_SSB; + else if (!strcmp (field[0], "spk") && key) + rectype = RT_SPK; + else + rectype = RT_NONE; + + /* Only look at signatures immediately following a user ID. For + this, clear the user ID pointer when encountering anything but a + signature. */ + if (rectype != RT_SIG && rectype != RT_REV) + opd->tmp_uid = NULL; + + /* Only look at subpackets immediately following a signature. For + this, clear the signature pointer when encountering anything but + a subpacket. */ + if (rectype != RT_SPK) + opd->tmp_keysig = NULL; + + switch (rectype) + { + case RT_PUB: + case RT_SEC: + case RT_CRT: + case RT_CRS: + /* Start a new keyblock. */ + err = _gpgme_key_new (&key); + if (err) + return err; + key->keylist_mode = ctx->keylist_mode; + err = _gpgme_key_add_subkey (key, &subkey); + if (err) + { + gpgme_key_unref (key); + return err; + } + + if (rectype == RT_SEC || rectype == RT_CRS) + key->secret = subkey->secret = 1; + if (rectype == RT_CRT || rectype == RT_CRS) + key->protocol = GPGME_PROTOCOL_CMS; + finish_key (ctx, opd); + opd->tmp_key = key; + + /* Field 2 has the trust info. */ + if (fields >= 2) + set_mainkey_trust_info (key, field[1]); + + /* Field 3 has the key length. */ + if (fields >= 3) + { + int i = atoi (field[2]); + /* Ignore invalid values. */ + if (i > 1) + subkey->length = i; + } + + /* Field 4 has the public key algorithm. */ + if (fields >= 4) + { + int i = atoi (field[3]); + if (i >= 1 && i < 128) + subkey->pubkey_algo = i; + } + + /* Field 5 has the long keyid. Allow short key IDs for the + output of an external keyserver listing. */ + if (fields >= 5 && strlen (field[4]) <= DIM(subkey->_keyid) - 1) + strcpy (subkey->_keyid, field[4]); + + /* Field 6 has the timestamp (seconds). */ + if (fields >= 6) + subkey->timestamp = _gpgme_parse_timestamp (field[5], NULL); + + /* Field 7 has the expiration time (seconds). */ + if (fields >= 7) + subkey->expires = _gpgme_parse_timestamp (field[6], NULL); + + /* Field 8 has the X.509 serial number. */ + if (fields >= 8 && (rectype == RT_CRT || rectype == RT_CRS)) + { + key->issuer_serial = strdup (field[7]); + if (!key->issuer_serial) + return gpg_error_from_errno (errno); + } + + /* Field 9 has the ownertrust. */ + if (fields >= 9) + set_ownertrust (key, field[8]); + + /* Field 10 is not used for gpg due to --fixed-list-mode option + but GPGSM stores the issuer name. */ + if (fields >= 10 && (rectype == RT_CRT || rectype == RT_CRS)) + if (_gpgme_decode_c_string (field[9], &key->issuer_name, 0)) + return gpg_error (GPG_ERR_ENOMEM); /* FIXME */ + + /* Field 11 has the signature class. */ + + /* Field 12 has the capabilities. */ + if (fields >= 12) + set_mainkey_capability (key, field[11]); + + /* Field 15 carries special flags of a secret key. We reset the + SECRET flag of a subkey here if the key is actually only a + stub. The SECRET flag of the key will be true even then. */ + if (fields >= 15 && key->secret) + if (*field[14] == '#') + subkey->secret = 0; + break; + + case RT_SUB: + case RT_SSB: + /* Start a new subkey. */ + err = _gpgme_key_add_subkey (key, &subkey); + if (err) + return err; + + if (rectype == RT_SSB) + subkey->secret = 1; + + /* Field 2 has the trust info. */ + if (fields >= 2) + set_subkey_trust_info (subkey, field[1]); + + /* Field 3 has the key length. */ + if (fields >= 3) + { + int i = atoi (field[2]); + /* Ignore invalid values. */ + if (i > 1) + subkey->length = i; + } + + /* Field 4 has the public key algorithm. */ + if (fields >= 4) + { + int i = atoi (field[3]); + if (i >= 1 && i < 128) + subkey->pubkey_algo = i; + } + + /* Field 5 has the long keyid. */ + if (fields >= 5 && strlen (field[4]) == DIM(subkey->_keyid) - 1) + strcpy (subkey->_keyid, field[4]); + + /* Field 6 has the timestamp (seconds). */ + if (fields >= 6) + subkey->timestamp = _gpgme_parse_timestamp (field[5], NULL); + + /* Field 7 has the expiration time (seconds). */ + if (fields >= 7) + subkey->expires = _gpgme_parse_timestamp (field[6], NULL); + + /* Field 8 is reserved (LID). */ + /* Field 9 has the ownertrust. */ + /* Field 10, the user ID, is n/a for a subkey. */ + + /* Field 11 has the signature class. */ + + /* Field 12 has the capabilities. */ + if (fields >= 12) + set_subkey_capability (subkey, field[11]); + + /* Field 15 carries special flags of a secret key. */ + if (fields >= 15 && key->secret) + if (*field[14] == '#') + subkey->secret = 0; + break; + + case RT_UID: + /* Field 2 has the trust info, and field 10 has the user ID. */ + if (fields >= 10) + { + if (_gpgme_key_append_name (key, field[9])) + return gpg_error_from_errno (GPG_ERR_ENOMEM); /* FIXME */ + else + { + if (field[1]) + set_userid_flags (key, field[1]); + opd->tmp_uid = key->_last_uid; + } + } + break; + + case RT_FPR: + /* Field 10 has the fingerprint (take only the first one). */ + if (fields >= 10 && field[9] && *field[9]) + { + /* Need to apply it to the last subkey because all subkeys + do have fingerprints. */ + subkey = key->_last_subkey; + if (!subkey->fpr) + { + subkey->fpr = strdup (field[9]); + if (!subkey->fpr) + return gpg_error_from_errno (errno); + } + } + + /* Field 13 has the gpgsm chain ID (take only the first one). */ + if (fields >= 13 && !key->chain_id && *field[12]) + { + key->chain_id = strdup (field[12]); + if (!key->chain_id) + return gpg_error_from_errno (errno); + } + break; + + case RT_SIG: + case RT_REV: + if (!opd->tmp_uid) + return 0; + + /* Start a new (revoked) signature. */ + assert (opd->tmp_uid == key->_last_uid); + keysig = _gpgme_key_add_sig (key, (fields >= 10) ? field[9] : NULL); + if (!keysig) + return gpg_error (GPG_ERR_ENOMEM); /* FIXME */ + + /* Field 2 has the calculated trust ('!', '-', '?', '%'). */ + if (fields >= 2) + switch (field[1][0]) + { + case '!': + keysig->status = gpg_error (GPG_ERR_NO_ERROR); + break; + + case '-': + keysig->status = gpg_error (GPG_ERR_BAD_SIGNATURE); + break; + + case '?': + keysig->status = gpg_error (GPG_ERR_NO_PUBKEY); + break; + + case '%': + keysig->status = gpg_error (GPG_ERR_GENERAL); + break; + + default: + keysig->status = gpg_error (GPG_ERR_NO_ERROR); + break; + } + + /* Field 4 has the public key algorithm. */ + if (fields >= 4) + { + int i = atoi (field[3]); + if (i >= 1 && i < 128) + keysig->pubkey_algo = i; + } + + /* Field 5 has the long keyid. */ + if (fields >= 5 && strlen (field[4]) == DIM(keysig->_keyid) - 1) + strcpy (keysig->_keyid, field[4]); + + /* Field 6 has the timestamp (seconds). */ + if (fields >= 6) + keysig->timestamp = _gpgme_parse_timestamp (field[5], NULL); + + /* Field 7 has the expiration time (seconds). */ + if (fields >= 7) + keysig->expires = _gpgme_parse_timestamp (field[6], NULL); + + /* Field 11 has the signature class (eg, 0x30 means revoked). */ + if (fields >= 11) + if (field[10][0] && field[10][1]) + { + int sig_class = _gpgme_hextobyte (field[10]); + if (sig_class >= 0) + { + keysig->sig_class = sig_class; + keysig->class = keysig->sig_class; + if (sig_class == 0x30) + keysig->revoked = 1; + } + if (field[10][2] == 'x') + keysig->exportable = 1; + } + + opd->tmp_keysig = keysig; + break; + + case RT_SPK: + if (!opd->tmp_keysig) + return 0; + assert (opd->tmp_keysig == key->_last_uid->_last_keysig); + + if (fields >= 4) + { + /* Field 2 has the subpacket type. */ + int type = atoi (field[1]); + + /* Field 3 has the flags. */ + int flags = atoi (field[2]); + + /* Field 4 has the length. */ + int len = atoi (field[3]); + + /* Field 5 has the data. */ + char *data = field[4]; + + /* Type 20: Notation data. */ + /* Type 26: Policy URL. */ + if (type == 20 || type == 26) + { + gpgme_sig_notation_t notation; + + keysig = opd->tmp_keysig; + + /* At this time, any error is serious. */ + err = _gpgme_parse_notation (¬ation, type, flags, len, data); + if (err) + return err; + + /* Add a new notation. FIXME: Could be factored out. */ + if (!keysig->notations) + keysig->notations = notation; + if (keysig->_last_notation) + keysig->_last_notation->next = notation; + keysig->_last_notation = notation; + } + } + + case RT_NONE: + /* Unknown record. */ + break; + } + return 0; +} + + +void +_gpgme_op_keylist_event_cb (void *data, gpgme_event_io_t type, void *type_data) +{ + gpgme_error_t err; + gpgme_ctx_t ctx = (gpgme_ctx_t) data; + gpgme_key_t key = (gpgme_key_t) type_data; + void *hook; + op_data_t opd; + struct key_queue_item_s *q, *q2; + + assert (type == GPGME_EVENT_NEXT_KEY); + + err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL); + opd = hook; + if (err) + return; + + q = malloc (sizeof *q); + if (!q) + { + gpgme_key_unref (key); + /* FIXME return GPGME_Out_Of_Core; */ + return; + } + q->key = key; + q->next = NULL; + /* FIXME: Use a tail pointer? */ + if (!(q2 = opd->key_queue)) + opd->key_queue = q; + else + { + for (; q2->next; q2 = q2->next) + ; + q2->next = q; + } + opd->key_cond = 1; +} + + +/* Start a keylist operation within CTX, searching for keys which + match PATTERN. If SECRET_ONLY is true, only secret keys are + returned. */ +gpgme_error_t +gpgme_op_keylist_start (gpgme_ctx_t ctx, const char *pattern, int secret_only) +{ + gpgme_error_t err; + void *hook; + op_data_t opd; + + err = _gpgme_op_reset (ctx, 2); + if (err) + return err; + + err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, + sizeof (*opd), release_op_data); + opd = hook; + if (err) + return err; + + _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx); + + err = _gpgme_engine_set_colon_line_handler (ctx->engine, + keylist_colon_handler, ctx); + if (err) + return err; + + return _gpgme_engine_op_keylist (ctx->engine, pattern, secret_only, + ctx->keylist_mode); +} + + +/* Start a keylist operation within CTX, searching for keys which + match PATTERN. If SECRET_ONLY is true, only secret keys are + returned. */ +gpgme_error_t +gpgme_op_keylist_ext_start (gpgme_ctx_t ctx, const char *pattern[], + int secret_only, int reserved) +{ + gpgme_error_t err; + void *hook; + op_data_t opd; + + err = _gpgme_op_reset (ctx, 2); + if (err) + return err; + + err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, + sizeof (*opd), release_op_data); + opd = hook; + if (err) + return err; + + _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx); + err = _gpgme_engine_set_colon_line_handler (ctx->engine, + keylist_colon_handler, ctx); + if (err) + return err; + + return _gpgme_engine_op_keylist_ext (ctx->engine, pattern, secret_only, + reserved, ctx->keylist_mode); +} + + +/* Return the next key from the keylist in R_KEY. */ +gpgme_error_t +gpgme_op_keylist_next (gpgme_ctx_t ctx, gpgme_key_t *r_key) +{ + gpgme_error_t err; + struct key_queue_item_s *queue_item; + void *hook; + op_data_t opd; + + if (!ctx || !r_key) + return gpg_error (GPG_ERR_INV_VALUE); + *r_key = NULL; + if (!ctx) + return gpg_error (GPG_ERR_INV_VALUE); + + err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL); + opd = hook; + if (err) + return err; + if (opd == NULL) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!opd->key_queue) + { + err = _gpgme_wait_on_condition (ctx, &opd->key_cond); + if (err) + return err; + + if (!opd->key_cond) + return gpg_error (GPG_ERR_EOF); + + opd->key_cond = 0; + assert (opd->key_queue); + } + queue_item = opd->key_queue; + opd->key_queue = queue_item->next; + if (!opd->key_queue) + opd->key_cond = 0; + + *r_key = queue_item->key; + free (queue_item); + return 0; +} + + +/* Terminate a pending keylist operation within CTX. */ +gpgme_error_t +gpgme_op_keylist_end (gpgme_ctx_t ctx) +{ + if (!ctx) + return gpg_error (GPG_ERR_INV_VALUE); + + return 0; +} + + +/* Get the key with the fingerprint FPR from the crypto backend. If + SECRET is true, get the secret key. */ +gpgme_error_t +gpgme_get_key (gpgme_ctx_t ctx, const char *fpr, gpgme_key_t *r_key, + int secret) +{ + gpgme_ctx_t listctx; + gpgme_error_t err; + gpgme_key_t key; + + if (!ctx || !r_key || !fpr) + return gpg_error (GPG_ERR_INV_VALUE); + + if (strlen (fpr) < 8) /* We have at least a key ID. */ + return gpg_error (GPG_ERR_INV_VALUE); + + /* FIXME: We use our own context because we have to avoid the user's + I/O callback handlers. */ + err = gpgme_new (&listctx); + if (err) + return err; + { + gpgme_protocol_t proto; + gpgme_engine_info_t info; + + /* Clone the relevant state. */ + proto = gpgme_get_protocol (ctx); + gpgme_set_protocol (listctx, proto); + gpgme_set_keylist_mode (listctx, gpgme_get_keylist_mode (ctx)); + info = gpgme_ctx_get_engine_info (ctx); + while (info && info->protocol != proto) + info = info->next; + if (info) + gpgme_ctx_set_engine_info (listctx, proto, + info->file_name, info->home_dir); + } + + err = gpgme_op_keylist_start (listctx, fpr, secret); + if (!err) + err = gpgme_op_keylist_next (listctx, r_key); + if (!err) + { + err = gpgme_op_keylist_next (listctx, &key); + if (gpgme_err_code (err) == GPG_ERR_EOF) + err = gpg_error (GPG_ERR_NO_ERROR); + else + { + if (!err) + { + gpgme_key_unref (key); + err = gpg_error (GPG_ERR_AMBIGUOUS_NAME); + } + gpgme_key_unref (*r_key); + } + } + gpgme_release (listctx); + return err; +} diff --git a/tags/gpgme-1.1.6/gpgme/libgpgme.vers b/tags/gpgme-1.1.6/gpgme/libgpgme.vers new file mode 100644 index 0000000..183a394 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/libgpgme.vers @@ -0,0 +1,177 @@ +# libgpgme.vers - List of symbols to export. +# Copyright (C) 2002, 2004, 2005 g10 Code GmbH +# +# This file is part of GPGME. +# +# GPGME is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser general Public License as +# published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser 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 + +#------------------------------------------------------- +# Please remember to add new functions also to gpgme.def +#------------------------------------------------------- + +GPGME_1.1 { + global: + gpgme_set_engine_info; + + gpgme_ctx_get_engine_info; + gpgme_ctx_set_engine_info; + + gpgme_data_set_file_name; + gpgme_data_get_file_name; + + gpgme_sig_notation_clear; + gpgme_sig_notation_add; + gpgme_sig_notation_get; + + gpgme_free; + + gpgme_op_getauditlog_start; + gpgme_op_getauditlog; + + gpgme_conf_release; + gpgme_conf_arg_new; + gpgme_conf_arg_release; + gpgme_conf_opt_change; + gpgme_op_conf_load; + gpgme_op_conf_save; +}; + + +GPGME_1.0 { + global: + gpgme_check_version; + gpgme_get_engine_info; + gpgme_engine_check_version; + + gpgme_err_code_from_errno; + gpgme_err_code_to_errno; + gpgme_err_make_from_errno; + gpgme_error_from_errno; + gpgme_strerror; + gpgme_strerror_r; + gpgme_strsource; + + gpgme_data_get_encoding; + gpgme_data_new; + gpgme_data_new_from_cbs; + gpgme_data_new_from_fd; + gpgme_data_new_from_file; + gpgme_data_new_from_filepart; + gpgme_data_new_from_mem; + gpgme_data_new_from_stream; + gpgme_data_read; + gpgme_data_release; + gpgme_data_release_and_get_mem; + gpgme_data_seek; + gpgme_data_set_encoding; + gpgme_data_write; + + gpgme_get_protocol_name; + gpgme_hash_algo_name; + gpgme_pubkey_algo_name; + + gpgme_new; + gpgme_get_armor; + gpgme_get_include_certs; + gpgme_get_io_cbs; + gpgme_get_keylist_mode; + gpgme_get_passphrase_cb; + gpgme_get_progress_cb; + gpgme_get_protocol; + gpgme_get_textmode; + gpgme_release; + gpgme_set_armor; + gpgme_set_include_certs; + gpgme_set_io_cbs; + gpgme_set_keylist_mode; + gpgme_set_locale; + gpgme_set_passphrase_cb; + gpgme_set_progress_cb; + gpgme_set_protocol; + gpgme_set_textmode; + gpgme_signers_add; + gpgme_signers_clear; + gpgme_signers_enum; + + gpgme_key_ref; + gpgme_key_unref; + gpgme_key_release; + + gpgme_trust_item_ref; + gpgme_trust_item_unref; + + gpgme_cancel; + gpgme_op_card_edit; + gpgme_op_card_edit_start; + gpgme_op_decrypt; + gpgme_op_decrypt_result; + gpgme_op_decrypt_start; + gpgme_op_decrypt_verify; + gpgme_op_decrypt_verify_start; + gpgme_op_delete; + gpgme_op_delete_start; + gpgme_op_edit; + gpgme_op_edit_start; + gpgme_op_encrypt; + gpgme_op_encrypt_result; + gpgme_op_encrypt_sign; + gpgme_op_encrypt_sign_start; + gpgme_op_encrypt_start; + gpgme_op_export; + gpgme_op_export_ext; + gpgme_op_export_ext_start; + gpgme_op_export_start; + gpgme_op_genkey; + gpgme_op_genkey_result; + gpgme_op_genkey_start; + gpgme_get_key; + gpgme_op_import; + gpgme_op_import_result; + gpgme_op_import_start; + gpgme_op_keylist_end; + gpgme_op_keylist_ext_start; + gpgme_op_keylist_next; + gpgme_op_keylist_result; + gpgme_op_keylist_start; + gpgme_op_sign; + gpgme_op_sign_result; + gpgme_op_sign_start; + gpgme_op_trustlist_end; + gpgme_op_trustlist_next; + gpgme_op_trustlist_start; + gpgme_op_verify; + gpgme_op_verify_result; + gpgme_op_verify_start; + gpgme_wait; + + gpgme_data_new_with_read_cb; + gpgme_data_rewind; + gpgme_get_sig_status; + gpgme_get_sig_string_attr; + gpgme_get_sig_ulong_attr; + gpgme_get_sig_key; + gpgme_key_get_string_attr; + gpgme_key_get_ulong_attr; + gpgme_key_sig_get_string_attr; + gpgme_key_sig_get_ulong_attr; + gpgme_op_import_ext; + gpgme_trust_item_get_int_attr; + gpgme_trust_item_get_string_attr; + gpgme_trust_item_release; + + local: + *; + +}; diff --git a/tags/gpgme-1.1.6/gpgme/memrchr.c b/tags/gpgme-1.1.6/gpgme/memrchr.c new file mode 100644 index 0000000..21662b1 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/memrchr.c @@ -0,0 +1,210 @@ +/* memrchr -- find the last occurrence of a byte in a memory block + Copyright (C) 1991, 93, 96, 97, 99, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Based on strlen implementation by Torbjorn Granlund (tege@sics.se), + with help from Dan Sahlin (dan@sics.se) and + commentary by Jim Blandy (jimb@ai.mit.edu); + adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu), + and implemented by Roland McGrath (roland@ai.mit.edu). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#ifdef HAVE_CONFIG_H +# include +#endif + +#undef __ptr_t +#if defined __cplusplus || (defined __STDC__ && __STDC__) +# define __ptr_t void * +#else /* Not C++ or ANSI C. */ +# define __ptr_t char * +#endif /* C++ or ANSI C. */ + +#if defined _LIBC +# include +# include +#else +# define reg_char char +#endif + +#if defined HAVE_LIMITS_H || defined _LIBC +# include +#endif + +#define LONG_MAX_32_BITS 2147483647 + +#ifndef LONG_MAX +# define LONG_MAX LONG_MAX_32_BITS +#endif + +#include + +#undef __memrchr +#undef memrchr + +#ifndef weak_alias +# define __memrchr memrchr +#endif + +/* Search no more than N bytes of S for C. */ +__ptr_t +__memrchr (s, c_in, n) + const __ptr_t s; + int c_in; + size_t n; +{ + const unsigned char *char_ptr; + const unsigned long int *longword_ptr; + unsigned long int longword, magic_bits, charmask; + unsigned reg_char c; + + c = (unsigned char) c_in; + + /* Handle the last few characters by reading one character at a time. + Do this until CHAR_PTR is aligned on a longword boundary. */ + for (char_ptr = (const unsigned char *) s + n; + n > 0 && ((unsigned long int) char_ptr + & (sizeof (longword) - 1)) != 0; + --n) + if (*--char_ptr == c) + return (__ptr_t) char_ptr; + + /* All these elucidatory comments refer to 4-byte longwords, + but the theory applies equally well to 8-byte longwords. */ + + longword_ptr = (const unsigned long int *) char_ptr; + + /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits + the "holes." Note that there is a hole just to the left of + each byte, with an extra at the end: + + bits: 01111110 11111110 11111110 11111111 + bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD + + The 1-bits make sure that carries propagate to the next 0-bit. + The 0-bits provide holes for carries to fall into. */ + + if (sizeof (longword) != 4 && sizeof (longword) != 8) + abort (); + +#if LONG_MAX <= LONG_MAX_32_BITS + magic_bits = 0x7efefeff; +#else + magic_bits = ((unsigned long int) 0x7efefefe << 32) | 0xfefefeff; +#endif + + /* Set up a longword, each of whose bytes is C. */ + charmask = c | (c << 8); + charmask |= charmask << 16; +#if LONG_MAX > LONG_MAX_32_BITS + charmask |= charmask << 32; +#endif + + /* Instead of the traditional loop which tests each character, + we will test a longword at a time. The tricky part is testing + if *any of the four* bytes in the longword in question are zero. */ + while (n >= sizeof (longword)) + { + /* We tentatively exit the loop if adding MAGIC_BITS to + LONGWORD fails to change any of the hole bits of LONGWORD. + + 1) Is this safe? Will it catch all the zero bytes? + Suppose there is a byte with all zeros. Any carry bits + propagating from its left will fall into the hole at its + least significant bit and stop. Since there will be no + carry from its most significant bit, the LSB of the + byte to the left will be unchanged, and the zero will be + detected. + + 2) Is this worthwhile? Will it ignore everything except + zero bytes? Suppose every byte of LONGWORD has a bit set + somewhere. There will be a carry into bit 8. If bit 8 + is set, this will carry into bit 16. If bit 8 is clear, + one of bits 9-15 must be set, so there will be a carry + into bit 16. Similarly, there will be a carry into bit + 24. If one of bits 24-30 is set, there will be a carry + into bit 31, so all of the hole bits will be changed. + + The one misfire occurs when bits 24-30 are clear and bit + 31 is set; in this case, the hole at bit 31 is not + changed. If we had access to the processor carry flag, + we could close this loophole by putting the fourth hole + at bit 32! + + So it ignores everything except 128's, when they're aligned + properly. + + 3) But wait! Aren't we looking for C, not zero? + Good point. So what we do is XOR LONGWORD with a longword, + each of whose bytes is C. This turns each byte that is C + into a zero. */ + + longword = *--longword_ptr ^ charmask; + + /* Add MAGIC_BITS to LONGWORD. */ + if ((((longword + magic_bits) + + /* Set those bits that were unchanged by the addition. */ + ^ ~longword) + + /* Look at only the hole bits. If any of the hole bits + are unchanged, most likely one of the bytes was a + zero. */ + & ~magic_bits) != 0) + { + /* Which of the bytes was C? If none of them were, it was + a misfire; continue the search. */ + + const unsigned char *cp = (const unsigned char *) longword_ptr; + +#if LONG_MAX > 2147483647 + if (cp[7] == c) + return (__ptr_t) &cp[7]; + if (cp[6] == c) + return (__ptr_t) &cp[6]; + if (cp[5] == c) + return (__ptr_t) &cp[5]; + if (cp[4] == c) + return (__ptr_t) &cp[4]; +#endif + if (cp[3] == c) + return (__ptr_t) &cp[3]; + if (cp[2] == c) + return (__ptr_t) &cp[2]; + if (cp[1] == c) + return (__ptr_t) &cp[1]; + if (cp[0] == c) + return (__ptr_t) cp; + } + + n -= sizeof (longword); + } + + char_ptr = (const unsigned char *) longword_ptr; + + while (n-- > 0) + { + if (*--char_ptr == c) + return (__ptr_t) char_ptr; + } + + return 0; +} +#ifdef weak_alias +weak_alias (__memrchr, memrchr) +#endif diff --git a/tags/gpgme-1.1.6/gpgme/mkstatus b/tags/gpgme-1.1.6/gpgme/mkstatus new file mode 100755 index 0000000..e64ab19 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/mkstatus @@ -0,0 +1,52 @@ +#!/bin/sh +# mkstatus - Extract error strings from rungpg.h +# and create a lookup table +# Copyright (C) 2000 Werner Koch (dd9jn) +# Copyright (C) 2001 g10 Code GmbH +# +# This file is part of GPGME. +# +# GPGME is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser 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 + +# resetting collate is important, so that the bsearch works properly +LC_ALL=C +LC_COLLATE=C +export LC_ALL LC_COLLATE + +cat <." +#elif Q_MOC_OUTPUT_REVISION != 59 +#error "This file was generated using the moc from 4.3.0. It" +#error "cannot be used with the include files from this version of Qt." +#error "(The moc has changed too much.)" +#endif + +static const uint qt_meta_data_KDPipeIODevice[] = { + + // content: + 1, // revision + 0, // classname + 0, 0, // classinfo + 0, 0, // methods + 0, 0, // properties + 0, 0, // enums/sets + + 0 // eod +}; + +static const char qt_meta_stringdata_KDPipeIODevice[] = { + "KDPipeIODevice\0" +}; + +const QMetaObject KDPipeIODevice::staticMetaObject = { + { &QIODevice::staticMetaObject, qt_meta_stringdata_KDPipeIODevice, + qt_meta_data_KDPipeIODevice, 0 } +}; + +const QMetaObject *KDPipeIODevice::metaObject() const +{ + return &staticMetaObject; +} + +void *KDPipeIODevice::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_KDPipeIODevice)) + return static_cast(const_cast< KDPipeIODevice*>(this)); + return QIODevice::qt_metacast(_clname); +} + +int KDPipeIODevice::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QIODevice::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + return _id; +} diff --git a/tags/gpgme-1.1.6/gpgme/op-support.c b/tags/gpgme-1.1.6/gpgme/op-support.c new file mode 100644 index 0000000..1212c54 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/op-support.c @@ -0,0 +1,295 @@ +/* op-support.c - Supporting functions. + Copyright (C) 2002, 2003, 2004, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, see . + */ + +#if HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include + +#include "gpgme.h" +#include "context.h" +#include "ops.h" + + +gpgme_error_t +_gpgme_op_data_lookup (gpgme_ctx_t ctx, ctx_op_data_id_t type, void **hook, + int size, void (*cleanup) (void *)) +{ + struct ctx_op_data *data = ctx->op_data; + while (data && data->type != type) + data = data->next; + if (!data) + { + if (size < 0) + { + *hook = NULL; + return 0; + } + + data = calloc (1, sizeof (struct ctx_op_data) + size); + if (!data) + return gpg_error_from_errno (errno); + data->next = ctx->op_data; + data->type = type; + data->cleanup = cleanup; + data->hook = (void *) (((char *) data) + sizeof (struct ctx_op_data)); + ctx->op_data = data; + } + *hook = data->hook; + return 0; +} + + +/* type is: 0: asynchronous operation (use global or user event loop). + 1: synchronous operation (always use private event loop). + 2: asynchronous private operation (use private or user + event loop). + 256: Modification flag to suppress the engine reset. +*/ +gpgme_error_t +_gpgme_op_reset (gpgme_ctx_t ctx, int type) +{ + gpgme_error_t err = 0; + struct gpgme_io_cbs io_cbs; + int no_reset = (type & 256); + int reuse_engine = 0; + + type &= 255; + + _gpgme_release_result (ctx); + + if (ctx->engine && no_reset) + reuse_engine = 1; + else if (ctx->engine) + { + /* Attempt to reset an existing engine. */ + + err = _gpgme_engine_reset (ctx->engine); + if (gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED) + { + _gpgme_engine_release (ctx->engine); + ctx->engine = NULL; + } + } + + if (!ctx->engine) + { + gpgme_engine_info_t info; + info = ctx->engine_info; + while (info && info->protocol != ctx->protocol) + info = info->next; + + if (!info) + return gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL); + + /* Create an engine object. */ + err = _gpgme_engine_new (info, &ctx->engine); + if (err) + return err; + } + + if (!reuse_engine) + { + err = _gpgme_engine_set_locale (ctx->engine, LC_CTYPE, ctx->lc_ctype); +#ifdef LC_MESSAGES + if (!err) + err = _gpgme_engine_set_locale (ctx->engine, + LC_MESSAGES, ctx->lc_messages); +#endif + if (gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED) + err = 0; + if (err) + { + _gpgme_engine_release (ctx->engine); + ctx->engine = NULL; + return err; + } + } + + if (type == 1 || (type == 2 && !ctx->io_cbs.add)) + { + /* Use private event loop. */ + io_cbs.add = _gpgme_add_io_cb; + io_cbs.add_priv = ctx; + io_cbs.remove = _gpgme_remove_io_cb; + io_cbs.event = _gpgme_wait_private_event_cb; + io_cbs.event_priv = ctx; + } + else if (! ctx->io_cbs.add) + { + /* Use global event loop. */ + io_cbs.add = _gpgme_add_io_cb; + io_cbs.add_priv = ctx; + io_cbs.remove = _gpgme_remove_io_cb; + io_cbs.event = _gpgme_wait_global_event_cb; + io_cbs.event_priv = ctx; + } + else + { + /* Use user event loop. */ + io_cbs.add = _gpgme_wait_user_add_io_cb; + io_cbs.add_priv = ctx; + io_cbs.remove = _gpgme_wait_user_remove_io_cb; + io_cbs.event = _gpgme_wait_user_event_cb; + io_cbs.event_priv = ctx; + } + _gpgme_engine_set_io_cbs (ctx->engine, &io_cbs); + return err; +} + + +/* Parse the INV_RECP status line in ARGS and return the result in + KEY. */ +gpgme_error_t +_gpgme_parse_inv_recp (char *args, gpgme_invalid_key_t *key) +{ + gpgme_invalid_key_t inv_key; + char *tail; + long int reason; + + inv_key = malloc (sizeof (*inv_key)); + if (!inv_key) + return gpg_error_from_errno (errno); + inv_key->next = NULL; + errno = 0; + reason = strtol (args, &tail, 0); + if (errno || args == tail || *tail != ' ') + { + /* The crypto backend does not behave. */ + free (inv_key); + return gpg_error (GPG_ERR_INV_ENGINE); + } + + switch (reason) + { + default: + case 0: + inv_key->reason = gpg_error (GPG_ERR_GENERAL); + break; + + case 1: + inv_key->reason = gpg_error (GPG_ERR_NO_PUBKEY); + break; + + case 2: + inv_key->reason = gpg_error (GPG_ERR_AMBIGUOUS_NAME); + break; + + case 3: + inv_key->reason = gpg_error (GPG_ERR_WRONG_KEY_USAGE); + break; + + case 4: + inv_key->reason = gpg_error (GPG_ERR_CERT_REVOKED); + break; + + case 5: + inv_key->reason = gpg_error (GPG_ERR_CERT_EXPIRED); + break; + + case 6: + inv_key->reason = gpg_error (GPG_ERR_NO_CRL_KNOWN); + break; + + case 7: + inv_key->reason = gpg_error (GPG_ERR_CRL_TOO_OLD); + break; + + case 8: + inv_key->reason = gpg_error (GPG_ERR_NO_POLICY_MATCH); + break; + + case 9: + inv_key->reason = gpg_error (GPG_ERR_NO_SECKEY); + break; + + case 10: + inv_key->reason = gpg_error (GPG_ERR_PUBKEY_NOT_TRUSTED); + break; + + case 11: + inv_key->reason = gpg_error (GPG_ERR_MISSING_CERT); + break; + } + + while (*tail == ' ') + tail++; + if (*tail) + { + inv_key->fpr = strdup (tail); + if (!inv_key->fpr) + { + int saved_errno = errno; + free (inv_key); + return gpg_error_from_errno (saved_errno); + } + } + else + inv_key->fpr = NULL; + + *key = inv_key; + return 0; +} + + +/* Parse the PLAINTEXT status line in ARGS and return the result in + FILENAMEP. */ +gpgme_error_t +_gpgme_parse_plaintext (char *args, char **filenamep) +{ + char *tail; + + while (*args == ' ') + args++; + if (*args == '\0') + return 0; + + /* First argument is file type. */ + while (*args != ' ' && *args != '\0') + args++; + while (*args == ' ') + args++; + if (*args == '\0') + return 0; + + /* Second argument is the timestamp. */ + while (*args != ' ' && *args != '\0') + args++; + while (*args == ' ') + args++; + if (*args == '\0') + return 0; + + tail = args; + while (*tail != ' ' && *tail != '\0') + tail++; + *tail = '\0'; + if (filenamep && *args != '\0') + { + char *filename = strdup (args); + if (!filename) + return gpg_error_from_errno (errno); + + *filenamep = filename; + } + return 0; +} diff --git a/tags/gpgme-1.1.6/gpgme/ops.h b/tags/gpgme-1.1.6/gpgme/ops.h new file mode 100644 index 0000000..d6a09e5 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/ops.h @@ -0,0 +1,169 @@ +/* ops.h - Internal operation support. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 "gpgme.h" +#include "context.h" + + +/* From gpgme.c. */ +void _gpgme_release_result (gpgme_ctx_t ctx); + + +/* From wait.c. */ +gpgme_error_t _gpgme_wait_one (gpgme_ctx_t ctx); +gpgme_error_t _gpgme_wait_on_condition (gpgme_ctx_t ctx, volatile int *cond); + + +/* From data.c. */ +gpgme_error_t _gpgme_data_inbound_handler (void *opaque, int fd); +gpgme_error_t _gpgme_data_outbound_handler (void *opaque, int fd); + + +/* From op-support.c. */ + +/* Find or create the op data object of type TYPE. */ +gpgme_error_t _gpgme_op_data_lookup (gpgme_ctx_t ctx, ctx_op_data_id_t type, + void **hook, int size, + void (*cleanup) (void *)); + +/* Prepare a new operation on CTX. */ +gpgme_error_t _gpgme_op_reset (gpgme_ctx_t ctx, int synchronous); + +/* Parse the INV_RECP status line in ARGS and return the result in + KEY. */ +gpgme_error_t _gpgme_parse_inv_recp (char *args, gpgme_invalid_key_t *key); + +/* Parse the PLAINTEXT status line in ARGS and return the result in + FILENAMEP. */ +gpgme_error_t _gpgme_parse_plaintext (char *args, char **filenamep); + + + +/* From verify.c. */ +gpgme_error_t _gpgme_op_verify_init_result (gpgme_ctx_t ctx); +gpgme_error_t _gpgme_verify_status_handler (void *priv, + gpgme_status_code_t code, + char *args); + + +/* From decrypt.c. */ +gpgme_error_t _gpgme_op_decrypt_init_result (gpgme_ctx_t ctx); +gpgme_error_t _gpgme_decrypt_status_handler (void *priv, + gpgme_status_code_t code, + char *args); + + +/* From sign.c. */ + +/* Create an initial op data object for signing. Needs to be called + once before calling _gpgme_sign_status_handler. */ +gpgme_error_t _gpgme_op_sign_init_result (gpgme_ctx_t ctx); + +/* Process a status line for signing operations. */ +gpgme_error_t _gpgme_sign_status_handler (void *priv, + gpgme_status_code_t code, + char *args); + + +/* From encrypt.c. */ + +/* Create an initial op data object for encrypt. Needs to be called + once before calling _gpgme_encrypt_status_handler. */ +gpgme_error_t _gpgme_op_encrypt_init_result (gpgme_ctx_t ctx); + +/* Process a status line for encryption operations. */ +gpgme_error_t _gpgme_encrypt_status_handler (void *priv, + gpgme_status_code_t code, + char *args); + + +/* From passphrase.c. */ +gpgme_error_t _gpgme_passphrase_status_handler (void *priv, + gpgme_status_code_t code, + char *args); +gpgme_error_t _gpgme_passphrase_command_handler (void *opaque, + gpgme_status_code_t code, + const char *key, int fd, + int *processed); + + +/* From progress.c. */ +gpgme_error_t _gpgme_progress_status_handler (void *priv, + gpgme_status_code_t code, + char *args); + + +/* From key.c. */ +gpgme_error_t _gpgme_key_new (gpgme_key_t *r_key); +gpgme_error_t _gpgme_key_add_subkey (gpgme_key_t key, + gpgme_subkey_t *r_subkey); +gpgme_error_t _gpgme_key_append_name (gpgme_key_t key, char *src); +gpgme_key_sig_t _gpgme_key_add_sig (gpgme_key_t key, char *src); + + +/* From keylist.c. */ +void _gpgme_op_keylist_event_cb (void *data, gpgme_event_io_t type, + void *type_data); + + +/* From trust-item.c. */ + +/* Create a new trust item. */ +gpgme_error_t _gpgme_trust_item_new (gpgme_trust_item_t *r_item); + + +/* From trustlist.c. */ +void _gpgme_op_trustlist_event_cb (void *data, gpgme_event_io_t type, + void *type_data); + + +/* From version.c. */ + +/* Return true if MY_VERSION is at least REQ_VERSION, and false + otherwise. */ +int _gpgme_compare_versions (const char *my_version, + const char *req_version); +char *_gpgme_get_program_version (const char *const path); + + +/* From sig-notation.c. */ + +/* Create a new, empty signature notation data object. */ +gpgme_error_t _gpgme_sig_notation_create (gpgme_sig_notation_t *notationp, + const char *name, int name_len, + const char *value, int value_len, + gpgme_sig_notation_flags_t flags); + +/* Free the signature notation object and all associated resources. + The object must already be removed from any linked list as the next + pointer is ignored. */ +void _gpgme_sig_notation_free (gpgme_sig_notation_t notation); + +/* Parse a notation or policy URL subpacket. If the packet type is + not known, return no error but NULL in NOTATION. */ +gpgme_error_t _gpgme_parse_notation (gpgme_sig_notation_t *notationp, + int type, int pkflags, int len, + char *data); + +#endif /* OPS_H */ diff --git a/tags/gpgme-1.1.6/gpgme/passphrase.c b/tags/gpgme-1.1.6/gpgme/passphrase.c new file mode 100644 index 0000000..7132684 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/passphrase.c @@ -0,0 +1,153 @@ +/* passphrase.c - Passphrase callback. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include + +#include "gpgme.h" +#include "context.h" +#include "ops.h" + + +typedef struct +{ + int no_passphrase; + char *uid_hint; + char *passphrase_info; + int bad_passphrase; +} *op_data_t; + + +static void +release_op_data (void *hook) +{ + op_data_t opd = (op_data_t) hook; + + if (opd->passphrase_info) + free (opd->passphrase_info); + if (opd->uid_hint) + free (opd->uid_hint); +} + + +gpgme_error_t +_gpgme_passphrase_status_handler (void *priv, gpgme_status_code_t code, + char *args) +{ + gpgme_ctx_t ctx = (gpgme_ctx_t) priv; + gpgme_error_t err; + void *hook; + op_data_t opd; + + err = _gpgme_op_data_lookup (ctx, OPDATA_PASSPHRASE, &hook, + sizeof (*opd), release_op_data); + opd = hook; + if (err) + return err; + + switch (code) + { + case GPGME_STATUS_USERID_HINT: + if (opd->uid_hint) + free (opd->uid_hint); + if (!(opd->uid_hint = strdup (args))) + return gpg_error_from_errno (errno); + break; + + case GPGME_STATUS_BAD_PASSPHRASE: + opd->bad_passphrase++; + opd->no_passphrase = 0; + break; + + case GPGME_STATUS_GOOD_PASSPHRASE: + opd->bad_passphrase = 0; + opd->no_passphrase = 0; + break; + + case GPGME_STATUS_NEED_PASSPHRASE: + case GPGME_STATUS_NEED_PASSPHRASE_SYM: + case GPGME_STATUS_NEED_PASSPHRASE_PIN: + if (opd->passphrase_info) + free (opd->passphrase_info); + opd->passphrase_info = strdup (args); + if (!opd->passphrase_info) + return gpg_error_from_errno (errno); + break; + + case GPGME_STATUS_MISSING_PASSPHRASE: + opd->no_passphrase = 1; + break; + + case GPGME_STATUS_EOF: + if (opd->no_passphrase || opd->bad_passphrase) + return gpg_error (GPG_ERR_BAD_PASSPHRASE); + break; + + default: + /* Ignore all other codes. */ + break; + } + return 0; +} + + +gpgme_error_t +_gpgme_passphrase_command_handler (void *priv, gpgme_status_code_t code, + const char *key, int fd, int *processed) +{ + gpgme_ctx_t ctx = (gpgme_ctx_t) priv; + gpgme_error_t err; + void *hook; + op_data_t opd; + + assert (ctx->passphrase_cb); + + err = _gpgme_op_data_lookup (ctx, OPDATA_PASSPHRASE, &hook, + sizeof (*opd), release_op_data); + opd = hook; + if (err) + return err; + + if (code == GPGME_STATUS_GET_HIDDEN + && (!strcmp (key, "passphrase.enter") + || !strcmp (key, "passphrase.pin.ask"))) + { + if (processed) + *processed = 1; + + err = ctx->passphrase_cb (ctx->passphrase_cb_value, + opd->uid_hint, opd->passphrase_info, + opd->bad_passphrase, fd); + + /* Reset bad passphrase flag, in case it is correct now. */ + opd->bad_passphrase = 0; + + return err; + } + + return 0; +} diff --git a/tags/gpgme-1.1.6/gpgme/posix-io.c b/tags/gpgme-1.1.6/gpgme/posix-io.c new file mode 100644 index 0000000..6b793f1 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/posix-io.c @@ -0,0 +1,550 @@ +/* posix-io.c - Posix I/O functions + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2004, 2005, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "priv-io.h" +#include "sema.h" +#include "ath.h" +#include "debug.h" + + +void +_gpgme_io_subsystem_init (void) +{ + 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); + } +} + + +/* Write the printable version of FD to the buffer BUF of length + BUFLEN. The printable version is the representation on the command + line that the child process expects. */ +int +_gpgme_io_fd2str (char *buf, int buflen, int fd) +{ + return snprintf (buf, buflen, "%d", fd); +} + + +static struct +{ + _gpgme_close_notify_handler_t handler; + void *value; +} notify_table[256]; + + +int +_gpgme_io_read (int fd, void *buffer, size_t count) +{ + int nread; + TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_read", fd, + "buffer=%p, count=%u", buffer, count); + + do + { + nread = _gpgme_ath_read (fd, buffer, count); + } + while (nread == -1 && errno == EINTR); + + TRACE_LOGBUF (buffer, nread); + return TRACE_SYSRES (nread); +} + + +int +_gpgme_io_write (int fd, const void *buffer, size_t count) +{ + int nwritten; + TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_write", fd, + "buffer=%p, count=%u", buffer, count); + TRACE_LOGBUF (buffer, count); + + do + { + nwritten = _gpgme_ath_write (fd, buffer, count); + } + while (nwritten == -1 && errno == EINTR); + + return TRACE_SYSRES (nwritten); +} + + +int +_gpgme_io_pipe (int filedes[2], int inherit_idx) +{ + int saved_errno; + int err; + TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_pipe", filedes, + "inherit_idx=%i (GPGME uses it for %s)", + inherit_idx, inherit_idx ? "reading" : "writing"); + + err = pipe (filedes); + if (err < 0) + return TRACE_SYSRES (err); + + /* FIXME: Should get the old flags first. */ + err = fcntl (filedes[1 - inherit_idx], F_SETFD, FD_CLOEXEC); + saved_errno = errno; + if (err < 0) + { + close (filedes[0]); + close (filedes[1]); + } + errno = saved_errno; + if (err) + return TRACE_SYSRES (err); + + return TRACE_SUC2 ("read=0x%x, write=0x%x", filedes[0], filedes[1]); +} + + +int +_gpgme_io_close (int fd) +{ + int res; + + TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_close", fd); + + if (fd == -1) + { + errno = EINVAL; + return TRACE_SYSRES (-1); + } + + /* First call the notify handler. */ + if (fd >= 0 && fd < (int) DIM (notify_table)) + { + if (notify_table[fd].handler) + { + TRACE_LOG2 ("invoking close handler %p/%p", + notify_table[fd].handler, notify_table[fd].value); + notify_table[fd].handler (fd, notify_table[fd].value); + notify_table[fd].handler = NULL; + notify_table[fd].value = NULL; + } + } + /* Then do the close. */ + res = close (fd); + return TRACE_SYSRES (res); +} + + +int +_gpgme_io_set_close_notify (int fd, _gpgme_close_notify_handler_t handler, + void *value) +{ + TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_set_close_notify", fd, + "close_handler=%p/%p", handler, value); + + assert (fd != -1); + + if (fd < 0 || fd >= (int) DIM (notify_table)) + { + errno = EINVAL; + return TRACE_SYSRES (-1); + } + notify_table[fd].handler = handler; + notify_table[fd].value = value; + return TRACE_SYSRES (0); +} + + +int +_gpgme_io_set_nonblocking (int fd) +{ + int flags; + int res; + TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_set_nonblocking", fd); + + flags = fcntl (fd, F_GETFL, 0); + if (flags == -1) + return TRACE_SYSRES (-1); + flags |= O_NONBLOCK; + res = fcntl (fd, F_SETFL, flags); + return TRACE_SYSRES (res); +} + + +static int +_gpgme_io_waitpid (int pid, int hang, int *r_status, int *r_signal) +{ + int status; + + *r_status = 0; + *r_signal = 0; + if (_gpgme_ath_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; +} + + +/* Returns 0 on success, -1 on error. */ +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) +{ + pid_t pid; + int i; + int status; + int signo; + TRACE_BEG1 (DEBUG_SYSIO, "_gpgme_io_spawn", path, + "path=%s", path); + i = 0; + while (argv[i]) + { + TRACE_LOG2 ("argv[%2i] = %s", i, argv[i]); + i++; + } + + pid = fork (); + if (pid == -1) + return TRACE_SYSRES (-1); + + if (!pid) + { + /* Intermediate child to prevent zombie processes. */ + if ((pid = fork ()) == 0) + { + /* 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) + { +#if 0 + /* FIXME: The debug file descriptor is not + dup'ed anyway, so we can't see this. */ + TRACE_LOG1 ("dup2 failed in child: %s\n", + strerror (errno)); +#endif + _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) + { +#if 0 + /* FIXME: The debug file descriptor is not dup'ed + anyway, so we can't see this. */ + TRACE_LOG1 ("can't open `/dev/null': %s\n", + strerror (errno)); +#endif + _exit (8); + } + /* Make sure that the process has a connected stdin. */ + if (!duped_stdin) + { + if (dup2 (fd, 0) == -1) + { +#if 0 + /* FIXME: The debug file descriptor is not dup'ed + anyway, so we can't see this. */ + TRACE_LOG1 ("dup2(/dev/null, 0) failed: %s\n", + strerror (errno)); +#endif + _exit (8); + } + } + if (!duped_stderr) + if (dup2 (fd, 2) == -1) + { +#if 0 + /* FIXME: The debug file descriptor is not dup'ed + anyway, so we can't see this. */ + TRACE_LOG1 ("dup2(dev/null, 2) failed: %s\n", + strerror (errno)); +#endif + _exit (8); + } + close (fd); + } + + execv ( path, argv ); + /* Hmm: in that case we could write a special status code to the + status-pipe. */ +#if 0 + /* FIXME: The debug file descriptor is not dup'ed anyway, so + we can't see this. */ + TRACE_LOG1 ("exec of `%s' failed\n", path); +#endif + _exit (8); + } /* End child. */ + if (pid == -1) + _exit (1); + else + _exit (0); + } + + TRACE_LOG1 ("waiting for child process pid=%i", pid); + _gpgme_io_waitpid (pid, 1, &status, &signo); + if (status) + return TRACE_SYSRES (-1); + + /* .dup_to is not used in the parent list. */ + for (i = 0; fd_parent_list[i].fd != -1; i++) + _gpgme_io_close (fd_parent_list[i].fd); + + return TRACE_SYSRES (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, int nonblock) +{ + fd_set readfds; + fd_set writefds; + unsigned int i; + int any; + int max_fd; + int n; + int count; + /* Use a 1s timeout. */ + struct timeval timeout = { 1, 0 }; + void *dbg_help = NULL; + TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_select", fds, + "nfds=%u, nonblock=%u", nfds, nonblock); + + FD_ZERO (&readfds); + FD_ZERO (&writefds); + max_fd = 0; + if (nonblock) + timeout.tv_sec = 0; + + TRACE_SEQ (dbg_help, "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; + TRACE_ADD1 (dbg_help, "r0x%x ", 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; + TRACE_ADD1 (dbg_help, "w0x%x ", fds[i].fd); + any = 1; + } + fds[i].signaled = 0; + } + TRACE_END (dbg_help, "]"); + if (!any) + return TRACE_SYSRES (0); + + do + { + count = _gpgme_ath_select (max_fd + 1, &readfds, &writefds, NULL, + &timeout); + } + while (count < 0 && errno == EINTR); + if (count < 0) + return TRACE_SYSRES (-1); + + TRACE_SEQ (dbg_help, "select OK [ "); + if (TRACE_ENABLED (dbg_help)) + { + for (i = 0; i <= max_fd; i++) + { + if (FD_ISSET (i, &readfds)) + TRACE_ADD1 (dbg_help, "r0x%x ", i); + if (FD_ISSET (i, &writefds)) + TRACE_ADD1 (dbg_help, "w0x%x ", i); + } + TRACE_END (dbg_help, "]"); + } + + /* The variable 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 TRACE_SYSRES (count); +} + + +int +_gpgme_io_recvmsg (int fd, struct msghdr *msg, int flags) +{ + int nread; + int saved_errno; + struct iovec *iov; + TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_recvmsg", fd, + "msg=%p, flags=%i", msg, flags); + + nread = 0; + iov = msg->msg_iov; + while (iov < msg->msg_iov + msg->msg_iovlen) + { + nread += iov->iov_len; + iov++; + } + + TRACE_LOG1 ("about to receive %d bytes", nread); + + do + { + nread = _gpgme_ath_recvmsg (fd, msg, flags); + } + while (nread == -1 && errno == EINTR); + saved_errno = errno; + if (nread > 0) + { + int nr = nread; + + iov = msg->msg_iov; + while (nr > 0) + { + int len = nr > iov->iov_len ? iov->iov_len : nr; + TRACE_LOGBUF (msg->msg_iov->iov_base, len); + iov++; + nr -= len; + } + } + errno = saved_errno; + return TRACE_SYSRES (nread); +} + + +int +_gpgme_io_sendmsg (int fd, const struct msghdr *msg, int flags) +{ + int nwritten; + struct iovec *iov; + TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_sendmsg", fd, + "msg=%p, flags=%i", msg, flags); + + nwritten = 0; + iov = msg->msg_iov; + while (iov < msg->msg_iov + msg->msg_iovlen) + { + nwritten += iov->iov_len; + iov++; + } + + TRACE_LOG1 ("about to receive %d bytes", nwritten); + iov = msg->msg_iov; + while (nwritten > 0) + { + int len = nwritten > iov->iov_len ? iov->iov_len : nwritten; + TRACE_LOGBUF (msg->msg_iov->iov_base, len); + iov++; + nwritten -= len; + } + + do + { + nwritten = _gpgme_ath_sendmsg (fd, msg, flags); + } + while (nwritten == -1 && errno == EINTR); + return TRACE_SYSRES (nwritten); +} + + +int +_gpgme_io_dup (int fd) +{ + return dup (fd); +} diff --git a/tags/gpgme-1.1.6/gpgme/posix-sema.c b/tags/gpgme-1.1.6/gpgme/posix-sema.c new file mode 100644 index 0000000..4ec3abb --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/posix-sema.c @@ -0,0 +1,62 @@ +/* posix-sema.c + Copyright (C) 2001 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2004, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "sema.h" +#include "ath.h" + +void +_gpgme_sema_subsystem_init () +{ +} + +void +_gpgme_sema_cs_enter (struct critsect_s *s) +{ + _gpgme_ath_mutex_lock (&s->priv); +} + +void +_gpgme_sema_cs_leave (struct critsect_s *s) +{ + _gpgme_ath_mutex_unlock (&s->priv); +} + +void +_gpgme_sema_cs_destroy (struct critsect_s *s) +{ + _gpgme_ath_mutex_destroy (&s->priv); + s->priv = NULL; +} diff --git a/tags/gpgme-1.1.6/gpgme/posix-util.c b/tags/gpgme-1.1.6/gpgme/posix-util.c new file mode 100644 index 0000000..168dad6 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/posix-util.c @@ -0,0 +1,67 @@ +/* posix-util.c - Utility functions for Posix + Copyright (C) 2001 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include + +#include "util.h" + +const char * +_gpgme_get_gpg_path (void) +{ +#ifdef GPG_PATH + return GPG_PATH; +#else + return NULL; +#endif +} + +const char * +_gpgme_get_gpgsm_path (void) +{ +#ifdef GPGSM_PATH + return GPGSM_PATH; +#else + return NULL; +#endif +} + +const char * +_gpgme_get_gpgconf_path (void) +{ +#ifdef GPGCONF_PATH + return GPGCONF_PATH; +#else + return NULL; +#endif +} + +/* See w32-util.c */ +int +_gpgme_get_conf_int (const char *key, int *value) +{ + return 0; +} diff --git a/tags/gpgme-1.1.6/gpgme/priv-io.h b/tags/gpgme-1.1.6/gpgme/priv-io.h new file mode 100644 index 0000000..5841dc9 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/priv-io.h @@ -0,0 +1,76 @@ +/* priv-io.h - Interface to the private I/O functions. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 + + +/* A single file descriptor passed to spawn. For child fds, dup_to + specifies the fd it should become in the child. */ +struct spawn_fd_item_s +{ + int fd; + int dup_to; +}; + +struct io_select_fd_s +{ + int fd; + int for_read; + int for_write; + int signaled; + void *opaque; +}; + +/* These function are either defined in posix-io.c or w32-io.c. */ +void _gpgme_io_subsystem_init (void); +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); +typedef void (*_gpgme_close_notify_handler_t) (int,void*); +int _gpgme_io_set_close_notify (int fd, _gpgme_close_notify_handler_t handler, + void *value); +int _gpgme_io_set_nonblocking (int fd); + +/* Spawn the executable PATH with ARGV as arguments, after forking + close all fds in FD_PARENT_LIST in the parent and close or dup all + fds in FD_CHILD_LIST in the child. */ +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_select (struct io_select_fd_s *fds, size_t nfds, int nonblock); + +/* Write the printable version of FD to the buffer BUF of length + BUFLEN. The printable version is the representation on the command + line that the child process expects. */ +int _gpgme_io_fd2str (char *buf, int buflen, int fd); + +/* Duplicate a file descriptor. This is more restrictive than dup(): + it assumes that the resulting file descriptors are essentially + co-equal (for example, no private offset), which is true for pipes + and sockets (but not files) under Unix with the standard dup() + function. Basically, this function is used to reference count the + status output file descriptor shared between GPGME and libassuan + (in engine-gpgsm.c). */ +int _gpgme_io_dup (int fd); + +#endif /* IO_H */ diff --git a/tags/gpgme-1.1.6/gpgme/progress.c b/tags/gpgme-1.1.6/gpgme/progress.c new file mode 100644 index 0000000..4fe6b63 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/progress.c @@ -0,0 +1,81 @@ +/* progress.c - status handler for progress status + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include + +#include "util.h" +#include "context.h" + + +gpgme_error_t +_gpgme_progress_status_handler (void *priv, gpgme_status_code_t code, + char *args) +{ + gpgme_ctx_t ctx = (gpgme_ctx_t) priv; + char *p; + char *args_cpy; + int type = 0; + int current = 0; + int total = 0; + + if (code != GPGME_STATUS_PROGRESS || !*args || !ctx->progress_cb) + return 0; + + args_cpy = strdup (args); + if (!args_cpy) + return gpg_error_from_errno (errno); + + p = strchr (args_cpy, ' '); + if (p) + { + *p++ = 0; + if (*p) + { + type = *(unsigned char *)p; + p = strchr (p+1, ' '); + if (p) + { + *p++ = 0; + if (*p) + { + current = atoi (p); + p = strchr (p+1, ' '); + if (p) + { + *p++ = 0; + total = atoi (p); + } + } + } + } + } + + if (type != 'X') + ctx->progress_cb (ctx->progress_cb_value, args_cpy, type, current, total); + + free (args_cpy); + return 0; +} diff --git a/tags/gpgme-1.1.6/gpgme/putc_unlocked.c b/tags/gpgme-1.1.6/gpgme/putc_unlocked.c new file mode 100644 index 0000000..a15aade --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/putc_unlocked.c @@ -0,0 +1,31 @@ +/* putc_unlocked.c - Replacement for putc_unlocked. + Copyright (C) 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +int +putc_unlocked (int c, FILE *stream) +{ + return putc (c, stream); +} diff --git a/tags/gpgme-1.1.6/gpgme/rungpg.c b/tags/gpgme-1.1.6/gpgme/rungpg.c new file mode 100644 index 0000000..0ffdc7c --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/rungpg.c @@ -0,0 +1,2129 @@ +/* rungpg.c - Gpg Engine. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include "gpgme.h" +#include "util.h" +#include "ops.h" +#include "wait.h" +#include "context.h" /*temp hack until we have GpmeData methods to do I/O */ +#include "priv-io.h" +#include "sema.h" +#include "debug.h" + +#include "status-table.h" +#include "engine-backend.h" + + +/* This type is used to build a list of gpg arguments and data + sources/sinks. */ +struct arg_and_data_s +{ + struct arg_and_data_s *next; + gpgme_data_t data; /* If this is not NULL, use arg below. */ + int inbound; /* True if this is used for reading from gpg. */ + int dup_to; + int print_fd; /* Print the fd number and not the special form of it. */ + char arg[1]; /* Used if data above is not used. */ +}; + + +struct fd_data_map_s +{ + gpgme_data_t data; + int inbound; /* true if this is used for reading from gpg */ + int dup_to; + int fd; /* the fd to use */ + int peer_fd; /* the outher side of the pipe */ + void *tag; +}; + + +typedef gpgme_error_t (*colon_preprocessor_t) (char *line, char **rline); + +struct engine_gpg +{ + char *file_name; + + char *lc_messages; + char *lc_ctype; + + struct arg_and_data_s *arglist; + struct arg_and_data_s **argtail; + + struct + { + int fd[2]; + size_t bufsize; + char *buffer; + size_t readpos; + int eof; + engine_status_handler_t fnc; + void *fnc_value; + void *tag; + } status; + + /* This is a kludge - see the comment at colon_line_handler. */ + struct + { + int fd[2]; + size_t bufsize; + char *buffer; + size_t readpos; + int eof; + engine_colon_line_handler_t fnc; /* this indicate use of this structrue */ + void *fnc_value; + void *tag; + colon_preprocessor_t preprocess_fnc; + } colon; + + char **argv; + struct fd_data_map_s *fd_data_map; + + /* stuff needed for interactive (command) mode */ + struct + { + int used; + int fd; + void *cb_data; + int idx; /* Index in fd_data_map */ + gpgme_status_code_t code; /* last code */ + char *keyword; /* what has been requested (malloced) */ + engine_command_handler_t fnc; + void *fnc_value; + /* The kludges never end. This is used to couple command handlers + with output data in edit key mode. */ + gpgme_data_t linked_data; + int linked_idx; + } cmd; + + struct gpgme_io_cbs io_cbs; +}; + +typedef struct engine_gpg *engine_gpg_t; + + +static void +gpg_io_event (void *engine, gpgme_event_io_t type, void *type_data) +{ + engine_gpg_t gpg = engine; + + TRACE3 (DEBUG_ENGINE, "gpgme:gpg_io_event", gpg, + "event %p, type %d, type_data %p", + gpg->io_cbs.event, type, type_data); + if (gpg->io_cbs.event) + (*gpg->io_cbs.event) (gpg->io_cbs.event_priv, type, type_data); +} + + +static void +close_notify_handler (int fd, void *opaque) +{ + engine_gpg_t gpg = opaque; + assert (fd != -1); + + if (gpg->status.fd[0] == fd) + { + if (gpg->status.tag) + (*gpg->io_cbs.remove) (gpg->status.tag); + gpg->status.fd[0] = -1; + } + else if (gpg->status.fd[1] == fd) + gpg->status.fd[1] = -1; + else if (gpg->colon.fd[0] == fd) + { + if (gpg->colon.tag) + (*gpg->io_cbs.remove) (gpg->colon.tag); + gpg->colon.fd[0] = -1; + } + else if (gpg->colon.fd[1] == fd) + gpg->colon.fd[1] = -1; + else if (gpg->fd_data_map) + { + int i; + + for (i = 0; gpg->fd_data_map[i].data; i++) + { + if (gpg->fd_data_map[i].fd == fd) + { + if (gpg->fd_data_map[i].tag) + (*gpg->io_cbs.remove) (gpg->fd_data_map[i].tag); + gpg->fd_data_map[i].fd = -1; + break; + } + if (gpg->fd_data_map[i].peer_fd == fd) + { + gpg->fd_data_map[i].peer_fd = -1; + break; + } + } + } +} + +/* If FRONT is true, push at the front of the list. Use this for + options added late in the process. */ +static gpgme_error_t +add_arg_ext (engine_gpg_t gpg, const char *arg, int front) +{ + struct arg_and_data_s *a; + + assert (gpg); + assert (arg); + + a = malloc (sizeof *a + strlen (arg)); + if (!a) + return gpg_error_from_errno (errno); + + a->data = NULL; + a->dup_to = -1; + strcpy (a->arg, arg); + if (front) + { + a->next = gpg->arglist; + if (!gpg->arglist) + { + /* If this is the first argument, we need to update the tail + pointer. */ + gpg->argtail = &a->next; + } + gpg->arglist = a; + } + else + { + a->next = NULL; + *gpg->argtail = a; + gpg->argtail = &a->next; + } + + return 0; +} + +static gpgme_error_t +add_arg (engine_gpg_t gpg, const char *arg) +{ + return add_arg_ext (gpg, arg, 0); +} + +static gpgme_error_t +add_data (engine_gpg_t gpg, gpgme_data_t data, int dup_to, int inbound) +{ + struct arg_and_data_s *a; + + assert (gpg); + assert (data); + + a = malloc (sizeof *a - 1); + if (!a) + return gpg_error_from_errno (errno); + a->next = NULL; + a->data = data; + a->inbound = inbound; + if (dup_to == -2) + { + a->print_fd = 1; + a->dup_to = -1; + } + else + { + a->print_fd = 0; + a->dup_to = dup_to; + } + *gpg->argtail = a; + gpg->argtail = &a->next; + return 0; +} + + +static char * +gpg_get_version (const char *file_name) +{ + return _gpgme_get_program_version (file_name ? file_name + : _gpgme_get_gpg_path ()); +} + + +static const char * +gpg_get_req_version (void) +{ + return NEED_GPG_VERSION; +} + + +static void +free_argv (char **argv) +{ + int i; + + for (i = 0; argv[i]; i++) + free (argv[i]); + free (argv); +} + + +static void +free_fd_data_map (struct fd_data_map_s *fd_data_map) +{ + int i; + + if (!fd_data_map) + return; + + for (i = 0; fd_data_map[i].data; i++) + { + if (fd_data_map[i].fd != -1) + _gpgme_io_close (fd_data_map[i].fd); + if (fd_data_map[i].peer_fd != -1) + _gpgme_io_close (fd_data_map[i].peer_fd); + /* Don't release data because this is only a reference. */ + } + free (fd_data_map); +} + + +static gpgme_error_t +gpg_cancel (void *engine) +{ + engine_gpg_t gpg = engine; + + if (!gpg) + return gpg_error (GPG_ERR_INV_VALUE); + + if (gpg->status.fd[0] != -1) + _gpgme_io_close (gpg->status.fd[0]); + if (gpg->status.fd[1] != -1) + _gpgme_io_close (gpg->status.fd[1]); + if (gpg->colon.fd[0] != -1) + _gpgme_io_close (gpg->colon.fd[0]); + if (gpg->colon.fd[1] != -1) + _gpgme_io_close (gpg->colon.fd[1]); + if (gpg->fd_data_map) + { + free_fd_data_map (gpg->fd_data_map); + gpg->fd_data_map = NULL; + } + if (gpg->cmd.fd != -1) + _gpgme_io_close (gpg->cmd.fd); + + return 0; +} + +static void +gpg_release (void *engine) +{ + engine_gpg_t gpg = engine; + + if (!gpg) + return; + + gpg_cancel (engine); + + if (gpg->file_name) + free (gpg->file_name); + + if (gpg->lc_messages) + free (gpg->lc_messages); + if (gpg->lc_ctype) + free (gpg->lc_ctype); + + while (gpg->arglist) + { + struct arg_and_data_s *next = gpg->arglist->next; + + if (gpg->arglist) + free (gpg->arglist); + gpg->arglist = next; + } + + if (gpg->status.buffer) + free (gpg->status.buffer); + if (gpg->colon.buffer) + free (gpg->colon.buffer); + if (gpg->argv) + free_argv (gpg->argv); + if (gpg->cmd.keyword) + free (gpg->cmd.keyword); + + free (gpg); +} + + +static gpgme_error_t +gpg_new (void **engine, const char *file_name, const char *home_dir) +{ + engine_gpg_t gpg; + gpgme_error_t rc = 0; + char *dft_display = NULL; + char dft_ttyname[64]; + char *dft_ttytype = NULL; + + gpg = calloc (1, sizeof *gpg); + if (!gpg) + return gpg_error_from_errno (errno); + + if (file_name) + { + gpg->file_name = strdup (file_name); + if (!gpg->file_name) + { + rc = gpg_error_from_errno (errno); + goto leave; + } + } + + gpg->argtail = &gpg->arglist; + gpg->status.fd[0] = -1; + gpg->status.fd[1] = -1; + gpg->colon.fd[0] = -1; + gpg->colon.fd[1] = -1; + gpg->cmd.fd = -1; + gpg->cmd.idx = -1; + gpg->cmd.linked_data = NULL; + gpg->cmd.linked_idx = -1; + + /* Allocate the read buffer for the status pipe. */ + gpg->status.bufsize = 1024; + gpg->status.readpos = 0; + gpg->status.buffer = malloc (gpg->status.bufsize); + if (!gpg->status.buffer) + { + rc = gpg_error_from_errno (errno); + goto leave; + } + /* In any case we need a status pipe - create it right here and + don't handle it with our generic gpgme_data_t mechanism. */ + if (_gpgme_io_pipe (gpg->status.fd, 1) == -1) + { + rc = gpg_error_from_errno (errno); + goto leave; + } + if (_gpgme_io_set_close_notify (gpg->status.fd[0], + close_notify_handler, gpg) + || _gpgme_io_set_close_notify (gpg->status.fd[1], + close_notify_handler, gpg)) + { + rc = gpg_error (GPG_ERR_GENERAL); + goto leave; + } + gpg->status.eof = 0; + + if (home_dir) + { + rc = add_arg (gpg, "--homedir"); + if (!rc) + rc = add_arg (gpg, home_dir); + if (rc) + goto leave; + } + + rc = add_arg (gpg, "--status-fd"); + if (rc) + goto leave; + + { + char buf[25]; + _gpgme_io_fd2str (buf, sizeof (buf), gpg->status.fd[1]); + rc = add_arg (gpg, buf); + if (rc) + goto leave; + } + + rc = add_arg (gpg, "--no-tty"); + if (!rc) + rc = add_arg (gpg, "--charset"); + if (!rc) + rc = add_arg (gpg, "utf8"); + if (!rc) + rc = add_arg (gpg, "--enable-progress-filter"); + if (rc) + goto leave; + + rc = _gpgme_getenv ("DISPLAY", &dft_display); + if (rc) + goto leave; + if (dft_display) + { + rc = add_arg (gpg, "--display"); + if (!rc) + rc = add_arg (gpg, dft_display); + + free (dft_display); + } + + if (isatty (1)) + { + int err; + + err = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname)); + if (err) + rc = gpg_error_from_errno (errno); + else + { + if (dft_ttyname) + { + rc = add_arg (gpg, "--ttyname"); + if (!rc) + rc = add_arg (gpg, dft_ttyname); + } + else + rc = 0; + if (!rc) + { + rc = _gpgme_getenv ("TERM", &dft_ttytype); + if (rc) + goto leave; + + if (dft_ttytype) + { + rc = add_arg (gpg, "--ttytype"); + if (!rc) + rc = add_arg (gpg, dft_ttytype); + } + + free (dft_ttytype); + } + } + if (rc) + goto leave; + } + + leave: + if (rc) + gpg_release (gpg); + else + *engine = gpg; + return rc; +} + + +static gpgme_error_t +gpg_set_locale (void *engine, int category, const char *value) +{ + engine_gpg_t gpg = engine; + + if (category == LC_CTYPE) + { + if (gpg->lc_ctype) + { + free (gpg->lc_ctype); + gpg->lc_ctype = NULL; + } + if (value) + { + gpg->lc_ctype = strdup (value); + if (!gpg->lc_ctype) + return gpg_error_from_syserror (); + } + } +#ifdef LC_MESSAGES + else if (category == LC_MESSAGES) + { + if (gpg->lc_messages) + { + free (gpg->lc_messages); + gpg->lc_messages = NULL; + } + if (value) + { + gpg->lc_messages = strdup (value); + if (!gpg->lc_messages) + return gpg_error_from_syserror (); + } + } +#endif /* LC_MESSAGES */ + else + return gpg_error (GPG_ERR_INV_VALUE); + + return 0; +} + + +/* Note, that the status_handler is allowed to modifiy the args + value. */ +static void +gpg_set_status_handler (void *engine, engine_status_handler_t fnc, + void *fnc_value) +{ + engine_gpg_t gpg = engine; + + gpg->status.fnc = fnc; + gpg->status.fnc_value = fnc_value; +} + +/* Kludge to process --with-colon output. */ +static gpgme_error_t +gpg_set_colon_line_handler (void *engine, engine_colon_line_handler_t fnc, + void *fnc_value) +{ + engine_gpg_t gpg = engine; + + gpg->colon.bufsize = 1024; + gpg->colon.readpos = 0; + gpg->colon.buffer = malloc (gpg->colon.bufsize); + if (!gpg->colon.buffer) + return gpg_error_from_errno (errno); + + if (_gpgme_io_pipe (gpg->colon.fd, 1) == -1) + { + int saved_errno = errno; + free (gpg->colon.buffer); + gpg->colon.buffer = NULL; + return gpg_error_from_errno (saved_errno); + } + if (_gpgme_io_set_close_notify (gpg->colon.fd[0], close_notify_handler, gpg) + || _gpgme_io_set_close_notify (gpg->colon.fd[1], + close_notify_handler, gpg)) + return gpg_error (GPG_ERR_GENERAL); + gpg->colon.eof = 0; + gpg->colon.fnc = fnc; + gpg->colon.fnc_value = fnc_value; + return 0; +} + + +static gpgme_error_t +command_handler (void *opaque, int fd) +{ + gpgme_error_t err; + engine_gpg_t gpg = (engine_gpg_t) opaque; + int processed = 0; + + assert (gpg->cmd.used); + assert (gpg->cmd.code); + assert (gpg->cmd.fnc); + + err = gpg->cmd.fnc (gpg->cmd.fnc_value, gpg->cmd.code, gpg->cmd.keyword, fd, + &processed); + if (err) + return err; + + /* We always need to send at least a newline character. */ + if (!processed) + _gpgme_io_write (fd, "\n", 1); + + gpg->cmd.code = 0; + /* And sleep again until read_status will wake us up again. */ + /* XXX We must check if there are any more fds active after removing + this one. */ + (*gpg->io_cbs.remove) (gpg->fd_data_map[gpg->cmd.idx].tag); + gpg->cmd.fd = gpg->fd_data_map[gpg->cmd.idx].fd; + gpg->fd_data_map[gpg->cmd.idx].fd = -1; + + return 0; +} + + + +/* The Fnc will be called to get a value for one of the commands with + a key KEY. If the Code pssed to FNC is 0, the function may release + resources associated with the returned value from another call. To + match such a second call to a first call, the returned value from + the first call is passed as keyword. */ +static gpgme_error_t +gpg_set_command_handler (void *engine, engine_command_handler_t fnc, + void *fnc_value, gpgme_data_t linked_data) +{ + engine_gpg_t gpg = engine; + gpgme_error_t rc; + + rc = add_arg (gpg, "--command-fd"); + if (rc) + return rc; + + /* This is a hack. We don't have a real data object. The only + thing that matters is that we use something unique, so we use the + address of the cmd structure in the gpg object. */ + rc = add_data (gpg, (void *) &gpg->cmd, -2, 0); + if (rc) + return rc; + + gpg->cmd.fnc = fnc; + gpg->cmd.cb_data = (void *) &gpg->cmd; + gpg->cmd.fnc_value = fnc_value; + gpg->cmd.linked_data = linked_data; + gpg->cmd.used = 1; + return 0; +} + + +static gpgme_error_t +build_argv (engine_gpg_t gpg) +{ + gpgme_error_t err; + struct arg_and_data_s *a; + struct fd_data_map_s *fd_data_map; + size_t datac=0, argc=0; + char **argv; + int need_special = 0; + int use_agent = 0; + char *p; + + /* We don't want to use the agent with a malformed environment + variable. This is only a very basic test but sufficient to make + our life in the regression tests easier. */ + err = _gpgme_getenv ("GPG_AGENT_INFO", &p); + if (err) + return err; + use_agent = (p && strchr (p, ':')); + if (p) + free (p); + + if (gpg->argv) + { + free_argv (gpg->argv); + gpg->argv = NULL; + } + if (gpg->fd_data_map) + { + free_fd_data_map (gpg->fd_data_map); + gpg->fd_data_map = NULL; + } + + argc++; /* For argv[0]. */ + for (a = gpg->arglist; a; a = a->next) + { + argc++; + if (a->data) + { + /*fprintf (stderr, "build_argv: data\n" );*/ + datac++; + if (a->dup_to == -1 && !a->print_fd) + need_special = 1; + } + else + { + /* fprintf (stderr, "build_argv: arg=`%s'\n", a->arg );*/ + } + } + if (need_special) + argc++; + if (use_agent) + argc++; + if (!gpg->cmd.used) + argc++; /* --batch */ + argc += 1; /* --no-sk-comment */ + + argv = calloc (argc + 1, sizeof *argv); + if (!argv) + return gpg_error_from_errno (errno); + fd_data_map = calloc (datac + 1, sizeof *fd_data_map); + if (!fd_data_map) + { + int saved_errno = errno; + free_argv (argv); + return gpg_error_from_errno (saved_errno); + } + + argc = datac = 0; + argv[argc] = strdup ("gpg"); /* argv[0] */ + if (!argv[argc]) + { + int saved_errno = errno; + free (fd_data_map); + free_argv (argv); + return gpg_error_from_errno (saved_errno); + } + argc++; + if (need_special) + { + argv[argc] = strdup ("--enable-special-filenames"); + if (!argv[argc]) + { + int saved_errno = errno; + free (fd_data_map); + free_argv (argv); + return gpg_error_from_errno (saved_errno); + } + argc++; + } + if (use_agent) + { + argv[argc] = strdup ("--use-agent"); + if (!argv[argc]) + { + int saved_errno = errno; + free (fd_data_map); + free_argv (argv); + return gpg_error_from_errno (saved_errno); + } + argc++; + } + if (!gpg->cmd.used) + { + argv[argc] = strdup ("--batch"); + if (!argv[argc]) + { + int saved_errno = errno; + free (fd_data_map); + free_argv (argv); + return gpg_error_from_errno (saved_errno); + } + argc++; + } + argv[argc] = strdup ("--no-sk-comment"); + if (!argv[argc]) + { + int saved_errno = errno; + free (fd_data_map); + free_argv (argv); + return gpg_error_from_errno (saved_errno); + } + argc++; + for (a = gpg->arglist; a; a = a->next) + { + if (a->data) + { + /* Create a pipe to pass it down to gpg. */ + fd_data_map[datac].inbound = a->inbound; + + /* Create a pipe. */ + { + int fds[2]; + + if (_gpgme_io_pipe (fds, fd_data_map[datac].inbound ? 1 : 0) + == -1) + { + int saved_errno = errno; + free (fd_data_map); + free_argv (argv); + return gpg_error (saved_errno); + } + if (_gpgme_io_set_close_notify (fds[0], + close_notify_handler, gpg) + || _gpgme_io_set_close_notify (fds[1], + close_notify_handler, + gpg)) + { + return gpg_error (GPG_ERR_GENERAL); + } + /* If the data_type is FD, we have to do a dup2 here. */ + if (fd_data_map[datac].inbound) + { + fd_data_map[datac].fd = fds[0]; + fd_data_map[datac].peer_fd = fds[1]; + } + else + { + fd_data_map[datac].fd = fds[1]; + fd_data_map[datac].peer_fd = fds[0]; + } + } + + /* Hack to get hands on the fd later. */ + if (gpg->cmd.used) + { + if (gpg->cmd.cb_data == a->data) + { + assert (gpg->cmd.idx == -1); + gpg->cmd.idx = datac; + } + else if (gpg->cmd.linked_data == a->data) + { + assert (gpg->cmd.linked_idx == -1); + gpg->cmd.linked_idx = datac; + } + } + + fd_data_map[datac].data = a->data; + fd_data_map[datac].dup_to = a->dup_to; + if (a->dup_to == -1) + { + char *ptr; + int buflen = 25; + + argv[argc] = malloc (buflen); + if (!argv[argc]) + { + int saved_errno = errno; + free (fd_data_map); + free_argv (argv); + return gpg_error_from_errno (saved_errno); + } + + ptr = argv[argc]; + if (!a->print_fd) + { + *(ptr++) = '-'; + *(ptr++) = '&'; + buflen -= 2; + } + + _gpgme_io_fd2str (ptr, buflen, fd_data_map[datac].peer_fd); + argc++; + } + datac++; + } + else + { + argv[argc] = strdup (a->arg); + if (!argv[argc]) + { + int saved_errno = errno; + free (fd_data_map); + free_argv (argv); + return gpg_error_from_errno (saved_errno); + } + argc++; + } + } + + gpg->argv = argv; + gpg->fd_data_map = fd_data_map; + return 0; +} + + +static gpgme_error_t +add_io_cb (engine_gpg_t gpg, int fd, int dir, gpgme_io_cb_t handler, void *data, + void **tag) +{ + gpgme_error_t err; + + err = (*gpg->io_cbs.add) (gpg->io_cbs.add_priv, fd, dir, handler, data, tag); + if (err) + return err; + if (!dir) + /* FIXME Kludge around poll() problem. */ + err = _gpgme_io_set_nonblocking (fd); + return err; +} + + +static int +status_cmp (const void *ap, const void *bp) +{ + const struct status_table_s *a = ap; + const struct status_table_s *b = bp; + + return strcmp (a->name, b->name); +} + + +/* Handle the status output of GnuPG. This function does read entire + lines and passes them as C strings to the callback function (we can + use C Strings because the status output is always UTF-8 encoded). + Of course we have to buffer the lines to cope with long lines + e.g. with a large user ID. Note: We can optimize this to only cope + with status line code we know about and skip all other stuff + without buffering (i.e. without extending the buffer). */ +static gpgme_error_t +read_status (engine_gpg_t gpg) +{ + char *p; + int nread; + size_t bufsize = gpg->status.bufsize; + char *buffer = gpg->status.buffer; + size_t readpos = gpg->status.readpos; + + assert (buffer); + if (bufsize - readpos < 256) + { + /* Need more room for the read. */ + bufsize += 1024; + buffer = realloc (buffer, bufsize); + if (!buffer) + return gpg_error_from_errno (errno); + } + + nread = _gpgme_io_read (gpg->status.fd[0], + buffer + readpos, bufsize-readpos); + if (nread == -1) + return gpg_error_from_errno (errno); + + if (!nread) + { + gpg->status.eof = 1; + if (gpg->status.fnc) + { + gpgme_error_t err; + err = gpg->status.fnc (gpg->status.fnc_value, GPGME_STATUS_EOF, ""); + if (err) + return err; + } + return 0; + } + + while (nread > 0) + { + for (p = buffer + readpos; nread; nread--, p++) + { + if (*p == '\n') + { + /* (we require that the last line is terminated by a LF) */ + if (p > buffer && p[-1] == '\r') + p[-1] = 0; + *p = 0; + if (!strncmp (buffer, "[GNUPG:] ", 9) + && buffer[9] >= 'A' && buffer[9] <= 'Z') + { + struct status_table_s t, *r; + char *rest; + + rest = strchr (buffer + 9, ' '); + if (!rest) + rest = p; /* Set to an empty string. */ + else + *rest++ = 0; + + t.name = buffer+9; + /* (the status table has one extra element) */ + r = bsearch (&t, status_table, DIM(status_table) - 1, + sizeof t, status_cmp); + if (r) + { + if (gpg->cmd.used + && (r->code == GPGME_STATUS_GET_BOOL + || r->code == GPGME_STATUS_GET_LINE + || r->code == GPGME_STATUS_GET_HIDDEN)) + { + gpg->cmd.code = r->code; + if (gpg->cmd.keyword) + free (gpg->cmd.keyword); + gpg->cmd.keyword = strdup (rest); + if (!gpg->cmd.keyword) + return gpg_error_from_errno (errno); + /* This should be the last thing we have + received and the next thing will be that + the command handler does its action. */ + if (nread > 1) + TRACE0 (DEBUG_CTX, "gpgme:read_status", 0, + "error: unexpected data"); + + add_io_cb (gpg, gpg->cmd.fd, 0, + command_handler, gpg, + &gpg->fd_data_map[gpg->cmd.idx].tag); + gpg->fd_data_map[gpg->cmd.idx].fd = gpg->cmd.fd; + gpg->cmd.fd = -1; + } + else if (gpg->status.fnc) + { + gpgme_error_t err; + err = gpg->status.fnc (gpg->status.fnc_value, + r->code, rest); + if (err) + return err; + } + + if (r->code == GPGME_STATUS_END_STREAM) + { + if (gpg->cmd.used) + { + /* Before we can actually add the + command fd, we might have to flush + the linked output data pipe. */ + if (gpg->cmd.linked_idx != -1 + && gpg->fd_data_map[gpg->cmd.linked_idx].fd + != -1) + { + struct io_select_fd_s fds; + fds.fd = + gpg->fd_data_map[gpg->cmd.linked_idx].fd; + fds.for_read = 1; + fds.for_write = 0; + fds.opaque = NULL; + do + { + fds.signaled = 0; + _gpgme_io_select (&fds, 1, 1); + if (fds.signaled) + _gpgme_data_inbound_handler + (gpg->cmd.linked_data, fds.fd); + } + while (fds.signaled); + } + + /* XXX We must check if there are any + more fds active after removing this + one. */ + (*gpg->io_cbs.remove) + (gpg->fd_data_map[gpg->cmd.idx].tag); + gpg->cmd.fd = gpg->fd_data_map[gpg->cmd.idx].fd; + gpg->fd_data_map[gpg->cmd.idx].fd = -1; + } + } + } + } + /* To reuse the buffer for the next line we have to + shift the remaining data to the buffer start and + restart the loop Hmmm: We can optimize this function + by looking forward in the buffer to see whether a + second complete line is available and in this case + avoid the memmove for this line. */ + nread--; p++; + if (nread) + memmove (buffer, p, nread); + readpos = 0; + break; /* the for loop */ + } + else + readpos++; + } + } + + /* Update the gpg object. */ + gpg->status.bufsize = bufsize; + gpg->status.buffer = buffer; + gpg->status.readpos = readpos; + return 0; +} + + +static gpgme_error_t +status_handler (void *opaque, int fd) +{ + engine_gpg_t gpg = opaque; + int err; + + assert (fd == gpg->status.fd[0]); + err = read_status (gpg); + if (err) + return err; + if (gpg->status.eof) + _gpgme_io_close (fd); + return 0; +} + + +static gpgme_error_t +read_colon_line (engine_gpg_t gpg) +{ + char *p; + int nread; + size_t bufsize = gpg->colon.bufsize; + char *buffer = gpg->colon.buffer; + size_t readpos = gpg->colon.readpos; + + assert (buffer); + if (bufsize - readpos < 256) + { + /* Need more room for the read. */ + bufsize += 1024; + buffer = realloc (buffer, bufsize); + if (!buffer) + return gpg_error_from_errno (errno); + } + + nread = _gpgme_io_read (gpg->colon.fd[0], buffer+readpos, bufsize-readpos); + if (nread == -1) + return gpg_error_from_errno (errno); + + if (!nread) + { + gpg->colon.eof = 1; + assert (gpg->colon.fnc); + gpg->colon.fnc (gpg->colon.fnc_value, NULL); + return 0; + } + + while (nread > 0) + { + for (p = buffer + readpos; nread; nread--, p++) + { + if ( *p == '\n' ) + { + /* (we require that the last line is terminated by a LF) + and we skip empty lines. Note: we use UTF8 encoding + and escaping of special characters. We require at + least one colon to cope with some other printed + information. */ + *p = 0; + if (*buffer && strchr (buffer, ':')) + { + char *line = NULL; + + if (gpg->colon.preprocess_fnc) + { + gpgme_error_t err; + + err = gpg->colon.preprocess_fnc (buffer, &line); + if (err) + return err; + } + + assert (gpg->colon.fnc); + gpg->colon.fnc (gpg->colon.fnc_value, line ? line : buffer); + if (line) + free (line); + } + + /* To reuse the buffer for the next line we have to + shift the remaining data to the buffer start and + restart the loop Hmmm: We can optimize this function + by looking forward in the buffer to see whether a + second complete line is available and in this case + avoid the memmove for this line. */ + nread--; p++; + if (nread) + memmove (buffer, p, nread); + readpos = 0; + break; /* The for loop. */ + } + else + readpos++; + } + } + + /* Update the gpg object. */ + gpg->colon.bufsize = bufsize; + gpg->colon.buffer = buffer; + gpg->colon.readpos = readpos; + return 0; +} + + +/* This colonline handler thing is not the clean way to do it. It + might be better to enhance the gpgme_data_t object to act as a wrapper + for a callback. Same goes for the status thing. For now we use + this thing here because it is easier to implement. */ +static gpgme_error_t +colon_line_handler (void *opaque, int fd) +{ + engine_gpg_t gpg = opaque; + gpgme_error_t rc = 0; + + assert (fd == gpg->colon.fd[0]); + rc = read_colon_line (gpg); + if (rc) + return rc; + if (gpg->colon.eof) + _gpgme_io_close (fd); + return 0; +} + + +static gpgme_error_t +start (engine_gpg_t gpg) +{ + gpgme_error_t rc; + int saved_errno; + int i, n; + int status; + struct spawn_fd_item_s *fd_child_list, *fd_parent_list; + + if (!gpg) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!gpg->file_name && !_gpgme_get_gpg_path ()) + return gpg_error (GPG_ERR_INV_ENGINE); + + if (gpg->lc_ctype) + { + rc = add_arg_ext (gpg, gpg->lc_ctype, 1); + if (!rc) + rc = add_arg_ext (gpg, "--lc-ctype", 1); + if (rc) + return rc; + } + + if (gpg->lc_messages) + { + rc = add_arg_ext (gpg, gpg->lc_messages, 1); + if (!rc) + rc = add_arg_ext (gpg, "--lc-messages", 1); + if (rc) + return rc; + } + + rc = build_argv (gpg); + if (rc) + return rc; + + n = 3; /* status_fd, colon_fd and end of list */ + for (i = 0; gpg->fd_data_map[i].data; i++) + n++; + fd_child_list = calloc (n + n, sizeof *fd_child_list); + if (!fd_child_list) + return gpg_error_from_errno (errno); + fd_parent_list = fd_child_list + n; + + /* build the fd list for the child */ + n = 0; + /* The status fd is never dup'ed, so do not include it in the list. */ + if (gpg->colon.fnc) + { + fd_child_list[n].fd = gpg->colon.fd[1]; + fd_child_list[n].dup_to = 1; /* dup to stdout */ + n++; + } + for (i = 0; gpg->fd_data_map[i].data; i++) + { + if (gpg->fd_data_map[i].dup_to != -1) + { + fd_child_list[n].fd = gpg->fd_data_map[i].peer_fd; + fd_child_list[n].dup_to = gpg->fd_data_map[i].dup_to; + n++; + } + } + fd_child_list[n].fd = -1; + fd_child_list[n].dup_to = -1; + + /* Build the fd list for the parent. */ + n = 0; + if (gpg->status.fd[1] != -1) + { + fd_parent_list[n].fd = gpg->status.fd[1]; + fd_parent_list[n].dup_to = -1; + n++; + } + if (gpg->colon.fd[1] != -1) + { + fd_parent_list[n].fd = gpg->colon.fd[1]; + fd_parent_list[n].dup_to = -1; + n++; + } + for (i = 0; gpg->fd_data_map[i].data; i++) + { + fd_parent_list[n].fd = gpg->fd_data_map[i].peer_fd; + fd_parent_list[n].dup_to = -1; + n++; + } + fd_parent_list[n].fd = -1; + fd_parent_list[n].dup_to = -1; + + status = _gpgme_io_spawn (gpg->file_name ? gpg->file_name : + _gpgme_get_gpg_path (), + gpg->argv, fd_child_list, fd_parent_list); + saved_errno = errno; + free (fd_child_list); + if (status == -1) + return gpg_error_from_errno (saved_errno); + + /*_gpgme_register_term_handler ( closure, closure_value, pid );*/ + + rc = add_io_cb (gpg, gpg->status.fd[0], 1, status_handler, gpg, + &gpg->status.tag); + if (rc) + /* FIXME: kill the child */ + return rc; + + if (gpg->colon.fnc) + { + assert (gpg->colon.fd[0] != -1); + rc = add_io_cb (gpg, gpg->colon.fd[0], 1, colon_line_handler, gpg, + &gpg->colon.tag); + if (rc) + /* FIXME: kill the child */ + return rc; + } + + for (i = 0; gpg->fd_data_map[i].data; i++) + { + if (gpg->cmd.used && i == gpg->cmd.idx) + { + /* Park the cmd fd. */ + gpg->cmd.fd = gpg->fd_data_map[i].fd; + gpg->fd_data_map[i].fd = -1; + } + else + { + rc = add_io_cb (gpg, gpg->fd_data_map[i].fd, + gpg->fd_data_map[i].inbound, + gpg->fd_data_map[i].inbound + ? _gpgme_data_inbound_handler + : _gpgme_data_outbound_handler, + gpg->fd_data_map[i].data, &gpg->fd_data_map[i].tag); + + if (rc) + /* FIXME: kill the child */ + return rc; + } + } + + gpg_io_event (gpg, GPGME_EVENT_START, NULL); + + /* fixme: check what data we can release here */ + return 0; +} + + +static gpgme_error_t +gpg_decrypt (void *engine, gpgme_data_t ciph, gpgme_data_t plain) +{ + engine_gpg_t gpg = engine; + gpgme_error_t err; + + err = add_arg (gpg, "--decrypt"); + + /* Tell the gpg object about the data. */ + if (!err) + err = add_arg (gpg, "--output"); + if (!err) + err = add_arg (gpg, "-"); + if (!err) + err = add_data (gpg, plain, 1, 1); + if (!err) + err = add_data (gpg, ciph, 0, 0); + + if (!err) + start (gpg); + return err; +} + +static gpgme_error_t +gpg_delete (void *engine, gpgme_key_t key, int allow_secret) +{ + engine_gpg_t gpg = engine; + gpgme_error_t err; + + err = add_arg (gpg, allow_secret ? "--delete-secret-and-public-key" + : "--delete-key"); + if (!err) + err = add_arg (gpg, "--"); + if (!err) + { + if (!key->subkeys || !key->subkeys->fpr) + return gpg_error (GPG_ERR_INV_VALUE); + else + err = add_arg (gpg, key->subkeys->fpr); + } + + if (!err) + start (gpg); + return err; +} + + +static gpgme_error_t +append_args_from_signers (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */) +{ + gpgme_error_t err = 0; + int i; + gpgme_key_t key; + + for (i = 0; (key = gpgme_signers_enum (ctx, i)); i++) + { + const char *s = key->subkeys ? key->subkeys->keyid : NULL; + if (s) + { + if (!err) + err = add_arg (gpg, "-u"); + if (!err) + err = add_arg (gpg, s); + } + gpgme_key_unref (key); + if (err) break; + } + return err; +} + + +static gpgme_error_t +append_args_from_sig_notations (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */) +{ + gpgme_error_t err = 0; + gpgme_sig_notation_t notation; + + notation = gpgme_sig_notation_get (ctx); + + while (!err && notation) + { + if (notation->name + && !(notation->flags & GPGME_SIG_NOTATION_HUMAN_READABLE)) + err = gpg_error (GPG_ERR_INV_VALUE); + else if (notation->name) + { + char *arg; + + /* Maximum space needed is one byte for the "critical" flag, + the name, one byte for '=', the value, and a terminating + '\0'. */ + + arg = malloc (1 + notation->name_len + 1 + notation->value_len + 1); + if (!arg) + err = gpg_error_from_errno (errno); + + if (!err) + { + char *argp = arg; + + if (notation->critical) + *(argp++) = '!'; + + memcpy (argp, notation->name, notation->name_len); + argp += notation->name_len; + + *(argp++) = '='; + + /* We know that notation->name is '\0' terminated. */ + strcpy (argp, notation->value); + } + + if (!err) + err = add_arg (gpg, "--sig-notation"); + if (!err) + err = add_arg (gpg, arg); + + if (arg) + free (arg); + } + else + { + /* This is a policy URL. */ + + char *value; + + if (notation->critical) + { + value = malloc (1 + notation->value_len + 1); + if (!value) + err = gpg_error_from_errno (errno); + else + { + value[0] = '!'; + /* We know that notation->value is '\0' terminated. */ + strcpy (&value[1], notation->value); + } + } + else + value = notation->value; + + if (!err) + err = add_arg (gpg, "--sig-policy-url"); + if (!err) + err = add_arg (gpg, value); + + if (value != notation->value) + free (value); + } + + notation = notation->next; + } + return err; +} + + +static gpgme_error_t +gpg_edit (void *engine, int type, gpgme_key_t key, gpgme_data_t out, + gpgme_ctx_t ctx /* FIXME */) +{ + engine_gpg_t gpg = engine; + gpgme_error_t err; + + err = add_arg (gpg, "--with-colons"); + if (!err) + err = append_args_from_signers (gpg, ctx); + if (!err) + err = add_arg (gpg, type == 0 ? "--edit-key" : "--card-edit"); + if (!err) + err = add_data (gpg, out, 1, 1); + if (!err) + err = add_arg (gpg, "--"); + if (!err && type == 0) + { + const char *s = key->subkeys ? key->subkeys->fpr : NULL; + if (!s) + err = gpg_error (GPG_ERR_INV_VALUE); + else + err = add_arg (gpg, s); + } + if (!err) + err = start (gpg); + + return err; +} + + +static gpgme_error_t +append_args_from_recipients (engine_gpg_t gpg, gpgme_key_t recp[]) +{ + gpgme_error_t err = 0; + int i = 0; + + while (recp[i]) + { + if (!recp[i]->subkeys || !recp[i]->subkeys->fpr) + err = gpg_error (GPG_ERR_INV_VALUE); + if (!err) + err = add_arg (gpg, "-r"); + if (!err) + err = add_arg (gpg, recp[i]->subkeys->fpr); + if (err) + break; + i++; + } + return err; +} + + +static gpgme_error_t +gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, + gpgme_data_t plain, gpgme_data_t ciph, int use_armor) +{ + engine_gpg_t gpg = engine; + gpgme_error_t err; + int symmetric = !recp; + + err = add_arg (gpg, symmetric ? "--symmetric" : "--encrypt"); + + if (!err && use_armor) + err = add_arg (gpg, "--armor"); + + if (!symmetric) + { + /* If we know that all recipients are valid (full or ultimate trust) + we can suppress further checks. */ + if (!err && !symmetric && (flags & GPGME_ENCRYPT_ALWAYS_TRUST)) + err = add_arg (gpg, "--always-trust"); + + if (!err) + err = append_args_from_recipients (gpg, recp); + } + + /* Tell the gpg object about the data. */ + if (!err) + err = add_arg (gpg, "--output"); + if (!err) + err = add_arg (gpg, "-"); + if (!err) + err = add_data (gpg, ciph, 1, 1); + if (gpgme_data_get_file_name (plain)) + { + if (!err) + err = add_arg (gpg, "--set-filename"); + if (!err) + err = add_arg (gpg, gpgme_data_get_file_name (plain)); + } + if (!err) + err = add_arg (gpg, "--"); + if (!err) + err = add_data (gpg, plain, 0, 0); + + if (!err) + err = start (gpg); + + return err; +} + + +static gpgme_error_t +gpg_encrypt_sign (void *engine, gpgme_key_t recp[], + gpgme_encrypt_flags_t flags, gpgme_data_t plain, + gpgme_data_t ciph, int use_armor, + gpgme_ctx_t ctx /* FIXME */) +{ + engine_gpg_t gpg = engine; + gpgme_error_t err; + + err = add_arg (gpg, "--encrypt"); + if (!err) + err = add_arg (gpg, "--sign"); + if (!err && use_armor) + err = add_arg (gpg, "--armor"); + + /* If we know that all recipients are valid (full or ultimate trust) + we can suppress further checks. */ + if (!err && (flags & GPGME_ENCRYPT_ALWAYS_TRUST)) + err = add_arg (gpg, "--always-trust"); + + if (!err) + err = append_args_from_recipients (gpg, recp); + + if (!err) + err = append_args_from_signers (gpg, ctx); + if (!err) + err = append_args_from_sig_notations (gpg, ctx); + + /* Tell the gpg object about the data. */ + if (!err) + err = add_arg (gpg, "--output"); + if (!err) + err = add_arg (gpg, "-"); + if (!err) + err = add_data (gpg, ciph, 1, 1); + if (gpgme_data_get_file_name (plain)) + { + if (!err) + err = add_arg (gpg, "--set-filename"); + if (!err) + err = add_arg (gpg, gpgme_data_get_file_name (plain)); + } + if (!err) + err = add_arg (gpg, "--"); + if (!err) + err = add_data (gpg, plain, 0, 0); + + if (!err) + err = start (gpg); + + return err; +} + + +static gpgme_error_t +gpg_export (void *engine, const char *pattern, unsigned int reserved, + gpgme_data_t keydata, int use_armor) +{ + engine_gpg_t gpg = engine; + gpgme_error_t err; + + if (reserved) + return gpg_error (GPG_ERR_INV_VALUE); + + err = add_arg (gpg, "--export"); + if (!err && use_armor) + err = add_arg (gpg, "--armor"); + if (!err) + err = add_data (gpg, keydata, 1, 1); + if (!err) + err = add_arg (gpg, "--"); + + if (!err && pattern && *pattern) + err = add_arg (gpg, pattern); + + if (!err) + err = start (gpg); + + return err; +} + + +static gpgme_error_t +gpg_export_ext (void *engine, const char *pattern[], unsigned int reserved, + gpgme_data_t keydata, int use_armor) +{ + engine_gpg_t gpg = engine; + gpgme_error_t err; + + if (reserved) + return gpg_error (GPG_ERR_INV_VALUE); + + err = add_arg (gpg, "--export"); + if (!err && use_armor) + err = add_arg (gpg, "--armor"); + if (!err) + err = add_data (gpg, keydata, 1, 1); + if (!err) + err = add_arg (gpg, "--"); + + if (pattern) + { + while (!err && *pattern && **pattern) + err = add_arg (gpg, *(pattern++)); + } + + if (!err) + err = start (gpg); + + return err; +} + + +static gpgme_error_t +gpg_genkey (void *engine, gpgme_data_t help_data, int use_armor, + gpgme_data_t pubkey, gpgme_data_t seckey) +{ + engine_gpg_t gpg = engine; + gpgme_error_t err; + + if (!gpg) + return gpg_error (GPG_ERR_INV_VALUE); + + /* 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) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + + err = add_arg (gpg, "--gen-key"); + if (!err && use_armor) + err = add_arg (gpg, "--armor"); + if (!err) + err = add_data (gpg, help_data, 0, 0); + + if (!err) + err = start (gpg); + + return err; +} + + +static gpgme_error_t +gpg_import (void *engine, gpgme_data_t keydata) +{ + engine_gpg_t gpg = engine; + gpgme_error_t err; + + err = add_arg (gpg, "--import"); + if (!err) + err = add_data (gpg, keydata, 0, 0); + + if (!err) + err = start (gpg); + + return err; +} + + +/* The output for external keylistings in GnuPG is different from all + the other key listings. We catch this here with a special + preprocessor that reformats the colon handler lines. */ +static gpgme_error_t +gpg_keylist_preprocess (char *line, char **r_line) +{ + enum + { + RT_NONE, RT_INFO, RT_PUB, RT_UID + } + rectype = RT_NONE; +#define NR_FIELDS 16 + char *field[NR_FIELDS]; + int fields = 0; + + *r_line = NULL; + + while (line && fields < NR_FIELDS) + { + field[fields++] = line; + line = strchr (line, ':'); + if (line) + *(line++) = '\0'; + } + + if (!strcmp (field[0], "info")) + rectype = RT_INFO; + else if (!strcmp (field[0], "pub")) + rectype = RT_PUB; + else if (!strcmp (field[0], "uid")) + rectype = RT_UID; + else + rectype = RT_NONE; + + switch (rectype) + { + case RT_INFO: + /* FIXME: Eventually, check the version number at least. */ + return 0; + + case RT_PUB: + if (fields < 7) + return 0; + + /* The format is: + + pub:::::: + + as defined in 5.2. Machine Readable Indexes of the OpenPGP + HTTP Keyserver Protocol (draft). + + We want: + pub:o::::::::::::: + */ + + if (asprintf (r_line, "pub:o%s:%s:%s:%s:%s:%s::::::::", + field[6], field[3], field[2], field[1], + field[4], field[5]) < 0) + return gpg_error_from_errno (errno); + return 0; + + case RT_UID: + /* The format is: + + uid:::: + + as defined in 5.2. Machine Readable Indexes of the OpenPGP + HTTP Keyserver Protocol (draft). + + We want: + uid:o::::::::: + */ + + if (asprintf (r_line, "uid:o%s::::%s:%s:::%s:", + field[4], field[2], field[3], field[1]) < 0) + return gpg_error_from_errno (errno); + return 0; + + case RT_NONE: + /* Unknown record. */ + break; + } + return 0; + +} + + +static gpgme_error_t +gpg_keylist (void *engine, const char *pattern, int secret_only, + gpgme_keylist_mode_t mode) +{ + engine_gpg_t gpg = engine; + gpgme_error_t err; + + if (mode & GPGME_KEYLIST_MODE_EXTERN) + { + if ((mode & GPGME_KEYLIST_MODE_LOCAL) + || secret_only) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + } + + err = add_arg (gpg, "--with-colons"); + if (!err) + err = add_arg (gpg, "--fixed-list-mode"); + if (!err) + err = add_arg (gpg, "--with-fingerprint"); + if (!err) + err = add_arg (gpg, "--with-fingerprint"); + if (!err && (mode & GPGME_KEYLIST_MODE_SIGS) + && (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS)) + { + err = add_arg (gpg, "--list-options"); + if (!err) + err = add_arg (gpg, "show-sig-subpackets=\"20,26\""); + } + if (!err) + { + if (mode & GPGME_KEYLIST_MODE_EXTERN) + { + err = add_arg (gpg, "--search-keys"); + gpg->colon.preprocess_fnc = gpg_keylist_preprocess; + } + else + { + err = add_arg (gpg, secret_only ? "--list-secret-keys" + : ((mode & GPGME_KEYLIST_MODE_SIGS) + ? "--check-sigs" : "--list-keys")); + } + } + + /* Tell the gpg object about the data. */ + if (!err) + err = add_arg (gpg, "--"); + if (!err && pattern && *pattern) + err = add_arg (gpg, pattern); + + if (!err) + err = start (gpg); + + return err; +} + + +static gpgme_error_t +gpg_keylist_ext (void *engine, const char *pattern[], int secret_only, + int reserved, gpgme_keylist_mode_t mode) +{ + engine_gpg_t gpg = engine; + gpgme_error_t err; + + if (reserved) + return gpg_error (GPG_ERR_INV_VALUE); + + err = add_arg (gpg, "--with-colons"); + if (!err) + err = add_arg (gpg, "--fixed-list-mode"); + if (!err) + err = add_arg (gpg, "--with-fingerprint"); + if (!err) + err = add_arg (gpg, "--with-fingerprint"); + if (!err && (mode & GPGME_KEYLIST_MODE_SIGS) + && (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS)) + { + err = add_arg (gpg, "--list-options"); + if (!err) + err = add_arg (gpg, "show-sig-subpackets=\"20,26\""); + } + if (!err) + err = add_arg (gpg, secret_only ? "--list-secret-keys" + : ((mode & GPGME_KEYLIST_MODE_SIGS) + ? "--check-sigs" : "--list-keys")); + if (!err) + err = add_arg (gpg, "--"); + + if (pattern) + { + while (!err && *pattern && **pattern) + err = add_arg (gpg, *(pattern++)); + } + + if (!err) + err = start (gpg); + + return err; +} + + +static gpgme_error_t +gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out, + gpgme_sig_mode_t mode, int use_armor, int use_textmode, + int include_certs, gpgme_ctx_t ctx /* FIXME */) +{ + engine_gpg_t gpg = engine; + gpgme_error_t err; + + if (mode == GPGME_SIG_MODE_CLEAR) + err = add_arg (gpg, "--clearsign"); + else + { + err = add_arg (gpg, "--sign"); + if (!err && mode == GPGME_SIG_MODE_DETACH) + err = add_arg (gpg, "--detach"); + if (!err && use_armor) + err = add_arg (gpg, "--armor"); + if (!err && use_textmode) + err = add_arg (gpg, "--textmode"); + } + + if (!err) + err = append_args_from_signers (gpg, ctx); + if (!err) + err = append_args_from_sig_notations (gpg, ctx); + + if (gpgme_data_get_file_name (in)) + { + if (!err) + err = add_arg (gpg, "--set-filename"); + if (!err) + err = add_arg (gpg, gpgme_data_get_file_name (in)); + } + + /* Tell the gpg object about the data. */ + if (!err) + err = add_data (gpg, in, 0, 0); + if (!err) + err = add_data (gpg, out, 1, 1); + + if (!err) + start (gpg); + + return err; +} + +static gpgme_error_t +gpg_trustlist (void *engine, const char *pattern) +{ + engine_gpg_t gpg = engine; + gpgme_error_t err; + + err = add_arg (gpg, "--with-colons"); + if (!err) + err = add_arg (gpg, "--list-trust-path"); + + /* Tell the gpg object about the data. */ + if (!err) + err = add_arg (gpg, "--"); + if (!err) + err = add_arg (gpg, pattern); + + if (!err) + err = start (gpg); + + return err; +} + + +static gpgme_error_t +gpg_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text, + gpgme_data_t plaintext) +{ + engine_gpg_t gpg = engine; + gpgme_error_t err = 0; + + if (plaintext) + { + /* Normal or cleartext signature. */ + + err = add_arg (gpg, "--output"); + if (!err) + err = add_arg (gpg, "-"); + if (!err) + err = add_arg (gpg, "--"); + if (!err) + err = add_data (gpg, sig, 0, 0); + if (!err) + err = add_data (gpg, plaintext, 1, 1); + } + else + { + err = add_arg (gpg, "--verify"); + if (!err) + err = add_arg (gpg, "--"); + if (!err) + err = add_data (gpg, sig, -1, 0); + if (signed_text) + { + if (!err) + err = add_arg (gpg, "-"); + if (!err) + err = add_data (gpg, signed_text, 0, 0); + } + } + + if (!err) + err = start (gpg); + + return err; +} + + +static void +gpg_set_io_cbs (void *engine, gpgme_io_cbs_t io_cbs) +{ + engine_gpg_t gpg = engine; + + gpg->io_cbs = *io_cbs; +} + + +struct engine_ops _gpgme_engine_ops_gpg = + { + /* Static functions. */ + _gpgme_get_gpg_path, + gpg_get_version, + gpg_get_req_version, + gpg_new, + + /* Member functions. */ + gpg_release, + NULL, /* reset */ + gpg_set_status_handler, + gpg_set_command_handler, + gpg_set_colon_line_handler, + gpg_set_locale, + gpg_decrypt, + gpg_delete, + gpg_edit, + gpg_encrypt, + gpg_encrypt_sign, + gpg_export, + gpg_export_ext, + gpg_genkey, + gpg_import, + gpg_keylist, + gpg_keylist_ext, + gpg_sign, + gpg_trustlist, + gpg_verify, + NULL, /* getauditlog */ + NULL, /* conf_load */ + NULL, /* conf_save */ + gpg_set_io_cbs, + gpg_io_event, + gpg_cancel + }; diff --git a/tags/gpgme-1.1.6/gpgme/sema.h b/tags/gpgme-1.1.6/gpgme/sema.h new file mode 100644 index 0000000..7d3870e --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/sema.h @@ -0,0 +1,67 @@ +/* sema.h - Definitions for semaphores. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2003, 2004, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 SEMA_H +#define SEMA_H + +struct critsect_s +{ + const char *name; + void *priv; +}; + +#define DEFINE_GLOBAL_LOCK(name) \ + struct critsect_s name = { #name, NULL } +#define DEFINE_STATIC_LOCK(name) \ + static struct critsect_s name = { #name, NULL } + +#define DECLARE_LOCK(name) \ + struct critsect_s name +#define INIT_LOCK(a) \ + do \ + { \ + (a).name = #a; \ + (a).priv = NULL; \ + } \ + while (0) +#define DESTROY_LOCK(name) _gpgme_sema_cs_destroy (&(name)) + + +#define LOCK(name) \ + do \ + { \ + _gpgme_sema_cs_enter (&(name)); \ + } \ + while (0) + +#define UNLOCK(name) \ + do \ + { \ + _gpgme_sema_cs_leave (&(name)); \ + } \ + while (0) + +void _gpgme_sema_subsystem_init (void); +void _gpgme_sema_cs_enter (struct critsect_s *s); +void _gpgme_sema_cs_leave (struct critsect_s *s); +void _gpgme_sema_cs_destroy (struct critsect_s *s); + +#endif /* SEMA_H */ diff --git a/tags/gpgme-1.1.6/gpgme/setenv.c b/tags/gpgme-1.1.6/gpgme/setenv.c new file mode 100644 index 0000000..d3a54c1 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/setenv.c @@ -0,0 +1,356 @@ +/* Copyright (C) 1992,1995-2001,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02110-1301 USA. */ + +#if HAVE_CONFIG_H +# include +#endif + +#if HAVE_ASSUAN_H +/* Fixme: Why do we need to include the assuan header and why the + internal ones? */ +#include "assuan-defs.h" +#endif /*HAVE_ASSUAN_H*/ + +#define __builtin_expect(cond,val) (cond) + +#include +#if !_LIBC +# if !defined errno && !defined HAVE_ERRNO_DECL +extern int errno; +# endif +# define __set_errno(ev) ((errno) = (ev)) +#endif + +#if _LIBC || HAVE_STDLIB_H +# include +#endif +#if _LIBC || HAVE_STRING_H +# include +#endif +#if _LIBC || HAVE_UNISTD_H +# include +#endif + +#if !_LIBC +# define __environ environ +# ifndef HAVE_ENVIRON_DECL +extern char **environ; +# endif +#endif + +#if _LIBC +/* This lock protects against simultaneous modifications of `environ'. */ +# include +__libc_lock_define_initialized (static, envlock) +# define LOCK __libc_lock_lock (envlock) +# define UNLOCK __libc_lock_unlock (envlock) +#else +# define LOCK +# define UNLOCK +#endif + +/* In the GNU C library we must keep the namespace clean. */ +#ifdef _LIBC +# define setenv __setenv +# define unsetenv __unsetenv +# define clearenv __clearenv +# define tfind __tfind +# define tsearch __tsearch +#endif + +/* In the GNU C library implementation we try to be more clever and + allow arbitrarily many changes of the environment given that the used + values are from a small set. Outside glibc this will eat up all + memory after a while. */ +#if defined _LIBC || (defined HAVE_SEARCH_H && defined HAVE_TSEARCH \ + && defined __GNUC__) +# define USE_TSEARCH 1 +# include + +/* This is a pointer to the root of the search tree with the known + values. */ +static void *known_values; + +# define KNOWN_VALUE(Str) \ + ({ \ + void *value = tfind (Str, &known_values, (__compar_fn_t) strcmp); \ + value != NULL ? *(char **) value : NULL; \ + }) +# define STORE_VALUE(Str) \ + tsearch (Str, &known_values, (__compar_fn_t) strcmp) + +#else +# undef USE_TSEARCH + +# define KNOWN_VALUE(Str) NULL +# define STORE_VALUE(Str) do { } while (0) + +#endif + + +/* If this variable is not a null pointer we allocated the current + environment. */ +static char **last_environ; + + +/* This function is used by `setenv' and `putenv'. The difference between + the two functions is that for the former must create a new string which + is then placed in the environment, while the argument of `putenv' + must be used directly. This is all complicated by the fact that we try + to reuse values once generated for a `setenv' call since we can never + free the strings. */ +static int +__add_to_environ (const char *name, const char *value, const char *combined, + int replace) +{ + register char **ep; + register size_t size; + const size_t namelen = strlen (name); + const size_t vallen = value != NULL ? strlen (value) + 1 : 0; + + LOCK; + + /* We have to get the pointer now that we have the lock and not earlier + since another thread might have created a new environment. */ + ep = __environ; + + size = 0; + if (ep != NULL) + { + for (; *ep != NULL; ++ep) + if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=') + break; + else + ++size; + } + + if (ep == NULL || __builtin_expect (*ep == NULL, 1)) + { + char **new_environ; + + /* We allocated this space; we can extend it. */ + new_environ = (char **) realloc (last_environ, + (size + 2) * sizeof (char *)); + if (new_environ == NULL) + { + UNLOCK; + return -1; + } + + /* If the whole entry is given add it. */ + if (combined != NULL) + /* We must not add the string to the search tree since it belongs + to the user. */ + new_environ[size] = (char *) combined; + else + { + /* See whether the value is already known. */ +#ifdef USE_TSEARCH +# ifdef __GNUC__ + char new_value[namelen + 1 + vallen]; +# else + char *new_value = (char *) alloca (namelen + 1 + vallen); +# endif +# ifdef _LIBC + __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1), + value, vallen); +# else + memcpy (new_value, name, namelen); + new_value[namelen] = '='; + memcpy (&new_value[namelen + 1], value, vallen); +# endif + + new_environ[size] = KNOWN_VALUE (new_value); + if (__builtin_expect (new_environ[size] == NULL, 1)) +#endif + { + new_environ[size] = (char *) malloc (namelen + 1 + vallen); + if (__builtin_expect (new_environ[size] == NULL, 0)) + { + __set_errno (ENOMEM); + UNLOCK; + return -1; + } + +#ifdef USE_TSEARCH + memcpy (new_environ[size], new_value, namelen + 1 + vallen); +#else + memcpy (new_environ[size], name, namelen); + new_environ[size][namelen] = '='; + memcpy (&new_environ[size][namelen + 1], value, vallen); +#endif + /* And save the value now. We cannot do this when we remove + the string since then we cannot decide whether it is a + user string or not. */ + STORE_VALUE (new_environ[size]); + } + } + + if (__environ != last_environ) + memcpy ((char *) new_environ, (char *) __environ, + size * sizeof (char *)); + + new_environ[size + 1] = NULL; + + last_environ = __environ = new_environ; + } + else if (replace) + { + char *np; + + /* Use the user string if given. */ + if (combined != NULL) + np = (char *) combined; + else + { +#ifdef USE_TSEARCH +# ifdef __GNUC__ + char new_value[namelen + 1 + vallen]; +# else + char *new_value = (char *) alloca (namelen + 1 + vallen); +# endif +# ifdef _LIBC + __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1), + value, vallen); +# else + memcpy (new_value, name, namelen); + new_value[namelen] = '='; + memcpy (&new_value[namelen + 1], value, vallen); +# endif + + np = KNOWN_VALUE (new_value); + if (__builtin_expect (np == NULL, 1)) +#endif + { + np = malloc (namelen + 1 + vallen); + if (__builtin_expect (np == NULL, 0)) + { + UNLOCK; + return -1; + } + +#ifdef USE_TSEARCH + memcpy (np, new_value, namelen + 1 + vallen); +#else + memcpy (np, name, namelen); + np[namelen] = '='; + memcpy (&np[namelen + 1], value, vallen); +#endif + /* And remember the value. */ + STORE_VALUE (np); + } + } + + *ep = np; + } + + UNLOCK; + + return 0; +} + +int +setenv (const char *name, const char *value, int replace) +{ + if (name == NULL || *name == '\0' || strchr (name, '=') != NULL) + { + __set_errno (EINVAL); + return -1; + } + + return __add_to_environ (name, value, NULL, replace); +} + +int +unsetenv (const char *name) +{ + size_t len; + char **ep; + + if (name == NULL || *name == '\0' || strchr (name, '=') != NULL) + { + __set_errno (EINVAL); + return -1; + } + + len = strlen (name); + + LOCK; + + ep = __environ; + while (*ep != NULL) + if (!strncmp (*ep, name, len) && (*ep)[len] == '=') + { + /* Found it. Remove this pointer by moving later ones back. */ + char **dp = ep; + + do + dp[0] = dp[1]; + while (*dp++); + /* Continue the loop in case NAME appears again. */ + } + else + ++ep; + + UNLOCK; + + return 0; +} + +/* The `clearenv' was planned to be added to POSIX.1 but probably + never made it. Nevertheless the POSIX.9 standard (POSIX bindings + for Fortran 77) requires this function. */ +int +clearenv (void) +{ + LOCK; + + if (__environ == last_environ && __environ != NULL) + { + /* We allocated this environment so we can free it. */ + free (__environ); + last_environ = NULL; + } + + /* Clear the environment pointer removes the whole environment. */ + __environ = NULL; + + UNLOCK; + + return 0; +} +#ifdef _LIBC +libc_freeres_fn (free_mem) +{ + /* Remove all traces. */ + clearenv (); + + /* Now remove the search tree. */ + __tdestroy (known_values, free); + known_values = NULL; +} + +# undef setenv +# undef unsetenv +# undef clearenv +weak_alias (__setenv, setenv) +weak_alias (__unsetenv, unsetenv) +weak_alias (__clearenv, clearenv) +#endif + + diff --git a/tags/gpgme-1.1.6/gpgme/sig-notation.c b/tags/gpgme-1.1.6/gpgme/sig-notation.c new file mode 100644 index 0000000..5800c37 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/sig-notation.c @@ -0,0 +1,260 @@ +/* sig-notation.c - Signature notation data support. + Copyright (C) 2005 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include + +#include "gpgme.h" +#include "util.h" +#include "context.h" +#include "ops.h" + + +/* Free the signature notation object and all associated resources. + The object must already be removed from any linked list as the next + pointer is ignored. */ +void +_gpgme_sig_notation_free (gpgme_sig_notation_t notation) +{ + if (notation->name) + free (notation->name); + + if (notation->value) + free (notation->value); + + free (notation); +} + + +/* Set the flags of NOTATION to FLAGS. */ +static void +sig_notation_set_flags (gpgme_sig_notation_t notation, + gpgme_sig_notation_flags_t flags) +{ + /* We copy the flags into individual bits to make them easier + accessible individually for the user. */ + notation->human_readable = flags & GPGME_SIG_NOTATION_HUMAN_READABLE ? 1 : 0; + notation->critical = flags & GPGME_SIG_NOTATION_CRITICAL ? 1 : 0; + + notation->flags = flags; +} + + +/* Create a new, empty signature notation data object. */ +gpgme_error_t +_gpgme_sig_notation_create (gpgme_sig_notation_t *notationp, + const char *name, int name_len, + const char *value, int value_len, + gpgme_sig_notation_flags_t flags) +{ + gpgme_error_t err = 0; + gpgme_sig_notation_t notation; + + /* Currently, we require all notations to be human-readable. */ + if (name && !(flags & GPGME_SIG_NOTATION_HUMAN_READABLE)) + return gpg_error (GPG_ERR_INV_VALUE); + + notation = calloc (1, sizeof (*notation)); + if (!notation) + return gpg_error_from_errno (errno); + + /* This is critical. We want to reliably identify policy URLs by + using a NULL pointer for NAME. So all notations must have a NAME + string, even if it is empty. */ + if (name) + { + /* We add a trailing '\0' for stringification in the good + case. */ + notation->name = malloc (name_len + 1); + if (!notation->name) + { + err = gpg_error_from_errno (errno); + goto err; + } + + memcpy (notation->name, name, name_len); + notation->name[name_len] = '\0'; + notation->name_len = name_len; + } + + if (value) + { + /* We add a trailing '\0' for stringification in the good + case. */ + notation->value = malloc (value_len + 1); + if (!notation->value) + { + err = gpg_error_from_errno (errno); + goto err; + } + + memcpy (notation->value, value, value_len); + notation->value[value_len] = '\0'; + notation->value_len = value_len; + } + + sig_notation_set_flags (notation, flags); + + *notationp = notation; + return 0; + + err: + _gpgme_sig_notation_free (notation); + return err; +} + + +/* GnuPG subpacket flags. */ + +/* This subpacket data is part of the hashed data. */ +#define GNUPG_SPK_HASHED 0x01 + +/* This subpacket is marked critical. */ +#define GNUPG_SPK_CRITICAL 0x02 + +/* Parse a notation or policy URL subpacket. If the packet type is + not known, return no error but NULL in NOTATION. */ +gpgme_error_t +_gpgme_parse_notation (gpgme_sig_notation_t *notationp, + int type, int pkflags, int len, char *data) +{ + gpgme_error_t err; + char *name = NULL; + int name_len = 0; + char *value = NULL; + int value_len = 0; + gpgme_sig_notation_flags_t flags = 0; + char *decoded_data; + unsigned char *bdata; + + /* Type 20: Notation data. */ + /* Type 26: Policy URL. */ + if (type != 20 && type != 26) + { + *notationp = NULL; + return 0; + } + + /* A few simple sanity checks. */ + if (len > strlen (data)) + return gpg_error (GPG_ERR_INV_ENGINE); + + /* See below for the format of a notation subpacket. It has at + least four octets of flags and two times two octets of length + information. */ + if (type == 20 && len < 4 + 2 + 2) + return gpg_error (GPG_ERR_INV_ENGINE); + + err = _gpgme_decode_percent_string (data, &decoded_data, 0, 1); + if (err) + return err; + bdata = (unsigned char *) decoded_data; + + /* Flags common to notation data and policy URL. */ + if (pkflags & GNUPG_SPK_CRITICAL) + flags |= GPGME_SIG_NOTATION_CRITICAL; + + /* This information is relevant in parsing multi-octet numbers below: + + 3.1. Scalar numbers + + Scalar numbers are unsigned, and are always stored in big-endian + format. Using n[k] to refer to the kth octet being interpreted, + the value of a two-octet scalar is ((n[0] << 8) + n[1]). The + value of a four-octet scalar is ((n[0] << 24) + (n[1] << 16) + + (n[2] << 8) + n[3]). + + From RFC2440: OpenPGP Message Format. Copyright (C) The Internet + Society (1998). All Rights Reserved. */ +#define RFC2440_GET_WORD(chr) ((((int)((unsigned char *)(chr))[0]) << 8) \ + + ((int)((unsigned char *)(chr))[1])) + + if (type == 20) + { + /* 5.2.3.15. Notation Data + + (4 octets of flags, 2 octets of name length (M), + 2 octets of value length (N), M octets of name data, + N octets of value data) + + [...] The "flags" field holds four octets of flags. + All undefined flags MUST be zero. Defined flags are: + + First octet: 0x80 = human-readable. [...] + Other octets: none. + + From RFC2440: OpenPGP Message Format. Copyright (C) The + Internet Society (1998). All Rights Reserved. */ + + int chr; + + /* First octet of flags. */ +#define RFC2440_SPK20_FLAG1_HUMAN_READABLE 0x80 + + chr = *bdata; + bdata++; + + if (chr & RFC2440_SPK20_FLAG1_HUMAN_READABLE) + flags |= GPGME_SIG_NOTATION_HUMAN_READABLE; + + /* The second, third and four octet of flags are unused. */ + bdata++; + bdata++; + bdata++; + + name_len = RFC2440_GET_WORD (bdata); + bdata += 2; + + value_len = RFC2440_GET_WORD (bdata); + bdata += 2; + + /* Small sanity check. */ + if (4 + 2 + 2 + name_len + value_len > len) + { + free (decoded_data); + return gpg_error (GPG_ERR_INV_ENGINE); + } + + name = (char *) bdata; + bdata += name_len; + + value = (char *) bdata; + } + else + { + /* Type is 26. */ + + /* NAME is NULL, name_len is 0. */ + + value = (char *) bdata; + value_len = strlen (value); + } + + err = _gpgme_sig_notation_create (notationp, name, name_len, + value, value_len, flags); + + free (decoded_data); + return err; +} diff --git a/tags/gpgme-1.1.6/gpgme/sign.c b/tags/gpgme-1.1.6/gpgme/sign.c new file mode 100644 index 0000000..8405b69 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/sign.c @@ -0,0 +1,380 @@ +/* sign.c - Signing function. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif +#include +#include +#include + +#include "gpgme.h" +#include "context.h" +#include "ops.h" +#include "util.h" +#include "debug.h" + + +typedef struct +{ + struct _gpgme_op_sign_result result; + + /* A pointer to the next pointer of the last invalid signer in + the list. This makes appending new invalid signers painless + while preserving the order. */ + gpgme_invalid_key_t *last_signer_p; + + /* Likewise for signature information. */ + gpgme_new_signature_t *last_sig_p; +} *op_data_t; + + +static void +release_op_data (void *hook) +{ + op_data_t opd = (op_data_t) hook; + gpgme_invalid_key_t invalid_signer = opd->result.invalid_signers; + gpgme_new_signature_t sig = opd->result.signatures; + + while (invalid_signer) + { + gpgme_invalid_key_t next = invalid_signer->next; + if (invalid_signer->fpr) + free (invalid_signer->fpr); + free (invalid_signer); + invalid_signer = next; + } + + while (sig) + { + gpgme_new_signature_t next = sig->next; + free (sig->fpr); + free (sig); + sig = next; + } +} + + +gpgme_sign_result_t +gpgme_op_sign_result (gpgme_ctx_t ctx) +{ + void *hook; + op_data_t opd; + gpgme_error_t err; + + TRACE_BEG (DEBUG_CTX, "gpgme_op_sign_result", ctx); + + err = _gpgme_op_data_lookup (ctx, OPDATA_SIGN, &hook, -1, NULL); + opd = hook; + if (err || !opd) + { + TRACE_SUC0 ("result=(null)"); + return NULL; + } + + if (_gpgme_debug_trace ()) + { + gpgme_invalid_key_t inv_key = opd->result.invalid_signers; + gpgme_new_signature_t sig = opd->result.signatures; + int inv_signers = 0; + int signatures = 0; + + while (inv_key) + { + inv_signers++; + inv_key = inv_key->next; + } + while (sig) + { + signatures++; + sig = sig->next; + } + + TRACE_LOG2 ("result: invalid signers: %i, signatures: %i", + inv_signers, signatures); + inv_key = opd->result.invalid_signers; + while (inv_key) + { + TRACE_LOG3 ("result: invalid signer: fpr=%s, reason=%s <%s>", + inv_key->fpr, gpgme_strerror (inv_key->reason), + gpgme_strsource (inv_key->reason)); + inv_key = inv_key->next; + } + sig = opd->result.signatures; + while (sig) + { + TRACE_LOG6 ("result: signature: type=%i, pubkey_algo=%i, " + "hash_algo=%i, timestamp=%li, fpr=%s, sig_class=%i", + sig->type, sig->pubkey_algo, sig->hash_algo, + sig->timestamp, sig->fpr, sig->sig_class); + sig = sig->next; + } + } + + TRACE_SUC1 ("result=%p", &opd->result); + return &opd->result; +} + + +static gpgme_error_t +parse_sig_created (char *args, gpgme_new_signature_t *sigp) +{ + gpgme_new_signature_t sig; + char *tail; + + sig = malloc (sizeof (*sig)); + if (!sig) + return gpg_error_from_errno (errno); + + sig->next = NULL; + switch (*args) + { + case 'S': + sig->type = GPGME_SIG_MODE_NORMAL; + break; + + case 'D': + sig->type = GPGME_SIG_MODE_DETACH; + break; + + case 'C': + sig->type = GPGME_SIG_MODE_CLEAR; + break; + + default: + /* The backend engine is not behaving. */ + free (sig); + return gpg_error (GPG_ERR_INV_ENGINE); + } + + args++; + if (*args != ' ') + { + free (sig); + return gpg_error (GPG_ERR_INV_ENGINE); + } + + errno = 0; + sig->pubkey_algo = strtol (args, &tail, 0); + if (errno || args == tail || *tail != ' ') + { + /* The crypto backend does not behave. */ + free (sig); + return gpg_error (GPG_ERR_INV_ENGINE); + } + args = tail; + + sig->hash_algo = strtol (args, &tail, 0); + if (errno || args == tail || *tail != ' ') + { + /* The crypto backend does not behave. */ + free (sig); + return gpg_error (GPG_ERR_INV_ENGINE); + } + args = tail; + + sig->sig_class = strtol (args, &tail, 0); + sig->class = sig->sig_class; + sig->_obsolete_class = sig->sig_class; + if (errno || args == tail || *tail != ' ') + { + /* The crypto backend does not behave. */ + free (sig); + return gpg_error (GPG_ERR_INV_ENGINE); + } + args = tail; + + sig->timestamp = _gpgme_parse_timestamp (args, &tail); + if (sig->timestamp == -1 || args == tail || *tail != ' ') + { + /* The crypto backend does not behave. */ + free (sig); + return gpg_error (GPG_ERR_INV_ENGINE); + } + args = tail; + while (*args == ' ') + args++; + + if (!*args) + { + /* The crypto backend does not behave. */ + free (sig); + return gpg_error (GPG_ERR_INV_ENGINE); + } + + tail = strchr (args, ' '); + if (tail) + *tail = '\0'; + + sig->fpr = strdup (args); + if (!sig->fpr) + { + int saved_errno = errno; + free (sig); + return gpg_error_from_errno (saved_errno); + } + *sigp = sig; + return 0; +} + + +gpgme_error_t +_gpgme_sign_status_handler (void *priv, gpgme_status_code_t code, char *args) +{ + gpgme_ctx_t ctx = (gpgme_ctx_t) priv; + gpgme_error_t err; + void *hook; + op_data_t opd; + + err = _gpgme_passphrase_status_handler (priv, code, args); + if (err) + return err; + + err = _gpgme_op_data_lookup (ctx, OPDATA_SIGN, &hook, -1, NULL); + opd = hook; + if (err) + return err; + + switch (code) + { + case GPGME_STATUS_SIG_CREATED: + err = parse_sig_created (args, opd->last_sig_p); + if (err) + return err; + + opd->last_sig_p = &(*opd->last_sig_p)->next; + break; + + case GPGME_STATUS_INV_RECP: + err = _gpgme_parse_inv_recp (args, opd->last_signer_p); + if (err) + return err; + + opd->last_signer_p = &(*opd->last_signer_p)->next; + break; + + case GPGME_STATUS_EOF: + if (opd->result.invalid_signers) + return gpg_error (GPG_ERR_UNUSABLE_SECKEY); + break; + + default: + break; + } + return err; +} + + +static gpgme_error_t +sign_status_handler (void *priv, gpgme_status_code_t code, char *args) +{ + gpgme_error_t err; + + err = _gpgme_progress_status_handler (priv, code, args); + if (!err) + err = _gpgme_sign_status_handler (priv, code, args); + return err; +} + + +gpgme_error_t +_gpgme_op_sign_init_result (gpgme_ctx_t ctx) +{ + gpgme_error_t err; + void *hook; + op_data_t opd; + + err = _gpgme_op_data_lookup (ctx, OPDATA_SIGN, &hook, + sizeof (*opd), release_op_data); + opd = hook; + if (err) + return err; + opd->last_signer_p = &opd->result.invalid_signers; + opd->last_sig_p = &opd->result.signatures; + return 0; +} + + +static gpgme_error_t +sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t plain, + gpgme_data_t sig, gpgme_sig_mode_t mode) +{ + gpgme_error_t err; + + err = _gpgme_op_reset (ctx, synchronous); + if (err) + return err; + + err = _gpgme_op_sign_init_result (ctx); + if (err) + return err; + + if (mode != GPGME_SIG_MODE_NORMAL && mode != GPGME_SIG_MODE_DETACH + && mode != GPGME_SIG_MODE_CLEAR) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!plain) + return gpg_error (GPG_ERR_NO_DATA); + if (!sig) + return gpg_error (GPG_ERR_INV_VALUE); + + if (ctx->passphrase_cb) + { + err = _gpgme_engine_set_command_handler + (ctx->engine, _gpgme_passphrase_command_handler, ctx, NULL); + if (err) + return err; + } + + _gpgme_engine_set_status_handler (ctx->engine, sign_status_handler, + ctx); + + return _gpgme_engine_op_sign (ctx->engine, plain, sig, mode, ctx->use_armor, + ctx->use_textmode, ctx->include_certs, + ctx /* FIXME */); +} + + +/* Sign the plaintext PLAIN and store the signature in SIG. */ +gpgme_error_t +gpgme_op_sign_start (gpgme_ctx_t ctx, gpgme_data_t plain, gpgme_data_t sig, + gpgme_sig_mode_t mode) +{ + TRACE_BEG3 (DEBUG_CTX, "gpgme_op_sign_start", ctx, + "plain=%p, sig=%p, mode=%i", plain, sig, mode); + return TRACE_ERR (sign_start (ctx, 0, plain, sig, mode)); +} + + +/* Sign the plaintext PLAIN and store the signature in SIG. */ +gpgme_error_t +gpgme_op_sign (gpgme_ctx_t ctx, gpgme_data_t plain, gpgme_data_t sig, + gpgme_sig_mode_t mode) +{ + gpgme_error_t err; + + TRACE_BEG3 (DEBUG_CTX, "gpgme_op_sign_start", ctx, + "plain=%p, sig=%p, mode=%i", plain, sig, mode); + err = sign_start (ctx, 1, plain, sig, mode); + if (!err) + err = _gpgme_wait_one (ctx); + return TRACE_ERR (err); +} diff --git a/tags/gpgme-1.1.6/gpgme/signers.c b/tags/gpgme-1.1.6/gpgme/signers.c new file mode 100644 index 0000000..f1ce58f --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/signers.c @@ -0,0 +1,95 @@ +/* signers.c - Maintain signer sets. + Copyright (C) 2001 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include "util.h" +#include "context.h" + + +/* Delete all signers from CTX. */ +void +gpgme_signers_clear (gpgme_ctx_t ctx) +{ + unsigned int i; + + if (!ctx || !ctx->signers) + return; + + for (i = 0; i < ctx->signers_len; i++) + { + assert (ctx->signers[i]); + gpgme_key_unref (ctx->signers[i]); + ctx->signers[i] = NULL; + } + ctx->signers_len = 0; +} + +/* Add KEY to list of signers in CTX. */ +gpgme_error_t +gpgme_signers_add (gpgme_ctx_t ctx, const gpgme_key_t key) +{ + if (!ctx || !key) + return gpg_error (GPG_ERR_INV_VALUE); + + if (ctx->signers_len == ctx->signers_size) + { + gpgme_key_t *newarr; + int n = ctx->signers_size + 5; + int j; + + newarr = realloc (ctx->signers, n * sizeof (*newarr)); + if (!newarr) + return gpg_error_from_errno (errno); + for (j = ctx->signers_size; j < n; j++) + newarr[j] = NULL; + ctx->signers = newarr; + ctx->signers_size = n; + } + + gpgme_key_ref (key); + ctx->signers[ctx->signers_len++] = key; + return 0; +} + + +/* Return the SEQth signer's key in CTX with one reference. */ +gpgme_key_t +gpgme_signers_enum (const gpgme_ctx_t ctx, int seq) +{ + unsigned int seqno; + + if (!ctx || seq < 0) + return NULL; + + seqno = (unsigned int) seq; + if (seqno >= ctx->signers_len) + return NULL; + gpgme_key_ref (ctx->signers[seqno]); + return ctx->signers[seqno]; +} diff --git a/tags/gpgme-1.1.6/gpgme/stpcpy.c b/tags/gpgme-1.1.6/gpgme/stpcpy.c new file mode 100644 index 0000000..6e42911 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/stpcpy.c @@ -0,0 +1,55 @@ +/* Copyright (C) 1992, 1995, 1997, 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#undef __stpcpy +#undef stpcpy + +#ifndef weak_alias +# define __stpcpy stpcpy +#endif + +/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */ +char * +__stpcpy (dest, src) + char *dest; + const char *src; +{ + register char *d = dest; + register const char *s = src; + + do + *d++ = *s; + while (*s++ != '\0'); + + return d - 1; +} +#ifdef libc_hidden_def +libc_hidden_def (__stpcpy) +#endif +#ifdef weak_alias +weak_alias (__stpcpy, stpcpy) +#endif +#ifdef libc_hidden_builtin_def +libc_hidden_builtin_def (stpcpy) +#endif diff --git a/tags/gpgme-1.1.6/gpgme/trust-item.c b/tags/gpgme-1.1.6/gpgme/trust-item.c new file mode 100644 index 0000000..4dd0c4e --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/trust-item.c @@ -0,0 +1,171 @@ +/* trust-item.c - Trust item objects. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include + +#include "util.h" +#include "ops.h" +#include "sema.h" + + +/* Protects all reference counters in trust items. All other accesses + to a trust item are either read only or happen before the trust + item is available to the user. */ +DEFINE_STATIC_LOCK (trust_item_ref_lock); + + +/* Create a new trust item. */ +gpgme_error_t +_gpgme_trust_item_new (gpgme_trust_item_t *r_item) +{ + gpgme_trust_item_t item; + + item = calloc (1, sizeof *item); + if (!item) + return gpg_error_from_errno (errno); + item->_refs = 1; + item->keyid = item->_keyid; + item->_keyid[16] = '\0'; + item->owner_trust = item->_owner_trust; + item->_owner_trust[1] = '\0'; + item->validity = item->_validity; + item->_validity[1] = '\0'; + *r_item = item; + return 0; +} + + +/* Acquire a reference to ITEM. */ +void +gpgme_trust_item_ref (gpgme_trust_item_t item) +{ + LOCK (trust_item_ref_lock); + item->_refs++; + UNLOCK (trust_item_ref_lock); +} + + +/* gpgme_trust_item_unref releases the trust item object. Note that + this function may not do an actual release if there are other + shallow copies of the object. You have to call this function for + every newly created trust item object as well as for every + gpgme_trust_item_ref() done on the trust item object. */ +void +gpgme_trust_item_unref (gpgme_trust_item_t item) +{ + LOCK (trust_item_ref_lock); + assert (item->_refs > 0); + if (--item->_refs) + { + UNLOCK (trust_item_ref_lock); + return; + } + UNLOCK (trust_item_ref_lock); + + if (item->name) + free (item->name); + free (item); +} + + +/* Compatibility interfaces. */ +void +gpgme_trust_item_release (gpgme_trust_item_t item) +{ + gpgme_trust_item_unref (item); +} + +/* Return the value of the attribute WHAT of ITEM, which has to be + representable by a string. */ +const char *gpgme_trust_item_get_string_attr (gpgme_trust_item_t item, + _gpgme_attr_t what, + const void *reserved, int idx) +{ + const char *val = NULL; + + if (!item) + return NULL; + if (reserved) + return NULL; + if (idx) + return NULL; + + switch (what) + { + case GPGME_ATTR_KEYID: + val = item->keyid; + break; + + case GPGME_ATTR_OTRUST: + val = item->owner_trust; + break; + + case GPGME_ATTR_VALIDITY: + val = item->validity; + break; + + case GPGME_ATTR_USERID: + val = item->name; + break; + + default: + break; + } + return val; +} + + +/* Return the value of the attribute WHAT of KEY, which has to be + representable by an integer. IDX specifies a running index if the + attribute appears more than once in the key. */ +int gpgme_trust_item_get_int_attr (gpgme_trust_item_t item, _gpgme_attr_t what, + const void *reserved, int idx) +{ + int val = 0; + + if (!item) + return 0; + if (reserved) + return 0; + if (idx) + return 0; + + switch (what) + { + case GPGME_ATTR_LEVEL: + val = item->level; + break; + + case GPGME_ATTR_TYPE: + val = item->type; + break; + + default: + break; + } + return val; +} diff --git a/tags/gpgme-1.1.6/gpgme/trustlist.c b/tags/gpgme-1.1.6/gpgme/trustlist.c new file mode 100644 index 0000000..e8cdb66 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/trustlist.c @@ -0,0 +1,248 @@ +/* trustlist.c - Trust item listing. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include + +#include "gpgme.h" +#include "util.h" +#include "context.h" +#include "ops.h" + + +struct trust_queue_item_s +{ + struct trust_queue_item_s *next; + gpgme_trust_item_t item; +}; + +typedef struct +{ + /* Something new is available. */ + int trust_cond; + struct trust_queue_item_s *trust_queue; +} *op_data_t; + + + +static gpgme_error_t +trustlist_status_handler (void *priv, gpgme_status_code_t code, char *args) +{ + return 0; +} + + +/* This handler is used to parse the output of --list-trust-path: + Format: + level:keyid:type:recno:ot:val:mc:cc:name: + With TYPE = U for a user ID + K for a key + The RECNO is either the one of the dir record or the one of the uid + record. OT is the the usual trust letter and only availabel on K + lines. VAL is the calcualted validity MC is the marginal trust + counter and only available on U lines CC is the same for the + complete count NAME ist the username and only printed on U + lines. */ +static gpgme_error_t +trustlist_colon_handler (void *priv, char *line) +{ + gpgme_ctx_t ctx = (gpgme_ctx_t) priv; + gpgme_error_t err; + char *p, *pend; + int field = 0; + gpgme_trust_item_t item = NULL; + + if (!line) + return 0; /* EOF */ + + for (p = line; p; p = pend) + { + field++; + pend = strchr (p, ':'); + if (pend) + *pend++ = 0; + + switch (field) + { + case 1: /* level */ + err = _gpgme_trust_item_new (&item); + if (err) + return err; + item->level = atoi (p); + break; + case 2: /* long keyid */ + if (strlen (p) == DIM(item->keyid) - 1) + strcpy (item->keyid, p); + break; + case 3: /* type */ + item->type = *p == 'K'? 1 : *p == 'U'? 2 : 0; + break; + case 5: /* owner trust */ + item->_owner_trust[0] = *p; + break; + case 6: /* validity */ + item->_validity[0] = *p; + break; + case 9: /* user ID */ + item->name = strdup (p); + if (!item->name) + { + int saved_errno = errno; + gpgme_trust_item_unref (item); + return gpg_error_from_errno (saved_errno); + } + break; + } + } + + if (item) + _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_NEXT_TRUSTITEM, item); + return 0; +} + + +void +_gpgme_op_trustlist_event_cb (void *data, gpgme_event_io_t type, + void *type_data) +{ + gpgme_ctx_t ctx = (gpgme_ctx_t) data; + gpgme_error_t err; + void *hook; + op_data_t opd; + gpgme_trust_item_t item = (gpgme_trust_item_t) type_data; + struct trust_queue_item_s *q, *q2; + + assert (type == GPGME_EVENT_NEXT_TRUSTITEM); + + err = _gpgme_op_data_lookup (ctx, OPDATA_TRUSTLIST, &hook, -1, NULL); + opd = hook; + if (err) + return; + + q = malloc (sizeof *q); + if (!q) + { + gpgme_trust_item_unref (item); + /* FIXME: GPGME_Out_Of_Core; */ + return; + } + q->item = item; + q->next = NULL; + /* FIXME: Use a tail pointer */ + q2 = opd->trust_queue; + if (!q2) + opd->trust_queue = q; + else + { + while (q2->next) + q2 = q2->next; + q2->next = q; + } + /* FIXME: unlock queue */ + opd->trust_cond = 1; +} + + +gpgme_error_t +gpgme_op_trustlist_start (gpgme_ctx_t ctx, const char *pattern, int max_level) +{ + gpgme_error_t err = 0; + void *hook; + op_data_t opd; + + if (!pattern || !*pattern) + return gpg_error (GPG_ERR_INV_VALUE); + + err = _gpgme_op_reset (ctx, 2); + if (err) + return err; + + err = _gpgme_op_data_lookup (ctx, OPDATA_TRUSTLIST, &hook, + sizeof (*opd), NULL); + opd = hook; + if (err) + return err; + + _gpgme_engine_set_status_handler (ctx->engine, + trustlist_status_handler, ctx); + err = _gpgme_engine_set_colon_line_handler (ctx->engine, + trustlist_colon_handler, ctx); + if (err) + return err; + + return _gpgme_engine_op_trustlist (ctx->engine, pattern); +} + + +gpgme_error_t +gpgme_op_trustlist_next (gpgme_ctx_t ctx, gpgme_trust_item_t *r_item) +{ + gpgme_error_t err; + void *hook; + op_data_t opd; + struct trust_queue_item_s *q; + + if (!r_item) + return gpg_error (GPG_ERR_INV_VALUE); + *r_item = NULL; + if (!ctx) + return gpg_error (GPG_ERR_INV_VALUE); + + err = _gpgme_op_data_lookup (ctx, OPDATA_TRUSTLIST, &hook, -1, NULL); + opd = hook; + if (err) + return err; + if (opd == NULL) + return gpg_error (GPG_ERR_INV_VALUE); + + if (!opd->trust_queue) + { + err = _gpgme_wait_on_condition (ctx, &opd->trust_cond); + if (err) + return err; + if (!opd->trust_cond) + return gpg_error (GPG_ERR_EOF); + opd->trust_cond = 0; + assert (opd->trust_queue); + } + q = opd->trust_queue; + opd->trust_queue = q->next; + + *r_item = q->item; + free (q); + return 0; +} + + +/* Terminate a pending trustlist operation within CTX. */ +gpgme_error_t +gpgme_op_trustlist_end (gpgme_ctx_t ctx) +{ + if (!ctx) + return gpg_error (GPG_ERR_INV_VALUE); + + return 0; +} diff --git a/tags/gpgme-1.1.6/gpgme/ttyname_r.c b/tags/gpgme-1.1.6/gpgme/ttyname_r.c new file mode 100644 index 0000000..4487658 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/ttyname_r.c @@ -0,0 +1,53 @@ +/* ttyname_r.c - A ttyname_r() replacement. + Copyright (C) 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include + + +#warning ttyname is not thread-safe, and ttyname_r is missing + +int +ttyname_r (int fd, char *buf, size_t buflen) +{ + char *tty; + +#if HAVE_W32_SYSTEM + /* We use this default one for now. AFAICS we only need it to be + passed to gpg and in turn to pinentry. Providing a replacement + is needed because elsewhere we bail out on error. If we + eventually implement a pinentry for Windows it is uinlikely that + we need a real tty at all. */ + tty = "/dev/tty"; +#else + tty = ttyname (fd); + if (!tty) + return errno; +#endif + + strncpy (buf, tty, buflen); + buf[buflen - 1] = '\0'; + return (strlen (tty) >= buflen) ? ERANGE : 0; +} diff --git a/tags/gpgme-1.1.6/gpgme/util.h b/tags/gpgme-1.1.6/gpgme/util.h new file mode 100644 index 0000000..0cd6ab5 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/util.h @@ -0,0 +1,107 @@ +/* util.h + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 "gpgme.h" + + +#define DIM(v) (sizeof(v)/sizeof((v)[0])) + + +/*-- {posix,w32}-util.c --*/ +const char *_gpgme_get_gpg_path (void); +const char *_gpgme_get_gpgsm_path (void); +const char *_gpgme_get_gpgconf_path (void); +int _gpgme_get_conf_int (const char *key, int *value); + + +/*-- replacement functions in .c --*/ +#ifdef HAVE_CONFIG_H + +#ifndef HAVE_STPCPY +static _GPGME_INLINE char * +_gpgme_stpcpy (char *a, const char *b) +{ + while (*b) + *a++ = *b++; + *a = 0; + return a; +} +#define stpcpy(a,b) _gpgme_stpcpy ((a), (b)) +#endif /*!HAVE_STPCPY*/ + +#if !HAVE_VASPRINTF +#include +int vasprintf (char **result, const char *format, va_list args); +int asprintf (char **result, const char *format, ...); +#endif + +#ifndef HAVE_TTYNAME_R +int ttyname_r (int fd, char *buf, size_t buflen); +#endif +#endif + + +/*-- conversion.c --*/ +/* Convert two hexadecimal digits from STR to the value they + represent. Returns -1 if one of the characters is not a + hexadecimal digit. */ +int _gpgme_hextobyte (const char *str); + +/* Decode the C formatted string SRC and store the result in the + buffer *DESTP which is LEN bytes long. If LEN is zero, then a + large enough buffer is allocated with malloc and *DESTP is set to + the result. Currently, LEN is only used to specify if allocation + is desired or not, the caller is expected to make sure that *DESTP + is large enough if LEN is not zero. */ +gpgme_error_t _gpgme_decode_c_string (const char *src, char **destp, + size_t len); + +/* Decode the percent escaped string SRC and store the result in the + buffer *DESTP which is LEN bytes long. If LEN is zero, then a + large enough buffer is allocated with malloc and *DESTP is set to + the result. Currently, LEN is only used to specify if allocation + is desired or not, the caller is expected to make sure that *DESTP + is large enough if LEN is not zero. If BINARY is 1, then '\0' + characters are allowed in the output. */ +gpgme_error_t _gpgme_decode_percent_string (const char *src, char **destp, + size_t len, int binary); + + +/* Parse the string TIMESTAMP into a time_t. The string may either be + seconds since Epoch or in the ISO 8601 format like + "20390815T143012". Returns 0 for an empty string or seconds since + Epoch. Leading spaces are skipped. If ENDP is not NULL, it will + point to the next non-parsed character in TIMESTRING. */ +time_t _gpgme_parse_timestamp (const char *timestamp, char **endp); + + +gpgme_error_t _gpgme_map_gnupg_error (char *err); + + +/* Retrieve the environment variable NAME and return a copy of it in a + malloc()'ed buffer in *VALUE. If the environment variable is not + set, return NULL in *VALUE. */ +gpgme_error_t _gpgme_getenv (const char *name, char **value); + +#endif /* UTIL_H */ diff --git a/tags/gpgme-1.1.6/gpgme/vasprintf.c b/tags/gpgme-1.1.6/gpgme/vasprintf.c new file mode 100644 index 0000000..77113a3 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/vasprintf.c @@ -0,0 +1,192 @@ +/* Like vsprintf but provides a pointer to malloc'd storage, which must + be freed by the caller. + Copyright (C) 1994, 2002 Free Software Foundation, Inc. + +This file is part of the libiberty library. +Libiberty is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +Libiberty 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with libiberty; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include + + +#ifndef va_copy /* According to POSIX, va_copy is a macro. */ +#if defined (__GNUC__) && defined (__PPC__) \ + && (defined (_CALL_SYSV) || defined (_WIN32)) +#define va_copy(d, s) (*(d) = *(s)) +#elif defined (MUST_COPY_VA_BYVAL) +#define va_copy(d, s) ((d) = (s)) +#else +#define va_copy(d, s) memcpy ((d), (s), sizeof (va_list)) +#endif +#endif + + +#ifdef TEST +int global_total_width; +#endif + +static int int_vasprintf (char **, const char *, va_list *); + +static int +int_vasprintf (result, format, args) + char **result; + const char *format; + va_list *args; +{ + const char *p = format; + /* Add one to make sure that it is never zero, which might cause malloc + to return NULL. */ + int total_width = strlen (format) + 1; + va_list ap; + + va_copy (ap, *args); + + while (*p != '\0') + { + if (*p++ == '%') + { + while (strchr ("-+ #0", *p)) + ++p; + if (*p == '*') + { + ++p; + total_width += abs (va_arg (ap, int)); + } + else + total_width += strtoul (p, (char **) &p, 10); + if (*p == '.') + { + ++p; + if (*p == '*') + { + ++p; + total_width += abs (va_arg (ap, int)); + } + else + total_width += strtoul (p, (char **) &p, 10); + } + while (strchr ("hlL", *p)) + ++p; + /* Should be big enough for any format specifier except %s and floats. */ + total_width += 30; + switch (*p) + { + case 'd': + case 'i': + case 'o': + case 'u': + case 'x': + case 'X': + case 'c': + (void) va_arg (ap, int); + break; + case 'f': + case 'e': + case 'E': + case 'g': + case 'G': + (void) va_arg (ap, double); + /* Since an ieee double can have an exponent of 307, we'll + make the buffer wide enough to cover the gross case. */ + total_width += 307; + break; + case 's': + { + char *tmp = va_arg (ap, char *); + if (tmp) + total_width += strlen (tmp); + else /* in case the vsprintf does prints a text */ + total_width += 25; /* e.g. "(null pointer reference)" */ + } + break; + case 'p': + case 'n': + (void) va_arg (ap, char *); + break; + } + p++; + } + } +#ifdef TEST + global_total_width = total_width; +#endif + *result = malloc (total_width); + if (*result != NULL) + return vsprintf (*result, format, *args); + else + return 0; +} + +int +vasprintf (result, format, args) + char **result; + const char *format; +#if defined (_BSD_VA_LIST_) && defined (__FreeBSD__) + _BSD_VA_LIST_ args; +#else + va_list args; +#endif +{ + return int_vasprintf (result, format, &args); +} + + +int +asprintf (char **buf, const char *fmt, ...) +{ + int status; + va_list ap; + + va_start (ap, fmt); + status = vasprintf (buf, fmt, ap); + va_end (ap); + return status; +} + + +#ifdef TEST +void +checkit (const char* format, ...) +{ + va_list args; + char *result; + + va_start (args, format); + vasprintf (&result, format, args); + if (strlen (result) < global_total_width) + printf ("PASS: "); + else + printf ("FAIL: "); + printf ("%d %s\n", global_total_width, result); +} + +int +main (void) +{ + checkit ("%d", 0x12345678); + checkit ("%200d", 5); + checkit ("%.300d", 6); + checkit ("%100.150d", 7); + checkit ("%s", "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\ +777777777777777777333333333333366666666666622222222222777777777777733333"); + checkit ("%f%s%d%s", 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx"); +} +#endif /* TEST */ diff --git a/tags/gpgme-1.1.6/gpgme/verify.c b/tags/gpgme-1.1.6/gpgme/verify.c new file mode 100644 index 0000000..ef1ccd6 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/verify.c @@ -0,0 +1,1003 @@ +/* verify.c - Signature verification. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include + +#include "gpgme.h" +#include "util.h" +#include "context.h" +#include "ops.h" + + +typedef struct +{ + struct _gpgme_op_verify_result result; + + gpgme_signature_t current_sig; + int did_prepare_new_sig; + int only_newsig_seen; + int plaintext_seen; +} *op_data_t; + + +static void +release_op_data (void *hook) +{ + op_data_t opd = (op_data_t) hook; + gpgme_signature_t sig = opd->result.signatures; + + while (sig) + { + gpgme_signature_t next = sig->next; + gpgme_sig_notation_t notation = sig->notations; + + while (notation) + { + gpgme_sig_notation_t next_nota = notation->next; + + _gpgme_sig_notation_free (notation); + notation = next_nota; + } + + if (sig->fpr) + free (sig->fpr); + if (sig->pka_address) + free (sig->pka_address); + free (sig); + sig = next; + } + + if (opd->result.file_name) + free (opd->result.file_name); +} + + +gpgme_verify_result_t +gpgme_op_verify_result (gpgme_ctx_t ctx) +{ + void *hook; + op_data_t opd; + gpgme_error_t err; + + err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook, -1, NULL); + opd = hook; + if (err || !opd) + return NULL; + + return &opd->result; +} + + +/* Build a summary vector from RESULT. */ +static void +calc_sig_summary (gpgme_signature_t sig) +{ + unsigned long sum = 0; + + /* Calculate the red/green flag. */ + if (sig->validity == GPGME_VALIDITY_FULL + || sig->validity == GPGME_VALIDITY_ULTIMATE) + { + if (gpg_err_code (sig->status) == GPG_ERR_NO_ERROR + || gpg_err_code (sig->status) == GPG_ERR_SIG_EXPIRED + || gpg_err_code (sig->status) == GPG_ERR_KEY_EXPIRED) + sum |= GPGME_SIGSUM_GREEN; + } + else if (sig->validity == GPGME_VALIDITY_NEVER) + { + if (gpg_err_code (sig->status) == GPG_ERR_NO_ERROR + || gpg_err_code (sig->status) == GPG_ERR_SIG_EXPIRED + || gpg_err_code (sig->status) == GPG_ERR_KEY_EXPIRED) + sum |= GPGME_SIGSUM_RED; + } + else if (gpg_err_code (sig->status) == GPG_ERR_BAD_SIGNATURE) + sum |= GPGME_SIGSUM_RED; + + + /* FIXME: handle the case when key and message are expired. */ + switch (gpg_err_code (sig->status)) + { + case GPG_ERR_SIG_EXPIRED: + sum |= GPGME_SIGSUM_SIG_EXPIRED; + break; + + case GPG_ERR_KEY_EXPIRED: + sum |= GPGME_SIGSUM_KEY_EXPIRED; + break; + + case GPG_ERR_NO_PUBKEY: + sum |= GPGME_SIGSUM_KEY_MISSING; + break; + + case GPG_ERR_BAD_SIGNATURE: + case GPG_ERR_NO_ERROR: + break; + + default: + sum |= GPGME_SIGSUM_SYS_ERROR; + break; + } + + /* Now look at the certain reason codes. */ + switch (gpg_err_code (sig->validity_reason)) + { + case GPG_ERR_CRL_TOO_OLD: + if (sig->validity == GPGME_VALIDITY_UNKNOWN) + sum |= GPGME_SIGSUM_CRL_TOO_OLD; + break; + + case GPG_ERR_CERT_REVOKED: + sum |= GPGME_SIGSUM_KEY_REVOKED; + break; + + default: + break; + } + + /* Check other flags. */ + if (sig->wrong_key_usage) + sum |= GPGME_SIGSUM_BAD_POLICY; + + /* Set the valid flag when the signature is unquestionable + valid. */ + if ((sum & GPGME_SIGSUM_GREEN) && !(sum & ~GPGME_SIGSUM_GREEN)) + sum |= GPGME_SIGSUM_VALID; + + sig->summary = sum; +} + + +static gpgme_error_t +prepare_new_sig (op_data_t opd) +{ + gpgme_signature_t sig; + + if (opd->only_newsig_seen && opd->current_sig) + { + /* We have only seen the NEWSIG status and nothing else - we + better skip this signature therefore and reuse it for the + next possible signature. */ + sig = opd->current_sig; + memset (sig, 0, sizeof *sig); + assert (opd->result.signatures == sig); + } + else + { + sig = calloc (1, sizeof (*sig)); + if (!sig) + return gpg_error_from_errno (errno); + if (!opd->result.signatures) + opd->result.signatures = sig; + if (opd->current_sig) + opd->current_sig->next = sig; + opd->current_sig = sig; + } + opd->did_prepare_new_sig = 1; + opd->only_newsig_seen = 0; + return 0; +} + +static gpgme_error_t +parse_new_sig (op_data_t opd, gpgme_status_code_t code, char *args) +{ + gpgme_signature_t sig; + char *end = strchr (args, ' '); + char *tail; + + if (end) + { + *end = '\0'; + end++; + } + + if (!opd->did_prepare_new_sig) + { + gpg_error_t err; + + err = prepare_new_sig (opd); + if (err) + return err; + } + assert (opd->did_prepare_new_sig); + opd->did_prepare_new_sig = 0; + + assert (opd->current_sig); + sig = opd->current_sig; + + /* FIXME: We should set the source of the state. */ + switch (code) + { + case GPGME_STATUS_GOODSIG: + sig->status = gpg_error (GPG_ERR_NO_ERROR); + break; + + case GPGME_STATUS_EXPSIG: + sig->status = gpg_error (GPG_ERR_SIG_EXPIRED); + break; + + case GPGME_STATUS_EXPKEYSIG: + sig->status = gpg_error (GPG_ERR_KEY_EXPIRED); + break; + + case GPGME_STATUS_BADSIG: + sig->status = gpg_error (GPG_ERR_BAD_SIGNATURE); + break; + + case GPGME_STATUS_REVKEYSIG: + sig->status = gpg_error (GPG_ERR_CERT_REVOKED); + break; + + case GPGME_STATUS_ERRSIG: + /* Parse the pubkey algo. */ + if (!end) + goto parse_err_sig_fail; + errno = 0; + sig->pubkey_algo = strtol (end, &tail, 0); + if (errno || end == tail || *tail != ' ') + goto parse_err_sig_fail; + end = tail; + while (*end == ' ') + end++; + + /* Parse the hash algo. */ + if (!*end) + goto parse_err_sig_fail; + errno = 0; + sig->hash_algo = strtol (end, &tail, 0); + if (errno || end == tail || *tail != ' ') + goto parse_err_sig_fail; + end = tail; + while (*end == ' ') + end++; + + /* Skip the sig class. */ + end = strchr (end, ' '); + if (!end) + goto parse_err_sig_fail; + while (*end == ' ') + end++; + + /* Parse the timestamp. */ + sig->timestamp = _gpgme_parse_timestamp (end, &tail); + if (sig->timestamp == -1 || end == tail || (*tail && *tail != ' ')) + return gpg_error (GPG_ERR_INV_ENGINE); + end = tail; + while (*end == ' ') + end++; + + /* Parse the return code. */ + if (end[0] && (!end[1] || end[1] == ' ')) + { + switch (end[0]) + { + case '4': + sig->status = gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); + break; + + case '9': + sig->status = gpg_error (GPG_ERR_NO_PUBKEY); + break; + + default: + sig->status = gpg_error (GPG_ERR_GENERAL); + } + } + else + goto parse_err_sig_fail; + + goto parse_err_sig_ok; + + parse_err_sig_fail: + sig->status = gpg_error (GPG_ERR_GENERAL); + parse_err_sig_ok: + break; + + default: + return gpg_error (GPG_ERR_GENERAL); + } + + if (*args) + { + sig->fpr = strdup (args); + if (!sig->fpr) + return gpg_error_from_errno (errno); + } + return 0; +} + + +static gpgme_error_t +parse_valid_sig (gpgme_signature_t sig, char *args) +{ + char *end = strchr (args, ' '); + if (end) + { + *end = '\0'; + end++; + } + + if (!*args) + /* We require at least the fingerprint. */ + return gpg_error (GPG_ERR_GENERAL); + + if (sig->fpr) + free (sig->fpr); + sig->fpr = strdup (args); + if (!sig->fpr) + return gpg_error_from_errno (errno); + + /* Skip the creation date. */ + end = strchr (end, ' '); + if (end) + { + char *tail; + + sig->timestamp = _gpgme_parse_timestamp (end, &tail); + if (sig->timestamp == -1 || end == tail || (*tail && *tail != ' ')) + return gpg_error (GPG_ERR_INV_ENGINE); + end = tail; + + sig->exp_timestamp = _gpgme_parse_timestamp (end, &tail); + if (sig->exp_timestamp == -1 || end == tail || (*tail && *tail != ' ')) + return gpg_error (GPG_ERR_INV_ENGINE); + end = tail; + + while (*end == ' ') + end++; + /* Skip the signature version. */ + end = strchr (end, ' '); + if (end) + { + while (*end == ' ') + end++; + + /* Skip the reserved field. */ + end = strchr (end, ' '); + if (end) + { + /* Parse the pubkey algo. */ + errno = 0; + sig->pubkey_algo = strtol (end, &tail, 0); + if (errno || end == tail || *tail != ' ') + return gpg_error (GPG_ERR_INV_ENGINE); + end = tail; + + while (*end == ' ') + end++; + + if (*end) + { + /* Parse the hash algo. */ + + errno = 0; + sig->hash_algo = strtol (end, &tail, 0); + if (errno || end == tail || *tail != ' ') + return gpg_error (GPG_ERR_INV_ENGINE); + end = tail; + } + } + } + } + return 0; +} + + +static gpgme_error_t +parse_notation (gpgme_signature_t sig, gpgme_status_code_t code, char *args) +{ + gpgme_error_t err; + gpgme_sig_notation_t *lastp = &sig->notations; + gpgme_sig_notation_t notation = sig->notations; + char *end = strchr (args, ' '); + + if (end) + *end = '\0'; + + if (code == GPGME_STATUS_NOTATION_NAME || code == GPGME_STATUS_POLICY_URL) + { + /* FIXME: We could keep a pointer to the last notation in the list. */ + while (notation && notation->value) + { + lastp = ¬ation->next; + notation = notation->next; + } + + if (notation) + /* There is another notation name without data for the + previous one. The crypto backend misbehaves. */ + return gpg_error (GPG_ERR_INV_ENGINE); + + err = _gpgme_sig_notation_create (¬ation, NULL, 0, NULL, 0, 0); + if (err) + return err; + + if (code == GPGME_STATUS_NOTATION_NAME) + { + err = _gpgme_decode_percent_string (args, ¬ation->name, 0, 0); + if (err) + { + _gpgme_sig_notation_free (notation); + return err; + } + + notation->name_len = strlen (notation->name); + + /* FIXME: For now we fake the human-readable flag. The + critical flag can not be reported as it is not + provided. */ + notation->flags = GPGME_SIG_NOTATION_HUMAN_READABLE; + notation->human_readable = 1; + } + else + { + /* This is a policy URL. */ + + err = _gpgme_decode_percent_string (args, ¬ation->value, 0, 0); + if (err) + { + _gpgme_sig_notation_free (notation); + return err; + } + + notation->value_len = strlen (notation->value); + } + *lastp = notation; + } + else if (code == GPGME_STATUS_NOTATION_DATA) + { + int len = strlen (args) + 1; + char *dest; + + /* FIXME: We could keep a pointer to the last notation in the list. */ + while (notation && notation->next) + { + lastp = ¬ation->next; + notation = notation->next; + } + + if (!notation || !notation->name) + /* There is notation data without a previous notation + name. The crypto backend misbehaves. */ + return gpg_error (GPG_ERR_INV_ENGINE); + + if (!notation->value) + { + dest = notation->value = malloc (len); + if (!dest) + return gpg_error_from_errno (errno); + } + else + { + int cur_len = strlen (notation->value); + dest = realloc (notation->value, len + strlen (notation->value)); + if (!dest) + return gpg_error_from_errno (errno); + notation->value = dest; + dest += cur_len; + } + + err = _gpgme_decode_percent_string (args, &dest, len, 0); + if (err) + return err; + + notation->value_len += strlen (dest); + } + else + return gpg_error (GPG_ERR_INV_ENGINE); + return 0; +} + + +static gpgme_error_t +parse_trust (gpgme_signature_t sig, gpgme_status_code_t code, char *args) +{ + char *end = strchr (args, ' '); + + if (end) + *end = '\0'; + + switch (code) + { + case GPGME_STATUS_TRUST_UNDEFINED: + default: + sig->validity = GPGME_VALIDITY_UNKNOWN; + break; + + case GPGME_STATUS_TRUST_NEVER: + sig->validity = GPGME_VALIDITY_NEVER; + break; + + case GPGME_STATUS_TRUST_MARGINAL: + sig->validity = GPGME_VALIDITY_MARGINAL; + break; + + case GPGME_STATUS_TRUST_FULLY: + case GPGME_STATUS_TRUST_ULTIMATE: + sig->validity = GPGME_VALIDITY_FULL; + break; + } + + sig->validity_reason = 0; + sig->chain_model = 0; + if (*args) + { + sig->validity_reason = _gpgme_map_gnupg_error (args); + while (*args && *args != ' ') + args++; + if (*args) + { + while (*args == ' ') + args++; + if (!strncmp (args, "chain", 2) && (args[2] == ' ' || !args[2])) + sig->chain_model = 1; + } + } + + return 0; +} + + +/* Parse an error status line and if SET_STATUS is true update the + result status as appropriate. With SET_STATUS being false, only + check for an error. */ +static gpgme_error_t +parse_error (gpgme_signature_t sig, char *args, int set_status) +{ + gpgme_error_t err; + char *where = strchr (args, ' '); + char *which; + + if (where) + { + *where = '\0'; + which = where + 1; + + where = strchr (which, ' '); + if (where) + *where = '\0'; + + where = args; + } + else + return gpg_error (GPG_ERR_INV_ENGINE); + + err = _gpgme_map_gnupg_error (which); + + if (!strcmp (where, "proc_pkt.plaintext") + && gpg_err_code (err) == GPG_ERR_BAD_DATA) + { + /* This indicates a double plaintext. The only solid way to + handle this is by failing the oepration. */ + return gpg_error (GPG_ERR_BAD_DATA); + } + else if (!set_status) + ; + else if (!strcmp (where, "verify.findkey")) + sig->status = err; + else if (!strcmp (where, "verify.keyusage") + && gpg_err_code (err) == GPG_ERR_WRONG_KEY_USAGE) + sig->wrong_key_usage = 1; + + return 0; +} + + +gpgme_error_t +_gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args) +{ + gpgme_ctx_t ctx = (gpgme_ctx_t) priv; + gpgme_error_t err; + void *hook; + op_data_t opd; + gpgme_signature_t sig; + char *end; + + err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook, -1, NULL); + opd = hook; + if (err) + return err; + + sig = opd->current_sig; + + switch (code) + { + case GPGME_STATUS_NEWSIG: + if (sig) + calc_sig_summary (sig); + err = prepare_new_sig (opd); + opd->only_newsig_seen = 1; + return err; + + case GPGME_STATUS_GOODSIG: + case GPGME_STATUS_EXPSIG: + case GPGME_STATUS_EXPKEYSIG: + case GPGME_STATUS_BADSIG: + case GPGME_STATUS_ERRSIG: + case GPGME_STATUS_REVKEYSIG: + if (sig && !opd->did_prepare_new_sig) + calc_sig_summary (sig); + opd->only_newsig_seen = 0; + return parse_new_sig (opd, code, args); + + case GPGME_STATUS_VALIDSIG: + opd->only_newsig_seen = 0; + return sig ? parse_valid_sig (sig, args) + : gpg_error (GPG_ERR_INV_ENGINE); + + case GPGME_STATUS_NODATA: + opd->only_newsig_seen = 0; + if (!sig) + return gpg_error (GPG_ERR_NO_DATA); + sig->status = gpg_error (GPG_ERR_NO_DATA); + break; + + case GPGME_STATUS_UNEXPECTED: + opd->only_newsig_seen = 0; + if (!sig) + return gpg_error (GPG_ERR_GENERAL); + sig->status = gpg_error (GPG_ERR_NO_DATA); + break; + + case GPGME_STATUS_NOTATION_NAME: + case GPGME_STATUS_NOTATION_DATA: + case GPGME_STATUS_POLICY_URL: + opd->only_newsig_seen = 0; + return sig ? parse_notation (sig, code, args) + : gpg_error (GPG_ERR_INV_ENGINE); + + case GPGME_STATUS_TRUST_UNDEFINED: + case GPGME_STATUS_TRUST_NEVER: + case GPGME_STATUS_TRUST_MARGINAL: + case GPGME_STATUS_TRUST_FULLY: + case GPGME_STATUS_TRUST_ULTIMATE: + opd->only_newsig_seen = 0; + return sig ? parse_trust (sig, code, args) + : gpg_error (GPG_ERR_INV_ENGINE); + + case GPGME_STATUS_PKA_TRUST_BAD: + case GPGME_STATUS_PKA_TRUST_GOOD: + opd->only_newsig_seen = 0; + /* Check that we only get one of these status codes per + signature; if not the crypto backend misbehaves. */ + if (!sig || sig->pka_trust || sig->pka_address) + return gpg_error (GPG_ERR_INV_ENGINE); + sig->pka_trust = code == GPGME_STATUS_PKA_TRUST_GOOD? 2 : 1; + end = strchr (args, ' '); + if (end) + *end = 0; + sig->pka_address = strdup (args); + break; + + case GPGME_STATUS_ERROR: + opd->only_newsig_seen = 0; + /* Some error stati are informational, so we don't return an + error code if we are not ready to process this status. */ + return parse_error (sig, args, !!sig ); + + case GPGME_STATUS_EOF: + if (sig && !opd->did_prepare_new_sig) + calc_sig_summary (sig); + if (opd->only_newsig_seen && sig) + { + gpgme_signature_t sig2; + /* The last signature has no valid information - remove it + from the list. */ + assert (!sig->next); + if (sig == opd->result.signatures) + opd->result.signatures = NULL; + else + { + for (sig2 = opd->result.signatures; sig2; sig2 = sig2->next) + if (sig2->next == sig) + { + sig2->next = NULL; + break; + } + } + /* Note that there is no need to release the members of SIG + because we won't be here if they have been set. */ + free (sig); + opd->current_sig = NULL; + } + opd->only_newsig_seen = 0; + break; + + case GPGME_STATUS_PLAINTEXT: + if (++opd->plaintext_seen > 1) + return gpg_error (GPG_ERR_BAD_DATA); + err = _gpgme_parse_plaintext (args, &opd->result.file_name); + if (err) + return err; + + default: + break; + } + return 0; +} + + +static gpgme_error_t +verify_status_handler (void *priv, gpgme_status_code_t code, char *args) +{ + gpgme_error_t err; + + err = _gpgme_progress_status_handler (priv, code, args); + if (!err) + err = _gpgme_verify_status_handler (priv, code, args); + return err; +} + + +gpgme_error_t +_gpgme_op_verify_init_result (gpgme_ctx_t ctx) +{ + void *hook; + op_data_t opd; + + return _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook, + sizeof (*opd), release_op_data); +} + + +static gpgme_error_t +verify_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t sig, + gpgme_data_t signed_text, gpgme_data_t plaintext) +{ + gpgme_error_t err; + + err = _gpgme_op_reset (ctx, synchronous); + if (err) + return err; + + err = _gpgme_op_verify_init_result (ctx); + if (err) + return err; + + _gpgme_engine_set_status_handler (ctx->engine, verify_status_handler, ctx); + + if (!sig) + return gpg_error (GPG_ERR_NO_DATA); + if (!signed_text && !plaintext) + return gpg_error (GPG_ERR_INV_VALUE); + + return _gpgme_engine_op_verify (ctx->engine, sig, signed_text, plaintext); +} + + +/* Decrypt ciphertext CIPHER and make a signature verification within + CTX and store the resulting plaintext in PLAIN. */ +gpgme_error_t +gpgme_op_verify_start (gpgme_ctx_t ctx, gpgme_data_t sig, + gpgme_data_t signed_text, gpgme_data_t plaintext) +{ + return verify_start (ctx, 0, sig, signed_text, plaintext); +} + + +/* Decrypt ciphertext CIPHER and make a signature verification within + CTX and store the resulting plaintext in PLAIN. */ +gpgme_error_t +gpgme_op_verify (gpgme_ctx_t ctx, gpgme_data_t sig, gpgme_data_t signed_text, + gpgme_data_t plaintext) +{ + gpgme_error_t err; + + err = verify_start (ctx, 1, sig, signed_text, plaintext); + if (!err) + err = _gpgme_wait_one (ctx); + return err; +} + + +/* Compatibility interfaces. */ + +/* Get the key used to create signature IDX in CTX and return it in + R_KEY. */ +gpgme_error_t +gpgme_get_sig_key (gpgme_ctx_t ctx, int idx, gpgme_key_t *r_key) +{ + gpgme_verify_result_t result; + gpgme_signature_t sig; + + result = gpgme_op_verify_result (ctx); + sig = result->signatures; + + while (sig && idx) + { + sig = sig->next; + idx--; + } + if (!sig || idx) + return gpg_error (GPG_ERR_EOF); + + return gpgme_get_key (ctx, sig->fpr, r_key, 0); +} + + +/* Retrieve the signature status of signature IDX in CTX after a + successful verify operation in R_STAT (if non-null). The creation + time stamp of the signature is returned in R_CREATED (if non-null). + The function returns a string containing the fingerprint. */ +const char * +gpgme_get_sig_status (gpgme_ctx_t ctx, int idx, + _gpgme_sig_stat_t *r_stat, time_t *r_created) +{ + gpgme_verify_result_t result; + gpgme_signature_t sig; + + result = gpgme_op_verify_result (ctx); + sig = result->signatures; + + while (sig && idx) + { + sig = sig->next; + idx--; + } + if (!sig || idx) + return NULL; + + if (r_stat) + { + switch (gpg_err_code (sig->status)) + { + case GPG_ERR_NO_ERROR: + *r_stat = GPGME_SIG_STAT_GOOD; + break; + + case GPG_ERR_BAD_SIGNATURE: + *r_stat = GPGME_SIG_STAT_BAD; + break; + + case GPG_ERR_NO_PUBKEY: + *r_stat = GPGME_SIG_STAT_NOKEY; + break; + + case GPG_ERR_NO_DATA: + *r_stat = GPGME_SIG_STAT_NOSIG; + break; + + case GPG_ERR_SIG_EXPIRED: + *r_stat = GPGME_SIG_STAT_GOOD_EXP; + break; + + case GPG_ERR_KEY_EXPIRED: + *r_stat = GPGME_SIG_STAT_GOOD_EXPKEY; + break; + + default: + *r_stat = GPGME_SIG_STAT_ERROR; + break; + } + } + if (r_created) + *r_created = sig->timestamp; + return sig->fpr; +} + + +/* Retrieve certain attributes of a signature. IDX is the index + number of the signature after a successful verify operation. WHAT + is an attribute where GPGME_ATTR_EXPIRE is probably the most useful + one. WHATIDX is to be passed as 0 for most attributes . */ +unsigned long +gpgme_get_sig_ulong_attr (gpgme_ctx_t ctx, int idx, + _gpgme_attr_t what, int whatidx) +{ + gpgme_verify_result_t result; + gpgme_signature_t sig; + + result = gpgme_op_verify_result (ctx); + sig = result->signatures; + + while (sig && idx) + { + sig = sig->next; + idx--; + } + if (!sig || idx) + return 0; + + switch (what) + { + case GPGME_ATTR_CREATED: + return sig->timestamp; + + case GPGME_ATTR_EXPIRE: + return sig->exp_timestamp; + + case GPGME_ATTR_VALIDITY: + return (unsigned long) sig->validity; + + case GPGME_ATTR_SIG_STATUS: + switch (gpg_err_code (sig->status)) + { + case GPG_ERR_NO_ERROR: + return GPGME_SIG_STAT_GOOD; + + case GPG_ERR_BAD_SIGNATURE: + return GPGME_SIG_STAT_BAD; + + case GPG_ERR_NO_PUBKEY: + return GPGME_SIG_STAT_NOKEY; + + case GPG_ERR_NO_DATA: + return GPGME_SIG_STAT_NOSIG; + + case GPG_ERR_SIG_EXPIRED: + return GPGME_SIG_STAT_GOOD_EXP; + + case GPG_ERR_KEY_EXPIRED: + return GPGME_SIG_STAT_GOOD_EXPKEY; + + default: + return GPGME_SIG_STAT_ERROR; + } + + case GPGME_ATTR_SIG_SUMMARY: + return sig->summary; + + default: + break; + } + return 0; +} + + +const char * +gpgme_get_sig_string_attr (gpgme_ctx_t ctx, int idx, + _gpgme_attr_t what, int whatidx) +{ + gpgme_verify_result_t result; + gpgme_signature_t sig; + + result = gpgme_op_verify_result (ctx); + sig = result->signatures; + + while (sig && idx) + { + sig = sig->next; + idx--; + } + if (!sig || idx) + return NULL; + + switch (what) + { + case GPGME_ATTR_FPR: + return sig->fpr; + + case GPGME_ATTR_ERRTOK: + if (whatidx == 1) + return sig->wrong_key_usage ? "Wrong_Key_Usage" : ""; + else + return ""; + default: + break; + } + + return NULL; +} diff --git a/tags/gpgme-1.1.6/gpgme/version.c b/tags/gpgme-1.1.6/gpgme/version.c new file mode 100644 index 0000000..03d7aa0 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/version.c @@ -0,0 +1,253 @@ +/* version.c - Version check routines. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#ifdef HAVE_W32_SYSTEM +#include +#endif + +#include "gpgme.h" +#include "priv-io.h" +#include "debug.h" + +/* For _gpgme_sema_subsystem_init (). */ +#include "sema.h" + +#ifdef HAVE_ASSUAN_H +#include "assuan.h" +#endif + + +/* Bootstrap the subsystems needed for concurrent operation. This + must be done once at startup. We can not guarantee this using a + lock, though, because the semaphore subsystem needs to be + initialized itself before it can be used. So we expect that the + user performs the necessary synchronization. */ +static void +do_subsystem_inits (void) +{ + static int done = 0; + + if (done) + return; + + _gpgme_sema_subsystem_init (); +#ifdef HAVE_ASSUAN_H + assuan_set_assuan_log_level (0); + assuan_set_assuan_err_source (GPG_ERR_SOURCE_GPGME); +#endif /*HAVE_ASSUAN_H*/ + _gpgme_debug_subsystem_init (); +#if defined(HAVE_W32_SYSTEM) && defined(HAVE_ASSUAN_H) + _gpgme_io_subsystem_init (); + /* We need to make sure that the sockets are initialized. */ + { + WSADATA wsadat; + + WSAStartup (0x202, &wsadat); + } +#endif /*HAVE_W32_SYSTEM && HAVE_ASSUAN_H*/ + + done = 1; +} + + +/* Read the next number in the version string STR and return it in + *NUMBER. Return a pointer to the tail of STR after parsing, or + *NULL if the version string was invalid. */ +static const char * +parse_version_number (const char *str, int *number) +{ +#define MAXVAL ((INT_MAX - 10) / 10) + int val = 0; + + /* Leading zeros are not allowed. */ + if (*str == '0' && isdigit(str[1])) + return NULL; + + while (isdigit (*str) && val <= MAXVAL) + { + val *= 10; + val += *(str++) - '0'; + } + *number = val; + return val > MAXVAL ? NULL : str; +} + + +/* Parse the version string STR in the format MAJOR.MINOR.MICRO (for + example, 9.3.2) and return the components in MAJOR, MINOR and MICRO + as integers. The function returns the tail of the string that + follows the version number. This might be te empty string if there + is nothing following the version number, or a patchlevel. The + function returns NULL if the version string is not valid. */ +static const char * +parse_version_string (const char *str, int *major, int *minor, int *micro) +{ + str = parse_version_number (str, major); + if (!str || *str != '.') + return NULL; + str++; + + str = parse_version_number (str, minor); + if (!str || *str != '.') + return NULL; + str++; + + str = parse_version_number (str, micro); + if (!str) + return NULL; + + /* A patchlevel might follow. */ + return str; +} + + +/* Return true if MY_VERSION is at least REQ_VERSION, and false + otherwise. */ +int +_gpgme_compare_versions (const char *my_version, + const char *rq_version) +{ + int my_major, my_minor, my_micro; + int rq_major, rq_minor, rq_micro; + const char *my_plvl, *rq_plvl; + + if (!rq_version) + return 1; + if (!my_version) + return 0; + + my_plvl = parse_version_string (my_version, &my_major, &my_minor, &my_micro); + if (!my_plvl) + return 0; + + rq_plvl = parse_version_string (rq_version, &rq_major, &rq_minor, &rq_micro); + if (!rq_plvl) + return 0; + + 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 1; + + return 0; +} + + +/* Check that the the version of the library is at minimum the + requested one and return the version string; return NULL if the + condition is not met. If a NULL is passed to this function, no + check is done and the version string is simply returned. + + This function must be run once at startup, as it also initializes + some subsystems. Its invocation must be synchronized against + calling any of the other functions in a multi-threaded + environments. */ +const char * +gpgme_check_version (const char *req_version) +{ + do_subsystem_inits (); + + /* Catch-22: We need to get at least the debug subsystem ready + before using the tarce facility. If we won't the tarce would + automagically initialize the debug system with out the locks + being initialized and missing the assuan log level setting. */ + TRACE2 (DEBUG_INIT, "gpgme_check_version: ", 0, + "req_version=%s, VERSION=%s", req_version, VERSION); + + return _gpgme_compare_versions (VERSION, req_version) ? VERSION : NULL; +} + + +#define LINELENGTH 80 + +/* Retrieve the version number from the --version output of the + program FILE_NAME. */ +char * +_gpgme_get_program_version (const char *const file_name) +{ + char line[LINELENGTH] = ""; + int linelen = 0; + char *mark = NULL; + int rp[2]; + int nread; + char *argv[] = {NULL /* file_name */, "--version", 0}; + struct spawn_fd_item_s pfd[] = { {0, -1}, {-1, -1} }; + struct spawn_fd_item_s cfd[] = { {-1, 1 /* STDOUT_FILENO */}, {-1, -1} }; + int status; + + if (!file_name) + return NULL; + argv[0] = (char *) file_name; + + if (_gpgme_io_pipe (rp, 1) < 0) + return NULL; + + pfd[0].fd = rp[1]; + cfd[0].fd = rp[1]; + + status = _gpgme_io_spawn (file_name, argv, cfd, pfd); + if (status < 0) + { + _gpgme_io_close (rp[0]); + _gpgme_io_close (rp[1]); + return NULL; + } + + do + { + nread = _gpgme_io_read (rp[0], &line[linelen], LINELENGTH - linelen - 1); + if (nread > 0) + { + line[linelen + nread] = '\0'; + mark = strchr (&line[linelen], '\n'); + if (mark) + { + if (mark > &line[0] && *mark == '\r') + mark--; + *mark = '\0'; + break; + } + linelen += nread; + } + } + while (nread > 0 && linelen < LINELENGTH - 1); + + _gpgme_io_close (rp[0]); + + if (mark) + { + mark = strrchr (line, ' '); + if (!mark) + return NULL; + return strdup (mark + 1); + } + + return NULL; +} diff --git a/tags/gpgme-1.1.6/gpgme/versioninfo.rc.in b/tags/gpgme-1.1.6/gpgme/versioninfo.rc.in new file mode 100644 index 0000000..bfb652e --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/versioninfo.rc.in @@ -0,0 +1,52 @@ +/* versioninfo.rc.in - for gpgme + * Copyright (C) 2005 g10 Code GmbH + * + * This file is free software; as a special exception the author gives + * unlimited permission to copy and/or distribute it, with or without + * modifications, as long as this notice is preserved. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* This file is processed by configure to create versioninfo.rc */ + +#line __LINE__ "versioninfo.rc.in" + +#include + + +VS_VERSION_INFO VERSIONINFO + FILEVERSION @LIBGPGME_LT_CURRENT@,@LIBGPGME_LT_AGE@,@LIBGPGME_LT_REVISION@,@BUILD_REVISION@ + PRODUCTVERSION @BUILD_FILEVERSION@ + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x21L +#else + FILEFLAGS 0x20L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "Provided under the terms of the GNU Lesser General Public License.\0" + VALUE "CompanyName", "g10 Code GmbH\0" + VALUE "FileDescription", "GPGME - GnuPG Made Easy\0" + VALUE "FileVersion", "@LIBGPGME_LT_CURRENT@.@LIBGPGME_LT_AGE@.@LIBGPGME_LT_REVISION@.@BUILD_REVISION@\0" + VALUE "InternalName", "gpgme\0" + VALUE "LegalCopyright", "Copyright © 2005 g10 Code GmbH\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "gpgme.dll\0" + VALUE "PrivateBuild", "\0" + VALUE "ProductName", "GPGME\0" + VALUE "ProductVersion", "@VERSION@\0" + VALUE "SpecialBuild", "@BUILD_TIMESTAMP@\0" + END + END +END + diff --git a/tags/gpgme-1.1.6/gpgme/w32-glib-io.c b/tags/gpgme-1.1.6/gpgme/w32-glib-io.c new file mode 100644 index 0000000..3204b57 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/w32-glib-io.c @@ -0,0 +1,771 @@ +/* w32-glib-io.c - W32 Glib I/O functions + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2004, 2005 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "priv-io.h" +#include "sema.h" +#include "debug.h" + +#ifndef O_BINARY +#ifdef _O_BINARY +#define O_BINARY _O_BINARY +#else +#define O_BINARY 0 +#endif +#endif + + +/* This file is an ugly hack to get GPGME working with glib on Windows + targets. On Windows, you can not select() on file descriptors. + The only way to check if there is something to read is to read + something. This means that GPGME can not let glib check for data + without letting glib also handle the data on Windows targets. + + The ugly consequence is that we need to work on GIOChannels in + GPGME, creating a glib dependency. Also, we need to export an + interface for the application to get at GPGME's GIOChannel. There + is no good way to abstract all this with callbacks, because the + whole thing is also interconnected with the creation of pipes and + child processes. + + The following rule applies only to this I/O backend: + + * ALL operations must use the user defined event loop. GPGME can + not anymore provide its own event loop. This is mostly a sanity + requirement: Although we have in theory all information we need to + make the GPGME W32 code for select still work, it would be a big + complication and require changes throughout GPGME. + + Eventually, we probably have to bite the bullet and make some + really nice callback interfaces to let the user control all this at + a per-context level. */ + + +#define MAX_SLAFD 256 + +static struct +{ + GIOChannel *chan; + /* The boolean PRIMARY is true if this file descriptor caused the + allocation of CHAN. Only then should CHAN be destroyed when this + FD is closed. This, together with the fact that dup'ed file + descriptors are closed before the file descriptors from which + they are dup'ed are closed, ensures that CHAN is always valid, + and shared among all file descriptors refering to the same + underlying object. + + The logic behind this is that there is only one reason for us to + dup file descriptors anyway: to allow simpler book-keeping of + file descriptors shared between GPGME and libassuan, which both + want to close something. Using the same channel for these + duplicates works just fine (and in fact, using different channels + does not work because the W32 backend in glib does not support + that: One would end up with several competing reader/writer + threads. */ + int primary; +} giochannel_table[MAX_SLAFD]; + + +static GIOChannel * +find_channel (int fd, int create) +{ + if (fd < 0 || fd >= MAX_SLAFD) + return NULL; + + if (create && !giochannel_table[fd].chan) + { + giochannel_table[fd].chan = g_io_channel_win32_new_fd (fd); + giochannel_table[fd].primary = 1; + g_io_channel_set_encoding (giochannel_table[fd].chan, NULL, NULL); + g_io_channel_set_buffered (giochannel_table[fd].chan, FALSE); + } + + return giochannel_table[fd].chan; +} + + +/* Compatibility interface. Obsolete. */ +void * +gpgme_get_giochannel (int fd) +{ + return find_channel (fd, 0); +} + + +/* Look up the giochannel for "file descriptor" FD. */ +void * +gpgme_get_fdptr (int fd) +{ + return find_channel (fd, 0); +} + + +/* Write the printable version of FD to the buffer BUF of length + BUFLEN. The printable version is the representation on the command + line that the child process expects. */ +int +_gpgme_io_fd2str (char *buf, int buflen, int fd) +{ + TRACE_BEG1 (DEBUG_SYSIO, "_gpgme_io_fd2str", fd, "fd=%d", fd); + TRACE_SUC1 ("syshd=%p", _get_osfhandle (fd)); + return snprintf (buf, buflen, "%ld", (long) _get_osfhandle (fd)); +} + + +void +_gpgme_io_subsystem_init (void) +{ +} + + +static struct +{ + _gpgme_close_notify_handler_t handler; + void *value; +} notify_table[MAX_SLAFD]; + + +int +_gpgme_io_read (int fd, void *buffer, size_t count) +{ + int saved_errno = 0; + gsize nread; + GIOChannel *chan; + GIOStatus status; + TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_read", fd, + "buffer=%p, count=%u", buffer, count); + + chan = find_channel (fd, 0); + if (!chan) + { + TRACE_LOG ("no channel registered"); + errno = EINVAL; + return TRACE_SYSRES (-1); + } + TRACE_LOG1 ("channel %p", chan); + + { + GError *err = NULL; + status = g_io_channel_read_chars (chan, (gchar *) buffer, + count, &nread, &err); + if (err) + { + TRACE_LOG2 ("status %i, err %s", status, err->message); + g_error_free (err); + } + } + + if (status == G_IO_STATUS_EOF) + nread = 0; + else if (status != G_IO_STATUS_NORMAL) + { + TRACE_LOG1 ("status %d", status); + nread = -1; + saved_errno = EIO; + } + + TRACE_LOGBUF (buffer, nread); + + errno = saved_errno; + return TRACE_SYSRES (nread); +} + + +int +_gpgme_io_write (int fd, const void *buffer, size_t count) +{ + int saved_errno = 0; + gsize nwritten; + GIOChannel *chan; + GIOStatus status; + TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_write", fd, + "buffer=%p, count=%u", buffer, count); + TRACE_LOGBUF (buffer, count); + + chan = find_channel (fd, 0); + if (!chan) + { + TRACE_LOG ("fd %d: no channel registered"); + errno = EINVAL; + return -1; + } + + status = g_io_channel_write_chars (chan, (gchar *) buffer, count, + &nwritten, NULL); + if (status != G_IO_STATUS_NORMAL) + { + nwritten = -1; + saved_errno = EIO; + } + errno = saved_errno; + + return TRACE_SYSRES (nwritten); +} + + +int +_gpgme_io_pipe (int filedes[2], int inherit_idx) +{ + GIOChannel *chan; + TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_pipe", filedes, + "inherit_idx=%i (GPGME uses it for %s)", + inherit_idx, inherit_idx ? "reading" : "writing"); + +#define PIPEBUF_SIZE 4096 + if (_pipe (filedes, PIPEBUF_SIZE, O_NOINHERIT | O_BINARY) == -1) + return TRACE_SYSRES (-1); + + /* Make one end inheritable. */ + if (inherit_idx == 0) + { + int new_read; + + new_read = _dup (filedes[0]); + _close (filedes[0]); + filedes[0] = new_read; + + if (new_read < 0) + { + _close (filedes[1]); + return TRACE_SYSRES (-1); + } + } + else if (inherit_idx == 1) + { + int new_write; + + new_write = _dup (filedes[1]); + _close (filedes[1]); + filedes[1] = new_write; + + if (new_write < 0) + { + _close (filedes[0]); + return TRACE_SYSRES (-1); + } + } + + /* Now we have a pipe with the right end inheritable. The other end + should have a giochannel. */ + chan = find_channel (filedes[1 - inherit_idx], 1); + if (!chan) + { + int saved_errno = errno; + _close (filedes[0]); + _close (filedes[1]); + errno = saved_errno; + return TRACE_SYSRES (-1); + } + + return TRACE_SUC5 ("read=0x%x/%p, write=0x%x/%p, channel=%p", + filedes[0], (HANDLE) _get_osfhandle (filedes[0]), + filedes[1], (HANDLE) _get_osfhandle (filedes[1]), + chan); +} + + +int +_gpgme_io_close (int fd) +{ + TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_close", fd); + + if (fd < 0 || fd >= MAX_SLAFD) + { + errno = EBADF; + return TRACE_SYSRES (-1); + } + + /* First call the notify handler. */ + if (notify_table[fd].handler) + { + notify_table[fd].handler (fd, notify_table[fd].value); + notify_table[fd].handler = NULL; + notify_table[fd].value = NULL; + } + + /* Then do the close. */ + if (giochannel_table[fd].chan) + { + if (giochannel_table[fd].primary) + g_io_channel_shutdown (giochannel_table[fd].chan, 1, NULL); + else + _close (fd); + + g_io_channel_unref (giochannel_table[fd].chan); + giochannel_table[fd].chan = NULL; + } + else + _close (fd); + + TRACE_SUC (); + return 0; +} + + +int +_gpgme_io_set_close_notify (int fd, _gpgme_close_notify_handler_t handler, + void *value) +{ + TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_set_close_notify", fd, + "close_handler=%p/%p", handler, value); + + assert (fd != -1); + + if (fd < 0 || fd >= (int) DIM (notify_table)) + { + errno = EINVAL; + return TRACE_SYSRES (-1); + } + notify_table[fd].handler = handler; + notify_table[fd].value = value; + return TRACE_SYSRES (0); +} + + +int +_gpgme_io_set_nonblocking (int fd) +{ + GIOChannel *chan; + GIOStatus status; + + TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_set_nonblocking", fd); + + chan = find_channel (fd, 0); + if (!chan) + { + errno = EIO; + return TRACE_SYSRES (-1); + } + + status = g_io_channel_set_flags (chan, + g_io_channel_get_flags (chan) | + G_IO_FLAG_NONBLOCK, NULL); + if (status != G_IO_STATUS_NORMAL) + { +#if 0 + /* glib 1.9.2 does not implement set_flags and returns an + error. */ + errno = EIO; + return TRACE_SYSRES (-1); +#else + TRACE_LOG1 ("g_io_channel_set_flags failed: status=%d (ignored)", + status); +#endif + } + + return TRACE_SYSRES (0); +} + + +static char * +build_commandline (char **argv) +{ + int i; + int n = 0; + char *buf; + char *p; + + /* We have to quote some things because under Windows the program + parses the commandline and does some unquoting. We enclose the + whole argument in double-quotes, and escape literal double-quotes + as well as backslashes with a backslash. We end up with a + trailing space at the end of the line, but that is harmless. */ + for (i = 0; argv[i]; i++) + { + p = argv[i]; + /* The leading double-quote. */ + n++; + while (*p) + { + /* An extra one for each literal that must be escaped. */ + if (*p == '\\' || *p == '"') + n++; + n++; + p++; + } + /* The trailing double-quote and the delimiter. */ + n += 2; + } + /* And a trailing zero. */ + n++; + + buf = p = malloc (n); + if (!buf) + return NULL; + for (i = 0; argv[i]; i++) + { + char *argvp = argv[i]; + + *(p++) = '"'; + while (*argvp) + { + if (*argvp == '\\' || *argvp == '"') + *(p++) = '\\'; + *(p++) = *(argvp++); + } + *(p++) = '"'; + *(p++) = ' '; + } + *(p++) = 0; + + 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; + /* FIXME. */ + int debug_me = 0; + TRACE_BEG1 (DEBUG_SYSIO, "_gpgme_io_spawn", path, + "path=%s", path); + i = 0; + while (argv[i]) + { + TRACE_LOG2 ("argv[%2i] = %s", i, argv[i]); + i++; + } + + 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 TRACE_SYSRES (-1); + + memset (&si, 0, sizeof si); + si.cb = sizeof (si); + si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; + si.wShowWindow = debug_me? SW_SHOW : SW_HIDE; + 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 = (HANDLE) _get_osfhandle (fd_child_list[i].fd); + TRACE_LOG2 ("using 0x%x/%p for stdin", fd_child_list[i].fd, + _get_osfhandle (fd_child_list[i].fd)); + duped_stdin = 1; + } + else if (fd_child_list[i].dup_to == 1) + { + si.hStdOutput = (HANDLE) _get_osfhandle (fd_child_list[i].fd); + TRACE_LOG2 ("using 0x%x/%p for stdout", fd_child_list[i].fd, + _get_osfhandle (fd_child_list[i].fd)); + } + else if (fd_child_list[i].dup_to == 2) + { + si.hStdError = (HANDLE) _get_osfhandle (fd_child_list[i].fd); + TRACE_LOG2 ("using 0x%x/%p for stderr", fd_child_list[i].fd, + _get_osfhandle (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 ("nul", + GENERIC_READ|GENERIC_WRITE, + FILE_SHARE_READ|FILE_SHARE_WRITE, + &sa, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hnul == INVALID_HANDLE_VALUE) + { + TRACE_LOG1 ("CreateFile (\"nul\") failed: ec=%d", + (int) GetLastError ()); + free (arg_string); + /* FIXME: Should translate the error code. */ + errno = EIO; + return TRACE_SYSRES (-1); + } + /* Make sure that the process has a connected stdin. */ + if (!duped_stdin) + { + si.hStdInput = hnul; + TRACE_LOG1 ("using 0x%x for dummy stdin", (int) hnul); + } + /* We normally don't want all the normal output. */ + if (!duped_stderr) + { + si.hStdError = hnul; + TRACE_LOG1 ("using %d for dummy stderr", (int)hnul); + } + } + + cr_flags |= CREATE_SUSPENDED; + cr_flags |= DETACHED_PROCESS; + if (!CreateProcessA (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 */ + { + TRACE_LOG1 ("CreateProcess failed: ec=%d", (int) GetLastError ()); + free (arg_string); + /* FIXME: Should translate the error code. */ + errno = EIO; + return TRACE_SYSRES (-1); + } + + /* Close the /dev/nul handle if used. */ + if (hnul != INVALID_HANDLE_VALUE) + { + if (!CloseHandle (hnul)) + TRACE_LOG1 ("CloseHandle (hnul) failed: ec=%d (ignored)", + (int) GetLastError ()); + } + + /* Close the other ends of the pipes. */ + for (i = 0; fd_parent_list[i].fd != -1; i++) + _gpgme_io_close (fd_parent_list[i].fd); + + TRACE_LOG4 ("CreateProcess ready: hProcess=%p, hThread=%p, " + "dwProcessID=%d, dwThreadId=%d", + pi.hProcess, pi.hThread, + (int) pi.dwProcessId, (int) pi.dwThreadId); + + if (ResumeThread (pi.hThread) < 0) + TRACE_LOG1 ("ResumeThread failed: ec=%d", (int) GetLastError ()); + + if (!CloseHandle (pi.hThread)) + TRACE_LOG1 ("CloseHandle of thread failed: ec=%d", + (int) GetLastError ()); + + TRACE_SUC1 ("process=%p", pi.hProcess); + + /* We don't need to wait for the process. */ + CloseHandle (pi.hProcess); + + return TRACE_SYSRES (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, int nonblock) +{ + int npollfds; + GPollFD *pollfds; + int *pollfds_map; + int i; + int j; + int any; + int n; + int count; + /* Use a 1s timeout. */ + int timeout = 1000; + void *dbg_help = NULL; + TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_select", fds, + "nfds=%u, nonblock=%u", nfds, nonblock); + + if (nonblock) + timeout = 0; + + pollfds = calloc (nfds, sizeof *pollfds); + if (!pollfds) + return -1; + pollfds_map = calloc (nfds, sizeof *pollfds_map); + if (!pollfds_map) + { + free (pollfds); + return -1; + } + npollfds = 0; + + TRACE_SEQ (dbg_help, "select on [ "); + any = 0; + for (i = 0; i < nfds; i++) + { + GIOChannel *chan = NULL; + + if (fds[i].fd == -1) + continue; + + if ((fds[i].for_read || fds[i].for_write) + && !(chan = find_channel (fds[i].fd, 0))) + { + TRACE_ADD1 (dbg_help, "[BAD0x%x ", fds[i].fd); + TRACE_END (dbg_help, "]"); + assert (!"see log file"); + } + else if (fds[i].for_read ) + { + assert(chan); + g_io_channel_win32_make_pollfd (chan, G_IO_IN, pollfds + npollfds); + pollfds_map[npollfds] = i; + TRACE_ADD2 (dbg_help, "r0x%x<%d> ", fds[i].fd, pollfds[npollfds].fd); + npollfds++; + any = 1; + } + else if (fds[i].for_write) + { + assert(chan); + g_io_channel_win32_make_pollfd (chan, G_IO_OUT, pollfds + npollfds); + pollfds_map[npollfds] = i; + TRACE_ADD2 (dbg_help, "w0x%x<%d> ", fds[i].fd, pollfds[npollfds].fd); + npollfds++; + any = 1; + } + fds[i].signaled = 0; + } + TRACE_END (dbg_help, "]"); + if (!any) + { + count = 0; + goto leave; + } + + + count = g_io_channel_win32_poll (pollfds, npollfds, timeout); + if (count < 0) + { + int saved_errno = errno; + errno = saved_errno; + goto leave; + } + + TRACE_SEQ (dbg_help, "select OK [ "); + if (TRACE_ENABLED (dbg_help)) + { + for (i = 0; i < npollfds; i++) + { + if ((pollfds[i].revents & G_IO_IN)) + TRACE_ADD1 (dbg_help, "r0x%x ", fds[pollfds_map[i]].fd); + if ((pollfds[i].revents & G_IO_OUT)) + TRACE_ADD1 (dbg_help, "w0x%x ", fds[pollfds_map[i]].fd); + } + TRACE_END (dbg_help, "]"); + } + + /* COUNT is used to stop the lop as soon as possible. */ + for (n = count, i = 0; i < npollfds && n; i++) + { + j = pollfds_map[i]; + assert (j >= 0 && j < nfds); + if (fds[j].fd == -1) + ; + else if (fds[j].for_read) + { + if ((pollfds[i].revents & G_IO_IN)) + { + fds[j].signaled = 1; + n--; + } + } + else if (fds[j].for_write) + { + if ((pollfds[i].revents & G_IO_OUT)) + { + fds[j].signaled = 1; + n--; + } + } + } + +leave: + free (pollfds); + free (pollfds_map); + return TRACE_SYSRES (count); +} + + +int +_gpgme_io_dup (int fd) +{ + int newfd; + GIOChannel *chan; + + TRACE_BEG1 (DEBUG_SYSIO, "_gpgme_io_dup", fd, "dup (%d)", fd); + + newfd = _dup (fd); + if (newfd == -1) + return TRACE_SYSRES (-1); + if (newfd < 0 || newfd >= MAX_SLAFD) + { + /* New FD won't fit into our table. */ + _close (newfd); + errno = EIO; + return TRACE_SYSRES (-1); + } + assert (giochannel_table[newfd].chan == NULL); + + chan = find_channel (fd, 0); + assert (chan); + + g_io_channel_ref (chan); + giochannel_table[newfd].chan = chan; + giochannel_table[newfd].primary = 0; + + return TRACE_SYSRES (newfd); +} diff --git a/tags/gpgme-1.1.6/gpgme/w32-io.c b/tags/gpgme-1.1.6/gpgme/w32-io.c new file mode 100644 index 0000000..c4d2a1b --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/w32-io.c @@ -0,0 +1,1423 @@ +/* w32-io.c - W32 API I/O functions. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "sema.h" +#include "priv-io.h" +#include "debug.h" + +/* 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)) + +#define READBUF_SIZE 4096 +#define WRITEBUF_SIZE 4096 +#define PIPEBUF_SIZE 4096 +#define MAX_READERS 20 +#define MAX_WRITERS 20 + +static struct +{ + int inuse; + int fd; + _gpgme_close_notify_handler_t handler; + void *value; +} notify_table[256]; +DEFINE_STATIC_LOCK (notify_table_lock); + + +struct reader_context_s +{ + HANDLE file_hd; + HANDLE thread_hd; + int refcount; + + DECLARE_LOCK (mutex); + + int stop_me; + int eof; + int eof_shortcut; + int error; + int error_code; + + /* This is manually reset. */ + HANDLE have_data_ev; + /* This is automatically reset. */ + HANDLE have_space_ev; + HANDLE stopped; + size_t readpos, writepos; + char buffer[READBUF_SIZE]; +}; + + +static struct +{ + volatile int used; + int fd; + struct reader_context_s *context; +} reader_table[MAX_READERS]; +static int reader_table_size= MAX_READERS; +DEFINE_STATIC_LOCK (reader_table_lock); + + +struct writer_context_s +{ + HANDLE file_hd; + HANDLE thread_hd; + int refcount; + + DECLARE_LOCK (mutex); + + int stop_me; + int error; + int error_code; + + /* This is manually reset. */ + HANDLE have_data; + HANDLE is_empty; + HANDLE stopped; + size_t nbytes; + char buffer[WRITEBUF_SIZE]; +}; + + +static struct +{ + volatile int used; + int fd; + struct writer_context_s *context; +} writer_table[MAX_WRITERS]; +static int writer_table_size= MAX_WRITERS; +DEFINE_STATIC_LOCK (writer_table_lock); + + +static int +get_desired_thread_priority (void) +{ + int value; + + if (!_gpgme_get_conf_int ("IOThreadPriority", &value)) + { + value = THREAD_PRIORITY_HIGHEST; + TRACE1 (DEBUG_SYSIO, "gpgme:get_desired_thread_priority", 0, + "%d (default)", value); + } + else + { + TRACE1 (DEBUG_SYSIO, "gpgme:get_desired_thread_priority", 0, + "%d (configured)", value); + } + return value; +} + + +static HANDLE +set_synchronize (HANDLE hd) +{ + HANDLE new_hd; + + /* For NT we have to set the sync flag. It seems that the only way + to do it is by duplicating the handle. Tsss... */ + if (!DuplicateHandle (GetCurrentProcess (), hd, + GetCurrentProcess (), &new_hd, + EVENT_MODIFY_STATE | SYNCHRONIZE, FALSE, 0)) + { + TRACE1 (DEBUG_SYSIO, "gpgme:set_synchronize", hd, + "DuplicateHandle failed: ec=%d", (int) GetLastError ()); + /* FIXME: Should translate the error code. */ + errno = EIO; + return INVALID_HANDLE_VALUE; + } + + CloseHandle (hd); + return new_hd; +} + + +static DWORD CALLBACK +reader (void *arg) +{ + struct reader_context_s *ctx = arg; + int nbytes; + DWORD nread; + TRACE_BEG1 (DEBUG_SYSIO, "gpgme:reader", ctx->file_hd, + "thread=%p", ctx->thread_hd); + + for (;;) + { + LOCK (ctx->mutex); + /* Leave a 1 byte gap so that we can see whether it is empty or + full. */ + if ((ctx->writepos + 1) % READBUF_SIZE == ctx->readpos) + { + /* Wait for space. */ + if (!ResetEvent (ctx->have_space_ev)) + TRACE_LOG1 ("ResetEvent failed: ec=%d", (int) GetLastError ()); + UNLOCK (ctx->mutex); + TRACE_LOG ("waiting for space"); + WaitForSingleObject (ctx->have_space_ev, INFINITE); + TRACE_LOG ("got space"); + LOCK (ctx->mutex); + } + if (ctx->stop_me) + { + UNLOCK (ctx->mutex); + break; + } + nbytes = (ctx->readpos + READBUF_SIZE + - ctx->writepos - 1) % READBUF_SIZE; + if (nbytes > READBUF_SIZE - ctx->writepos) + nbytes = READBUF_SIZE - ctx->writepos; + UNLOCK (ctx->mutex); + + TRACE_LOG1 ("reading %d bytes", nbytes); + if (!ReadFile (ctx->file_hd, + ctx->buffer + ctx->writepos, nbytes, &nread, NULL)) + { + ctx->error_code = (int) GetLastError (); + if (ctx->error_code == ERROR_BROKEN_PIPE) + { + ctx->eof = 1; + TRACE_LOG ("got EOF (broken pipe)"); + } + else + { + ctx->error = 1; + TRACE_LOG1 ("read error: ec=%d", ctx->error_code); + } + break; + } + if (!nread) + { + ctx->eof = 1; + TRACE_LOG ("got eof"); + break; + } + TRACE_LOG1 ("got %u bytes", nread); + + LOCK (ctx->mutex); + if (ctx->stop_me) + { + UNLOCK (ctx->mutex); + break; + } + ctx->writepos = (ctx->writepos + nread) % READBUF_SIZE; + if (!SetEvent (ctx->have_data_ev)) + TRACE_LOG1 ("SetEvent failed: ec=%d", (int) GetLastError ()); + UNLOCK (ctx->mutex); + } + /* Indicate that we have an error or EOF. */ + if (!SetEvent (ctx->have_data_ev)) + TRACE_LOG1 ("SetEvent failed: ec=%d", (int) GetLastError ()); + SetEvent (ctx->stopped); + + return TRACE_SUC (); +} + + +static struct reader_context_s * +create_reader (HANDLE fd) +{ + struct reader_context_s *ctx; + SECURITY_ATTRIBUTES sec_attr; + DWORD tid; + + TRACE_BEG (DEBUG_SYSIO, "gpgme:create_reader", fd); + + memset (&sec_attr, 0, sizeof sec_attr); + sec_attr.nLength = sizeof sec_attr; + sec_attr.bInheritHandle = FALSE; + + ctx = calloc (1, sizeof *ctx); + if (!ctx) + { + TRACE_SYSERR (errno); + return NULL; + } + + ctx->file_hd = fd; + ctx->refcount = 1; + ctx->have_data_ev = CreateEvent (&sec_attr, TRUE, FALSE, NULL); + if (ctx->have_data_ev) + ctx->have_space_ev = CreateEvent (&sec_attr, FALSE, TRUE, NULL); + if (ctx->have_space_ev) + ctx->stopped = CreateEvent (&sec_attr, TRUE, FALSE, NULL); + if (!ctx->have_data_ev || !ctx->have_space_ev || !ctx->stopped) + { + TRACE_LOG1 ("CreateEvent failed: ec=%d", (int) GetLastError ()); + if (ctx->have_data_ev) + CloseHandle (ctx->have_data_ev); + if (ctx->have_space_ev) + CloseHandle (ctx->have_space_ev); + if (ctx->stopped) + CloseHandle (ctx->stopped); + free (ctx); + /* FIXME: Translate the error code. */ + TRACE_SYSERR (EIO); + return NULL; + } + + ctx->have_data_ev = set_synchronize (ctx->have_data_ev); + INIT_LOCK (ctx->mutex); + + ctx->thread_hd = CreateThread (&sec_attr, 0, reader, ctx, 0, &tid); + if (!ctx->thread_hd) + { + TRACE_LOG1 ("CreateThread failed: ec=%d", (int) GetLastError ()); + DESTROY_LOCK (ctx->mutex); + if (ctx->have_data_ev) + CloseHandle (ctx->have_data_ev); + if (ctx->have_space_ev) + CloseHandle (ctx->have_space_ev); + if (ctx->stopped) + CloseHandle (ctx->stopped); + free (ctx); + TRACE_SYSERR (EIO); + return NULL; + } + else + { + /* We set the priority of the thread higher because we know that + it only runs for a short time. This greatly helps to + increase the performance of the I/O. */ + SetThreadPriority (ctx->thread_hd, get_desired_thread_priority ()); + } + + TRACE_SUC (); + return ctx; +} + + +static void +destroy_reader (struct reader_context_s *ctx) +{ + LOCK (ctx->mutex); + ctx->refcount--; + if (ctx->refcount != 0) + { + UNLOCK (ctx->mutex); + return; + } + ctx->stop_me = 1; + if (ctx->have_space_ev) + SetEvent (ctx->have_space_ev); + UNLOCK (ctx->mutex); + + TRACE1 (DEBUG_SYSIO, "gpgme:destroy_reader", ctx->file_hd, + "waiting for termination of thread %p", ctx->thread_hd); + WaitForSingleObject (ctx->stopped, INFINITE); + TRACE1 (DEBUG_SYSIO, "gpgme:destroy_reader", ctx->file_hd, + "thread %p has terminated", ctx->thread_hd); + + if (ctx->stopped) + CloseHandle (ctx->stopped); + if (ctx->have_data_ev) + CloseHandle (ctx->have_data_ev); + if (ctx->have_space_ev) + CloseHandle (ctx->have_space_ev); + CloseHandle (ctx->thread_hd); + DESTROY_LOCK (ctx->mutex); + free (ctx); +} + + +/* Find a reader context or create a new one. Note that the reader + context will last until a _gpgme_io_close. */ +static struct reader_context_s * +find_reader (int fd, int start_it) +{ + struct reader_context_s *rd = NULL; + int i; + + LOCK (reader_table_lock); + for (i = 0; i < reader_table_size; i++) + if (reader_table[i].used && reader_table[i].fd == fd) + rd = reader_table[i].context; + + if (rd || !start_it) + { + UNLOCK (reader_table_lock); + return rd; + } + + for (i = 0; i < reader_table_size; i++) + if (!reader_table[i].used) + break; + + if (i != reader_table_size) + { + rd = create_reader (fd_to_handle (fd)); + reader_table[i].fd = fd; + reader_table[i].context = rd; + reader_table[i].used = 1; + } + + UNLOCK (reader_table_lock); + return rd; +} + + +static void +kill_reader (int fd) +{ + int i; + + LOCK (reader_table_lock); + for (i = 0; i < reader_table_size; i++) + { + if (reader_table[i].used && reader_table[i].fd == fd) + { + destroy_reader (reader_table[i].context); + reader_table[i].context = NULL; + reader_table[i].used = 0; + break; + } + } + UNLOCK (reader_table_lock); +} + + +int +_gpgme_io_read (int fd, void *buffer, size_t count) +{ + int nread; + struct reader_context_s *ctx; + TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_read", fd, + "buffer=%p, count=%u", buffer, count); + + ctx = find_reader (fd, 1); + if (!ctx) + { + errno = EBADF; + return TRACE_SYSRES (-1); + } + if (ctx->eof_shortcut) + return TRACE_SYSRES (0); + + LOCK (ctx->mutex); + if (ctx->readpos == ctx->writepos && !ctx->error) + { + /* No data available. */ + UNLOCK (ctx->mutex); + TRACE_LOG1 ("waiting for data from thread %p", ctx->thread_hd); + WaitForSingleObject (ctx->have_data_ev, INFINITE); + TRACE_LOG1 ("data from thread %p available", ctx->thread_hd); + LOCK (ctx->mutex); + } + + if (ctx->readpos == ctx->writepos || ctx->error) + { + UNLOCK (ctx->mutex); + ctx->eof_shortcut = 1; + if (ctx->eof) + return TRACE_SYSRES (0); + if (!ctx->error) + { + TRACE_LOG ("EOF but ctx->eof flag not set"); + return 0; + } + errno = ctx->error_code; + return TRACE_SYSRES (-1); + } + + nread = ctx->readpos < ctx->writepos + ? ctx->writepos - ctx->readpos + : READBUF_SIZE - ctx->readpos; + if (nread > count) + nread = count; + memcpy (buffer, ctx->buffer + ctx->readpos, nread); + ctx->readpos = (ctx->readpos + nread) % READBUF_SIZE; + if (ctx->readpos == ctx->writepos && !ctx->eof) + { + if (!ResetEvent (ctx->have_data_ev)) + { + TRACE_LOG1 ("ResetEvent failed: ec=%d", (int) GetLastError ()); + UNLOCK (ctx->mutex); + /* FIXME: Should translate the error code. */ + errno = EIO; + return TRACE_SYSRES (-1); + } + } + if (!SetEvent (ctx->have_space_ev)) + { + TRACE_LOG1 ("SetEvent failed: ec=%d", (int) GetLastError ()); + UNLOCK (ctx->mutex); + /* FIXME: Should translate the error code. */ + errno = EIO; + return TRACE_SYSRES (-1); + } + UNLOCK (ctx->mutex); + + TRACE_LOGBUF (buffer, nread); + return TRACE_SYSRES (nread); +} + + +/* The writer does use a simple buffering strategy so that we are + informed about write errors as soon as possible (i. e. with the the + next call to the write function. */ +static DWORD CALLBACK +writer (void *arg) +{ + struct writer_context_s *ctx = arg; + DWORD nwritten; + TRACE_BEG1 (DEBUG_SYSIO, "gpgme:writer", ctx->file_hd, + "thread=%p", ctx->thread_hd); + + for (;;) + { + LOCK (ctx->mutex); + if (ctx->stop_me) + { + UNLOCK (ctx->mutex); + break; + } + if (!ctx->nbytes) + { + if (!SetEvent (ctx->is_empty)) + TRACE_LOG1 ("SetEvent failed: ec=%d", (int) GetLastError ()); + if (!ResetEvent (ctx->have_data)) + TRACE_LOG1 ("ResetEvent failed: ec=%d", (int) GetLastError ()); + UNLOCK (ctx->mutex); + TRACE_LOG ("idle"); + WaitForSingleObject (ctx->have_data, INFINITE); + TRACE_LOG ("got data to send"); + LOCK (ctx->mutex); + } + if (ctx->stop_me) + { + UNLOCK (ctx->mutex); + break; + } + UNLOCK (ctx->mutex); + + TRACE_LOG1 ("writing %d bytes", ctx->nbytes); + /* Note that CTX->nbytes is not zero at this point, because + _gpgme_io_write always writes at least 1 byte before waking + us up, unless CTX->stop_me is true, which we catch above. */ + if (!WriteFile (ctx->file_hd, ctx->buffer, + ctx->nbytes, &nwritten, NULL)) + { + ctx->error_code = (int) GetLastError (); + ctx->error = 1; + TRACE_LOG1 ("write error: ec=%d", ctx->error_code); + break; + } + TRACE_LOG1 ("wrote %d bytes", (int) nwritten); + + LOCK (ctx->mutex); + ctx->nbytes -= nwritten; + UNLOCK (ctx->mutex); + } + /* Indicate that we have an error. */ + if (!SetEvent (ctx->is_empty)) + TRACE_LOG1 ("SetEvent failed: ec=%d", (int) GetLastError ()); + SetEvent (ctx->stopped); + + return TRACE_SUC (); +} + + +static struct writer_context_s * +create_writer (HANDLE fd) +{ + struct writer_context_s *ctx; + SECURITY_ATTRIBUTES sec_attr; + DWORD tid; + + TRACE_BEG (DEBUG_SYSIO, "gpgme:create_writer", fd); + + memset (&sec_attr, 0, sizeof sec_attr); + sec_attr.nLength = sizeof sec_attr; + sec_attr.bInheritHandle = FALSE; + + ctx = calloc (1, sizeof *ctx); + if (!ctx) + { + TRACE_SYSERR (errno); + return NULL; + } + + ctx->file_hd = fd; + ctx->refcount = 1; + ctx->have_data = CreateEvent (&sec_attr, TRUE, FALSE, NULL); + if (ctx->have_data) + ctx->is_empty = CreateEvent (&sec_attr, TRUE, TRUE, NULL); + if (ctx->is_empty) + ctx->stopped = CreateEvent (&sec_attr, TRUE, FALSE, NULL); + if (!ctx->have_data || !ctx->is_empty || !ctx->stopped) + { + TRACE_LOG1 ("CreateEvent failed: ec=%d", (int) GetLastError ()); + if (ctx->have_data) + CloseHandle (ctx->have_data); + if (ctx->is_empty) + CloseHandle (ctx->is_empty); + if (ctx->stopped) + CloseHandle (ctx->stopped); + free (ctx); + /* FIXME: Translate the error code. */ + TRACE_SYSERR (EIO); + return NULL; + } + + ctx->is_empty = set_synchronize (ctx->is_empty); + INIT_LOCK (ctx->mutex); + + ctx->thread_hd = CreateThread (&sec_attr, 0, writer, ctx, 0, &tid ); + if (!ctx->thread_hd) + { + TRACE_LOG1 ("CreateThread failed: ec=%d", (int) GetLastError ()); + DESTROY_LOCK (ctx->mutex); + if (ctx->have_data) + CloseHandle (ctx->have_data); + if (ctx->is_empty) + CloseHandle (ctx->is_empty); + if (ctx->stopped) + CloseHandle (ctx->stopped); + free (ctx); + TRACE_SYSERR (EIO); + return NULL; + } + else + { + /* We set the priority of the thread higher because we know + that it only runs for a short time. This greatly helps to + increase the performance of the I/O. */ + SetThreadPriority (ctx->thread_hd, get_desired_thread_priority ()); + } + + TRACE_SUC (); + return ctx; +} + +static void +destroy_writer (struct writer_context_s *ctx) +{ + LOCK (ctx->mutex); + ctx->refcount--; + if (ctx->refcount != 0) + { + UNLOCK (ctx->mutex); + return; + } + ctx->stop_me = 1; + if (ctx->have_data) + SetEvent (ctx->have_data); + UNLOCK (ctx->mutex); + + TRACE1 (DEBUG_SYSIO, "gpgme:destroy_writer", ctx->file_hd, + "waiting for termination of thread %p", ctx->thread_hd); + WaitForSingleObject (ctx->stopped, INFINITE); + TRACE1 (DEBUG_SYSIO, "gpgme:destroy_writer", ctx->file_hd, + "thread %p has terminated", ctx->thread_hd); + + if (ctx->stopped) + CloseHandle (ctx->stopped); + if (ctx->have_data) + CloseHandle (ctx->have_data); + if (ctx->is_empty) + CloseHandle (ctx->is_empty); + CloseHandle (ctx->thread_hd); + DESTROY_LOCK (ctx->mutex); + free (ctx); +} + + +/* Find a writer context or create a new one. Note that the writer + context will last until a _gpgme_io_close. */ +static struct writer_context_s * +find_writer (int fd, int start_it) +{ + struct writer_context_s *wt = NULL; + int i; + + LOCK (writer_table_lock); + for (i = 0; i < writer_table_size; i++) + if (writer_table[i].used && writer_table[i].fd == fd) + wt = writer_table[i].context; + + if (wt || !start_it) + { + UNLOCK (writer_table_lock); + return wt; + } + + for (i = 0; i < writer_table_size; i++) + if (!writer_table[i].used) + break; + + if (i != writer_table_size) + { + wt = create_writer (fd_to_handle (fd)); + writer_table[i].fd = fd; + writer_table[i].context = wt; + writer_table[i].used = 1; + } + + UNLOCK (writer_table_lock); + return wt; +} + + +static void +kill_writer (int fd) +{ + int i; + + LOCK (writer_table_lock); + for (i = 0; i < writer_table_size; i++) + { + if (writer_table[i].used && writer_table[i].fd == fd) + { + destroy_writer (writer_table[i].context); + writer_table[i].context = NULL; + writer_table[i].used = 0; + break; + } + } + UNLOCK (writer_table_lock); +} + + +int +_gpgme_io_write (int fd, const void *buffer, size_t count) +{ + struct writer_context_s *ctx; + TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_write", fd, + "buffer=%p, count=%u", buffer, count); + TRACE_LOGBUF (buffer, count); + + if (count == 0) + return TRACE_SYSRES (0); + + ctx = find_writer (fd, 1); + if (!ctx) + return TRACE_SYSRES (-1); + + LOCK (ctx->mutex); + if (!ctx->error && ctx->nbytes) + { + /* Bytes are pending for send. */ + + /* Reset the is_empty event. Better safe than sorry. */ + if (!ResetEvent (ctx->is_empty)) + { + TRACE_LOG1 ("ResetEvent failed: ec=%d", (int) GetLastError ()); + UNLOCK (ctx->mutex); + /* FIXME: Should translate the error code. */ + errno = EIO; + return TRACE_SYSRES (-1); + } + UNLOCK (ctx->mutex); + TRACE_LOG1 ("waiting for empty buffer in thread %p", ctx->thread_hd); + WaitForSingleObject (ctx->is_empty, INFINITE); + TRACE_LOG1 ("thread %p buffer is empty", ctx->thread_hd); + LOCK (ctx->mutex); + } + + if (ctx->error) + { + UNLOCK (ctx->mutex); + if (ctx->error_code == ERROR_NO_DATA) + errno = EPIPE; + else + errno = EIO; + return TRACE_SYSRES (-1); + } + + /* If no error occured, the number of bytes in the buffer must be + zero. */ + assert (!ctx->nbytes); + + if (count > WRITEBUF_SIZE) + count = WRITEBUF_SIZE; + memcpy (ctx->buffer, buffer, count); + ctx->nbytes = count; + + /* We have to reset the is_empty event early, because it is also + used by the select() implementation to probe the channel. */ + if (!ResetEvent (ctx->is_empty)) + { + TRACE_LOG1 ("ResetEvent failed: ec=%d", (int) GetLastError ()); + UNLOCK (ctx->mutex); + /* FIXME: Should translate the error code. */ + errno = EIO; + return TRACE_SYSRES (-1); + } + if (!SetEvent (ctx->have_data)) + { + TRACE_LOG1 ("SetEvent failed: ec=%d", (int) GetLastError ()); + UNLOCK (ctx->mutex); + /* FIXME: Should translate the error code. */ + errno = EIO; + return TRACE_SYSRES (-1); + } + UNLOCK (ctx->mutex); + + return TRACE_SYSRES ((int) count); +} + + +int +_gpgme_io_pipe (int filedes[2], int inherit_idx) +{ + HANDLE rh; + HANDLE wh; + SECURITY_ATTRIBUTES sec_attr; + TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_pipe", filedes, + "inherit_idx=%i (GPGME uses it for %s)", + inherit_idx, inherit_idx ? "reading" : "writing"); + + memset (&sec_attr, 0, sizeof (sec_attr)); + sec_attr.nLength = sizeof (sec_attr); + sec_attr.bInheritHandle = FALSE; + + if (!CreatePipe (&rh, &wh, &sec_attr, PIPEBUF_SIZE)) + { + TRACE_LOG1 ("CreatePipe failed: ec=%d", (int) GetLastError ()); + /* FIXME: Should translate the error code. */ + errno = EIO; + return TRACE_SYSRES (-1); + } + + /* Make one end inheritable. */ + if (inherit_idx == 0) + { + HANDLE hd; + if (!DuplicateHandle (GetCurrentProcess(), rh, + GetCurrentProcess(), &hd, 0, + TRUE, DUPLICATE_SAME_ACCESS)) + { + TRACE_LOG1 ("DuplicateHandle failed: ec=%d", + (int) GetLastError ()); + CloseHandle (rh); + CloseHandle (wh); + /* FIXME: Should translate the error code. */ + errno = EIO; + return TRACE_SYSRES (-1); + } + CloseHandle (rh); + rh = hd; + } + else if (inherit_idx == 1) + { + HANDLE hd; + if (!DuplicateHandle( GetCurrentProcess(), wh, + GetCurrentProcess(), &hd, 0, + TRUE, DUPLICATE_SAME_ACCESS)) + { + TRACE_LOG1 ("DuplicateHandle failed: ec=%d", + (int) GetLastError ()); + CloseHandle (rh); + CloseHandle (wh); + /* FIXME: Should translate the error code. */ + errno = EIO; + return TRACE_SYSRES (-1); + } + CloseHandle (wh); + wh = hd; + } + + filedes[0] = handle_to_fd (rh); + filedes[1] = handle_to_fd (wh); + return TRACE_SUC2 ("read=%p, write=%p", rh, wh); +} + + +int +_gpgme_io_close (int fd) +{ + int i; + _gpgme_close_notify_handler_t handler = NULL; + void *value = NULL; + TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_close", fd); + + if (fd == -1) + { + errno = EBADF; + return TRACE_SYSRES (-1); + } + + kill_reader (fd); + kill_writer (fd); + LOCK (notify_table_lock); + for (i = 0; i < DIM (notify_table); i++) + { + if (notify_table[i].inuse && notify_table[i].fd == fd) + { + handler = notify_table[i].handler; + value = notify_table[i].value; + notify_table[i].handler = NULL; + notify_table[i].value = NULL; + notify_table[i].inuse = 0; + break; + } + } + UNLOCK (notify_table_lock); + if (handler) + handler (fd, value); + + if (!CloseHandle (fd_to_handle (fd))) + { + TRACE_LOG1 ("CloseHandle failed: ec=%d", (int) GetLastError ()); + /* FIXME: Should translate the error code. */ + errno = EIO; + return TRACE_SYSRES (-1); + } + + return TRACE_SYSRES (0); +} + + +int +_gpgme_io_set_close_notify (int fd, _gpgme_close_notify_handler_t handler, + void *value) +{ + int i; + TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_set_close_notify", fd, + "close_handler=%p/%p", handler, value); + + assert (fd != -1); + + LOCK (notify_table_lock); + for (i=0; i < DIM (notify_table); i++) + if (notify_table[i].inuse && notify_table[i].fd == fd) + break; + if (i == DIM (notify_table)) + for (i = 0; i < DIM (notify_table); i++) + if (!notify_table[i].inuse) + break; + if (i == DIM (notify_table)) + { + UNLOCK (notify_table_lock); + errno = EINVAL; + return TRACE_SYSRES (-1); + } + notify_table[i].fd = fd; + notify_table[i].handler = handler; + notify_table[i].value = value; + notify_table[i].inuse = 1; + UNLOCK (notify_table_lock); + return TRACE_SYSRES (0); +} + + +int +_gpgme_io_set_nonblocking (int fd) +{ + TRACE (DEBUG_SYSIO, "_gpgme_io_set_nonblocking", fd); + return 0; +} + + +static char * +build_commandline (char **argv) +{ + int i; + int n = 0; + char *buf; + char *p; + + /* We have to quote some things because under Windows the program + parses the commandline and does some unquoting. We enclose the + whole argument in double-quotes, and escape literal double-quotes + as well as backslashes with a backslash. We end up with a + trailing space at the end of the line, but that is harmless. */ + for (i = 0; argv[i]; i++) + { + p = argv[i]; + /* The leading double-quote. */ + n++; + while (*p) + { + /* An extra one for each literal that must be escaped. */ + if (*p == '\\' || *p == '"') + n++; + n++; + p++; + } + /* The trailing double-quote and the delimiter. */ + n += 2; + } + /* And a trailing zero. */ + n++; + + buf = p = malloc (n); + if (!buf) + return NULL; + for (i = 0; argv[i]; i++) + { + char *argvp = argv[i]; + + *(p++) = '"'; + while (*argvp) + { + if (*argvp == '\\' || *argvp == '"') + *(p++) = '\\'; + *(p++) = *(argvp++); + } + *(p++) = '"'; + *(p++) = ' '; + } + *(p++) = 0; + + 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; + /* FIXME. */ + int debug_me = 0; + TRACE_BEG1 (DEBUG_SYSIO, "_gpgme_io_spawn", path, + "path=%s", path); + i = 0; + while (argv[i]) + { + TRACE_LOG2 ("argv[%2i] = %s", i, argv[i]); + i++; + } + + 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 TRACE_SYSRES (-1); + + memset (&si, 0, sizeof si); + si.cb = sizeof (si); + si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; + si.wShowWindow = debug_me ? SW_SHOW : SW_HIDE; + 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); + TRACE_LOG1 ("using 0x%x for stdin", 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); + TRACE_LOG1 ("using 0x%x for stdout", fd_child_list[i].fd); + } + else if (fd_child_list[i].dup_to == 2) + { + si.hStdError = fd_to_handle (fd_child_list[i].fd); + TRACE_LOG1 ("using 0x%x for stderr", 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 ("nul", + GENERIC_READ|GENERIC_WRITE, + FILE_SHARE_READ|FILE_SHARE_WRITE, + &sa, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hnul == INVALID_HANDLE_VALUE) + { + TRACE_LOG1 ("CreateFile (\"nul\") failed: ec=%d", + (int) GetLastError ()); + free (arg_string); + /* FIXME: Should translate the error code. */ + errno = EIO; + return TRACE_SYSRES (-1); + } + /* Make sure that the process has a connected stdin. */ + if (!duped_stdin) + { + si.hStdInput = hnul; + TRACE_LOG1 ("using 0x%x for dummy stdin", (int) hnul); + } + /* We normally don't want all the normal output. */ + if (!duped_stderr) + { + si.hStdError = hnul; + TRACE_LOG1 ("using 0x%x for dummy stderr", (int) hnul); + } + } + + cr_flags |= CREATE_SUSPENDED; + cr_flags |= DETACHED_PROCESS; + if (!CreateProcessA (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 */ + { + TRACE_LOG1 ("CreateProcess failed: ec=%d", (int) GetLastError ()); + free (arg_string); + /* FIXME: Should translate the error code. */ + errno = EIO; + return TRACE_SYSRES (-1); + } + + /* Close the /dev/nul handle if used. */ + if (hnul != INVALID_HANDLE_VALUE) + { + if (!CloseHandle (hnul)) + TRACE_LOG1 ("CloseHandle (hnul) failed: ec=%d (ignored)", + (int) GetLastError ()); + } + + /* Close the other ends of the pipes. */ + for (i = 0; fd_parent_list[i].fd != -1; i++) + _gpgme_io_close (fd_parent_list[i].fd); + + TRACE_LOG4 ("CreateProcess ready: hProcess=%p, hThread=%p, " + "dwProcessID=%d, dwThreadId=%d", + pi.hProcess, pi.hThread, + (int) pi.dwProcessId, (int) pi.dwThreadId); + + if (ResumeThread (pi.hThread) < 0) + TRACE_LOG1 ("ResumeThread failed: ec=%d", (int) GetLastError ()); + + if (!CloseHandle (pi.hThread)) + TRACE_LOG1 ("CloseHandle of thread failed: ec=%d", + (int) GetLastError ()); + + TRACE_SUC1 ("process=%p", pi.hProcess); + + /* We don't need to wait for the process. */ + CloseHandle (pi.hProcess); + + return TRACE_SYSRES (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, int nonblock) +{ + HANDLE waitbuf[MAXIMUM_WAIT_OBJECTS]; + int waitidx[MAXIMUM_WAIT_OBJECTS]; + int code; + int nwait; + int i; + int any; + int count; + void *dbg_help; + TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_select", fds, + "nfds=%u, nonblock=%u", nfds, nonblock); + + restart: + TRACE_SEQ (dbg_help, "select on [ "); + any = 0; + nwait = 0; + count = 0; + for (i=0; i < nfds; i++) + { + if (fds[i].fd == -1) + continue; + fds[i].signaled = 0; + if (fds[i].for_read || fds[i].for_write) + { + if (fds[i].for_read) + { + struct reader_context_s *ctx = find_reader (fds[i].fd,1); + + if (!ctx) + TRACE_LOG1 ("error: no reader for FD 0x%x (ignored)", + fds[i].fd); + else + { + if (nwait >= DIM (waitbuf)) + { + TRACE_END (dbg_help, "oops ]"); + TRACE_LOG ("Too many objects for WFMO!"); + /* FIXME: Should translate the error code. */ + errno = EIO; + return TRACE_SYSRES (-1); + } + waitidx[nwait] = i; + waitbuf[nwait++] = ctx->have_data_ev; + } + TRACE_ADD1 (dbg_help, "r0x%x ", fds[i].fd); + any = 1; + } + else if (fds[i].for_write) + { + struct writer_context_s *ctx = find_writer (fds[i].fd,1); + + if (!ctx) + TRACE_LOG1 ("error: no writer for FD 0x%x (ignored)", + fds[i].fd); + else + { + if (nwait >= DIM (waitbuf)) + { + TRACE_END (dbg_help, "oops ]"); + TRACE_LOG ("Too many objects for WFMO!"); + /* FIXME: Should translate the error code. */ + errno = EIO; + return TRACE_SYSRES (-1); + } + waitidx[nwait] = i; + waitbuf[nwait++] = ctx->is_empty; + } + TRACE_ADD1 (dbg_help, "w0x%x ", fds[i].fd); + any = 1; + } + } + } + TRACE_END (dbg_help, "]"); + if (!any) + return TRACE_SYSRES (0); + + code = WaitForMultipleObjects (nwait, waitbuf, 0, nonblock ? 0 : 1000); + 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], 0) == WAIT_OBJECT_0) + { + assert (waitidx[i] >=0 && waitidx[i] < nfds); + fds[waitidx[i]].signaled = 1; + any = 1; + count++; + } + } + if (!any) + { + TRACE_LOG ("no signaled objects found after WFMO"); + count = -1; + } + } + else if (code == WAIT_TIMEOUT) + TRACE_LOG ("WFMO timed out"); + else if (code == WAIT_FAILED) + { + int le = (int) GetLastError (); + if (le == ERROR_INVALID_HANDLE) + { + int k; + int j = handle_to_fd (waitbuf[i]); + + TRACE_LOG1 ("WFMO invalid handle %d removed", j); + for (k = 0 ; k < nfds; k++) + { + if (fds[k].fd == j) + { + fds[k].for_read = fds[k].for_write = 0; + goto restart; + } + } + TRACE_LOG (" oops, or not???"); + } + TRACE_LOG1 ("WFMO failed: %d", le); + count = -1; + } + else + { + TRACE_LOG1 ("WFMO returned %d", code); + count = -1; + } + + if (count > 0) + { + TRACE_SEQ (dbg_help, "select OK [ "); + for (i = 0; i < nfds; i++) + { + if (fds[i].fd == -1) + continue; + if ((fds[i].for_read || fds[i].for_write) && fds[i].signaled) + TRACE_ADD2 (dbg_help, "%c0x%x ", + fds[i].for_read ? 'r' : 'w', fds[i].fd); + } + TRACE_END (dbg_help, "]"); + } + + if (count < 0) + { + /* FIXME: Should determine a proper error code. */ + errno = EIO; + } + + return TRACE_SYSRES (count); +} + + +void +_gpgme_io_subsystem_init (void) +{ + /* Nothing to do. */ +} + + +/* Write the printable version of FD to the buffer BUF of length + BUFLEN. The printable version is the representation on the command + line that the child process expects. */ +int +_gpgme_io_fd2str (char *buf, int buflen, int fd) +{ + return snprintf (buf, buflen, "%d", fd); +} + + +int +_gpgme_io_dup (int fd) +{ + HANDLE handle = fd_to_handle (fd); + HANDLE new_handle = fd_to_handle (fd); + int i; + struct reader_context_s *rd_ctx; + struct writer_context_s *wt_ctx; + + TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_dup", fd); + + if (!DuplicateHandle (GetCurrentProcess(), handle, + GetCurrentProcess(), &new_handle, + 0, FALSE, DUPLICATE_SAME_ACCESS)) + { + TRACE_LOG1 ("DuplicateHandle failed: ec=%d\n", (int) GetLastError ()); + /* FIXME: Translate error code. */ + errno = EIO; + return TRACE_SYSRES (-1); + } + + rd_ctx = find_reader (fd, 1); + if (rd_ctx) + { + /* No need for locking, as the only races are against the reader + thread itself, which doesn't touch refcount. */ + rd_ctx->refcount++; + + LOCK (reader_table_lock); + for (i = 0; i < reader_table_size; i++) + if (!reader_table[i].used) + break; + /* FIXME. */ + assert (i != reader_table_size); + reader_table[i].fd = handle_to_fd (new_handle); + reader_table[i].context = rd_ctx; + reader_table[i].used = 1; + UNLOCK (reader_table_lock); + } + + wt_ctx = find_writer (fd, 1); + if (wt_ctx) + { + /* No need for locking, as the only races are against the writer + thread itself, which doesn't touch refcount. */ + wt_ctx->refcount++; + + LOCK (writer_table_lock); + for (i = 0; i < writer_table_size; i++) + if (!writer_table[i].used) + break; + /* FIXME. */ + assert (i != writer_table_size); + writer_table[i].fd = handle_to_fd (new_handle); + writer_table[i].context = wt_ctx; + writer_table[i].used = 1; + UNLOCK (writer_table_lock); + } + + return TRACE_SYSRES (handle_to_fd (new_handle)); +} + + +/* The following interface is only useful for GPGME Glib and Qt. */ + +/* Compatibility interface, obsolete. */ +void * +gpgme_get_giochannel (int fd) +{ + return NULL; +} + + +/* Look up the giochannel or qiodevice for file descriptor FD. */ +void * +gpgme_get_fdptr (int fd) +{ + return NULL; +} diff --git a/tags/gpgme-1.1.6/gpgme/w32-qt-io.cpp b/tags/gpgme-1.1.6/gpgme/w32-qt-io.cpp new file mode 100644 index 0000000..ba43913 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/w32-qt-io.cpp @@ -0,0 +1,636 @@ +/* w32-qt-io.c - W32 Glib I/O functions + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2004, 2005, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kdpipeiodevice.h" + +extern "C" +{ +#include "util.h" +#include "priv-io.h" +#include "sema.h" +#include "debug.h" +} + +#ifndef O_BINARY +#ifdef _O_BINARY +#define O_BINARY _O_BINARY +#else +#define O_BINARY 0 +#endif +#endif + +using _gpgme_::KDPipeIODevice; + + +/* This file is an ugly hack to get GPGME working with Qt on Windows + targets. On Windows, you can not select() on file descriptors. + + The only way to check if there is something to read is to read + something. This means that GPGME can not let Qt check for data + without letting Qt also handle the data on Windows targets. + + The ugly consequence is that we need to work on QIODevices in + GPGME, creating a Qt dependency. Also, we need to export an + interface for the application to get at GPGME's QIODevices. There + is no good way to abstract all this with callbacks, because the + whole thing is also interconnected with the creation of pipes and + child processes. + + The following rule applies only to this I/O backend: + + * ALL operations must use the user defined event loop. GPGME can + not anymore provide its own event loop. This is mostly a sanity + requirement: Although we have in theory all information we need to + make the GPGME W32 code for select still work, it would be a big + complication and require changes throughout GPGME. + + Eventually, we probably have to bite the bullet and make some + really nice callback interfaces to let the user control all this at + a per-context level. */ + +#define MAX_SLAFD 1024 + +struct DeviceEntry { + DeviceEntry() : iodev( 0 ), refCount( 1 ), blocking( true ) {} + KDPipeIODevice* iodev; + bool blocking; + mutable int refCount; + void ref() const { ++refCount; } + int unref() const { assert( refCount > 0 ); return --refCount; } +}; + +DeviceEntry* iodevice_table[MAX_SLAFD]; + + +static KDPipeIODevice * +find_channel (int fd, int create) +{ + assert( fd < MAX_SLAFD ); + if (fd < 0 || fd >= MAX_SLAFD) + return NULL; + + if (create && !iodevice_table[fd]) + { + DeviceEntry* entry = new DeviceEntry; + entry->iodev = new KDPipeIODevice + (fd, QIODevice::ReadWrite|QIODevice::Unbuffered); + iodevice_table[fd] = entry; + } + return iodevice_table[fd] ? iodevice_table[fd]->iodev : 0; +} + +/* Write the printable version of FD to the buffer BUF of length + BUFLEN. The printable version is the representation on the command + line that the child process expects. */ +int +_gpgme_io_fd2str (char *buf, int buflen, int fd) +{ + return snprintf (buf, buflen, "%d", (long)_get_osfhandle( fd ) ); +} + + +void +_gpgme_io_subsystem_init (void) +{ +} + + +static struct +{ + _gpgme_close_notify_handler_t handler; + void *value; +} notify_table[MAX_SLAFD]; + + +int +_gpgme_io_read (int fd, void *buffer, size_t count) +{ + int saved_errno = 0; + qint64 nread; + KDPipeIODevice *chan; + TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_read", fd, + "buffer=%p, count=%u", buffer, count); + + chan = find_channel (fd, 0); + if (!chan) + { + TRACE_LOG ("no channel registered"); + errno = EINVAL; + return TRACE_SYSRES (-1); + } + TRACE_LOG1 ("channel %p", chan); + if ( iodevice_table[fd] && !iodevice_table[fd]->blocking && chan->readWouldBlock() ) { + errno = EAGAIN; + return TRACE_SYSRES( -1 ); + } + + nread = chan->read ((char *) buffer, count); + if (nread < 0) + { + TRACE_LOG1 ("err %s", qPrintable (chan->errorString ())); + saved_errno = EIO; + nread = -1; + } + + TRACE_LOGBUF ((char *) buffer, nread); + + errno = saved_errno; + return TRACE_SYSRES (nread); +} + + +int +_gpgme_io_write (int fd, const void *buffer, size_t count) +{ + qint64 nwritten; + KDPipeIODevice *chan; + TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_write", fd, + "buffer=%p, count=%u", buffer, count); + TRACE_LOGBUF ((char *) buffer, count); + + chan = find_channel (fd, 0); + if (!chan) + { + TRACE_LOG ("fd %d: no channel registered"); + errno = EINVAL; + return -1; + } + + if ( iodevice_table[fd] && !iodevice_table[fd]->blocking && chan->writeWouldBlock() ) + { + errno = EAGAIN; + return TRACE_SYSRES( -1 ); + } + nwritten = chan->write ((char *) buffer, count); + + if (nwritten < 0) + { + nwritten = -1; + errno = EIO; + return TRACE_SYSRES(-1); + } + errno = 0; + return TRACE_SYSRES (nwritten); +} + + +int +_gpgme_io_pipe (int filedes[2], int inherit_idx) +{ + KDPipeIODevice *chan; + TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_pipe", filedes, + "inherit_idx=%i (GPGME uses it for %s)", + inherit_idx, inherit_idx ? "reading" : "writing"); + +#define PIPEBUF_SIZE 4096 + if (_pipe (filedes, PIPEBUF_SIZE, O_NOINHERIT | O_BINARY) == -1) + return TRACE_SYSRES (-1); + + /* Make one end inheritable. */ + if (inherit_idx == 0) + { + int new_read; + + new_read = _dup (filedes[0]); + _close (filedes[0]); + filedes[0] = new_read; + + if (new_read < 0) + { + _close (filedes[1]); + return TRACE_SYSRES (-1); + } + } + else if (inherit_idx == 1) + { + int new_write; + + new_write = _dup (filedes[1]); + _close (filedes[1]); + filedes[1] = new_write; + + if (new_write < 0) + { + _close (filedes[0]); + return TRACE_SYSRES (-1); + } + } + + /* Now we have a pipe with the right end inheritable. The other end + should have a giochannel. */ + + chan = find_channel (filedes[1 - inherit_idx], 1); + + if (!chan) + { + int saved_errno = errno; + _close (filedes[0]); + _close (filedes[1]); + errno = saved_errno; + return TRACE_SYSRES (-1); + } + + return TRACE_SUC5 ("read=0x%x/%p, write=0x%x/%p, channel=%p", + filedes[0], (HANDLE) _get_osfhandle (filedes[0]), + filedes[1], (HANDLE) _get_osfhandle (filedes[1]), + chan); +} + +int +_gpgme_io_close (int fd) +{ + KDPipeIODevice *chan; + TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_close", fd); + + if (fd < 0 || fd >= MAX_SLAFD) + { + errno = EBADF; + return TRACE_SYSRES (-1); + } + + /* First call the notify handler. */ + if (notify_table[fd].handler) + { + notify_table[fd].handler (fd, notify_table[fd].value); + notify_table[fd].handler = NULL; + notify_table[fd].value = NULL; + } + + /* Then do the close. */ + + DeviceEntry* const entry = iodevice_table[fd]; + if ( entry ) { + if ( entry->unref() == 0 ) { + entry->iodev->close(); + delete entry->iodev; + delete entry; + iodevice_table[fd] = 0; + } + } else { + _close( fd ); + } + + + + return 0; +} + + +int +_gpgme_io_set_close_notify (int fd, _gpgme_close_notify_handler_t handler, + void *value) +{ + TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_set_close_notify", fd, + "close_handler=%p/%p", handler, value); + + assert (fd != -1); + + if (fd < 0 || fd >= (int) DIM (notify_table)) + { + errno = EINVAL; + return TRACE_SYSRES (-1); + } + notify_table[fd].handler = handler; + notify_table[fd].value = value; + return TRACE_SYSRES (0); +} + + +int +_gpgme_io_set_nonblocking (int fd) +{ + DeviceEntry* const entry = iodevice_table[fd]; + assert( entry ); + entry->blocking = false; + TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_set_nonblocking", fd); + return TRACE_SYSRES (0); +} + + +static char * +build_commandline (char **argv) +{ + int i; + int n = 0; + char *buf; + char *p; + + /* We have to quote some things because under Windows the program + parses the commandline and does some unquoting. We enclose the + whole argument in double-quotes, and escape literal double-quotes + as well as backslashes with a backslash. We end up with a + trailing space at the end of the line, but that is harmless. */ + for (i = 0; argv[i]; i++) + { + p = argv[i]; + /* The leading double-quote. */ + n++; + while (*p) + { + /* An extra one for each literal that must be escaped. */ + if (*p == '\\' || *p == '"') + n++; + n++; + p++; + } + /* The trailing double-quote and the delimiter. */ + n += 2; + } + /* And a trailing zero. */ + n++; + + buf = p = (char *) malloc (n); + if (!buf) + return NULL; + for (i = 0; argv[i]; i++) + { + char *argvp = argv[i]; + + *(p++) = '"'; + while (*argvp) + { + if (*argvp == '\\' || *argvp == '"') + *(p++) = '\\'; + *(p++) = *(argvp++); + } + *(p++) = '"'; + *(p++) = ' '; + } + *(p++) = 0; + + 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; + /* FIXME. */ + int debug_me = 0; + TRACE_BEG1 (DEBUG_SYSIO, "_gpgme_io_spawn", path, + "path=%s", path); + i = 0; + while (argv[i]) + { + TRACE_LOG2 ("argv[%2i] = %s", i, argv[i]); + i++; + } + + 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 TRACE_SYSRES (-1); + + memset (&si, 0, sizeof si); + si.cb = sizeof (si); + si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; + si.wShowWindow = debug_me? SW_SHOW : SW_HIDE; + 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 = (HANDLE) _get_osfhandle (fd_child_list[i].fd); + TRACE_LOG2 ("using 0x%x/%p for stdin", fd_child_list[i].fd, + _get_osfhandle (fd_child_list[i].fd)); + duped_stdin = 1; + } + else if (fd_child_list[i].dup_to == 1) + { + si.hStdOutput = (HANDLE) _get_osfhandle (fd_child_list[i].fd); + TRACE_LOG2 ("using 0x%x/%p for stdout", fd_child_list[i].fd, + _get_osfhandle (fd_child_list[i].fd)); + } + else if (fd_child_list[i].dup_to == 2) + { + si.hStdError = (HANDLE) _get_osfhandle (fd_child_list[i].fd); + TRACE_LOG2 ("using 0x%x/%p for stderr", fd_child_list[i].fd, + _get_osfhandle (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 ("nul", + GENERIC_READ|GENERIC_WRITE, + FILE_SHARE_READ|FILE_SHARE_WRITE, + &sa, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hnul == INVALID_HANDLE_VALUE) + { + TRACE_LOG1 ("CreateFile (\"nul\") failed: ec=%d", + (int) GetLastError ()); + free (arg_string); + /* FIXME: Should translate the error code. */ + errno = EIO; + return TRACE_SYSRES (-1); + } + /* Make sure that the process has a connected stdin. */ + if (!duped_stdin) + { + si.hStdInput = hnul; + TRACE_LOG1 ("using 0x%x for dummy stdin", (int) hnul); + } + /* We normally don't want all the normal output. */ + if (!duped_stderr) + { + si.hStdError = hnul; + TRACE_LOG1 ("using %d for dummy stderr", (int)hnul); + } + } + + cr_flags |= CREATE_SUSPENDED; + cr_flags |= DETACHED_PROCESS; + if (!CreateProcessA (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 */ + { + TRACE_LOG1 ("CreateProcess failed: ec=%d", (int) GetLastError ()); + free (arg_string); + /* FIXME: Should translate the error code. */ + errno = EIO; + return TRACE_SYSRES (-1); + } + + /* Close the /dev/nul handle if used. */ + if (hnul != INVALID_HANDLE_VALUE) + { + if (!CloseHandle (hnul)) + TRACE_LOG1 ("CloseHandle (hnul) failed: ec=%d (ignored)", + (int) GetLastError ()); + } + + /* Close the other ends of the pipes. */ + for (i = 0; fd_parent_list[i].fd != -1; i++) + _gpgme_io_close (fd_parent_list[i].fd); + + + TRACE_LOG4 ("CreateProcess ready: hProcess=%p, hThread=%p, " + "dwProcessID=%d, dwThreadId=%d", + pi.hProcess, pi.hThread, + (int) pi.dwProcessId, (int) pi.dwThreadId); + + if (ResumeThread (pi.hThread) < 0) + TRACE_LOG1 ("ResumeThread failed: ec=%d", (int) GetLastError ()); + + if (!CloseHandle (pi.hThread)) + TRACE_LOG1 ("CloseHandle of thread failed: ec=%d", + (int) GetLastError ()); + + TRACE_SUC1 ("process=%p", pi.hProcess); + + /* We don't need to wait for the process. */ + CloseHandle (pi.hProcess); + + return TRACE_SYSRES (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, int nonblock) +{ + /* Use a 1s timeout. */ + + void *dbg_help = NULL; + TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_select", fds, + "nfds=%u, nonblock=%u", nfds, nonblock); + + /* We only implement the special case of nonblock == true. */ + assert (nonblock); + + int count = 0; + + TRACE_SEQ (dbg_help, "select on [ "); + for (int i = 0; i < nfds; i++) + { + if (fds[i].fd == -1) + { + fds[i].signaled = 0; + } + else if (fds[i].for_read ) + { + const KDPipeIODevice * const chan = find_channel (fds[i].fd, 0); + assert (chan); + fds[i].signaled = chan->readWouldBlock() ? 0 : 1; + TRACE_ADD1 (dbg_help, "w0x%x ", fds[i].fd); + if ( fds[i].signaled ) + count++; + } + else if (fds[i].for_write) + { + const KDPipeIODevice * const chan = find_channel (fds[i].fd, 0); + assert (chan); + fds[i].signaled = chan->writeWouldBlock() ? 0 : 1; + TRACE_ADD1 (dbg_help, "w0x%x ", fds[i].fd); + if ( fds[i].signaled ) + count++; + } + } + TRACE_END (dbg_help, "]"); + + return TRACE_SYSRES (count); +} + + +/* Look up the qiodevice for file descriptor FD. */ +extern "C" +void * +gpgme_get_fdptr (int fd) +{ + return find_channel (fd, 0); +} + + +/* Obsolete compatibility interface. */ +extern "C" +void * +gpgme_get_giochannel (int fd) +{ + return NULL; +} + + +int +_gpgme_io_dup (int fd) +{ + assert( iodevice_table[fd] ); + iodevice_table[fd]->ref(); + return fd; +} + diff --git a/tags/gpgme-1.1.6/gpgme/w32-sema.c b/tags/gpgme-1.1.6/gpgme/w32-sema.c new file mode 100644 index 0000000..5228cc7 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/w32-sema.c @@ -0,0 +1,115 @@ +/* w32-sema.c + Copyright (C) 2001 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2004, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "sema.h" +#include "debug.h" + +static void +sema_fatal (const char *text) +{ + fprintf (stderr, "sema.c: %s\n", text); + abort (); +} + + +static void +critsect_init (struct critsect_s *s) +{ + CRITICAL_SECTION *mp; + static CRITICAL_SECTION init_lock; + static int initialized; + + if (!initialized) { + /* The very first time we call this function, we assume that + only one thread is running, so that we can bootstrap the + semaphore code. */ + InitializeCriticalSection (&init_lock); + initialized = 1; + } + if (!s) + return; /* we just want to initialize ourself */ + + /* first test whether it is really not initialized */ + EnterCriticalSection (&init_lock); + if ( s->priv ) { + LeaveCriticalSection (&init_lock); + return; + } + /* now init it */ + mp = malloc ( sizeof *mp ); + if (!mp) { + LeaveCriticalSection (&init_lock); + sema_fatal ("out of core while creating critical section lock"); + } + InitializeCriticalSection (mp); + s->priv = mp; + LeaveCriticalSection (&init_lock); +} + +void +_gpgme_sema_subsystem_init () +{ + /* fixme: we should check that there is only one thread running */ + critsect_init (NULL); +} + + +void +_gpgme_sema_cs_enter ( struct critsect_s *s ) +{ + if (!s->priv) + critsect_init (s); + EnterCriticalSection ( (CRITICAL_SECTION*)s->priv ); +} + +void +_gpgme_sema_cs_leave (struct critsect_s *s) +{ + if (!s->priv) + critsect_init (s); + LeaveCriticalSection ((CRITICAL_SECTION*)s->priv); +} + +void +_gpgme_sema_cs_destroy ( struct critsect_s *s ) +{ + if (s && s->priv) { + DeleteCriticalSection ((CRITICAL_SECTION*)s->priv); + free (s->priv); + s->priv = NULL; + } +} diff --git a/tags/gpgme-1.1.6/gpgme/w32-util.c b/tags/gpgme-1.1.6/gpgme/w32-util.c new file mode 100644 index 0000000..b0f6df2 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/w32-util.c @@ -0,0 +1,365 @@ +/* w32-util.c - Utility functions for the W32 API + Copyright (C) 1999 Free Software Foundation, Inc + Copyright (C) 2001 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "sema.h" +#include "debug.h" + +DEFINE_STATIC_LOCK (get_path_lock); + + +#define RTLD_LAZY 0 + +static __inline__ void * +dlopen (const char * name, int flag) +{ + void * hd = LoadLibrary (name); + return hd; +} + +static __inline__ void * +dlsym (void * hd, const char * sym) +{ + if (hd && sym) + { + void * fnc = GetProcAddress (hd, sym); + if (!fnc) + return NULL; + return fnc; + } + return NULL; +} + +static __inline__ int +dlclose (void * hd) +{ + if (hd) + { + FreeLibrary (hd); + return 0; + } + return -1; +} + + +/* Return a string from the W32 Registry or NULL in case of error. + Caller must release the return value. A NULL for root is an alias + for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn. */ +static char * +read_w32_registry_string (const char *root, const char *dir, const char *name) +{ + HKEY root_key, key_handle; + DWORD n1, nbytes, type; + char *result = NULL; + + if ( !root ) + root_key = HKEY_CURRENT_USER; + else if ( !strcmp( root, "HKEY_CLASSES_ROOT" ) ) + root_key = HKEY_CLASSES_ROOT; + else if ( !strcmp( root, "HKEY_CURRENT_USER" ) ) + root_key = HKEY_CURRENT_USER; + else if ( !strcmp( root, "HKEY_LOCAL_MACHINE" ) ) + root_key = HKEY_LOCAL_MACHINE; + else if ( !strcmp( root, "HKEY_USERS" ) ) + root_key = HKEY_USERS; + else if ( !strcmp( root, "HKEY_PERFORMANCE_DATA" ) ) + root_key = HKEY_PERFORMANCE_DATA; + else if ( !strcmp( root, "HKEY_CURRENT_CONFIG" ) ) + root_key = HKEY_CURRENT_CONFIG; + else + return NULL; + + if ( RegOpenKeyEx ( root_key, dir, 0, KEY_READ, &key_handle ) ) + { + if (root) + return NULL; /* no need for a RegClose, so return direct */ + /* It seems to be common practise to fall back to HKLM. */ + if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) ) + return NULL; /* still no need for a RegClose, so return direct */ + } + + nbytes = 1; + if ( RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes ) ) + { + if (root) + goto leave; + /* Try to fallback to HKLM also vor a missing value. */ + RegCloseKey (key_handle); + if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) ) + return NULL; /* Nope. */ + if (RegQueryValueEx ( key_handle, name, 0, NULL, NULL, &nbytes)) + goto leave; + } + result = malloc ( (n1=nbytes+1) ); + if ( !result ) + goto leave; + if ( RegQueryValueEx ( key_handle, name, 0, &type, result, &n1 ) ) + { + free(result); result = NULL; + goto leave; + } + result[nbytes] = 0; /* Make sure it is really a string. */ + if (type == REG_EXPAND_SZ && strchr (result, '%')) + { + char *tmp; + + n1 += 1000; + tmp = malloc (n1+1); + if (!tmp) + goto leave; + nbytes = ExpandEnvironmentStrings (result, tmp, n1); + if (nbytes && nbytes > n1) + { + free (tmp); + n1 = nbytes; + tmp = malloc (n1 + 1); + if (!tmp) + goto leave; + nbytes = ExpandEnvironmentStrings (result, tmp, n1); + if (nbytes && nbytes > n1) { + free (tmp); /* Oops - truncated, better don't expand at all. */ + goto leave; + } + tmp[nbytes] = 0; + free (result); + result = tmp; + } + else if (nbytes) /* Okay, reduce the length. */ + { + tmp[nbytes] = 0; + free (result); + result = malloc (strlen (tmp)+1); + if (!result) + result = tmp; + else + { + strcpy (result, tmp); + free (tmp); + } + } + else /* Error - don't expand. */ + { + free (tmp); + } + } + + leave: + RegCloseKey( key_handle ); + return result; +} + + +/* This is a helper function to load and run a Windows function from + either of one DLLs. */ +static HRESULT +w32_shgetfolderpath (HWND a, int b, HANDLE c, DWORD d, LPSTR e) +{ + static int initialized; + static HRESULT (WINAPI * func)(HWND,int,HANDLE,DWORD,LPSTR); + + if (!initialized) + { + static char *dllnames[] = { "shell32.dll", "shfolder.dll", NULL }; + void *handle; + int i; + + initialized = 1; + + for (i=0, handle = NULL; !handle && dllnames[i]; i++) + { + handle = dlopen (dllnames[i], RTLD_LAZY); + if (handle) + { + func = dlsym (handle, "SHGetFolderPathA"); + if (!func) + { + dlclose (handle); + handle = NULL; + } + } + } + } + + if (func) + return func (a,b,c,d,e); + else + return -1; +} + + +static char * +find_program_in_registry (const char *name) +{ + char *program = NULL; + + program = read_w32_registry_string (NULL, "Software\\GNU\\GnuPG", name); + if (program) + { + int i; + + TRACE2 (DEBUG_CTX, "gpgme:find_program_in_registry", 0, + "found %s in registry: `%s'", name, program); + for (i = 0; program[i]; i++) + { + if (program[i] == '/') + program[i] = '\\'; + } + } + return program; +} + + +static char * +find_program_in_inst_dir (const char *name) +{ + char *result = NULL; + char *tmp; + + tmp = read_w32_registry_string ("HKEY_LOCAL_MACHINE", + "Software\\GNU\\GnuPG", + "Install Directory"); + if (!tmp) + return NULL; + + result = malloc (strlen (tmp) + 1 + strlen (name) + 1); + if (!result) + { + free (tmp); + return NULL; + } + + strcpy (stpcpy (stpcpy (result, tmp), "\\"), name); + free (tmp); + if (access (result, F_OK)) + { + free (result); + return NULL; + } + + return result; +} + + +static char * +find_program_at_standard_place (const char *name) +{ + char path[MAX_PATH]; + char *result = NULL; + + if (w32_shgetfolderpath (NULL, CSIDL_PROGRAM_FILES, NULL, 0, path) >= 0) + { + result = malloc (strlen (path) + 1 + strlen (name) + 1); + if (result) + { + strcpy (stpcpy (stpcpy (result, path), "\\"), name); + if (access (result, F_OK)) + { + free (result); + result = NULL; + } + } + } + return result; +} + + +const char * +_gpgme_get_gpg_path (void) +{ + static char *gpg_program; + + LOCK (get_path_lock); + if (!gpg_program) + gpg_program = find_program_in_registry ("gpgProgram"); + if (!gpg_program) + gpg_program = find_program_in_inst_dir ("gpg.exe"); + if (!gpg_program) + gpg_program = find_program_at_standard_place ("GNU\\GnuPG\\gpg.exe"); + UNLOCK (get_path_lock); + return gpg_program; +} + + +const char * +_gpgme_get_gpgsm_path (void) +{ + static char *gpgsm_program; + + LOCK (get_path_lock); + if (!gpgsm_program) + gpgsm_program = find_program_in_registry ("gpgsmProgram"); + if (!gpgsm_program) + gpgsm_program = find_program_in_inst_dir ("gpgsm.exe"); + if (!gpgsm_program) + gpgsm_program = find_program_at_standard_place ("GNU\\GnuPG\\gpgsm.exe"); + UNLOCK (get_path_lock); + return gpgsm_program; +} + + +const char * +_gpgme_get_gpgconf_path (void) +{ + static char *gpgconf_program; + + LOCK (get_path_lock); + if (!gpgconf_program) + gpgconf_program = find_program_in_registry ("gpgconfProgram"); + if (!gpgconf_program) + gpgconf_program = find_program_in_inst_dir ("gpgconf.exe"); + if (!gpgconf_program) + gpgconf_program + = find_program_at_standard_place ("GNU\\GnuPG\\gpgconf.exe"); + UNLOCK (get_path_lock); + return gpgconf_program; +} + + +/* Return an integer value from gpgme specific configuration + entries. VALUE receives that value; function returns true if a value + has been configured and false if not. */ +int +_gpgme_get_conf_int (const char *key, int *value) +{ + char *tmp = read_w32_registry_string (NULL, "Software\\GNU\\gpgme", key); + if (!tmp) + return 0; + *value = atoi (tmp); + free (tmp); + return 1; +} diff --git a/tags/gpgme-1.1.6/gpgme/wait-global.c b/tags/gpgme-1.1.6/gpgme/wait-global.c new file mode 100644 index 0000000..3b1e3d9 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/wait-global.c @@ -0,0 +1,384 @@ +/* wait-global.c + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include + +#include "gpgme.h" +#include "sema.h" +#include "util.h" +#include "context.h" +#include "wait.h" +#include "priv-io.h" + +/* The global event loop is used for all asynchronous operations + (except key listing) for which no user I/O callbacks are specified. + + A context sets up its initial I/O callbacks and then sends the + GPGME_EVENT_START event. After that, it is added to the global + list of active contexts. + + The gpgme_wait function contains a select() loop over all file + descriptors in all active contexts. If an error occurs, it closes + all fds in that context and moves the context to the global done + list. Likewise, if a context has removed all I/O callbacks, it is + moved to the global done list. + + All contexts in the global done list are eligible for being + returned by gpgme_wait if requested by the caller. */ + +/* The ctx_list_lock protects the list of active and done contexts. + Insertion into any of these lists is only allowed when the lock is + held. This allows a muli-threaded program to loop over gpgme_wait + and in parallel start asynchronous gpgme operations. + + However, the fd tables in the contexts are not protected by this + lock. They are only allowed to change either before the context is + added to the active list (ie, before the start event is signalled) + or in a callback handler. */ +DEFINE_STATIC_LOCK (ctx_list_lock); + +/* A ctx_list_item is an item in the global list of active or done + contexts. */ +struct ctx_list_item +{ + /* Every ctx_list_item is an element in a doubly linked list. The + list pointers are protected by the ctx_list_lock. */ + struct ctx_list_item *next; + struct ctx_list_item *prev; + + gpgme_ctx_t ctx; + /* The status is set when the ctx is moved to the done list. */ + gpgme_error_t status; +}; + +/* The active list contains all contexts that are in the global event + loop, have active I/O callbacks, and have already seen the start + event. */ +static struct ctx_list_item *ctx_active_list; + +/* The done list contains all contexts that have previously been + active but now are not active any longer, either because they + finished successfully or an I/O callback returned an error. The + status field in the list item contains the error value (or 0 if + successful). */ +static struct ctx_list_item *ctx_done_list; + + +/* Enter the context CTX into the active list. */ +static gpgme_error_t +ctx_active (gpgme_ctx_t ctx) +{ + struct ctx_list_item *li = malloc (sizeof (struct ctx_list_item)); + if (!li) + return gpg_error_from_errno (errno); + li->ctx = ctx; + + LOCK (ctx_list_lock); + /* Add LI to active list. */ + li->next = ctx_active_list; + li->prev = NULL; + if (ctx_active_list) + ctx_active_list->prev = li; + ctx_active_list = li; + UNLOCK (ctx_list_lock); + return 0; +} + + +/* Enter the context CTX into the done list with status STATUS. */ +static void +ctx_done (gpgme_ctx_t ctx, gpgme_error_t status) +{ + struct ctx_list_item *li; + + LOCK (ctx_list_lock); + li = ctx_active_list; + while (li && li->ctx != ctx) + li = li->next; + assert (li); + + /* Remove LI from active list. */ + if (li->next) + li->next->prev = li->prev; + if (li->prev) + li->prev->next = li->next; + else + ctx_active_list = li->next; + + li->status = status; + + /* Add LI to done list. */ + li->next = ctx_done_list; + li->prev = NULL; + if (ctx_done_list) + ctx_done_list->prev = li; + ctx_done_list = li; + UNLOCK (ctx_list_lock); +} + + +/* Find finished context CTX (or any context if CTX is NULL) and + return its status in STATUS after removing it from the done list. + If a matching context could be found, return it. Return NULL if no + context could be found. */ +static gpgme_ctx_t +ctx_wait (gpgme_ctx_t ctx, gpgme_error_t *status) +{ + struct ctx_list_item *li; + + LOCK (ctx_list_lock); + li = ctx_done_list; + if (ctx) + { + /* A specific context is requested. */ + while (li && li->ctx != ctx) + li = li->next; + } + if (li) + { + ctx = li->ctx; + if (status) + *status = li->status; + + /* Remove LI from done list. */ + if (li->next) + li->next->prev = li->prev; + if (li->prev) + li->prev->next = li->next; + else + ctx_done_list = li->next; + free (li); + } + else + ctx = NULL; + UNLOCK (ctx_list_lock); + return ctx; +} + + +/* Internal I/O callback functions. */ + +/* The add_io_cb and remove_io_cb handlers are shared with the private + event loops. */ + +void +_gpgme_wait_global_event_cb (void *data, gpgme_event_io_t type, + void *type_data) +{ + gpgme_ctx_t ctx = (gpgme_ctx_t) data; + + assert (ctx); + + switch (type) + { + case GPGME_EVENT_START: + { + gpgme_error_t err = ctx_active (ctx); + + if (err) + { + /* An error occured. Close all fds in this context, and + send the error in a done event. */ + unsigned int idx; + + for (idx = 0; idx <= ctx->fdt.size; idx++) + if (ctx->fdt.fds[idx].fd != -1) + _gpgme_io_close (ctx->fdt.fds[idx].fd); + _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &err); + } + } + break; + + case GPGME_EVENT_DONE: + { + gpgme_error_t *errp = (gpgme_error_t *) type_data; + assert (errp); + ctx_done (ctx, *errp); + } + break; + + case GPGME_EVENT_NEXT_KEY: + assert (!"Unexpected event GPGME_EVENT_NEXT_KEY"); + break; + + case GPGME_EVENT_NEXT_TRUSTITEM: + assert (!"Unexpected event GPGME_EVENT_NEXT_TRUSTITEM"); + break; + + default: + assert (!"Unexpected event"); + break; + } +} + + + +/* Perform asynchronous operations in the global event loop (ie, any + asynchronous operation except key listing and trustitem listing + operations). If CTX is not a null pointer, the function will + return if the asynchronous operation in the context CTX finished. + Otherwise the function will return if any asynchronous operation + finished. If HANG is zero, the function will not block for a long + time. Otherwise the function does not return until an operation + matching CTX finished. + + If a matching context finished, it is returned, and *STATUS is set + to the error value of the operation in that context. Otherwise, if + the timeout expires, NULL is returned and *STATUS is 0. If an + error occurs, NULL is returned and *STATUS is set to the error + value. */ +gpgme_ctx_t +gpgme_wait (gpgme_ctx_t ctx, gpgme_error_t *status, int hang) +{ + do + { + unsigned int i = 0; + struct ctx_list_item *li; + struct fd_table fdt; + int nr; + + /* Collect the active file descriptors. */ + LOCK (ctx_list_lock); + for (li = ctx_active_list; li; li = li->next) + i += li->ctx->fdt.size; + fdt.fds = malloc (i * sizeof (struct io_select_fd_s)); + if (!fdt.fds) + { + int saved_errno = errno; + UNLOCK (ctx_list_lock); + if (status) + *status = gpg_error_from_errno (saved_errno); + return NULL; + } + fdt.size = i; + i = 0; + for (li = ctx_active_list; li; li = li->next) + { + memcpy (&fdt.fds[i], li->ctx->fdt.fds, + li->ctx->fdt.size * sizeof (struct io_select_fd_s)); + i += li->ctx->fdt.size; + } + UNLOCK (ctx_list_lock); + + nr = _gpgme_io_select (fdt.fds, fdt.size, 0); + if (nr < 0) + { + int saved_errno = errno; + free (fdt.fds); + if (status) + *status = gpg_error_from_errno (saved_errno); + return NULL; + } + + for (i = 0; i < fdt.size && nr; i++) + { + if (fdt.fds[i].fd != -1 && fdt.fds[i].signaled) + { + gpgme_ctx_t ictx; + gpgme_error_t err; + struct wait_item_s *item; + + assert (nr); + nr--; + + item = (struct wait_item_s *) fdt.fds[i].opaque; + assert (item); + ictx = item->ctx; + assert (ictx); + + err = _gpgme_run_io_cb (&fdt.fds[i], 0); + if (err) + { + /* An error occured. Close all fds in this context, + and signal it. */ + unsigned int idx; + + for (idx = 0; idx < ictx->fdt.size; idx++) + if (ictx->fdt.fds[idx].fd != -1) + _gpgme_io_close (ictx->fdt.fds[idx].fd); + _gpgme_engine_io_event (ictx->engine, GPGME_EVENT_DONE, + &err); + + /* Break out of the loop, and retry the select() + from scratch, because now all fds should be + gone. */ + break; + } + } + } + free (fdt.fds); + + /* Now some contexts might have finished successfully. */ + LOCK (ctx_list_lock); + retry: + for (li = ctx_active_list; li; li = li->next) + { + gpgme_ctx_t actx = li->ctx; + + for (i = 0; i < actx->fdt.size; i++) + if (actx->fdt.fds[i].fd != -1) + break; + if (i == actx->fdt.size) + { + gpgme_error_t err = 0; + + /* FIXME: This does not perform too well. We have to + release the lock because the I/O event handler + acquires it to remove the context from the active + list. Two alternative strategies are worth + considering: Either implement the DONE event handler + here in a lock-free manner, or save a list of all + contexts to be released and call the DONE events + afterwards. */ + UNLOCK (ctx_list_lock); + _gpgme_engine_io_event (actx->engine, GPGME_EVENT_DONE, &err); + LOCK (ctx_list_lock); + goto retry; + } + } + UNLOCK (ctx_list_lock); + + { + gpgme_ctx_t dctx = ctx_wait (ctx, status); + + if (dctx) + { + ctx = dctx; + hang = 0; + } + else if (!hang) + { + ctx = NULL; + if (status) + *status = 0; + } + } + } + while (hang); + + return ctx; +} diff --git a/tags/gpgme-1.1.6/gpgme/wait-private.c b/tags/gpgme-1.1.6/gpgme/wait-private.c new file mode 100644 index 0000000..73f11b7 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/wait-private.c @@ -0,0 +1,147 @@ +/* wait-private.c + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif +#include +#include + +#include "gpgme.h" +#include "context.h" +#include "wait.h" +#include "ops.h" +#include "priv-io.h" +#include "util.h" + + +/* The private event loops are used for all blocking operations, and + for the key and trust item listing operations. They are completely + separated from each other. */ + + +/* Internal I/O callback functions. */ + +/* The add_io_cb and remove_io_cb handlers are shared with the global + event loops. */ + +void +_gpgme_wait_private_event_cb (void *data, gpgme_event_io_t type, + void *type_data) +{ + switch (type) + { + case GPGME_EVENT_START: + /* Nothing to do here, as the wait routine is called after the + initialization is finished. */ + break; + + case GPGME_EVENT_DONE: + break; + + case GPGME_EVENT_NEXT_KEY: + _gpgme_op_keylist_event_cb (data, type, type_data); + break; + + case GPGME_EVENT_NEXT_TRUSTITEM: + _gpgme_op_trustlist_event_cb (data, type, type_data); + break; + } +} + + +/* If COND is a null pointer, wait until the blocking operation in CTX + finished and return its error value. Otherwise, wait until COND is + satisfied or the operation finished. */ +gpgme_error_t +_gpgme_wait_on_condition (gpgme_ctx_t ctx, volatile int *cond) +{ + gpgme_error_t err = 0; + int hang = 1; + + do + { + int nr = _gpgme_io_select (ctx->fdt.fds, ctx->fdt.size, 0); + unsigned int i; + + if (nr < 0) + { + /* An error occured. Close all fds in this context, and + signal it. */ + unsigned int idx; + + err = gpg_error_from_errno (errno); + for (idx = 0; idx < ctx->fdt.size; idx++) + if (ctx->fdt.fds[idx].fd != -1) + _gpgme_io_close (ctx->fdt.fds[idx].fd); + _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &err); + + return err; + } + + for (i = 0; i < ctx->fdt.size && nr; i++) + { + if (ctx->fdt.fds[i].fd != -1 && ctx->fdt.fds[i].signaled) + { + ctx->fdt.fds[i].signaled = 0; + assert (nr); + nr--; + + err = _gpgme_run_io_cb (&ctx->fdt.fds[i], 0); + if (err) + { + /* An error occured. Close all fds in this context, + and signal it. */ + unsigned int idx; + + for (idx = 0; idx < ctx->fdt.size; idx++) + if (ctx->fdt.fds[idx].fd != -1) + _gpgme_io_close (ctx->fdt.fds[idx].fd); + _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &err); + return err; + } + } + } + + for (i = 0; i < ctx->fdt.size; i++) + if (ctx->fdt.fds[i].fd != -1) + break; + if (i == ctx->fdt.size) + { + _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &err); + hang = 0; + } + if (cond && *cond) + hang = 0; + } + while (hang); + + return 0; +} + + +/* Wait until the blocking operation in context CTX has finished and + return the error value. */ +gpgme_error_t +_gpgme_wait_one (gpgme_ctx_t ctx) +{ + return _gpgme_wait_on_condition (ctx, NULL); +} diff --git a/tags/gpgme-1.1.6/gpgme/wait-user.c b/tags/gpgme-1.1.6/gpgme/wait-user.c new file mode 100644 index 0000000..605401e --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/wait-user.c @@ -0,0 +1,122 @@ +/* wait-user.c + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif +#include + +#include "gpgme.h" +#include "context.h" +#include "priv-io.h" +#include "wait.h" + + +/* The user event loops are used for all asynchronous operations for + which a user callback is defined. */ + + +/* Internal I/O Callbacks. */ + +gpgme_error_t +_gpgme_user_io_cb_handler (void *data, int fd) +{ + gpgme_error_t err; + struct tag *tag = (struct tag *) data; + gpgme_ctx_t ctx; + + assert (data); + ctx = tag->ctx; + assert (ctx); + + err = _gpgme_run_io_cb (&ctx->fdt.fds[tag->idx], 0); + if (err) + { + unsigned int idx; + + for (idx = 0; idx < ctx->fdt.size; idx++) + if (ctx->fdt.fds[idx].fd != -1) + _gpgme_io_close (ctx->fdt.fds[idx].fd); + _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &err); + } + else + { + unsigned int i; + + for (i = 0; i < ctx->fdt.size; i++) + if (ctx->fdt.fds[i].fd != -1) + break; + if (i == ctx->fdt.size) + _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &err); + } + return 0; +} + + +/* Register the file descriptor FD with the handler FNC (which gets + FNC_DATA as its first argument) for the direction DIR. DATA should + be the context for which the fd is added. R_TAG will hold the tag + that can be used to remove the fd. */ +gpgme_error_t +_gpgme_wait_user_add_io_cb (void *data, int fd, int dir, gpgme_io_cb_t fnc, + void *fnc_data, void **r_tag) +{ + gpgme_ctx_t ctx = (gpgme_ctx_t) data; + struct tag *tag; + gpgme_error_t err; + + assert (ctx); + err = _gpgme_add_io_cb (data, fd, dir, fnc, fnc_data, r_tag); + if (err) + return err; + tag = *r_tag; + assert (tag); + err = (*ctx->io_cbs.add) (ctx->io_cbs.add_priv, fd, dir, + _gpgme_user_io_cb_handler, *r_tag, + &tag->user_tag); + if (err) + _gpgme_remove_io_cb (*r_tag); + return err; +} + + +void +_gpgme_wait_user_remove_io_cb (void *data) +{ + struct tag *tag = (struct tag *) data; + gpgme_ctx_t ctx; + + assert (tag); + ctx = tag->ctx; + + (*ctx->io_cbs.remove) (tag->user_tag); + _gpgme_remove_io_cb (data); +} + + +void +_gpgme_wait_user_event_cb (void *data, gpgme_event_io_t type, void *type_data) +{ + gpgme_ctx_t ctx = data; + + if (ctx->io_cbs.event) + (*ctx->io_cbs.event) (ctx->io_cbs.event_priv, type, type_data); +} diff --git a/tags/gpgme-1.1.6/gpgme/wait.c b/tags/gpgme-1.1.6/gpgme/wait.c new file mode 100644 index 0000000..f5bc2d9 --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/wait.c @@ -0,0 +1,211 @@ +/* wait.c + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#if HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include + +#include "util.h" +#include "context.h" +#include "ops.h" +#include "wait.h" +#include "sema.h" +#include "priv-io.h" +#include "engine.h" +#include "debug.h" + + +void +_gpgme_fd_table_init (fd_table_t fdt) +{ + fdt->fds = NULL; + fdt->size = 0; +} + +void +_gpgme_fd_table_deinit (fd_table_t fdt) +{ + if (fdt->fds) + free (fdt->fds); +} + + +/* XXX We should keep a marker and roll over for speed. */ +static gpgme_error_t +fd_table_put (fd_table_t fdt, int fd, int dir, void *opaque, int *idx) +{ + unsigned int i, j; + struct io_select_fd_s *new_fds; + + for (i = 0; i < fdt->size; i++) + { + if (fdt->fds[i].fd == -1) + break; + } + if (i == fdt->size) + { +#define FDT_ALLOCSIZE 10 + new_fds = realloc (fdt->fds, (fdt->size + FDT_ALLOCSIZE) + * sizeof (*new_fds)); + if (!new_fds) + return gpg_error_from_errno (errno); + + fdt->fds = new_fds; + fdt->size += FDT_ALLOCSIZE; + for (j = 0; j < FDT_ALLOCSIZE; j++) + fdt->fds[i + j].fd = -1; + } + + fdt->fds[i].fd = fd; + fdt->fds[i].for_read = (dir == 1); + fdt->fds[i].for_write = (dir == 0); + fdt->fds[i].signaled = 0; + fdt->fds[i].opaque = opaque; + *idx = i; + return 0; +} + + +/* Register the file descriptor FD with the handler FNC (which gets + FNC_DATA as its first argument) for the direction DIR. DATA should + be the context for which the fd is added. R_TAG will hold the tag + that can be used to remove the fd. */ +gpgme_error_t +_gpgme_add_io_cb (void *data, int fd, int dir, gpgme_io_cb_t fnc, + void *fnc_data, void **r_tag) +{ + gpgme_error_t err; + gpgme_ctx_t ctx = (gpgme_ctx_t) data; + fd_table_t fdt; + struct wait_item_s *item; + struct tag *tag; + + assert (fnc); + assert (ctx); + + fdt = &ctx->fdt; + assert (fdt); + + tag = malloc (sizeof *tag); + if (!tag) + return gpg_error_from_errno (errno); + tag->ctx = ctx; + + /* Allocate a structure to hold information about the handler. */ + item = calloc (1, sizeof *item); + if (!item) + { + int saved_errno = errno; + free (tag); + return gpg_error_from_errno (saved_errno); + } + item->ctx = ctx; + item->dir = dir; + item->handler = fnc; + item->handler_value = fnc_data; + + err = fd_table_put (fdt, fd, dir, item, &tag->idx); + if (err) + { + free (tag); + free (item); + return err; + } + + TRACE3 (DEBUG_CTX, "_gpgme_add_io_cb", ctx, + "fd %d, dir=%d -> tag=%p", fd, dir, tag); + + *r_tag = tag; + return 0; +} + + +void +_gpgme_remove_io_cb (void *data) +{ + struct tag *tag = data; + gpgme_ctx_t ctx; + fd_table_t fdt; + int idx; + + assert (tag); + ctx = tag->ctx; + assert (ctx); + fdt = &ctx->fdt; + assert (fdt); + idx = tag->idx; + + TRACE2 (DEBUG_CTX, "_gpgme_remove_io_cb", data, + "setting fd 0x%x (item=%p) done", fdt->fds[idx].fd, + fdt->fds[idx].opaque); + + free (fdt->fds[idx].opaque); + free (tag); + + /* Free the table entry. */ + fdt->fds[idx].fd = -1; + fdt->fds[idx].for_read = 0; + fdt->fds[idx].for_write = 0; + fdt->fds[idx].opaque = NULL; +} + + +/* This is slightly embarrassing. The problem is that running an I/O + callback _may_ influence the status of other file descriptors. Our + own event loops could compensate for that, but the external event + loops cannot. FIXME: We may still want to optimize this a bit when + we are called from our own event loops. So if CHECKED is 1, the + check is skipped. */ +gpgme_error_t +_gpgme_run_io_cb (struct io_select_fd_s *an_fds, int checked) +{ + struct wait_item_s *item; + item = (struct wait_item_s *) an_fds->opaque; + assert (item); + + if (!checked) + { + int nr; + struct io_select_fd_s fds; + + TRACE0 (DEBUG_CTX, "_gpgme_run_io_cb", item, "need to check"); + fds = *an_fds; + fds.signaled = 0; + /* Just give it a quick poll. */ + nr = _gpgme_io_select (&fds, 1, 1); + assert (nr <= 1); + if (nr < 0) + return errno; + else if (nr == 0) + /* The status changed in the meantime, there is nothing left + to do. */ + return 0; + } + + TRACE2 (DEBUG_CTX, "_gpgme_run_io_cb", item, "handler (%p, %d)", + item->handler_value, an_fds->fd); + return item->handler (item->handler_value, an_fds->fd); +} diff --git a/tags/gpgme-1.1.6/gpgme/wait.h b/tags/gpgme-1.1.6/gpgme/wait.h new file mode 100644 index 0000000..eafbb6f --- /dev/null +++ b/tags/gpgme-1.1.6/gpgme/wait.h @@ -0,0 +1,82 @@ +/* wait.h - Definitions for the wait queue interface. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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" +#include "sema.h" + +struct fd_table +{ + struct io_select_fd_s *fds; + size_t size; +}; +typedef struct fd_table *fd_table_t; + +/* Wait items are hooked into the io_select_fd_s to connect an fd with + a callback handler. */ +struct wait_item_s +{ + gpgme_ctx_t ctx; + gpgme_io_cb_t handler; + void *handler_value; + int dir; +}; + +/* A registered fd handler is removed later using the tag that + identifies it. */ +struct tag +{ + /* The context for which the fd was registered. */ + gpgme_ctx_t ctx; + + /* The index into the fd table for this context. */ + int idx; + + /* This is used by the wrappers for the user event loop. */ + void *user_tag; +}; + + +void _gpgme_fd_table_init (fd_table_t fdt); +void _gpgme_fd_table_deinit (fd_table_t fdt); + +gpgme_error_t _gpgme_add_io_cb (void *data, int fd, int dir, + gpgme_io_cb_t fnc, void *fnc_data, void **r_tag); +void _gpgme_remove_io_cb (void *tag); +void _gpgme_wait_private_event_cb (void *data, gpgme_event_io_t type, + void *type_data); +void _gpgme_wait_global_event_cb (void *data, gpgme_event_io_t type, + void *type_data); + +gpgme_error_t _gpgme_wait_user_add_io_cb (void *data, int fd, int dir, + gpgme_io_cb_t fnc, void *fnc_data, + void **r_tag); +void _gpgme_wait_user_remove_io_cb (void *tag); +void _gpgme_wait_user_event_cb (void *data, gpgme_event_io_t type, + void *type_data); + +gpgme_error_t _gpgme_wait_one (gpgme_ctx_t ctx); + +gpgme_error_t _gpgme_run_io_cb (struct io_select_fd_s *an_fds, int checked); + +#endif /* WAIT_H */ diff --git a/tags/gpgme-1.1.6/install-sh b/tags/gpgme-1.1.6/install-sh new file mode 100755 index 0000000..6ce63b9 --- /dev/null +++ b/tags/gpgme-1.1.6/install-sh @@ -0,0 +1,294 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# 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 +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd=$cpprog + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd=$stripprog + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "$0: no input file specified" >&2 + exit 1 +else + : +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d "$dst" ]; then + instcmd=: + chmodcmd="" + else + instcmd=$mkdirprog + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f "$src" ] || [ -d "$src" ] + then + : + else + echo "$0: $src does not exist" >&2 + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "$0: no destination specified" >&2 + exit 1 + else + : + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d "$dst" ] + then + dst=$dst/`basename "$src"` + else + : + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' + ' +IFS="${IFS-$defaultIFS}" + +oIFS=$IFS +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS=$oIFS + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp=$pathcomp$1 + shift + + if [ ! -d "$pathcomp" ] ; + then + $mkdirprog "$pathcomp" + else + : + fi + + pathcomp=$pathcomp/ +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd "$dst" && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename "$dst"` + else + dstfile=`basename "$dst" $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename "$dst"` + else + : + fi + +# Make a couple of temp file names in the proper directory. + + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + +# Trap to clean up temp files at exit. + + trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0 + trap '(exit $?); exit' 1 2 13 15 + +# Move or copy the file name to the temp name + + $doit $instcmd "$src" "$dsttmp" && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi && + +# Now remove or move aside any old file at destination location. We try this +# two ways since rm can't unlink itself on some systems and the destination +# file might be busy for other reasons. In this case, the final cleanup +# might fail but the new file should still install successfully. + +{ + if [ -f "$dstdir/$dstfile" ] + then + $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null || + $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null || + { + echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 + (exit 1); exit + } + else + : + fi +} && + +# Now rename the file to the real destination. + + $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" + +fi && + +# The final little trick to "correctly" pass the exit status to the exit trap. + +{ + (exit 0); exit +} diff --git a/tags/gpgme-1.1.6/lang/Makefile.am b/tags/gpgme-1.1.6/lang/Makefile.am new file mode 100644 index 0000000..3b07992 --- /dev/null +++ b/tags/gpgme-1.1.6/lang/Makefile.am @@ -0,0 +1,22 @@ +# Makefile.am for gpgme/lang. +# Copyright (C) 2003, 2006 g10 Code GmbH +# +# This file is part of GPGME. +# +# GPGME is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser 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 + +SUBDIRS = cl + +EXTRA_DIST = README diff --git a/tags/gpgme-1.1.6/lang/README b/tags/gpgme-1.1.6/lang/README new file mode 100644 index 0000000..da54c78 --- /dev/null +++ b/tags/gpgme-1.1.6/lang/README @@ -0,0 +1,12 @@ +Language Support for GPGME +-------------------------- + +This directory contains support for other languages than C. + +Please note that language support components may be under a different +license than GPGME itself. You can find more information in each +sub-directory. + +Directory Language + +cl Common Lisp diff --git a/tags/gpgme-1.1.6/lang/cl/ChangeLog b/tags/gpgme-1.1.6/lang/cl/ChangeLog new file mode 100644 index 0000000..6862273 --- /dev/null +++ b/tags/gpgme-1.1.6/lang/cl/ChangeLog @@ -0,0 +1,4 @@ +2006-07-06 Marcus Brinkmann + + * Initial release. + diff --git a/tags/gpgme-1.1.6/lang/cl/Makefile.am b/tags/gpgme-1.1.6/lang/cl/Makefile.am new file mode 100644 index 0000000..e0064ba --- /dev/null +++ b/tags/gpgme-1.1.6/lang/cl/Makefile.am @@ -0,0 +1,29 @@ +# Makefile.am for GPGME-CL. +# Copyright (C) 2003, 2006 g10 Code GmbH +# +# This file is part of GPGME-CL. +# +# GPGME-CL 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-CL 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 Lesser 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 + +clfiles = gpgme.asd gpgme-package.lisp gpgme.lisp + +# FIXME: Should be configurable. +clfilesdir = $(datadir)/common-lisp/source/gpgme +dist_clfiles_DATA = $(clfiles) + +EXTRA_DIST = README + + diff --git a/tags/gpgme-1.1.6/lang/cl/README b/tags/gpgme-1.1.6/lang/cl/README new file mode 100644 index 0000000..b4a3c81 --- /dev/null +++ b/tags/gpgme-1.1.6/lang/cl/README @@ -0,0 +1,40 @@ +Common Lisp Support for GPGME +----------------------------- + +Requirements: + +ASDF Packaging Support +CFFI Foreign Function Interface +gpg-error GPG Error Codes + +Use with: + +> (asdf:operate 'asdf:load-op ':gpgme) + + +Examples +-------- + +(with-open-file (stream "/tmp/myout" :direction :output + :if-exists :supersede :element-type '(unsigned-byte 8)) + (with-context (ctx) + (setf (armor-p ctx) t) + (op-export ctx "DEADBEEF" out))) + +(with-context (ctx) + (with-output-to-string (out) + (setf (armor-p ctx) t) + (op-export ctx "McTester" out))) + +(gpgme:with-context (ctx :armor t) + (with-output-to-string (out) + (gpgme:op-export ctx "McTester" out))) + + +TODO +---- + +* When GPGME defines macros for include cert values -2, -1, 0 and 1, + define lisp macros for them as well. + +* diff --git a/tags/gpgme-1.1.6/lang/cl/gpgme-package.lisp b/tags/gpgme-1.1.6/lang/cl/gpgme-package.lisp new file mode 100644 index 0000000..239d57f --- /dev/null +++ b/tags/gpgme-1.1.6/lang/cl/gpgme-package.lisp @@ -0,0 +1,49 @@ +;;;; gpgme-package.lisp + +;;; Copyright (C) 2006 g10 Code GmbH +;;; +;;; This file is part of GPGME-CL. +;;; +;;; GPGME-CL 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-CL 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 +;;; Lesser General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GPGME; if not, write to the Free Software Foundation, +;;; Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +;;; Conventions: +;;; +;;; gpg-error is used for error handling. +;;; +;;; Standard I/O streams are used for input and output. + +(defpackage #:gpgme + (:use #:common-lisp #:cffi #:gpg-error) + + (:export #:check-version + #:*version* + #:context + #:protocol + #:armorp + #:textmodep + #:+include-certs-default+ + #:include-certs + #:keylist-mode + #:signers + #:sig-notations + #:with-context + #:key-data + #:get-key + #:op-encrypt + #:op-decrypt + #:op-sign + #:op-verify + #:op-import + #:op-export)) diff --git a/tags/gpgme-1.1.6/lang/cl/gpgme.asd.in b/tags/gpgme-1.1.6/lang/cl/gpgme.asd.in new file mode 100644 index 0000000..86e8d51 --- /dev/null +++ b/tags/gpgme-1.1.6/lang/cl/gpgme.asd.in @@ -0,0 +1,35 @@ +;;; -*- Mode: lisp -*- + +;;; Copyright (C) 2006 g10 Code GmbH +;;; +;;; This file is part of GPGME. +;;; +;;; GPGME is free software; you can redistribute it and/or +;;; modify it under the terms of the GNU Lesser General Public License +;;; as published by the Free Software Foundation; either version 2.1 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 +;;; Lesser General Public License for more details. +;;; +;;; You should have received a copy of the GNU Lesser General Public +;;; License along with GPGME; if not, write to the Free +;;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +;;; 02111-1307, USA. + +(defpackage #:gpgme-system + (:use #:common-lisp #:asdf)) + +(in-package #:gpgme-system) + +(defsystem gpgme + :description "GnuPG Made Easy." + :author "g10 Code GmbH" + :version "@VERSION@" + :licence "GPL" + :depends-on ("cffi" "gpg-error") + :components ((:file "gpgme-package") + (:file "gpgme" + :depends-on ("gpgme-package")))) diff --git a/tags/gpgme-1.1.6/lang/cl/gpgme.lisp b/tags/gpgme-1.1.6/lang/cl/gpgme.lisp new file mode 100644 index 0000000..cb536fa --- /dev/null +++ b/tags/gpgme-1.1.6/lang/cl/gpgme.lisp @@ -0,0 +1,2077 @@ +;;;; gpgme.lisp + +;;; Copyright (C) 2006 g10 Code GmbH +;;; +;;; This file is part of GPGME-CL. +;;; +;;; GPGME-CL 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-CL 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 +;;; Lesser General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GPGME; if not, write to the Free Software Foundation, +;;; Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +;;; TODO + +;;; Set up the library. + +(in-package :gpgme) + +;;; Debugging. + +(defvar *debug* nil "If debugging output should be given or not.") + +;;; Load the foreign library. + +(define-foreign-library libgpgme + (:unix "libgpgme.so") + (t (:default "libgpgme"))) + +(use-foreign-library libgpgme) + +;;; System dependencies. + +; FIXME: Use cffi-grovel? cffi-unix? + +(defctype size-t :unsigned-int + :documentation "The system size_t type.") + +(defctype ssize-t :int + :documentation "The system ssize_t type.") + +; FIXME: Ouch. Grovel? Helper function? +(defconstant +seek-set+ 0) +(defconstant +seek-cur+ 1) +(defconstant +seek-end+ 2) +(defctype off-t :long-long + :documentation "The system off_t type.") + +(defcfun ("strerror" c-strerror) :string + (err :int)) + +; Access to ERRNO. +; FIXME: Ouch. Should be grovel + helper function. + +(define-condition system-error (error) + ((errno :initarg :errno :reader system-error-errno)) + (:report (lambda (c stream) + (format stream "System error: ~A: ~A" + (system-error-errno c) + (c-strerror (system-error-errno c))))) + (:documentation "Signalled when an errno is encountered.")) + +(defconstant +ebadf+ 1) + +; Ouch. +(defun get-errno () + +ebadf+) + +;;; More about errno below. + +; Needed to write passphrases. +(defcfun ("write" c-write) ssize-t + (fd :int) + (buffer :string) ; Actually :pointer, but we only need string. + (size size-t)) + +(defun system-write (fd buffer size) + (let ((res (c-write fd buffer size))) + (when (< res 0) (error 'system-error :errno (get-errno))) + res)) + +;;; More about errno here. + +(defun set-errno (errno) + (cond + ; Works on GNU/Linux. + ((eql errno +ebadf+) (system-write -1 (null-pointer) 0)) + (t (error 'invalid-errno :errno errno)))) + +;;; +;;; C Interface Definitions +;;; + +;;; Data Type Interface + +;;; Some new data types used for easier translation. + +;;; The number of include certs. Translates to NIL for default. +(defctype cert-int-t :int) + +;;; A string that may be NIL to indicate a null pointer. +(defctype string-or-nil-t :string) + +;;; Some opaque data types used by GPGME. + +(defctype gpgme-ctx-t :pointer + :documentation "The GPGME context type.") + +(defctype gpgme-data-t :pointer + :documentation "The GPGME data object type.") + +;;; Wrappers for the libgpg-error library. + +(defctype gpgme-error-t gpg-error::gpg-error-t + :documentation "The GPGME error type.") + +(defctype gpgme-error-no-signal-t gpg-error::gpg-error-t + :documentation "The GPGME error type (this version does not + signal conditions in translation.") + +(defctype gpgme-err-code-t gpg-error::gpg-err-code-t + :documentation "The GPGME error code type.") + +(defctype gpgme-err-source-t gpg-error::gpg-err-source-t + :documentation "The GPGME error source type.") + +(defun gpgme-err-make (source code) + "Construct an error value from an error code and source." + (gpg-err-make source code)) + +(defun gpgme-error (code) + "Construct an error value from an error code." + (gpgme-err-make :gpg-err-source-gpgme code)) + +(defun gpgme-err-code (err) + "Retrieve an error code from the error value ERR." + (gpg-err-code err)) + +(defun gpgme-err-source (err) + "Retrieve an error source from the error value ERR." + (gpg-err-source err)) + +(defun gpgme-strerror (err) + "Return a string containig a description of the error code." + (gpg-strerror err)) + +(defun gpgme-strsource (err) + "Return a string containig a description of the error source." + (gpg-strsource err)) + +(defun gpgme-err-code-from-errno (err) + "Retrieve the error code for the system error. If the system error + is not mapped, :gpg-err-unknown-errno is returned." + (gpg-err-code-from-errno err)) + +(defun gpgme-err-code-to-errno (code) + "Retrieve the system error for the error code. If this is not a + system error, 0 is returned." + (gpg-err-code-to-errno code)) + +(defun gpgme-err-make-from-errno (source err) + (gpg-err-make-from-errno source err)) + +(defun gpgme-error-from-errno (err) + (gpg-error-from-errno err)) + +;;; + +(defcenum gpgme-data-encoding-t + "The possible encoding mode of gpgme-data-t objects." + (:none 0) + (:binary 1) + (:base64 2) + (:armor 3)) + +;;; + +(defcenum gpgme-pubkey-algo-t + "Public key algorithms from libgcrypt." + (:rsa 1) + (:rsa-e 2) + (:rsa-s 3) + (:elg-e 16) + (:dsa 17) + (:elg 20)) + +(defcenum gpgme-hash-algo-t + "Hash algorithms from libgcrypt." + (:none 0) + (:md5 1) + (:sha1 2) + (:rmd160 3) + (:md2 5) + (:tiger 6) + (:haval 7) + (:sha256 8) + (:sha384 9) + (:sha512 10) + (:md4 301) + (:crc32 302) + (:crc32-rfc1510 303) + (:crc24-rfc2440 304)) + +;;; + +(defcenum gpgme-sig-mode-t + "The available signature modes." + (:none 0) + (:detach 1) + (:clear 2)) + +;;; + +(defcenum gpgme-validity-t + "The available validities for a trust item or key." + (:unknown 0) + (:undefined 1) + (:never 2) + (:marginal 3) + (:full 4) + (:ultimate 5)) + +;;; + +(defcenum gpgme-protocol-t + "The available protocols." + (:openpgp 0) + (:cms 1)) + +;;; + +(defbitfield (gpgme-keylist-mode-t :unsigned-int) + "The available keylist mode flags." + (:local 1) + (:extern 2) + (:sigs 4) + (:validate 256)) + +;;; + +(defbitfield (gpgme-sig-notation-flags-t :unsigned-int) + "The available signature notation flags." + (:human-readable 1) + (:critical 2)) + +(defctype gpgme-sig-notation-t :pointer + :documentation "Signature notation pointer type.") + +;; FIXME: Doesn't this depend on endianess? +(defbitfield (gpgme-sig-notation-bitfield :unsigned-int) + (:human-readable 1) + (:critical 2)) + +(defcstruct gpgme-sig-notation + "Signature notations." + (next gpgme-sig-notation-t) + (name :pointer) + (value :pointer) + (name-len :int) + (value-len :int) + (flags gpgme-sig-notation-flags-t) + (bitfield gpgme-sig-notation-bitfield)) + +;;; + +;; FIXME: Add status codes. +(defcenum gpgme-status-code-t + "The possible status codes for the edit operation." + (:eof 0) + (:enter 1)) + +;;; + +(defctype gpgme-engine-info-t :pointer + :documentation "The engine information structure pointer type.") + +(defcstruct gpgme-engine-info + "Engine information." + (next gpgme-engine-info-t) + (protocol gpgme-protocol-t) + (file-name :string) + (version :string) + (req-version :string) + (home-dir :string)) + +;;; + +(defctype gpgme-subkey-t :pointer + :documentation "A subkey from a key.") + +;; FIXME: Doesn't this depend on endianess? +(defbitfield (gpgme-subkey-bitfield :unsigned-int) + "The subkey bitfield." + (:revoked 1) + (:expired 2) + (:disabled 4) + (:invalid 8) + (:can-encrypt 16) + (:can-sign 32) + (:can-certify 64) + (:secret 128) + (:can-authenticate 256) + (:is-qualified 512)) + +(defcstruct gpgme-subkey + "Subkey from a key." + (next gpgme-subkey-t) + (bitfield gpgme-subkey-bitfield) + (pubkey-algo gpgme-pubkey-algo-t) + (length :unsigned-int) + (keyid :string) + (-keyid :char :count 17) + (fpr :string) + (timestamp :long) + (expires :long)) + + +(defctype gpgme-key-sig-t :pointer + :documentation "A signature on a user ID.") + +;; FIXME: Doesn't this depend on endianess? +(defbitfield (gpgme-key-sig-bitfield :unsigned-int) + "The key signature bitfield." + (:revoked 1) + (:expired 2) + (:invalid 4) + (:exportable 16)) + +(defcstruct gpgme-key-sig + "A signature on a user ID." + (next gpgme-key-sig-t) + (bitfield gpgme-key-sig-bitfield) + (pubkey-algo gpgme-pubkey-algo-t) + (keyid :string) + (-keyid :char :count 17) + (timestamp :long) + (expires :long) + (status gpgme-error-no-signal-t) + (-class :unsigned-int) + (uid :string) + (name :string) + (email :string) + (comment :string) + (sig-class :unsigned-int)) + + +(defctype gpgme-user-id-t :pointer + :documentation "A user ID from a key.") + +;; FIXME: Doesn't this depend on endianess? +(defbitfield (gpgme-user-id-bitfield :unsigned-int) + "The user ID bitfield." + (:revoked 1) + (:invalid 2)) + +(defcstruct gpgme-user-id + "A user ID from a key." + (next gpgme-user-id-t) + (bitfield gpgme-user-id-bitfield) + (validity gpgme-validity-t) + (uid :string) + (name :string) + (email :string) + (comment :string) + (signatures gpgme-key-sig-t) + (-last-keysig gpgme-key-sig-t)) + + +(defctype gpgme-key-t :pointer + :documentation "A key from the keyring.") + +;; FIXME: Doesn't this depend on endianess? +(defbitfield (gpgme-key-bitfield :unsigned-int) + "The key bitfield." + (:revoked 1) + (:expired 2) + (:disabled 4) + (:invalid 8) + (:can-encrypt 16) + (:can-sign 32) + (:can-certify 64) + (:secret 128) + (:can-authenticate 256) + (:is-qualified 512)) + +(defcstruct gpgme-key + "A signature on a user ID." + (-refs :unsigned-int) + (bitfield gpgme-key-bitfield) + (protocol gpgme-protocol-t) + (issuer-serial :string) + (issuer-name :string) + (chain-id :string) + (owner-trust gpgme-validity-t) + (subkeys gpgme-subkey-t) + (uids gpgme-user-id-t) + (-last-subkey gpgme-subkey-t) + (-last-uid gpgme-user-id-t) + (keylist-mode gpgme-keylist-mode-t)) + +;;; + +;;; There is no support in CFFI to define callback C types and have +;;; automatic type checking with the callback definition. + +(defctype gpgme-passphrase-cb-t :pointer) + +(defctype gpgme-progress-cb-t :pointer) + +(defctype gpgme-edit-cb-t :pointer) + + +;;; +;;; Function Interface +;;; + +;;; Context management functions. + +(defcfun ("gpgme_new" c-gpgme-new) gpgme-error-t + (ctx :pointer)) + +(defcfun ("gpgme_release" c-gpgme-release) :void + (ctx gpgme-ctx-t)) + +(defcfun ("gpgme_set_protocol" c-gpgme-set-protocol) gpgme-error-t + (ctx gpgme-ctx-t) + (proto gpgme-protocol-t)) + +(defcfun ("gpgme_get_protocol" c-gpgme-get-protocol) gpgme-protocol-t + (ctx gpgme-ctx-t)) + +(defcfun ("gpgme_get_protocol_name" c-gpgme-get-protocol-name) :string + (proto gpgme-protocol-t)) + +(defcfun ("gpgme_set_armor" c-gpgme-set-armor) :void + (ctx gpgme-ctx-t) + (yes :boolean)) + +(defcfun ("gpgme_get_armor" c-gpgme-get-armor) :boolean + (ctx gpgme-ctx-t)) + +(defcfun ("gpgme_set_textmode" c-gpgme-set-textmode) :void + (ctx gpgme-ctx-t) + (yes :boolean)) + +(defcfun ("gpgme_get_textmode" c-gpgme-get-textmode) :boolean + (ctx gpgme-ctx-t)) + +(defconstant +include-certs-default+ -256) + +(defcfun ("gpgme_set_include_certs" c-gpgme-set-include-certs) :void + (ctx gpgme-ctx-t) + (nr-of-certs cert-int-t)) + +(defcfun ("gpgme_get_include_certs" c-gpgme-get-include-certs) cert-int-t + (ctx gpgme-ctx-t)) + +(defcfun ("gpgme_set_keylist_mode" c-gpgme-set-keylist-mode) gpgme-error-t + (ctx gpgme-ctx-t) + (mode gpgme-keylist-mode-t)) + +(defcfun ("gpgme_get_keylist_mode" c-gpgme-get-keylist-mode) + gpgme-keylist-mode-t + (ctx gpgme-ctx-t)) + +(defcfun ("gpgme_set_passphrase_cb" c-gpgme-set-passphrase-cb) :void + (ctx gpgme-ctx-t) + (cb gpgme-passphrase-cb-t) + (hook-value :pointer)) + +(defcfun ("gpgme_get_passphrase_cb" c-gpgme-get-passphrase-cb) :void + (ctx gpgme-ctx-t) + (cb-p :pointer) + (hook-value-p :pointer)) + +(defcfun ("gpgme_set_progress_cb" c-gpgme-set-progress-cb) :void + (ctx gpgme-ctx-t) + (cb gpgme-progress-cb-t) + (hook-value :pointer)) + +(defcfun ("gpgme_get_progress_cb" c-gpgme-get-progress-cb) :void + (ctx gpgme-ctx-t) + (cb-p :pointer) + (hook-value-p :pointer)) + +(defcfun ("gpgme_set_locale" c-gpgme-set-locale) gpgme-error-t + (ctx gpgme-ctx-t) + (category :int) + (value string-or-nil-t)) + +(defcfun ("gpgme_ctx_get_engine_info" c-gpgme-ctx-get-engine-info) + gpgme-engine-info-t + (ctx gpgme-ctx-t)) + +(defcfun ("gpgme_ctx_set_engine_info" c-gpgme-ctx-set-engine-info) + gpgme-error-t + (ctx gpgme-ctx-t) + (proto gpgme-protocol-t) + (file-name string-or-nil-t) + (home-dir string-or-nil-t)) + +;;; + +(defcfun ("gpgme_pubkey_algo_name" c-gpgme-pubkey-algo-name) :string + (algo gpgme-pubkey-algo-t)) + +(defcfun ("gpgme_hash_algo_name" c-gpgme-hash-algo-name) :string + (algo gpgme-hash-algo-t)) + +;;; + +(defcfun ("gpgme_signers_clear" c-gpgme-signers-clear) :void + (ctx gpgme-ctx-t)) + +(defcfun ("gpgme_signers_add" c-gpgme-signers-add) gpgme-error-t + (ctx gpgme-ctx-t) + (key gpgme-key-t)) + +(defcfun ("gpgme_signers_enum" c-gpgme-signers-enum) gpgme-key-t + (ctx gpgme-ctx-t) + (seq :int)) + +;;; + +(defcfun ("gpgme_sig_notation_clear" c-gpgme-sig-notation-clear) :void + (ctx gpgme-ctx-t)) + +(defcfun ("gpgme_sig_notation_add" c-gpgme-sig-notation-add) gpgme-error-t + (ctx gpgme-ctx-t) + (name :string) + (value string-or-nil-t) + (flags gpgme-sig-notation-flags-t)) + +(defcfun ("gpgme_sig_notation_get" c-gpgme-sig-notation-get) + gpgme-sig-notation-t + (ctx gpgme-ctx-t)) + +;;; Run Control. + +;;; There is no support in CFFI to define callback C types and have +;;; automatic type checking with the callback definition. + +(defctype gpgme-io-cb-t :pointer) + +(defctype gpgme-register-io-cb-t :pointer) + +(defctype gpgme-remove-io-cb-t :pointer) + +(defcenum gpgme-event-io-t + "The possible events on I/O event callbacks." + (:start 0) + (:done 1) + (:next-key 2) + (:next-trustitem 3)) + +(defctype gpgme-event-io-cb-t :pointer) + +(defcstruct gpgme-io-cbs + "I/O callbacks." + (add gpgme-register-io-cb-t) + (add-priv :pointer) + (remove gpgme-remove-io-cb-t) + (event gpgme-event-io-cb-t) + (event-priv :pointer)) + +(defctype gpgme-io-cbs-t :pointer) + +(defcfun ("gpgme_set_io_cbs" c-gpgme-set-io-cbs) :void + (ctx gpgme-ctx-t) + (io-cbs gpgme-io-cbs-t)) + +(defcfun ("gpgme_get_io_cbs" c-gpgme-get-io-cbs) :void + (ctx gpgme-ctx-t) + (io-cbs gpgme-io-cbs-t)) + +(defcfun ("gpgme_wait" c-gpgme-wait) gpgme-ctx-t + (ctx gpgme-ctx-t) + (status-p :pointer) + (hang :int)) + +;;; Functions to handle data objects. + +;;; There is no support in CFFI to define callback C types and have +;;; automatic type checking with the callback definition. + +(defctype gpgme-data-read-cb-t :pointer) +(defctype gpgme-data-write-cb-t :pointer) +(defctype gpgme-data-seek-cb-t :pointer) +(defctype gpgme-data-release-cb-t :pointer) + +(defcstruct gpgme-data-cbs + "Data callbacks." + (read gpgme-data-read-cb-t) + (write gpgme-data-write-cb-t) + (seek gpgme-data-seek-cb-t) + (release gpgme-data-release-cb-t)) + +(defctype gpgme-data-cbs-t :pointer + :documentation "Data callbacks pointer.") + +(defcfun ("gpgme_data_read" c-gpgme-data-read) ssize-t + (dh gpgme-data-t) + (buffer :pointer) + (size size-t)) + +(defcfun ("gpgme_data_write" c-gpgme-data-write) ssize-t + (dh gpgme-data-t) + (buffer :pointer) + (size size-t)) + +(defcfun ("gpgme_data_seek" c-gpgme-data-seek) off-t + (dh gpgme-data-t) + (offset off-t) + (whence :int)) + +(defcfun ("gpgme_data_new" c-gpgme-data-new) gpgme-error-t + (dh-p :pointer)) + +(defcfun ("gpgme_data_release" c-gpgme-data-release) :void + (dh gpgme-data-t)) + +(defcfun ("gpgme_data_new_from_mem" c-gpgme-data-new-from-mem) gpgme-error-t + (dh-p :pointer) + (buffer :pointer) + (size size-t) + (copy :int)) + +(defcfun ("gpgme_data_release_and_get_mem" c-gpgme-data-release-and-get-mem) + :pointer + (dh gpgme-data-t) + (len-p :pointer)) + +(defcfun ("gpgme_data_new_from_cbs" c-gpgme-data-new-from-cbs) gpgme-error-t + (dh-p :pointer) + (cbs gpgme-data-cbs-t) + (handle :pointer)) + +(defcfun ("gpgme_data_new_from_fd" c-gpgme-data-new-from-fd) gpgme-error-t + (dh-p :pointer) + (fd :int)) + +(defcfun ("gpgme_data_new_from_stream" c-gpgme-data-new-from-stream) + gpgme-error-t + (dh-p :pointer) + (stream :pointer)) + +(defcfun ("gpgme_data_get_encoding" c-gpgme-data-get-encoding) + gpgme-data-encoding-t + (dh gpgme-data-t)) + +(defcfun ("gpgme_data_set_encoding" c-gpgme-data-set-encoding) + gpgme-error-t + (dh gpgme-data-t) + (enc gpgme-data-encoding-t)) + +(defcfun ("gpgme_data_get_file_name" c-gpgme-data-get-file-name) :string + (dh gpgme-data-t)) + +(defcfun ("gpgme_data_set_file_name" c-gpgme-data-set-file-name) gpgme-error-t + (dh gpgme-data-t) + (file-name string-or-nil-t)) + +(defcfun ("gpgme_data_new_from_file" c-gpgme-data-new-from-file) gpgme-error-t + (dh-p :pointer) + (fname :string) + (copy :int)) + +(defcfun ("gpgme_data_new_from_filepart" c-gpgme-data-new-from-filepart) + gpgme-error-t + (dh-p :pointer) + (fname :string) + (fp :pointer) + (offset off-t) + (length size-t)) + +;;; Key and trust functions. + +(defcfun ("gpgme_get_key" c-gpgme-get-key) gpgme-error-t + (ctx gpgme-ctx-t) + (fpr :string) + (key-p :pointer) + (secret :boolean)) + +(defcfun ("gpgme_key_ref" c-gpgme-key-ref) :void + (key gpgme-key-t)) + +(defcfun ("gpgme_key_unref" c-gpgme-key-unref) :void + (key gpgme-key-t)) + +;;; Crypto operations. + +(defcfun ("gpgme_cancel" c-gpgme-cancel) gpgme-error-t + (ctx gpgme-ctx-t)) + +;;; + +(defctype gpgme-invalid-key-t :pointer + :documentation "An invalid key structure.") + +(defcstruct gpgme-invalid-key + "An invalid key structure." + (next gpgme-invalid-key-t) + (fpr :string) + (reason gpgme-error-no-signal-t)) + +;;; Encryption. + +(defcstruct gpgme-op-encrypt-result + "Encryption result structure." + (invalid-recipients gpgme-invalid-key-t)) + +(defctype gpgme-op-encrypt-result-t :pointer + :documentation "An encryption result structure.") + +(defcfun ("gpgme_op_encrypt_result" c-gpgme-op-encrypt-result) + gpgme-op-encrypt-result-t + (ctx gpgme-ctx-t)) + +(defbitfield gpgme-encrypt-flags-t + (:always-trust 1)) + +(defcfun ("gpgme_op_encrypt_start" c-gpgme-op-encrypt-start) gpgme-error-t + (ctx gpgme-ctx-t) + (recp :pointer) ; Key array. + (flags gpgme-encrypt-flags-t) + (plain gpgme-data-t) + (cipher gpgme-data-t)) + +(defcfun ("gpgme_op_encrypt" c-gpgme-op-encrypt) gpgme-error-t + (ctx gpgme-ctx-t) + (recp :pointer) ; Key array. + (flags gpgme-encrypt-flags-t) + (plain gpgme-data-t) + (cipher gpgme-data-t)) + +(defcfun ("gpgme_op_encrypt_sign_start" c-gpgme-op-encrypt-sign-start) + gpgme-error-t + (ctx gpgme-ctx-t) + (recp :pointer) ; Key array. + (flags gpgme-encrypt-flags-t) + (plain gpgme-data-t) + (cipher gpgme-data-t)) + +(defcfun ("gpgme_op_encrypt_sign" c-gpgme-op-encrypt-sign) gpgme-error-t + (ctx gpgme-ctx-t) + (recp :pointer) ; Key array. + (flags gpgme-encrypt-flags-t) + (plain gpgme-data-t) + (cipher gpgme-data-t)) + +;;; Decryption. + +(defctype gpgme-recipient-t :pointer + :documentation "A recipient structure.") + +(defcstruct gpgme-recipient + "Recipient structure." + (next gpgme-recipient-t) + (keyid :string) + (-keyid :char :count 17) + (pubkey-algo gpgme-pubkey-algo-t) + (status gpgme-error-no-signal-t)) + +(defbitfield gpgme-op-decrypt-result-bitfield + "Decryption result structure bitfield." + (:wrong-key-usage 1)) + +(defcstruct gpgme-op-decrypt-result + "Decryption result structure." + (unsupported-algorithm :string) + (bitfield gpgme-op-decrypt-result-bitfield) + (recipients gpgme-recipient-t) + (file-name :string)) + +(defctype gpgme-op-decrypt-result-t :pointer + :documentation "A decryption result structure.") + +(defcfun ("gpgme_op_decrypt_result" c-gpgme-op-decrypt-result) + gpgme-op-decrypt-result-t + (ctx gpgme-ctx-t)) + +(defcfun ("gpgme_op_decrypt_start" c-gpgme-op-decrypt-start) gpgme-error-t + (ctx gpgme-ctx-t) + (cipher gpgme-data-t) + (plain gpgme-data-t)) + +(defcfun ("gpgme_op_decrypt" c-gpgme-op-decrypt) gpgme-error-t + (ctx gpgme-ctx-t) + (cipher gpgme-data-t) + (plain gpgme-data-t)) + +(defcfun ("gpgme_op_decrypt_verify_start" c-gpgme-op-decrypt-verify-start) + gpgme-error-t + (ctx gpgme-ctx-t) + (cipher gpgme-data-t) + (plain gpgme-data-t)) + +(defcfun ("gpgme_op_decrypt_verify" c-gpgme-op-decrypt-verify) gpgme-error-t + (ctx gpgme-ctx-t) + (cipher gpgme-data-t) + (plain gpgme-data-t)) + +;;; Signing. + +(defctype gpgme-new-signature-t :pointer + :documentation "A new signature structure.") + +(defcstruct gpgme-new-signature + "New signature structure." + (next gpgme-new-signature-t) + (type gpgme-sig-mode-t) + (pubkey-algo gpgme-pubkey-algo-t) + (hash-algo gpgme-hash-algo-t) + (-obsolete-class :unsigned-long) + (timestamp :long) + (fpr :string) + (-obsolete-class-2 :unsigned-int) + (sig-class :unsigned-int)) + +(defcstruct gpgme-op-sign-result + "Signing result structure." + (invalid-signers gpgme-invalid-key-t) + (signatures gpgme-new-signature-t)) + +(defctype gpgme-op-sign-result-t :pointer + :documentation "A signing result structure.") + +(defcfun ("gpgme_op_sign_result" c-gpgme-op-sign-result) + gpgme-op-sign-result-t + (ctx gpgme-ctx-t)) + +(defcfun ("gpgme_op_sign_start" c-gpgme-op-sign-start) gpgme-error-t + (ctx gpgme-ctx-t) + (plain gpgme-data-t) + (sig gpgme-data-t) + (mode gpgme-sig-mode-t)) + +(defcfun ("gpgme_op_sign" c-gpgme-op-sign) gpgme-error-t + (ctx gpgme-ctx-t) + (plain gpgme-data-t) + (sig gpgme-data-t) + (mode gpgme-sig-mode-t)) + +;;; Verify. + +(defbitfield (gpgme-sigsum-t :unsigned-int) + "Flags used for the summary field in a gpgme-signature-t." + (:valid #x0001) + (:green #x0002) + (:red #x0004) + (:key-revoked #x0010) + (:key-expired #x0020) + (:sig-expired #x0040) + (:key-missing #x0080) + (:crl-missing #x0100) + (:crl-too-old #x0200) + (:bad-policy #x0400) + (:sys-error #x0800)) + +(defctype gpgme-signature-t :pointer + :documentation "A signature structure.") + +;; FIXME: Doesn't this depend on endianess? +(defbitfield (gpgme-signature-bitfield :unsigned-int) + "The signature bitfield." + (:wrong-key-usage 1)) + +(defcstruct gpgme-signature + "Signature structure." + (next gpgme-signature-t) + (summary gpgme-sigsum-t) + (fpr :string) + (status gpgme-error-no-signal-t) + (notations gpgme-sig-notation-t) + (timestamp :unsigned-long) + (exp-timestamp :unsigned-long) + (bitfield gpgme-signature-bitfield) + (validity gpgme-validity-t) + (validity-reason gpgme-error-no-signal-t) + (pubkey-algo gpgme-pubkey-algo-t) + (hash-algo gpgme-hash-algo-t)) + +(defcstruct gpgme-op-verify-result + "Verify result structure." + (signatures gpgme-signature-t) + (file-name :string)) + +(defctype gpgme-op-verify-result-t :pointer + :documentation "A verify result structure.") + +(defcfun ("gpgme_op_verify_result" c-gpgme-op-verify-result) + gpgme-op-verify-result-t + (ctx gpgme-ctx-t)) + +(defcfun ("gpgme_op_verify_start" c-gpgme-op-verify-start) gpgme-error-t + (ctx gpgme-ctx-t) + (sig gpgme-data-t) + (signed-text gpgme-data-t) + (plaintext gpgme-data-t)) + +(defcfun ("gpgme_op_verify" c-gpgme-op-verify) gpgme-error-t + (ctx gpgme-ctx-t) + (sig gpgme-data-t) + (signed-text gpgme-data-t) + (plaintext gpgme-data-t)) + +;;; Import. + +(defbitfield (gpgme-import-flags-t :unsigned-int) + "Flags used for the import status field." + (:new #x0001) + (:uid #x0002) + (:sig #x0004) + (:subkey #x0008) + (:secret #x0010)) + +(defctype gpgme-import-status-t :pointer + :documentation "An import status structure.") + +(defcstruct gpgme-import-status + "New import status structure." + (next gpgme-import-status-t) + (fpr :string) + (result gpgme-error-no-signal-t) + (status :unsigned-int)) + +(defcstruct gpgme-op-import-result + "Import result structure." + (considered :int) + (no-user-id :int) + (imported :int) + (imported-rsa :int) + (unchanged :int) + (new-user-ids :int) + (new-sub-keys :int) + (new-signatures :int) + (new-revocations :int) + (secret-read :int) + (secret-imported :int) + (secret-unchanged :int) + (skipped-new-keys :int) + (not-imported :int) + (imports gpgme-import-status-t)) + +(defctype gpgme-op-import-result-t :pointer + :documentation "An import status result structure.") + +(defcfun ("gpgme_op_import_result" c-gpgme-op-import-result) + gpgme-op-import-result-t + (ctx gpgme-ctx-t)) + +(defcfun ("gpgme_op_import_start" c-gpgme-op-import-start) gpgme-error-t + (ctx gpgme-ctx-t) + (keydata gpgme-data-t)) + +(defcfun ("gpgme_op_import" c-gpgme-op-import) gpgme-error-t + (ctx gpgme-ctx-t) + (keydata gpgme-data-t)) + +;;; Export. + +(defcfun ("gpgme_op_export_start" c-gpgme-op-export-start) gpgme-error-t + (ctx gpgme-ctx-t) + (pattern :string) + (reserved :unsigned-int) + (keydata gpgme-data-t)) + +(defcfun ("gpgme_op_export" c-gpgme-op-export) gpgme-error-t + (ctx gpgme-ctx-t) + (pattern :string) + (reserved :unsigned-int) + (keydata gpgme-data-t)) + +;;; FIXME: Extended export interfaces require array handling. + +;;; Key generation. + +(defbitfield (gpgme-genkey-flags-t :unsigned-int) + "Flags used for the key generation result bitfield." + (:primary #x0001) + (:sub #x0002)) + +(defcstruct gpgme-op-genkey-result + "Key generation result structure." + (bitfield gpgme-genkey-flags-t) + (fpr :string)) + +(defctype gpgme-op-genkey-result-t :pointer + :documentation "A key generation result structure.") + +(defcfun ("gpgme_op_genkey_result" c-gpgme-op-genkey-result) + gpgme-op-genkey-result-t + (ctx gpgme-ctx-t)) + +(defcfun ("gpgme_op_genkey_start" c-gpgme-op-genkey-start) gpgme-error-t + (ctx gpgme-ctx-t) + (parms :string) + (pubkey gpgme-data-t) + (seckey gpgme-data-t)) + +(defcfun ("gpgme_op_genkey" c-gpgme-op-genkey) gpgme-error-t + (ctx gpgme-ctx-t) + (parms :string) + (pubkey gpgme-data-t) + (seckey gpgme-data-t)) + +;;; Key deletion. + +(defcfun ("gpgme_op_delete_start" c-gpgme-op-delete-start) gpgme-error-t + (ctx gpgme-ctx-t) + (key gpgme-key-t) + (allow-secret :int)) + +(defcfun ("gpgme_op_delete" c-gpgme-op-delete) gpgme-error-t + (ctx gpgme-ctx-t) + (key gpgme-key-t) + (allow-secret :int)) + +;;; FIXME: Add edit interfaces. + +;;; Keylist interface. + +(defbitfield (gpgme-keylist-flags-t :unsigned-int) + "Flags used for the key listing result bitfield." + (:truncated #x0001)) + +(defcstruct gpgme-op-keylist-result + "Key listing result structure." + (bitfield gpgme-keylist-flags-t)) + +(defctype gpgme-op-keylist-result-t :pointer + :documentation "A key listing result structure.") + +(defcfun ("gpgme_op_keylist_result" c-gpgme-op-keylist-result) + gpgme-op-keylist-result-t + (ctx gpgme-ctx-t)) + +(defcfun ("gpgme_op_keylist_start" c-gpgme-op-keylist-start) gpgme-error-t + (ctx gpgme-ctx-t) + (pattern :string) + (secret_only :boolean)) + +;;; FIXME: Extended keylisting requires array handling. + +(defcfun ("gpgme_op_keylist_next" c-gpgme-op-keylist-next) gpgme-error-t + (ctx gpgme-ctx-t) + (r-key :pointer)) + +(defcfun ("gpgme_op_keylist_end" c-gpgme-op-keylist-end) gpgme-error-t + (ctx gpgme-ctx-t)) + +;;; Various functions. + +(defcfun ("gpgme_check_version" c-gpgme-check-version) :string + (req-version string-or-nil-t)) + +(defcfun ("gpgme_get_engine_info" c-gpgme-get-engine-info) gpgme-error-t + (engine-info-p :pointer)) + +(defcfun ("gpgme_set_engine_info" c-gpgme-set-engine-info) gpgme-error-t + (proto gpgme-protocol-t) + (file-name string-or-nil-t) + (home-dir string-or-nil-t)) + +(defcfun ("gpgme_engine_check_version" c-gpgme-engine-check-verson) + gpgme-error-t + (proto gpgme-protocol-t)) + +;;; +;;; L I S P I N T E R F A C E +;;; + +;;; +;;; Lisp type translators. +;;; + +;;; Both directions. + +;;; cert-int-t is a helper type that takes care of representing the +;;; default number of certs as NIL. + +(defmethod translate-from-foreign (value (type (eql 'cert-int-t))) + (cond + ((eql value +include-certs-default+) nil) + (t value))) + +(defmethod translate-to-foreign (value (type (eql 'cert-int-t))) + (cond + (value value) + (t +include-certs-default+))) + +;;; string-or-nil-t translates a null pointer to NIL and vice versa. +;;; Translation from foreign null pointer already works as expected. +;;; FIXME: May the "to foreign" conversion problem be a bug in CFFI? + +(defmethod translate-to-foreign (value (type (eql 'string-or-nil-t))) + (cond + (value value) + (t (null-pointer)))) + +;;; Output only. + +;;; These type translators only convert from foreign type, because we +;;; never use these types in the other direction. + +;;; Convert gpgme-engine-info-t linked lists into a list of property +;;; lists. Note that this converter will automatically be invoked +;;; recursively. +;;; +;;; FIXME: Should we use a hash table (or struct, or clos) instead of +;;; property list, as recommended by the Lisp FAQ? + +(defmethod translate-from-foreign (value (type (eql 'gpgme-engine-info-t))) + (cond + ((null-pointer-p value) nil) + (t (with-foreign-slots + ((next protocol file-name version req-version home-dir) + value gpgme-engine-info) + (append (list protocol (list + :file-name file-name + :version version + :req-version req-version + :home-dir home-dir)) + next))))) + +(defmethod translate-from-foreign (value (type (eql 'gpgme-invalid-key-t))) + (cond + ((null-pointer-p value) nil) + (t (with-foreign-slots + ((next fpr reason) + value gpgme-invalid-key) + (append (list (list :fpr fpr + :reason reason)) + next))))) + +(defmethod translate-from-foreign (value + (type (eql 'gpgme-op-encrypt-result-t))) + (cond + ((null-pointer-p value) nil) + (t (with-foreign-slots + ((invalid-recipients) + value gpgme-op-encrypt-result) + (list :encrypt + (list :invalid-recipients invalid-recipients)))))) + +(defmethod translate-from-foreign (value (type (eql 'gpgme-recipient-t))) + (cond + ((null-pointer-p value) nil) + (t (with-foreign-slots + ((next keyid pubkey-algo status) + value gpgme-recipient) + (append (list (list :keyid keyid + :pubkey-algo pubkey-algo + :status status)) + next))))) + +(defmethod translate-from-foreign (value + (type (eql 'gpgme-op-decrypt-result-t))) + (cond + ((null-pointer-p value) nil) + (t (with-foreign-slots + ((unsupported-algorithm bitfield recipients file-name) + value gpgme-op-decrypt-result) + (list :decrypt (list :unsupported-algorithm unsupported-algorithm + :bitfield bitfield + :recipients recipients + :file-name file-name)))))) + +(defmethod translate-from-foreign (value (type (eql 'gpgme-new-signature-t))) + (cond + ((null-pointer-p value) nil) + (t (with-foreign-slots + ((next type pubkey-algo hash-algo timestamp fpr sig-class) + value gpgme-new-signature) + (append (list (list :type type + :pubkey-algo pubkey-algo + :hash-algo hash-algo + :timestamp timestamp + :fpr fpr + :sig-class sig-class)) + next))))) + +(defmethod translate-from-foreign (value + (type (eql 'gpgme-op-sign-result-t))) + (cond + ((null-pointer-p value) nil) + (t (with-foreign-slots + ((invalid-signers signatures) + value gpgme-op-sign-result) + (list :sign (list :invalid-signers invalid-signers + :signatures signatures)))))) + +(defmethod translate-from-foreign (value (type (eql 'gpgme-signature-t))) + (cond + ((null-pointer-p value) nil) + (t (with-foreign-slots + ((next summary fpr status notations timestamp + exp-timestamp bitfield validity validity-reason + pubkey-algo hash-algo) + value gpgme-signature) + (append (list (list :summary summary + :fpr fpr + :status status + :notations notations + :timestamp timestamp + :exp-timestamp exp-timestamp + :bitfield bitfield + :validity validity + :validity-reason validity-reason + :pubkey-algo pubkey-algo)) + next))))) + +(defmethod translate-from-foreign (value + (type (eql 'gpgme-op-verify-result-t))) + (cond + ((null-pointer-p value) nil) + (t (with-foreign-slots + ((signatures file-name) + value gpgme-op-verify-result) + (list :verify (list :signatures signatures + :file-name file-name)))))) + +(defmethod translate-from-foreign (value (type (eql 'gpgme-import-status-t))) + (cond + ((null-pointer-p value) nil) + (t (with-foreign-slots + ((next fpr result status) + value gpgme-import-status) + (append (list (list :fpr fpr + :result result + :status status)) + next))))) + +(defmethod translate-from-foreign (value + (type (eql 'gpgme-op-import-result-t))) + (cond + ((null-pointer-p value) nil) + (t (with-foreign-slots + ((considered no-user-id imported imported-rsa unchanged + new-user-ids new-sub-keys new-signatures + new-revocations secret-read secret-imported + secret-unchanged skipped-new-keys not-imported + imports) + value gpgme-op-import-result) + (list :verify (list :considered considered + :no-user-id no-user-id + :imported imported + :imported-rsa imported-rsa + :unchanged unchanged + :new-user-ids new-user-ids + :new-sub-keys new-sub-keys + :new-signatures new-signatures + :new-revocations new-revocations + :secret-read secret-read + :secret-imported secret-imported + :secret-unchanged secret-unchanged + :skipped-new-keys skipped-new-keys + :not-imported not-imported + :imports imports)))))) + +;;; Error handling. + +;;; Use gpgme-error-no-signal-t to suppress automatic error handling +;;; at translation time. +;;; +;;; FIXME: Part of this probably should be in gpg-error! + +(define-condition gpgme-error (error) + ((value :initarg :gpgme-error :reader gpgme-error-value)) + (:report (lambda (c stream) + (format stream "GPGME returned error: ~A (~A)" + (gpgme-strerror (gpgme-error-value c)) + (gpgme-strsource (gpgme-error-value c))))) + (:documentation "Signalled when a GPGME function returns an error.")) + +(defmethod translate-from-foreign (value (name (eql 'gpgme-error-t))) + "Raise a GPGME-ERROR if VALUE is non-zero." + (when (not (eql (gpgme-err-code value) :gpg-err-no-error)) + (error 'gpgme-error :gpgme-error value)) + (gpg-err-canonicalize value)) + +(defmethod translate-to-foreign (value (name (eql 'gpgme-error-t))) + "Canonicalize the error value." + (if (eql (gpgme-err-code value) :gpg-err-no-error) + 0 + (gpg-err-as-value value))) + +(defmethod translate-from-foreign (value (name (eql 'gpgme-error-no-signal-t))) + "Canonicalize the error value." + (gpg-err-canonicalize value)) + + +;;; *INTERNAL* Lispy Function Interface that is still close to the C +;;; interface. + +;;; Passphrase callback management. + +;;; Maybe: Instead, use subclassing, and provide a customizable +;;; default implementation for ease-of-use. + +(defvar *passphrase-handles* (make-hash-table) + "Hash table with GPGME context address as key and the corresponding + passphrase callback object as value.") + +(defcallback passphrase-cb gpgme-error-t ((handle :pointer) + (uid-hint :string) + (passphrase-info :string) + (prev-was-bad :boolean) + (fd :int)) + (handler-case + (let* ((passphrase-cb + (gethash (pointer-address handle) *passphrase-handles*)) + (passphrase + (cond + ((functionp passphrase-cb) + (concatenate 'string + (funcall passphrase-cb uid-hint passphrase-info + prev-was-bad) + '(#\Newline))) + (t (concatenate 'string passphrase-cb '(#\Newline))))) + (passphrase-len (length passphrase)) + ;; FIXME: Could be more robust. + (res (system-write fd passphrase passphrase-len))) + (cond + ((< res passphrase-len) ; FIXME: Blech. A weak attempt to be robust. + (gpgme-error :gpg-err-inval)) + (t (gpgme-error :gpg-err-no-error)))) + (gpgme-error (err) (gpgme-error-value err)) + (system-error (err) (gpgme-error-from-errno (system-error-errno err))) + ;; FIXME: The original error gets lost here. + (condition (err) (progn + (when *debug* + (format t "DEBUG: passphrase-cb: Unexpressable: ~A~%" + err)) + (gpgme-error :gpg-err-general))))) + +;;; CTX is a C-pointer to the context. +(defun gpgme-set-passphrase-cb (ctx cb) + "Set the passphrase callback for CTX." + (let ((handle (pointer-address ctx))) + (cond + (cb (setf (gethash handle *passphrase-handles*) cb) + (c-gpgme-set-passphrase-cb ctx (callback passphrase-cb) ctx)) + (t (c-gpgme-set-passphrase-cb ctx (null-pointer) (null-pointer)) + (remhash handle *passphrase-handles*))))) + +;;; Progress callback management. + +;;; Maybe: Instead, use subclassing, and provide a customizable +;;; default implementation for ease-of-use. + +(defvar *progress-handles* (make-hash-table) + "Hash table with GPGME context address as key and the corresponding + progress callback object as value.") + +(defcallback progress-cb :void ((handle :pointer) + (what :string) + (type :int) + (current :int) + (total :int)) + (handler-case + (let* ((progress-cb + (gethash (pointer-address handle) *progress-handles*))) + (funcall progress-cb what type current total)) + ;; FIXME: The original error gets lost here. + (condition (err) (when *debug* + (format t "DEBUG: progress-cb: Unexpressable: ~A~%" + err))))) + +;;; CTX is a C-pointer to the context. +(defun gpgme-set-progress-cb (ctx cb) + "Set the progress callback for CTX." + (let ((handle (pointer-address ctx))) + (cond + (cb (setf (gethash handle *progress-handles*) cb) + (c-gpgme-set-progress-cb ctx (callback progress-cb) ctx)) + (t (c-gpgme-set-progress-cb ctx (null-pointer) (null-pointer)) + (remhash handle *progress-handles*))))) + +;;; Context management. + +(defun gpgme-new (&key (protocol :openpgp) armor textmode include-certs + keylist-mode passphrase progress file-name home-dir) + "Allocate a new GPGME context." + (with-foreign-object (ctx-p 'gpgme-ctx-t) + (c-gpgme-new ctx-p) + (let ((ctx (mem-ref ctx-p 'gpgme-ctx-t))) + ;;; Set locale? + (gpgme-set-protocol ctx protocol) + (gpgme-set-armor ctx armor) + (gpgme-set-textmode ctx textmode) + (when include-certs (gpgme-set-include-certs ctx include-certs)) + (when keylist-mode (gpgme-set-keylist-mode ctx keylist-mode)) + (gpgme-set-passphrase-cb ctx passphrase) + (gpgme-set-progress-cb ctx progress) + (gpgme-set-engine-info ctx protocol + :file-name file-name :home-dir home-dir) + (when *debug* (format t "DEBUG: gpgme-new: ~A~%" ctx)) + ctx))) + +(defun gpgme-release (ctx) + "Release a GPGME context." + (when *debug* (format t "DEBUG: gpgme-release: ~A~%" ctx)) + (c-gpgme-release ctx)) + +(defun gpgme-set-protocol (ctx proto) + "Set the protocol to be used by CTX to PROTO." + (c-gpgme-set-protocol ctx proto)) + +(defun gpgme-get-protocol (ctx) + "Get the protocol used with CTX." + (c-gpgme-get-protocol ctx)) + +;;; FIXME: How to do pretty printing? +;;; +;;; gpgme-get-protocol-name + +(defun gpgme-set-armor (ctx armor) + "If ARMOR is true, enable armor mode in CTX, disable it otherwise." + (c-gpgme-set-armor ctx armor)) + +(defun gpgme-armor-p (ctx) + "Return true if armor mode is set for CTX." + (c-gpgme-get-armor ctx)) + +(defun gpgme-set-textmode (ctx textmode) + "If TEXTMODE is true, enable text mode mode in CTX, disable it otherwise." + (c-gpgme-set-textmode ctx textmode)) + +(defun gpgme-textmode-p (ctx) + "Return true if text mode mode is set for CTX." + (c-gpgme-get-textmode ctx)) + +(defun gpgme-set-include-certs (ctx &optional certs) + "Include up to CERTS certificates in an S/MIME message." + (c-gpgme-set-include-certs ctx certs)) + +(defun gpgme-get-include-certs (ctx) + "Return the number of certs to include in an S/MIME message, + or NIL if the default is used." + (c-gpgme-get-include-certs ctx)) + +(defun gpgme-get-keylist-mode (ctx) + "Get the keylist mode in CTX." + (c-gpgme-get-keylist-mode ctx)) + +(defun gpgme-set-keylist-mode (ctx mode) + "Set the keylist mode in CTX." + (c-gpgme-set-keylist-mode ctx mode)) + + +;;; FIXME: How to handle locale? cffi-grovel? + +(defun gpgme-get-engine-info (&optional ctx) + "Retrieve the engine info for CTX, or the default if CTX is omitted." + (cond + (ctx (c-gpgme-ctx-get-engine-info ctx)) + (t (with-foreign-object (info-p 'gpgme-engine-info-t) + (c-gpgme-get-engine-info info-p) + (mem-ref info-p 'gpgme-engine-info-t))))) + +(defun gpgme-set-engine-info (ctx proto &key file-name home-dir) + "Set the engine info for CTX, or the default if CTX is NIL." + (cond + (ctx (c-gpgme-ctx-set-engine-info ctx proto file-name home-dir)) + (t (c-gpgme-set-engine-info proto file-name home-dir)))) + +;;; FIXME: How to do pretty printing? +;;; +;;; gpgme_pubkey_algo_name, gpgme_hash_algo_name + +(defun gpgme-set-signers (ctx keys) + "Set the signers for the context CTX." + (c-gpgme-signers-clear ctx) + (dolist (key keys) (c-gpgme-signers-add ctx key))) + +;;; + +(defun gpgme-set-sig-notation (ctx notations) + "Set the sig notation for the context CTX." + (c-gpgme-sig-notation-clear ctx) + (dolist (notation notations) + (c-gpgme-sig-notation-add + ctx (first notation) (second notation) (third notation)))) + +(defun gpgme-get-sig-notation (ctx) + "Get the signature notation data for the context CTX." + (c-gpgme-sig-notation-get ctx)) + +;;; FIXME: Add I/O callback interface, for integration with clg. + +;;; FIXME: Add gpgme_wait? + +;;; Streams +;;; ------- +;;; +;;; GPGME uses standard streams. You can define your own streams, or +;;; use the existing file or string streams. +;;; +;;; A stream-spec is either a stream, or a list with a stream as its +;;; first argument followed by keyword parameters: encoding, +;;; file-name. +;;; +;;; FIXME: Eventually, we should provide a class that can be mixed +;;; into stream classes and which provides accessors for encoding and +;;; file-names. This interface should be provided in addition to the +;;; above sleazy interface, because the sleazy interface is easier to +;;; use (less typing), and is quite sufficient in a number of cases. +;;; +;;; For best results, streams with element type (unsigned-byte 8) +;;; should be used. Character streams may work if armor mode is used. + +;;; Do we need to provide access to GPGME data objects through streams +;;; as well? It seems to me that specific optimizations, like +;;; directly writing to file descriptors, is better done by extending +;;; the sleazy syntax (stream-spec) instead of customized streams. +;;; Customized streams do buffering, and this may mess up things. Mmh. + +(defvar *data-handles* (make-hash-table) + "Hash table with GPGME data user callback handle address as key + and the corresponding stream as value.") + +;;; The release callback removes the stream from the *data-handles* +;;; hash and releases the CBS structure that is used as the key in +;;; that hash. It is implicitely invoked (through GPGME) by +;;; gpgme-data-release. +(defcallback data-release-cb :void ((handle :pointer)) + (unwind-protect (remhash (pointer-address handle) *data-handles*) + (when (not (null-pointer-p handle)) (foreign-free handle)))) + +(defcallback data-read-cb ssize-t ((handle :pointer) (buffer :pointer) + (size size-t)) + (when *debug* (format t "DEBUG: gpgme-data-read-cb: want ~A~%" size)) + (let ((stream (gethash (pointer-address handle) *data-handles*))) + (cond + (stream + (let* ((stream-type (stream-element-type stream)) + (seq (make-array size :element-type stream-type)) + (read (read-sequence seq stream))) + (loop for i from 0 to (- read 1) + do (setf (mem-aref buffer :unsigned-char i) + ;;; FIXME: This is a half-assed attempt at + ;;; supporting character streams. + (cond + ((eql stream-type 'character) + (char-code (elt seq i))) + (t (coerce (elt seq i) stream-type))))) + (when *debug* (format t "DEBUG: gpgme-data-read-cb: read ~A~%" read)) + read)) + (t (set-errno +ebadf+) + -1)))) + +(defcallback data-write-cb ssize-t ((handle :pointer) (buffer :pointer) + (size size-t)) + (when *debug* (format t "DEBUG: gpgme-data-write-cb: want ~A~%" size)) + (let ((stream (gethash (pointer-address handle) *data-handles*))) + (cond + (stream + (let* ((stream-type (stream-element-type stream)) + (seq (make-array size :element-type stream-type))) + (loop for i from 0 to (- size 1) + do (setf (elt seq i) + ;;; FIXME: This is a half-assed attempt at + ;;; supporting character streams. + (cond + ((eql stream-type 'character) + (code-char (mem-aref buffer :unsigned-char i))) + (t (coerce (mem-aref buffer :unsigned-char i) + stream-type))))) + (write-sequence seq stream) + ;;; FIXME: What about write errors? + size)) + (t (set-errno +ebadf+) + -1)))) + +;;; This little helper macro allows us to swallow the cbs structure by +;;; simply setting it to a null pointer, but still protect against +;;; conditions. +(defmacro with-cbs-swallowed ((cbs) &body body) + `(let ((,cbs (foreign-alloc 'gpgme-data-cbs))) + (unwind-protect (progn ,@body) + (when (not (null-pointer-p ,cbs)) (foreign-free ,cbs))))) + +;;; FIXME: Wrap the object and attach to it a finalizer. Requires new +;;; CFFI. Should we use an OO interface, ie make-instance? For now, +;;; we do not provide direct access to data objects. +(defun gpgme-data-new (stream &key encoding file-name) + "Allocate a new GPGME data object for STREAM." + (with-foreign-object (dh-p 'gpgme-data-t) + ;;; We allocate one CBS structure for each stream we wrap in a + ;;; data object. Although we could also share all these + ;;; structures, as they contain the very same callbacks, we need a + ;;; unique C pointer as handle anyway to look up the stream in the + ;;; callback. This is a convenient one to use. + (with-cbs-swallowed (cbs) + (setf + (foreign-slot-value cbs 'gpgme-data-cbs 'read) (callback data-read-cb) + (foreign-slot-value cbs 'gpgme-data-cbs 'write) (callback data-write-cb) + (foreign-slot-value cbs 'gpgme-data-cbs 'seek) (null-pointer) + (foreign-slot-value cbs 'gpgme-data-cbs 'release) (callback + data-release-cb)) + (c-gpgme-data-new-from-cbs dh-p cbs cbs) + (let ((dh (mem-ref dh-p 'gpgme-data-t))) + (when encoding (gpgme-data-set-encoding dh encoding)) + (when file-name (gpgme-data-set-file-name dh file-name)) + ;;; Install the stream into the hash table and swallow the cbs + ;;; structure while protecting against any errors. + (unwind-protect + (progn + (setf (gethash (pointer-address cbs) *data-handles*) stream) + (setf cbs (null-pointer))) + (when (not (null-pointer-p cbs)) (c-gpgme-data-release dh))) + (when *debug* (format t "DEBUG: gpgme-data-new: ~A~%" dh)) + dh)))) + +;;; This function releases a GPGME data object. It implicitely +;;; invokes the data-release-cb function to clean up associated junk. +(defun gpgme-data-release (dh) + "Release a GPGME data object." + (when *debug* (format t "DEBUG: gpgme-data-release: ~A~%" dh)) + (c-gpgme-data-release dh)) + +(defmacro with-gpgme-data ((dh streamspec) &body body) + `(let ((,dh (if (listp ,streamspec) + (apply 'gpgme-data-new ,streamspec) + (gpgme-data-new ,streamspec)))) + (unwind-protect (progn ,@body) + (when (not (null-pointer-p ,dh)) (gpgme-data-release ,dh))))) + +(defun gpgme-data-get-encoding (dh) + "Get the encoding associated with the data object DH." + (c-gpgme-data-get-encoding dh)) + +(defun gpgme-data-set-encoding (dh encoding) + "Set the encoding associated with the data object DH to ENCODING." + (c-gpgme-data-set-encoding dh encoding)) + +(defun gpgme-data-get-file-name (dh) + "Get the file name associated with the data object DH." + (c-gpgme-data-get-file-name dh)) + +(defun gpgme-data-set-file-name (dh file-name) + "Set the file name associated with the data object DH to FILE-NAME." + (c-gpgme-data-set-file-name dh file-name)) + +;;; FIXME: Add key accessor interfaces. + +(defun gpgme-get-key (ctx fpr &optional secret) + "Get the key with the fingerprint FPR from the context CTX." + (with-foreign-object (key-p 'gpgme-key-t) + (c-gpgme-get-key ctx fpr key-p secret) + (mem-ref key-p 'gpgme-key-t))) + +(defun gpgme-key-ref (key) + "Acquire an additional reference to the key KEY." + (when *debug* (format t "DEBUG: gpgme-key-ref: ~A~%" key)) + (c-gpgme-key-ref key)) + +(defun gpgme-key-unref (key) + "Release a reference to the key KEY." + (when *debug* (format t "DEBUG: gpgme-key-unref: ~A~%" key)) + (c-gpgme-key-unref key)) + +;;; FIXME: We REALLY need pretty printing for keys and all the other +;;; big structs. + +;;; Various interfaces. + +(defun gpgme-check-version (&optional req-version) + (c-gpgme-check-version req-version)) + +;;; +;;; The *EXPORTED* CLOS interface. +;;; + +;;; The context type. + +;;; We wrap the C context pointer into a class object to be able to +;;; stick a finalizer on it. + +(defclass context () + (c-ctx ; The C context object pointer. + signers ; The list of signers. + sig-notation) ; The list of signers. + (:documentation "The GPGME context type.")) + +(defmethod initialize-instance :after ((ctx context) &rest rest + &key &allow-other-keys) + (let ((c-ctx (apply #'gpgme-new rest)) + (cleanup t)) + (unwind-protect + (progn (setf (slot-value ctx 'c-ctx) c-ctx) + (finalize ctx (lambda () (gpgme-release c-ctx))) + (setf cleanup nil)) + (if cleanup (gpgme-release c-ctx))))) + +(defmethod translate-to-foreign (value (type (eql 'gpgme-ctx-t))) + ;; Allow a pointer to be passed directly for the finalizer to work. + (if (pointerp value) value (slot-value value 'c-ctx))) + +(defmacro context (&rest rest) + "Create a new GPGME context." + `(make-instance 'context ,@rest)) + +;;; The context type: Accessor functions. + +;;; The context type: Accessor functions: Protocol. + +(defgeneric protocol (ctx) + (:documentation "Get the protocol of CONTEXT.")) + +(defmethod protocol ((ctx context)) + (gpgme-get-protocol ctx)) + +(defgeneric (setf protocol) (protocol ctx) + (:documentation "Set the protocol of CONTEXT to PROTOCOL.")) + +;;; FIXME: Adjust translator to reject invalid protocols. Currently, +;;; specifing an invalid protocol throws a "NIL is not 32 signed int" +;;; error. This is suboptimal. +(defmethod (setf protocol) (protocol (ctx context)) + (gpgme-set-protocol ctx protocol)) + +;;; The context type: Accessor functions: Armor. +;;; FIXME: Is it good style to make foop setf-able? Or should it be +;;; foo/foop for set/get? + +(defgeneric armorp (ctx) + (:documentation "Get the armor flag of CONTEXT.")) + +(defmethod armorp ((ctx context)) + (gpgme-armor-p ctx)) + +(defgeneric (setf armorp) (armor ctx) + (:documentation "Set the armor flag of CONTEXT to ARMOR.")) + +(defmethod (setf armorp) (armor (ctx context)) + (gpgme-set-armor ctx armor)) + +;;; The context type: Accessor functions: Textmode. +;;; FIXME: Is it good style to make foop setf-able? Or should it be +;;; foo/foop for set/get? + +(defgeneric textmodep (ctx) + (:documentation "Get the text mode flag of CONTEXT.")) + +(defmethod textmodep ((ctx context)) + (gpgme-textmode-p ctx)) + +(defgeneric (setf textmodep) (textmode ctx) + (:documentation "Set the text mode flag of CONTEXT to TEXTMODE.")) + +(defmethod (setf textmodep) (textmode (ctx context)) + (gpgme-set-textmode ctx textmode)) + +;;; The context type: Accessor functions: Include Certs. + +(defgeneric include-certs (ctx) + (:documentation "Get the number of included certificates in an + S/MIME message, or NIL if the default is used.")) + +(defmethod include-certs ((ctx context)) + (gpgme-get-include-certs ctx)) + +(defgeneric (setf include-certs) (certs ctx) + (:documentation "Return the number of certificates to include in an + S/MIME message, or NIL if the default is used.")) + +(defmethod (setf include-certs) (certs (ctx context)) + (gpgme-set-include-certs ctx certs)) + +;;; The context type: Accessor functions: Engine info. + +(defgeneric engine-info (ctx) + (:documentation "Retrieve the engine info for CTX.")) + +(defmethod engine-info ((ctx context)) + (gpgme-get-engine-info ctx)) + +(defgeneric (setf engine-info) (info ctx) + (:documentation "Set the engine info for CTX.")) + +(defmethod (setf engine-info) (info (ctx context)) + (dolist (proto '(:openpgp :cms)) + (let ((pinfo (getf info proto))) + (when pinfo + (gpgme-set-engine-info ctx proto :file-name (getf pinfo :file-name) + :home-dir (getf pinfo :home-dir)))))) + +;;; The context type: Accessor functions: Keylist mode. + +(defgeneric keylist-mode (ctx) + (:documentation "Get the keylist mode of CTX.")) + +(defmethod keylist-mode ((ctx context)) + (gpgme-get-keylist-mode ctx)) + +(defgeneric (setf keylist-mode) (mode ctx) + (:documentation "Set the keylist mode of CTX to MODE.")) + +(defmethod (setf keylist-mode) (mode (ctx context)) + (gpgme-set-keylist-mode ctx mode)) + +;;; The context type: Accessor functions: Signers. + +(defgeneric signers (ctx) + (:documentation "Get the signers of CTX.")) + +(defmethod signers ((ctx context)) + (slot-value ctx 'signers)) + +(defgeneric (setf signers) (signers ctx) + (:documentation "Set the signers of CTX to SIGNERS.")) + +(defmethod (setf keylist-mode) (signers (ctx context)) + (gpgme-set-signers ctx signers) + (setf (slot-value ctx 'signers) signers)) + +;;; The context type: Accessor functions: Sig notations. + +(defgeneric sig-notations (ctx) + (:documentation "Get the signature notations of CTX.")) + +(defmethod sig-notations ((ctx context)) + (slot-value ctx 'signers)) + +(defgeneric (setf sig-notations) (notations ctx) + (:documentation "Set the signatire notations of CTX to NOTATIONS.")) + +(defmethod (setf sig-notations) (notations (ctx context)) + (gpgme-set-signers ctx notations) + (setf (slot-value ctx 'notations) notations)) + +;;; The context type: Support macros. + +(defmacro with-context ((ctx &rest rest) &body body) + `(let ((,ctx (make-instance 'context ,@rest))) + ,@body)) + +;;; The key type. + +(defclass key () + (c-key) ; The C key object pointer. + (:documentation "The GPGME key type.")) + +;;; In the initializer, we swallow the c-key argument. +(defmethod initialize-instance :after ((key key) &key c-key + &allow-other-keys) + (setf (slot-value key 'c-key) c-key) + (finalize key (lambda () (gpgme-key-unref c-key)))) + +(defmethod translate-from-foreign (value (type (eql 'gpgme-key-t))) + (when *debug* (format t "DEBUG: import key: ~A~%" value)) + (make-instance 'key :c-key value)) + +(defmethod translate-to-foreign (value (type (eql 'gpgme-key-t))) + ;; Allow a pointer to be passed directly for the finalizer to work. + (if (pointerp value) value (slot-value value 'c-key))) + +(defmethod print-object ((key key) stream) + (print-unreadable-object (key stream :type t :identity t) + (format stream "~s" (fpr key)))) + +;;; The key type: Accessor functions. + +;;; FIXME: The bitfield and flags contain redundant information at +;;; this point. FIXME: Deal nicer with zero-length name (policy url) +;;; and zero length value (omit?) and human-readable (convert to string). +;;; FIXME: Turn binary data into sequence or vector or what it should be. +;;; FIXME: Turn the whole thing into a hash? +(defmethod translate-from-foreign (value (type (eql 'gpgme-sig-notation-t))) + (cond + ((null-pointer-p value) nil) + (t (with-foreign-slots + ((next name value name-len value-len flags bitfield) + value gpgme-sig-notation) + (append (list (list + :name name + :value value + :name-len name-len + :value-len value-len + :flags flags + :bitfield bitfield)) + next))))) + +;;; FIXME: Deal nicer with timestamps. bitfield field name? +(defmethod translate-from-foreign (value (type (eql 'gpgme-subkey-t))) + (cond + ((null-pointer-p value) nil) + (t (with-foreign-slots + ((next bitfield pubkey-algo length keyid fpr timestamp expires) + value gpgme-subkey) + (append (list (list + :bitfield bitfield + :pubkey-algo pubkey-algo + :length length + :keyid keyid + :fpr fpr + :timestamp timestamp + :expires expires)) + next))))) + +(defmethod translate-from-foreign (value (type (eql 'gpgme-key-sig-t))) + (cond + ((null-pointer-p value) nil) + (t (with-foreign-slots + ((next bitfield pubkey-algo keyid timestamp expires status + uid name email comment sig-class) + value gpgme-key-sig) + (append (list (list + :bitfield bitfield + :pubkey-algo pubkey-algo + :keyid keyid + :timestamp timestamp + :expires expires + :status status + :uid uid + :name name + :email email + :comment comment + :sig-class sig-class)) + next))))) + +(defmethod translate-from-foreign (value (type (eql 'gpgme-user-id-t))) + (cond + ((null-pointer-p value) nil) + (t (with-foreign-slots + ((next bitfield validity uid name email comment signatures) + value gpgme-user-id) + (append (list (list + :bitfield bitfield + :validity validity + :uid uid + :name name + :email email + :comment comment + :signatures signatures)) + next))))) + +(defun key-data (key) + (with-slots (c-key) key + (with-foreign-slots + ((bitfield protocol issuer-serial issuer-name chain-id + owner-trust subkeys uids keylist-mode) + c-key gpgme-key) + (list + :bitfield bitfield + :protocol protocol + :issuer-serial issuer-serial + :issuer-name issuer-name + :chain-id chain-id + :owner-trust owner-trust + :subkeys subkeys + :uids uids + :keylist-mode keylist-mode)) + )) + + +(defgeneric fpr (key) + (:documentation "Get the primary fingerprint of the key.")) + +(defmethod fpr ((key key)) + (getf (car (getf (key-data key) :subkeys)) :fpr)) + + +;;; The context type: Crypto-Operations. + +(defgeneric get-key (ctx fpr &optional secret) + (:documentation "Get the (secret) key FPR from CTX.")) + +(defmethod get-key ((ctx context) fpr &optional secret) + (gpgme-get-key ctx fpr secret)) + +;;; Encrypt. + +(defgeneric op-encrypt (ctx recp plain cipher &key always-trust sign) + (:documentation "Encrypt.")) + +(defmethod op-encrypt ((ctx context) recp plain cipher + &key always-trust sign) + (with-foreign-object (c-recp :pointer (+ 1 (length recp))) + (dotimes (i (length recp)) + (setf (mem-aref c-recp 'gpgme-key-t i) (elt recp i))) + (setf (mem-aref c-recp :pointer (length recp)) (null-pointer)) + (with-gpgme-data (in plain) + (with-gpgme-data (out cipher) + (let ((flags)) + (if always-trust (push :always-trust flags)) + (cond + (sign + (c-gpgme-op-encrypt-sign ctx c-recp flags in out) + (append (c-gpgme-op-encrypt-result ctx) + (c-gpgme-op-sign-result ctx))) + (t + (c-gpgme-op-encrypt ctx c-recp flags in out) + (c-gpgme-op-encrypt-result ctx)))))))) + +;;; Decrypt. + +(defgeneric op-decrypt (ctx cipher plain &key verify) + (:documentation "Decrypt.")) + +(defmethod op-decrypt ((ctx context) cipher plain &key verify) + (with-gpgme-data (in cipher) + (with-gpgme-data (out plain) + (cond + (verify + (c-gpgme-op-decrypt-verify ctx in out) + (append (c-gpgme-op-decrypt-result ctx) + (c-gpgme-op-verify-result ctx))) + (t + (c-gpgme-op-decrypt ctx in out) + (c-gpgme-op-decrypt-result ctx)))))) + +;;; Signing. + +(defgeneric op-sign (ctx plain sig &optional mode) + (:documentation "Sign.")) + +(defmethod op-sign ((ctx context) plain sig &optional (mode :none)) + (with-gpgme-data (in plain) + (with-gpgme-data (out sig) + (c-gpgme-op-sign ctx in out mode) + (c-gpgme-op-sign-result ctx)))) + +;;; Verify. + +(defgeneric op-verify (ctx sig text &key detached) + (:documentation "Verify.")) + +(defmethod op-verify ((ctx context) sig text &key detached) + (with-gpgme-data (in sig) + (with-gpgme-data (on text) + (c-gpgme-op-verify ctx in (if detached on nil) + (if detached nil on)) + (c-gpgme-op-verify-result ctx)))) + +;;; Import. + +(defgeneric op-import (ctx keydata) + (:documentation "Import.")) + +(defmethod op-import ((ctx context) keydata) + (with-gpgme-data (in keydata) + (c-gpgme-op-import ctx in) + (c-gpgme-op-import-result ctx))) + +;;; Export. + +(defgeneric op-export (ctx pattern keydata) + (:documentation "Export public key data matching PATTERN to the + stream KEYDATA.")) + +(defmethod op-export ((ctx context) pattern keydata) + (with-gpgme-data (dh keydata) + (c-gpgme-op-export ctx pattern 0 dh))) + +;;; Key generation. + + +;;; +;;; Initialization +;;; + +(defun check-version (&optional req-version) + "Check that the GPGME version requirement is satisfied." + (gpgme-check-version req-version)) + +(defparameter *version* (check-version) + "The version number of GPGME used.") diff --git a/tags/gpgme-1.1.6/ltmain.sh b/tags/gpgme-1.1.6/ltmain.sh new file mode 100644 index 0000000..927f716 --- /dev/null +++ b/tags/gpgme-1.1.6/ltmain.sh @@ -0,0 +1,6425 @@ +# ltmain.sh - Provide generalized library-building support services. +# NOTE: Changing this file will not affect anything until you rerun configure. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004 +# Free Software Foundation, Inc. +# Originally by Gordon Matzigkeit , 1996 +# +# This program 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. +# +# This program 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. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +basename="s,^.*/,,g" + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath="$0" + +# The name of this program: +progname=`echo "$progpath" | $SED $basename` +modename="$progname" + +# Global variables: +EXIT_SUCCESS=0 +EXIT_FAILURE=1 + +PROGRAM=ltmain.sh +PACKAGE=libtool +VERSION=1.5.4 +TIMESTAMP=" (1.1220.2.90 2004/04/03 14:10:19) Debian$Rev$" + + +# Check that we have a working $echo. +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then + # Yippee, $echo works! + : +else + # Restart under the correct shell, and then maybe $echo will work. + exec $SHELL "$progpath" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat <&2 + $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit $EXIT_FAILURE +fi + +# Global variables. +mode=$default_mode +nonopt= +prev= +prevopt= +run= +show="$echo" +show_help= +execute_dlfiles= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" + +##################################### +# Shell function definitions: +# This seems to be the best place for them + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +func_win32_libid () { + win32_libid_type="unknown" + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \ + $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then + win32_nmres=`eval $NM -f posix -A $1 | \ + sed -n -e '1,100{/ I /{x;/import/!{s/^/import/;h;p;};x;};}'` + if test "X$win32_nmres" = "Ximport" ; then + win32_libid_type="x86 archive import" + else + win32_libid_type="x86 archive static" + fi + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $echo $win32_libid_type +} + + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () { + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + CC_quoted="$CC_quoted $arg" + done + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + CC_quoted="$CC_quoted $arg" + done + case "$@ " in + " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + $echo "$modename: unable to infer tagged configuration" + $echo "$modename: specify a tag with \`--tag'" 1>&2 + exit $EXIT_FAILURE +# else +# $echo "$modename: using $tagname tagged configuration" + fi + ;; + esac + fi +} +# End of Shell function definitions +##################################### + +# Darwin sucks +eval std_shrext=\"$shrext_cmds\" + +# Parse our command line options once, thoroughly. +while test "$#" -gt 0 +do + arg="$1" + shift + + case $arg in + -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + execute_dlfiles) + execute_dlfiles="$execute_dlfiles $arg" + ;; + tag) + tagname="$arg" + preserve_args="${preserve_args}=$arg" + + # Check whether tagname contains only valid characters + case $tagname in + *[!-_A-Za-z0-9,/]*) + $echo "$progname: invalid tag name: $tagname" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + case $tagname in + CC) + # Don't test for the "default" C tag, as we know, it's there, but + # not specially marked. + ;; + *) + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$progpath" > /dev/null; then + taglist="$taglist $tagname" + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $progpath`" + else + $echo "$progname: ignoring unknown tag $tagname" 1>&2 + fi + ;; + esac + ;; + *) + eval "$prev=\$arg" + ;; + esac + + prev= + prevopt= + continue + fi + + # Have we seen a non-optional argument yet? + case $arg in + --help) + show_help=yes + ;; + + --version) + $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" + $echo + $echo "Copyright (C) 2003 Free Software Foundation, Inc." + $echo "This is free software; see the source for copying conditions. There is NO" + $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + exit $EXIT_SUCCESS + ;; + + --config) + ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $progpath + # Now print the configurations for the tags. + for tagname in $taglist; do + ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath" + done + exit $EXIT_SUCCESS + ;; + + --debug) + $echo "$progname: enabling shell trace mode" + set -x + preserve_args="$preserve_args $arg" + ;; + + --dry-run | -n) + run=: + ;; + + --features) + $echo "host: $host" + if test "$build_libtool_libs" = yes; then + $echo "enable shared libraries" + else + $echo "disable shared libraries" + fi + if test "$build_old_libs" = yes; then + $echo "enable static libraries" + else + $echo "disable static libraries" + fi + exit $EXIT_SUCCESS + ;; + + --finish) mode="finish" ;; + + --mode) prevopt="--mode" prev=mode ;; + --mode=*) mode="$optarg" ;; + + --preserve-dup-deps) duplicate_deps="yes" ;; + + --quiet | --silent) + show=: + preserve_args="$preserve_args $arg" + ;; + + --tag) prevopt="--tag" prev=tag ;; + --tag=*) + set tag "$optarg" ${1+"$@"} + shift + prev=tag + preserve_args="$preserve_args --tag" + ;; + + -dlopen) + prevopt="-dlopen" + prev=execute_dlfiles + ;; + + -*) + $echo "$modename: unrecognized option \`$arg'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + + *) + nonopt="$arg" + break + ;; + esac +done + +if test -n "$prevopt"; then + $echo "$modename: option \`$prevopt' requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE +fi + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + +if test -z "$show_help"; then + + # Infer the operation mode. + if test -z "$mode"; then + $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2 + $echo "*** Future versions of Libtool will require -mode=MODE be specified." 1>&2 + case $nonopt in + *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*) + mode=link + for arg + do + case $arg in + -c) + mode=compile + break + ;; + esac + done + ;; + *db | *dbx | *strace | *truss) + mode=execute + ;; + *install*|cp|mv) + mode=install + ;; + *rm) + mode=uninstall + ;; + *) + # If we have no mode, but dlfiles were specified, then do execute mode. + test -n "$execute_dlfiles" && mode=execute + + # Just use the default operation mode. + if test -z "$mode"; then + if test -n "$nonopt"; then + $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 + else + $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 + fi + fi + ;; + esac + fi + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$execute_dlfiles" && test "$mode" != execute; then + $echo "$modename: unrecognized option \`-dlopen'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$modename --help --mode=$mode' for more information." + + # These modes are in order of execution frequency so that they run quickly. + case $mode in + # libtool compile mode + compile) + modename="$modename: compile" + # Get the compilation command and the source file. + base_compile= + srcfile="$nonopt" # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + + for arg + do + case "$arg_mode" in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg="$arg" + arg_mode=normal + ;; + + target ) + libobj="$arg" + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + if test -n "$libobj" ; then + $echo "$modename: you cannot specify \`-o' more than once" 1>&2 + exit $EXIT_FAILURE + fi + arg_mode=target + continue + ;; + + -static | -prefer-pic | -prefer-non-pic) + later="$later $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"` + lastarg= + save_ifs="$IFS"; IFS=',' + for arg in $args; do + IFS="$save_ifs" + + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + lastarg="$lastarg $arg" + done + IFS="$save_ifs" + lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"` + + # Add the arguments to base_compile. + base_compile="$base_compile $lastarg" + continue + ;; + + * ) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg="$srcfile" + srcfile="$arg" + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` + + case $lastarg in + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + lastarg="\"$lastarg\"" + ;; + esac + + base_compile="$base_compile $lastarg" + done # for arg + + case $arg_mode in + arg) + $echo "$modename: you must specify an argument for -Xcompile" + exit $EXIT_FAILURE + ;; + target) + $echo "$modename: you must specify a target with \`-o'" 1>&2 + exit $EXIT_FAILURE + ;; + *) + # Get the name of the library object. + [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + xform='[cCFSifmso]' + case $libobj in + *.ada) xform=ada ;; + *.adb) xform=adb ;; + *.ads) xform=ads ;; + *.asm) xform=asm ;; + *.c++) xform=c++ ;; + *.cc) xform=cc ;; + *.ii) xform=ii ;; + *.class) xform=class ;; + *.cpp) xform=cpp ;; + *.cxx) xform=cxx ;; + *.f90) xform=f90 ;; + *.for) xform=for ;; + *.java) xform=java ;; + esac + + libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` + + case $libobj in + *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; + *) + $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -static) + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` + xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$obj"; then + xdir= + else + xdir=$xdir/ + fi + lobj=${xdir}$objdir/$objname + + if test -z "$base_compile"; then + $echo "$modename: you must specify a compilation command" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + $run $rm $removelist + trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2*) + pic_mode=default + ;; + esac + if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + removelist="$removelist $output_obj $lockfile" + trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until $run ln "$progpath" "$lockfile" 2>/dev/null; do + $show "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + $echo "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit $EXIT_FAILURE + fi + $echo $srcfile > "$lockfile" + fi + + if test -n "$fix_srcfile_path"; then + eval srcfile=\"$fix_srcfile_path\" + fi + + $run $rm "$libobj" "${libobj}T" + + # Create a libtool object file (analogous to a ".la" file), + # but don't create it if we're doing a dry run. + test -z "$run" && cat > ${libobj}T </dev/null`" != "X$srcfile"; then + $echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + $show "$mv $output_obj $lobj" + if $run $mv $output_obj $lobj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Append the name of the PIC object to the libtool object file. + test -z "$run" && cat >> ${libobj}T <> ${libobj}T </dev/null`" != "X$srcfile"; then + $echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + $show "$mv $output_obj $obj" + if $run $mv $output_obj $obj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Append the name of the non-PIC object the libtool object file. + # Only append if the libtool object file exists. + test -z "$run" && cat >> ${libobj}T <> ${libobj}T <&2 + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + else + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + fi + build_libtool_libs=no + build_old_libs=yes + prefer_static_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg="$1" + shift + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test + ;; + *) qarg=$arg ;; + esac + libtool_args="$libtool_args $qarg" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + compile_command="$compile_command @OUTPUT@" + finalize_command="$finalize_command @OUTPUT@" + ;; + esac + + case $prev in + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + compile_command="$compile_command @SYMFILE@" + finalize_command="$finalize_command @SYMFILE@" + preload=yes + fi + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + else + dlprefiles="$dlprefiles $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + if test ! -f "$arg"; then + $echo "$modename: symbol file \`$arg' does not exist" + exit $EXIT_FAILURE + fi + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; + precious_regex) + precious_files_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat $save_arg` + do +# moreargs="$moreargs $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + pic_object= + non_pic_object= + + # Read the .lo file + # If there is no directory component, then add one. + case $arg in + */* | *\\*) . $arg ;; + *) . ./$arg ;; + esac + + if test -z "$pic_object" || \ + test -z "$non_pic_object" || + test "$pic_object" = none && \ + test "$non_pic_object" = none; then + $echo "$modename: cannot find name of object for \`$arg'" 1>&2 + exit $EXIT_FAILURE + fi + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + libobjs="$libobjs $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + non_pic_objects="$non_pic_objects $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + fi + else + # Only an error if not doing a dry-run. + if test -z "$run"; then + $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 + exit $EXIT_FAILURE + else + # Dry-run case. + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` + non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` + libobjs="$libobjs $pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + fi + done + else + $echo "$modename: link input file \`$save_arg' does not exist" + exit $EXIT_FAILURE + fi + arg=$save_arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit $EXIT_FAILURE + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) rpath="$rpath $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) xrpath="$xrpath $arg" ;; + esac + fi + prev= + continue + ;; + xcompiler) + compiler_flags="$compiler_flags $qarg" + prev= + compile_command="$compile_command $qarg" + finalize_command="$finalize_command $qarg" + continue + ;; + xlinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $wl$qarg" + prev= + compile_command="$compile_command $wl$qarg" + finalize_command="$finalize_command $wl$qarg" + continue + ;; + xcclinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $qarg" + prev= + compile_command="$compile_command $qarg" + finalize_command="$finalize_command $qarg" + continue + ;; + shrext) + shrext_cmds="$arg" + prev= + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg="$arg" + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + compile_command="$compile_command $link_static_flag" + finalize_command="$finalize_command $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 + continue + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: more than one -exported-symbols argument is not allowed" + exit $EXIT_FAILURE + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + ;; + esac + continue + ;; + + -L*) + dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 + exit $EXIT_FAILURE + fi + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "*) ;; + *) + deplibs="$deplibs -L$dir" + lib_search_path="$lib_search_path $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + case :$dllsearchpath: in + *":$dir:"*) ;; + *) dllsearchpath="$dllsearchpath:$dir";; + esac + ;; + esac + continue + ;; + + -l*) + if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + case $host in + *-*-cygwin* | *-*-pw32* | *-*-beos*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-mingw* | *-*-os2*) + # These systems don't actually have a C library (as such) + test "X$arg" = "X-lc" && continue + ;; + *-*-openbsd* | *-*-freebsd*) + # Do not include libc due to us having libc/libc_r. + test "X$arg" = "X-lc" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + deplibs="$deplibs -framework System" + continue + esac + elif test "X$arg" = "X-lc_r"; then + case $host in + *-*-openbsd* | *-*-freebsd*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + deplibs="$deplibs $arg" + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) + deplibs="$deplibs $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + # gcc -m* arguments should be passed to the linker via $compiler_flags + # in order to pass architecture information to the linker + # (e.g. 32 vs 64-bit). This may also be accomplished via -Wl,-mfoo + # but this is not reliable with gcc because gcc may use -mfoo to + # select a different linker, different libraries, etc, while + # -Wl,-mfoo simply passes -mfoo to the linker. + -m*) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + if test "$with_gcc" = "yes" ; then + compiler_flags="$compiler_flags $arg" + fi + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + # The PATH hackery in wrapper scripts is required on Windows + # in order for the loader to find any dlls it needs. + $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2 + $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2 + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit $EXIT_FAILURE + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + continue + ;; + + -static) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -Wc,*) + args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'` + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + case $flag in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + flag="\"$flag\"" + ;; + esac + arg="$arg $wl$flag" + compiler_flags="$compiler_flags $flag" + done + IFS="$save_ifs" + arg=`$echo "X$arg" | $Xsed -e "s/^ //"` + ;; + + -Wl,*) + args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'` + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + case $flag in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + flag="\"$flag\"" + ;; + esac + arg="$arg $wl$flag" + compiler_flags="$compiler_flags $wl$flag" + linker_flags="$linker_flags $flag" + done + IFS="$save_ifs" + arg=`$echo "X$arg" | $Xsed -e "s/^ //"` + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # Some other compiler flag. + -* | +*) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + ;; + + *.$objext) + # A standard object. + objs="$objs $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + pic_object= + non_pic_object= + + # Read the .lo file + # If there is no directory component, then add one. + case $arg in + */* | *\\*) . $arg ;; + *) . ./$arg ;; + esac + + if test -z "$pic_object" || \ + test -z "$non_pic_object" || + test "$pic_object" = none && \ + test "$non_pic_object" = none; then + $echo "$modename: cannot find name of object for \`$arg'" 1>&2 + exit $EXIT_FAILURE + fi + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + libobjs="$libobjs $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + non_pic_objects="$non_pic_objects $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + fi + else + # Only an error if not doing a dry-run. + if test -z "$run"; then + $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 + exit $EXIT_FAILURE + else + # Dry-run case. + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` + non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` + libobjs="$libobjs $pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + fi + ;; + + *.$libext) + # An archive. + deplibs="$deplibs $arg" + old_deplibs="$old_deplibs $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + dlfiles="$dlfiles $arg" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + dlprefiles="$dlprefiles $arg" + prev= + else + deplibs="$deplibs $arg" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + done # argument parsing loop + + if test -n "$prev"; then + $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` + if test "X$output_objdir" = "X$output"; then + output_objdir="$objdir" + else + output_objdir="$output_objdir/$objdir" + fi + # Create the object directory. + if test ! -d "$output_objdir"; then + $show "$mkdir $output_objdir" + $run $mkdir $output_objdir + status=$? + if test "$status" -ne 0 && test ! -d "$output_objdir"; then + exit $status + fi + fi + + # Determine the type of output + case $output in + "") + $echo "$modename: you must specify an output file" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + case $host in + *cygwin* | *mingw* | *pw32*) + # don't eliminate duplications in $postdeps and $predeps + duplicate_compiler_generated_deps=yes + ;; + *) + duplicate_compiler_generated_deps=$duplicate_deps + ;; + esac + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if test "X$duplicate_deps" = "Xyes" ; then + case "$libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + libs="$libs $deplib" + done + + if test "$linkmode" = lib; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; + esac + pre_post_deps="$pre_post_deps $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + case $linkmode in + lib) + passes="conv link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2 + exit $EXIT_FAILURE + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=no + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + for pass in $passes; do + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan"; then + libs="$deplibs" + deplibs= + fi + if test "$linkmode" = prog; then + case $pass in + dlopen) libs="$dlfiles" ;; + dlpreopen) libs="$dlprefiles" ;; + link) + libs="$deplibs %DEPLIBS%" + test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" + ;; + esac + fi + if test "$pass" = dlopen; then + # Collect dlpreopened libraries + save_deplibs="$deplibs" + deplibs= + fi + for deplib in $libs; do + lib= + found=no + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + fi + continue + ;; + -l*) + if test "$linkmode" != lib && test "$linkmode" != prog; then + $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2 + continue + fi + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` + for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib="$searchdir/lib${name}${search_ext}" + if test -f "$lib"; then + if test "$search_ext" = ".la"; then + found=yes + else + found=no + fi + break 2 + fi + done + done + if test "$found" != yes; then + # deplib doesn't seem to be a libtool library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + else # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $deplib "*) + if (${SED} -e '2q' $lib | + grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + library_names= + old_library= + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + for l in $old_library $library_names; do + ll="$l" + done + if test "X$ll" = "X$old_library" ; then # only static version available + found=no + ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` + test "X$ladir" = "X$lib" && ladir="." + lib=$ladir/$old_library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + fi + ;; # -l + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test "$pass" = conv && continue + newdependency_libs="$deplib $newdependency_libs" + newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` + ;; + prog) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + if test "$pass" = scan; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` + ;; + *) + $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2 + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test "$pass" = link; then + dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'` + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) lib="$deplib" ;; + *.$libext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + if test "$deplibs_check_method" != pass_all; then + $echo + $echo "*** Warning: Trying to link with static lib archive $deplib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have" + $echo "*** because the file extensions .$libext of this argument makes me believe" + $echo "*** that it is just a static archive that I should not used here." + else + $echo + $echo "*** Warning: Linking the shared library $output against the" + $echo "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + continue + ;; + prog) + if test "$pass" != link; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + elif test "$linkmode" = prog; then + if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + newdlprefiles="$newdlprefiles $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + newdlfiles="$newdlfiles $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + if test "$found" = yes || test -f "$lib"; then : + else + $echo "$modename: cannot find the library \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + + ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` + test "X$ladir" = "X$lib" && ladir="." + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + + # Read the .la file + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test "$linkmode" != prog && test "$linkmode" != lib; }; then + test -n "$dlopen" && dlfiles="$dlfiles $dlopen" + test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" + fi + + if test "$pass" = conv; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + # It is a libtool convenience library, so add in its objects. + convenience="$convenience $ladir/$objdir/$old_library" + old_convenience="$old_convenience $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + elif test "$linkmode" != prog && test "$linkmode" != lib; then + $echo "$modename: \`$lib' is not a convenience library" 1>&2 + exit $EXIT_FAILURE + fi + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + for l in $old_library $library_names; do + linklib="$l" + done + if test -z "$linklib"; then + $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + + # This library was specified with -dlopen. + if test "$pass" = dlopen; then + if test -z "$libdir"; then + $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + if test -z "$dlname" || + test "$dlopen_support" != yes || + test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + dlprefiles="$dlprefiles $lib $dependency_libs" + else + newdlfiles="$newdlfiles $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2 + $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 + abs_ladir="$ladir" + fi + ;; + esac + laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + $echo "$modename: warning: library \`$lib' was moved." 1>&2 + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$libdir" + absdir="$libdir" + fi + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + fi # $installed = yes + name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + + # This library was specified with -dlpreopen. + if test "$pass" = dlpreopen; then + if test -z "$libdir"; then + $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + newdlprefiles="$newdlprefiles $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + newdlprefiles="$newdlprefiles $dir/$dlname" + else + newdlprefiles="$newdlprefiles $dir/$linklib" + fi + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test "$linkmode" = lib; then + deplibs="$dir/$old_library $deplibs" + elif test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test "$linkmode" = prog && test "$pass" != link; then + newlib_search_path="$newlib_search_path $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=no + if test "$link_all_deplibs" != no || test -z "$library_names" || + test "$build_libtool_libs" = no; then + linkalldeplibs=yes + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test + esac + # Need to link against all dependency_libs? + if test "$linkalldeplibs" = yes; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test "$linkmode,$pass" = "prog,link"; then + if test -n "$library_names" && + { test "$prefer_static_libs" = no || test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var"; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath " in + *" $dir "*) ;; + *" $absdir "*) ;; + *) temp_rpath="$temp_rpath $dir" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + if test -n "$library_names" && + { test "$prefer_static_libs" = no || test -z "$old_library"; }; then + if test "$installed" = no; then + notinst_deplibs="$notinst_deplibs $lib" + need_relink=yes + fi + # This is a shared library + + # Warn about portability, can't link against -module's on + # some systems (darwin) + if test "$shouldnotlink" = yes && test "$pass" = link ; then + $echo + if test "$linkmode" = prog; then + $echo "*** Warning: Linking the executable $output against the loadable module" + else + $echo "*** Warning: Linking the shared library $output against the loadable module" + fi + $echo "*** $linklib is not portable!" + fi + if test "$linkmode" = lib && + test "$hardcode_into_libs" = yes; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + realname="$2" + shift; shift + libname=`eval \\$echo \"$libname_spec\"` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname="$dlname" + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw*) + major=`expr $current - $age` + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + soname=`$echo $soroot | ${SED} -e 's/^.*\///'` + newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a" + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + $show "extracting exported symbol list from \`$soname'" + save_ifs="$IFS"; IFS='~' + cmds=$extract_expsyms_cmds + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + $show "generating import library for \`$soname'" + save_ifs="$IFS"; IFS='~' + cmds=$old_archive_from_expsyms_cmds + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test "$linkmode" = prog || test "$mode" != relink; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test "$hardcode_direct" = no; then + add="$dir/$linklib" + case $host in + *-*-sco3.2v5* ) add_dir="-L$dir" ;; + *-*-darwin* ) + # if the lib is a module then we can not link against + # it, someone is ignoring the new warnings I added + if /usr/bin/file -L $add 2> /dev/null | $EGREP "bundle" >/dev/null ; then + $echo "** Warning, lib $linklib is a module, not a shared library" + if test -z "$old_library" ; then + $echo + $echo "** And there doesn't seem to be a static archive available" + $echo "** The link will probably fail, sorry" + else + add="$dir/$old_library" + fi + fi + esac + elif test "$hardcode_minus_L" = no; then + case $host in + *-*-sunos*) add_shlibpath="$dir" ;; + esac + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = no; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + relink) + if test "$hardcode_direct" = yes; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$dir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case "$libdir" in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test "$lib_linked" != yes; then + $echo "$modename: configuration error: unsupported hardcode properties" + exit $EXIT_FAILURE + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; + esac + fi + if test "$linkmode" = prog; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test "$hardcode_direct" != yes && \ + test "$hardcode_minus_L" != yes && \ + test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + fi + fi + fi + + if test "$linkmode" = prog || test "$mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + add="-l$name" + elif test "$hardcode_automatic" = yes; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib" ; then + add="$inst_prefix_dir$libdir/$linklib" + else + add="$libdir/$linklib" + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir="-L$libdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case "$libdir" in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + fi + + if test "$linkmode" = prog; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test "$linkmode" = prog; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test "$build_libtool_libs" = yes; then + # Not a shared library + if test "$deplibs_check_method" != pass_all; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + $echo + $echo "*** Warning: This system can not link to static lib archive $lib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have." + if test "$module" = yes; then + $echo "*** But as you try to build a module library, libtool will still create " + $echo "*** a static module, that should work as long as the dlopening application" + $echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + $echo + $echo "*** However, this would only work if libtool was able to extract symbol" + $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + $echo "*** not find such a program. So, this module is probably useless." + $echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + convenience="$convenience $dir/$old_library" + old_convenience="$old_convenience $dir/$old_library" + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test "$linkmode" = lib; then + if test -n "$dependency_libs" && + { test "$hardcode_into_libs" != yes || + test "$build_old_libs" = yes || + test "$link_static" = yes; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'` + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) xrpath="$xrpath $temp_xrpath";; + esac;; + *) temp_deplibs="$temp_deplibs $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + newlib_search_path="$newlib_search_path $absdir" + # Link against this library + test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + + if test "$link_all_deplibs" != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + case $deplib in + -L*) path="$deplib" ;; + *.la) + dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$deplib" && dir="." + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 + absdir="$dir" + fi + ;; + esac + if grep "^installed=no" $deplib > /dev/null; then + path="$absdir/$objdir" + else + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + if test -z "$libdir"; then + $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + if test "$absdir" != "$libdir"; then + $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2 + fi + path="$absdir" + fi + depdepl= + case $host in + *-*-darwin*) + # we do not want to link against static libs, + # but need to link against shared + eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names" ; then + for tmp in $deplibrary_names ; do + depdepl=$tmp + done + if test -f "$path/$depdepl" ; then + depdepl="$path/$depdepl" + fi + # do not add paths which are already there + case " $newlib_search_path " in + *" $path "*) ;; + *) newlib_search_path="$newlib_search_path $path";; + esac + fi + path="" + ;; + *) + path="-L$path" + ;; + esac + ;; + -l*) + case $host in + *-*-darwin*) + # Again, we only want to link against shared libraries + eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"` + for tmp in $newlib_search_path ; do + if test -f "$tmp/lib$tmp_libs.dylib" ; then + eval depdepl="$tmp/lib$tmp_libs.dylib" + break + fi + done + path="" + ;; + *) continue ;; + esac + ;; + *) continue ;; + esac + case " $deplibs " in + *" $depdepl "*) ;; + *) deplibs="$depdepl $deplibs" ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$deplibs $path" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + dependency_libs="$newdependency_libs" + if test "$pass" = dlpreopen; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test "$pass" != dlopen; then + if test "$pass" != conv; then + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) lib_search_path="$lib_search_path $dir" ;; + esac + done + newlib_search_path= + fi + + if test "$linkmode,$pass" != "prog,link"; then + vars="deplibs" + else + vars="compile_deplibs finalize_deplibs" + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs ; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i="" + ;; + esac + if test -n "$i" ; then + tmp_libs="$tmp_libs $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test "$linkmode" = prog; then + dlfiles="$newdlfiles" + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 + fi + + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 + fi + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + objs="$objs$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + if test "$module" = no; then + $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1 + exit $EXIT_FAILURE + else + $echo + $echo "*** Warning: Linking the shared library $output against the non-libtool" + $echo "*** objects $objs is not portable!" + libobjs="$libobjs $objs" + fi + fi + + if test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2 + fi + + set dummy $rpath + if test "$#" -gt 2; then + $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 + fi + install_libdir="$2" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + # Some compilers have problems with a `.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 + fi + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + IFS="$save_ifs" + + if test -n "$8"; then + $echo "$modename: too many parameters to \`-version-info'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major="$2" + number_minor="$3" + number_revision="$4" + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # which has an extra 1 added just for fun + # + case $version_type in + darwin|linux|osf|windows) + current=`expr $number_major + $number_minor` + age="$number_minor" + revision="$number_revision" + ;; + freebsd-aout|freebsd-elf|sunos) + current="$number_major" + revision="$number_minor" + age="0" + ;; + irix|nonstopux) + current=`expr $number_major + $number_minor - 1` + age="$number_minor" + revision="$number_minor" + ;; + esac + ;; + no) + current="$2" + revision="$3" + age="$4" + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; + *) + $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + case $revision in + 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; + *) + $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + case $age in + 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; + *) + $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + if test "$age" -gt "$current"; then + $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + minor_current=`expr $current + 1` + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current"; + ;; + + irix | nonstopux) + major=`expr $current - $age + 1` + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring="$verstring_prefix$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test "$loop" -ne 0; do + iface=`expr $revision - $loop` + loop=`expr $loop - 1` + verstring="$verstring_prefix$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + ;; + + osf) + major=.`expr $current - $age` + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test "$loop" -ne 0; do + iface=`expr $current - $loop` + loop=`expr $loop - 1` + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + verstring="$verstring:${current}.0" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + major=`expr $current - $age` + versuffix="-$major" + ;; + + *) + $echo "$modename: unknown library version type \`$version_type'" 1>&2 + $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit $EXIT_FAILURE + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring="0.0" + ;; + esac + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + fi + + if test "$mode" != relink; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$echo "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) + if test "X$precious_files_regex" != "X"; then + if echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + removelist="$removelist $p" + ;; + *) ;; + esac + done + if test -n "$removelist"; then + $show "${rm}r $removelist" + $run ${rm}r $removelist + fi + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + oldlibs="$oldlibs $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + for path in $notinst_path; do + lib_search_path=`$echo "$lib_search_path " | ${SED} -e 's% $path % %g'` + deplibs=`$echo "$deplibs " | ${SED} -e 's% -L$path % %g'` + dependency_libs=`$echo "$dependency_libs " | ${SED} -e 's% -L$path % %g'` + done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + temp_xrpath="$temp_xrpath -R$libdir" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles="$dlfiles" + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) dlfiles="$dlfiles $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles="$dlprefiles" + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) dlprefiles="$dlprefiles $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + deplibs="$deplibs -framework System" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd*) + # Do not include libc due to us having libc/libc_r. + test "X$arg" = "X-lc" && continue + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test "$build_libtool_need_lc" = "yes"; then + deplibs="$deplibs -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $rm conftest.c + cat > conftest.c </dev/null` + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null \ + | grep " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ + | ${SED} 10q \ + | $EGREP "$file_magic_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $echo + $echo "*** Warning: linker path does not have real file for library $a_deplib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have" + $echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $echo "*** with $libname but no candidates were found. (...for file magic test)" + else + $echo "*** with $libname and none of the candidates passed a file format test" + $echo "*** using a file magic. Last file checked: $potlib" + fi + fi + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method + match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` + for a_deplib in $deplibs; do + name="`expr $a_deplib : '-l\(.*\)'`" + # If $name is empty we are operating on a -L argument. + if test -n "$name" && test "$name" != "0"; then + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + ;; + esac + fi + if test -n "$a_deplib" ; then + libname=`eval \\$echo \"$libname_spec\"` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib="$potent_lib" # see symlink-check above in file_magic test + if eval $echo \"$potent_lib\" 2>/dev/null \ + | ${SED} 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $echo + $echo "*** Warning: linker path does not have real file for library $a_deplib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have" + $echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $echo "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $echo "*** with $libname and none of the candidates passed a file format test" + $echo "*** using a regex pattern. Last file checked: $potlib" + fi + fi + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ + -e 's/ -[LR][^ ]*//g'` + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + for i in $predeps $postdeps ; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"` + done + fi + if $echo "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' \ + | grep . >/dev/null; then + $echo + if test "X$deplibs_check_method" = "Xnone"; then + $echo "*** Warning: inter-library dependencies are not supported in this platform." + else + $echo "*** Warning: inter-library dependencies are not known to be supported." + fi + $echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + fi + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'` + ;; + esac + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + $echo + $echo "*** Warning: libtool could not satisfy all declared inter-library" + $echo "*** dependencies of module $libname. Therefore, libtool will create" + $echo "*** a static module, that should work as long as the dlopening" + $echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + $echo + $echo "*** However, this would only work if libtool was able to extract symbol" + $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + $echo "*** not find such a program. So, this module is probably useless." + $echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + $echo "*** The inter-library dependencies that have been dropped here will be" + $echo "*** automatically added whenever a program is linked with this library" + $echo "*** or is declared to -dlopen it." + + if test "$allow_undefined" = no; then + $echo + $echo "*** Since this library must not contain undefined symbols," + $echo "*** because either the platform does not support them or" + $echo "*** it was explicitly requested with -no-undefined," + $echo "*** libtool will only create a static version of it." + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + if test "$hardcode_into_libs" = yes; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath="$finalize_rpath" + test "$mode" != relink && rpath="$compile_rpath$rpath" + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + dep_rpath="$dep_rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + if test -n "$hardcode_libdir_flag_spec_ld"; then + eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" + else + eval dep_rpath=\"$hardcode_libdir_flag_spec\" + fi + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath="$finalize_shlibpath" + test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + realname="$2" + shift; shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib="$output_objdir/$realname" + for link + do + linknames="$linknames $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + $show "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $run $rm $export_symbols + cmds=$export_symbols_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + if len=`expr "X$cmd" : ".*"` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + $show "$cmd" + $run eval "$cmd" || exit $? + skipped_export=false + else + # The command line is too long to execute in one step. + $show "using reloadable object file for export list..." + skipped_export=: + fi + done + IFS="$save_ifs" + if test -n "$export_symbols_regex"; then + $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" + $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + $show "$mv \"${export_symbols}T\" \"$export_symbols\"" + $run eval '$mv "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + tmp_deplibs="$tmp_deplibs $test_deplib" + ;; + esac + done + deplibs="$tmp_deplibs" + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${outputname}x" + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "$mkdir $gentop" + $run $mkdir "$gentop" + status=$? + if test "$status" -ne 0 && test ! -d "$gentop"; then + exit $status + fi + generated="$generated $gentop" + + for xlib in $convenience; do + # Extract the objects. + case $xlib in + [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; + *) xabs=`pwd`"/$xlib" ;; + esac + xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` + xdir="$gentop/$xlib" + + $show "${rm}r $xdir" + $run ${rm}r "$xdir" + $show "$mkdir $xdir" + $run $mkdir "$xdir" + status=$? + if test "$status" -ne 0 && test ! -d "$xdir"; then + exit $status + fi + # We will extract separately just the conflicting names and we will no + # longer touch any unique names. It is faster to leave these extract + # automatically by $AR in one run. + $show "(cd $xdir && $AR x $xabs)" + $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? + if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then + : + else + $echo "$modename: warning: object name conflicts; renaming object files" 1>&2 + $echo "$modename: warning: to ensure that they will not overwrite" 1>&2 + $AR t "$xabs" | sort | uniq -cd | while read -r count name + do + i=1 + while test "$i" -le "$count" + do + # Put our $i before any first dot (extension) + # Never overwrite any file + name_to="$name" + while test "X$name_to" = "X$name" || test -f "$xdir/$name_to" + do + name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"` + done + $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')" + $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $? + i=`expr $i + 1` + done + done + fi + + libobjs="$libobjs "`find $xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` + done + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + linker_flags="$linker_flags $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test "X$skipped_export" != "X:" && len=`expr "X$test_cmds" : ".*"` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise. + $echo "creating reloadable object files..." + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + delfiles= + last_robj= + k=1 + output=$output_objdir/$save_output-${k}.$objext + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + eval test_cmds=\"$reload_cmds $objlist $last_robj\" + if test "X$objlist" = X || + { len=`expr "X$test_cmds" : ".*"` && + test "$len" -le "$max_cmd_len"; }; then + objlist="$objlist $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test "$k" -eq 1 ; then + # The first file doesn't have a previous command to add. + eval concat_cmds=\"$reload_cmds $objlist $last_robj\" + else + # All subsequent reloadable object files will link in + # the last one created. + eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\" + fi + last_robj=$output_objdir/$save_output-${k}.$objext + k=`expr $k + 1` + output=$output_objdir/$save_output-${k}.$objext + objlist=$obj + len=1 + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" + + if ${skipped_export-false}; then + $show "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $run $rm $export_symbols + libobjs=$output + # Append the command to create the export file. + eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\" + fi + + # Set up a command to remove the reloadale object files + # after they are used. + i=0 + while test "$i" -lt "$k" + do + i=`expr $i + 1` + delfiles="$delfiles $output_objdir/$save_output-${i}.$objext" + done + + $echo "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs="$IFS"; IFS='~' + for cmd in $concat_cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + + # Append the command to remove the reloadable object files + # to the just-reset $cmds. + eval cmds=\"\$cmds~\$rm $delfiles\" + fi + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $? + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" + $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + obj) + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 + fi + + case $output in + *.lo) + if test -n "$objs$old_deplibs"; then + $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 + exit $EXIT_FAILURE + fi + libobj="$output" + obj=`$echo "X$output" | $Xsed -e "$lo2o"` + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $run $rm $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${obj}x" + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "$mkdir $gentop" + $run $mkdir "$gentop" + status=$? + if test "$status" -ne 0 && test ! -d "$gentop"; then + exit $status + fi + generated="$generated $gentop" + + for xlib in $convenience; do + # Extract the objects. + case $xlib in + [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; + *) xabs=`pwd`"/$xlib" ;; + esac + xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` + xdir="$gentop/$xlib" + + $show "${rm}r $xdir" + $run ${rm}r "$xdir" + $show "$mkdir $xdir" + $run $mkdir "$xdir" + status=$? + if test "$status" -ne 0 && test ! -d "$xdir"; then + exit $status + fi + # We will extract separately just the conflicting names and we will no + # longer touch any unique names. It is faster to leave these extract + # automatically by $AR in one run. + $show "(cd $xdir && $AR x $xabs)" + $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? + if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then + : + else + $echo "$modename: warning: object name conflicts; renaming object files" 1>&2 + $echo "$modename: warning: to ensure that they will not overwrite" 1>&2 + $AR t "$xabs" | sort | uniq -cd | while read -r count name + do + i=1 + while test "$i" -le "$count" + do + # Put our $i before any first dot (extension) + # Never overwrite any file + name_to="$name" + while test "X$name_to" = "X$name" || test -f "$xdir/$name_to" + do + name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"` + done + $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')" + $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $? + i=`expr $i + 1` + done + done + fi + + reload_conv_objs="$reload_objs "`find $xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` + done + fi + fi + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + cmds=$reload_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit $EXIT_SUCCESS + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $run eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + fi + + if test -n "$pic_flag" || test "$pic_mode" != default; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + cmds=$reload_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;; + esac + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 + fi + + if test "$preload" = yes; then + if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown && + test "$dlopen_self_static" = unknown; then + $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." + fi + fi + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'` + finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'` + ;; + esac + + case $host in + *darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + if test "$tagname" = CXX ; then + compile_command="$compile_command ${wl}-bind_at_load" + finalize_command="$finalize_command ${wl}-bind_at_load" + fi + ;; + esac + + compile_command="$compile_command $compile_deplibs" + finalize_command="$finalize_command $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + case :$dllsearchpath: in + *":$libdir:"*) ;; + *) dllsearchpath="$dllsearchpath:$libdir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + fi + + dlsyms= + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + dlsyms="${outputname}S.c" + else + $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 + fi + fi + + if test -n "$dlsyms"; then + case $dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${outputname}.nm" + + $show "$rm $nlist ${nlist}S ${nlist}T" + $run $rm "$nlist" "${nlist}S" "${nlist}T" + + # Parse the name list into a source file. + $show "creating $output_objdir/$dlsyms" + + test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ +/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ +/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +/* Prevent the only kind of declaration conflicts we can make. */ +#define lt_preloaded_symbols some_other_symbol + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + $show "generating symbol list for \`$output'" + + test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + for arg in $progfiles; do + $show "extracting global C symbols from \`$arg'" + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + if test -n "$export_symbols_regex"; then + $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$output.exp" + $run $rm $export_symbols + $run eval "${SED} -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + else + $run eval "${SED} -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"' + $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T' + $run eval 'mv "$nlist"T "$nlist"' + fi + fi + + for arg in $dlprefiles; do + $show "extracting global C symbols from \`$arg'" + name=`$echo "$arg" | ${SED} -e 's%^.*/%%'` + $run eval '$echo ": $name " >> "$nlist"' + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -z "$run"; then + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $mv "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if grep -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + grep -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' + else + $echo '/* NONE */' >> "$output_objdir/$dlsyms" + fi + + $echo >> "$output_objdir/$dlsyms" "\ + +#undef lt_preloaded_symbols + +#if defined (__STDC__) && __STDC__ +# define lt_ptr void * +#else +# define lt_ptr char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr address; +} +lt_preloaded_symbols[] = +{\ +" + + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms" + + $echo >> "$output_objdir/$dlsyms" "\ + {0, (lt_ptr) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + fi + + pic_flag_for_symtable= + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";; + esac;; + *-*-hpux*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag";; + esac + esac + + # Now compile the dynamic symbol file. + $show "(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" + $run eval '(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? + + # Clean up the generated files. + $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" + $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" + + # Transform the symbol file into the correct name. + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + ;; + *) + $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 + exit $EXIT_FAILURE + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi + + if test "$need_relink" = no || test "$build_libtool_libs" != yes; then + # Replace the output file specification. + compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + $show "$link_command" + $run eval "$link_command" + status=$? + + # Delete the generated files. + if test -n "$dlsyms"; then + $show "$rm $output_objdir/${outputname}S.${objext}" + $run $rm "$output_objdir/${outputname}S.${objext}" + fi + + exit $status + fi + + if test -n "$shlibpath_var"; then + # We should set the shlibpath_var + rpath= + for dir in $temp_rpath; do + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) + # Absolute path. + rpath="$rpath$dir:" + ;; + *) + # Relative path: add a thisdir entry. + rpath="$rpath\$thisdir/$dir:" + ;; + esac + done + temp_rpath="$rpath" + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + rpath="$rpath$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$no_install" = yes; then + # We don't need to create a wrapper script. + link_command="$compile_var$compile_command$compile_rpath" + # Replace the output file specification. + link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $run $rm $output + # Link the executable and exit + $show "$link_command" + $run eval "$link_command" || exit $? + exit $EXIT_SUCCESS + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 + $echo "$modename: \`$output' will be relinked during installation" 1>&2 + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname + + $show "$link_command" + $run eval "$link_command" || exit $? + + # Now create the wrapper script. + $show "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` + relink_command="$var=\"$var_value\"; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` + fi + + # Quote $echo for shipping. + if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then + case $progpath in + [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";; + *) qecho="$SHELL `pwd`/$progpath --fallback-echo";; + esac + qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` + else + qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` + fi + + # Only actually do things if our run command is non-null. + if test -z "$run"; then + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + cwrappersource=`$echo ${objdir}/lt-${output}.c` + cwrapper=`$echo ${output}.exe` + $rm $cwrappersource $cwrapper + trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + cat > $cwrappersource <> $cwrappersource<<"EOF" +#include +#include +#include +#include +#include +#include + +#if defined(PATH_MAX) +# define LT_PATHMAX PATH_MAX +#elif defined(MAXPATHLEN) +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef DIR_SEPARATOR +#define DIR_SEPARATOR '/' +#endif + +#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ + defined (__OS2__) +#define HAVE_DOS_BASED_FILE_SYSTEM +#ifndef DIR_SEPARATOR_2 +#define DIR_SEPARATOR_2 '\\' +#endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free ((void *) stale); stale = 0; } \ +} while (0) + +const char *program_name = NULL; + +void * xmalloc (size_t num); +char * xstrdup (const char *string); +char * basename (const char *name); +char * fnqualify(const char *path); +char * strendzap(char *str, const char *pat); +void lt_fatal (const char *message, ...); + +int +main (int argc, char *argv[]) +{ + char **newargz; + int i; + + program_name = (char *) xstrdup ((char *) basename (argv[0])); + newargz = XMALLOC(char *, argc+2); +EOF + + cat >> $cwrappersource <> $cwrappersource <<"EOF" + newargz[1] = fnqualify(argv[0]); + /* we know the script has the same name, without the .exe */ + /* so make sure newargz[1] doesn't end in .exe */ + strendzap(newargz[1],".exe"); + for (i = 1; i < argc; i++) + newargz[i+1] = xstrdup(argv[i]); + newargz[argc+1] = NULL; +EOF + + cat >> $cwrappersource <> $cwrappersource <<"EOF" +} + +void * +xmalloc (size_t num) +{ + void * p = (void *) malloc (num); + if (!p) + lt_fatal ("Memory exhausted"); + + return p; +} + +char * +xstrdup (const char *string) +{ + return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL +; +} + +char * +basename (const char *name) +{ + const char *base; + +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + /* Skip over the disk name in MSDOS pathnames. */ + if (isalpha (name[0]) && name[1] == ':') + name += 2; +#endif + + for (base = name; *name; name++) + if (IS_DIR_SEPARATOR (*name)) + base = name + 1; + return (char *) base; +} + +char * +fnqualify(const char *path) +{ + size_t size; + char *p; + char tmp[LT_PATHMAX + 1]; + + assert(path != NULL); + + /* Is it qualified already? */ +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + if (isalpha (path[0]) && path[1] == ':') + return xstrdup (path); +#endif + if (IS_DIR_SEPARATOR (path[0])) + return xstrdup (path); + + /* prepend the current directory */ + /* doesn't handle '~' */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + size = strlen(tmp) + 1 + strlen(path) + 1; /* +2 for '/' and '\0' */ + p = XMALLOC(char, size); + sprintf(p, "%s%c%s", tmp, DIR_SEPARATOR, path); + return p; +} + +char * +strendzap(char *str, const char *pat) +{ + size_t len, patlen; + + assert(str != NULL); + assert(pat != NULL); + + len = strlen(str); + patlen = strlen(pat); + + if (patlen <= len) + { + str += len - patlen; + if (strcmp(str, pat) == 0) + *str = '\0'; + } + return str; +} + +static void +lt_error_core (int exit_status, const char * mode, + const char * message, va_list ap) +{ + fprintf (stderr, "%s: %s: ", program_name, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, "FATAL", message, ap); + va_end (ap); +} +EOF + # we should really use a build-platform specific compiler + # here, but OTOH, the wrappers (shell script and this C one) + # are only useful if you want to execute the "real" binary. + # Since the "real" binary is built for $host, then this + # wrapper might as well be built for $host, too. + $run $LTCC -s -o $cwrapper $cwrappersource + ;; + esac + $rm $output + trap "$rm $output; exit $EXIT_FAILURE" 1 2 15 + + $echo > $output "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='${SED} -e 1s/^X//' +sed_quote_subst='$sed_quote_subst' + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variable: + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$echo are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + echo=\"$qecho\" + file=\"\$0\" + # Make sure echo works. + if test \"X\$1\" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift + elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then + # Yippee, \$echo works! + : + else + # Restart under the correct shell, and then maybe \$echo will work. + exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} + fi + fi\ +" + $echo >> $output "\ + + # Find the directory that this script lives in. + thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` + done + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + $echo >> $output "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || \\ + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $mkdir \"\$progdir\" + else + $rm \"\$progdir/\$file\" + fi" + + $echo >> $output "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + $echo \"\$relink_command_output\" >&2 + $rm \"\$progdir/\$file\" + exit $EXIT_FAILURE + fi + fi + + $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $rm \"\$progdir/\$program\"; + $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $rm \"\$progdir/\$file\" + fi" + else + $echo >> $output "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $echo >> $output "\ + + if test -f \"\$progdir/\$program\"; then" + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $echo >> $output "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` + + export $shlibpath_var +" + fi + + # fixup the dll searchpath if we need to. + if test -n "$dllsearchpath"; then + $echo >> $output "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + $echo >> $output "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2*) + $echo >> $output "\ + exec \$progdir\\\\\$program \${1+\"\$@\"} +" + ;; + + *) + $echo >> $output "\ + exec \$progdir/\$program \${1+\"\$@\"} +" + ;; + esac + $echo >> $output "\ + \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" + exit $EXIT_FAILURE + fi + else + # The program doesn't exist. + \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2 + \$echo \"This script is just a wrapper for \$program.\" 1>&2 + $echo \"See the $PACKAGE documentation for more information.\" 1>&2 + exit $EXIT_FAILURE + fi +fi\ +" + chmod +x $output + fi + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$old_deplibs $non_pic_objects" + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "$mkdir $gentop" + $run $mkdir "$gentop" + status=$? + if test "$status" -ne 0 && test ! -d "$gentop"; then + exit $status + fi + generated="$generated $gentop" + + # Add in members from convenience archives. + for xlib in $addlibs; do + # Extract the objects. + case $xlib in + [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; + *) xabs=`pwd`"/$xlib" ;; + esac + xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` + xdir="$gentop/$xlib" + + $show "${rm}r $xdir" + $run ${rm}r "$xdir" + $show "$mkdir $xdir" + $run $mkdir "$xdir" + status=$? + if test "$status" -ne 0 && test ! -d "$xdir"; then + exit $status + fi + # We will extract separately just the conflicting names and we will no + # longer touch any unique names. It is faster to leave these extract + # automatically by $AR in one run. + $show "(cd $xdir && $AR x $xabs)" + $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? + if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then + : + else + $echo "$modename: warning: object name conflicts; renaming object files" 1>&2 + $echo "$modename: warning: to ensure that they will not overwrite" 1>&2 + $AR t "$xabs" | sort | uniq -cd | while read -r count name + do + i=1 + while test "$i" -le "$count" + do + # Put our $i before any first dot (extension) + # Never overwrite any file + name_to="$name" + while test "X$name_to" = "X$name" || test -f "$xdir/$name_to" + do + name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"` + done + $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')" + $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $? + i=`expr $i + 1` + done + done + fi + + oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP` + done + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + cmds=$old_archive_from_new_cmds + else + eval cmds=\"$old_archive_cmds\" + + if len=`expr "X$cmds" : ".*"` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + $echo "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + # GNU ar 2.10+ was changed to match POSIX; thus no paths are + # encoded into archives. This makes 'ar r' malfunction in + # this piecewise linking case whenever conflicting object + # names appear in distinct ar calls; check, warn and compensate. + if (for obj in $save_oldobjs + do + $echo "X$obj" | $Xsed -e 's%^.*/%%' + done | sort | sort -uc >/dev/null 2>&1); then + : + else + $echo "$modename: warning: object name conflicts; overriding AR_FLAGS to 'cq'" 1>&2 + $echo "$modename: warning: to ensure that POSIX-compatible ar will work" 1>&2 + AR_FLAGS=cq + fi + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + for obj in $save_oldobjs + do + oldobjs="$objlist $obj" + objlist="$objlist $obj" + eval test_cmds=\"$old_archive_cmds\" + if len=`expr "X$test_cmds" : ".*"` && + test "$len" -le "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj" ; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" + objlist= + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test "X$oldobjs" = "X" ; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + eval cmd=\"$cmd\" + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$generated"; then + $show "${rm}r$generated" + $run ${rm}r$generated + fi + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + $show "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` + relink_command="$var=\"$var_value\"; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` + if test "$hardcode_automatic" = yes ; then + relink_command= + fi + + + # Only create the output if not a dry run. + if test -z "$run"; then + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + if test -z "$libdir"; then + $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdependency_libs="$newdependency_libs $libdir/$name" + ;; + *) newdependency_libs="$newdependency_libs $deplib" ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + for lib in $dlfiles; do + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdlfiles="$newdlfiles $libdir/$name" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdlprefiles="$newdlprefiles $libdir/$name" + done + dlprefiles="$newdlprefiles" + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlfiles="$newdlfiles $abs" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlprefiles="$newdlprefiles $abs" + done + dlprefiles="$newdlprefiles" + fi + $rm $output + # place dlname in correct position for cygwin + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; + esac + $echo > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test "$installed" = no && test "$need_relink" = yes; then + $echo >> $output "\ +relink_command=\"$relink_command\"" + fi + done + fi + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" + $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $? + ;; + esac + exit $EXIT_SUCCESS + ;; + + # libtool install mode + install) + modename="$modename: install" + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + # Allow the use of GNU shtool's install command. + $echo "X$nonopt" | $Xsed | grep shtool > /dev/null; then + # Aesthetically quote it. + arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$arg " + arg="$1" + shift + else + install_prog= + arg="$nonopt" + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog$arg" + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + for arg + do + if test -n "$dest"; then + files="$files $dest" + dest="$arg" + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) prev="-f" ;; + -g) prev="-g" ;; + -m) prev="-m" ;; + -o) prev="-o" ;; + -s) + stripme=" -s" + continue + ;; + -*) ;; + + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + prev= + else + dest="$arg" + continue + fi + ;; + esac + + # Aesthetically quote the argument. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog $arg" + done + + if test -z "$install_prog"; then + $echo "$modename: you must specify an install program" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test -n "$prev"; then + $echo "$modename: the \`$prev' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test -z "$files"; then + if test -z "$dest"; then + $echo "$modename: no file or destination specified" 1>&2 + else + $echo "$modename: you must specify a destination" 1>&2 + fi + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Strip any trailing slash from the destination. + dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` + test "X$destdir" = "X$dest" && destdir=. + destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` + + # Not a directory, so check to see that there is only one file specified. + set dummy $files + if test "$#" -gt 2; then + $echo "$modename: \`$dest' is not a directory" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + staticlibs="$staticlibs $file" + ;; + + *.la) + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + library_names= + old_library= + relink_command= + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) current_libdirs="$current_libdirs $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) future_libdirs="$future_libdirs $libdir" ;; + esac + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/ + test "X$dir" = "X$file/" && dir= + dir="$dir$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + if test "$inst_prefix_dir" = "$destdir"; then + $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2 + exit $EXIT_FAILURE + fi + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + $echo "$modename: warning: relinking \`$file'" 1>&2 + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + exit $EXIT_FAILURE + fi + fi + + # See the names of the shared library. + set dummy $library_names + if test -n "$2"; then + realname="$2" + shift + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + $show "$install_prog $dir/$srcname $destdir/$realname" + $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $? + if test -n "$stripme" && test -n "$striplib"; then + $show "$striplib $destdir/$realname" + $run eval "$striplib $destdir/$realname" || exit $? + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + for linkname + do + if test "$linkname" != "$realname"; then + $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" + $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" + fi + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + cmds=$postinstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Install the pseudo-library for information purposes. + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + instname="$dir/$name"i + $show "$install_prog $instname $destdir/$name" + $run eval "$install_prog $instname $destdir/$name" || exit $? + + # Maybe install the static library, too. + test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + # Install the libtool object if requested. + if test -n "$destfile"; then + $show "$install_prog $file $destfile" + $run eval "$install_prog $file $destfile" || exit $? + fi + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` + + $show "$install_prog $staticobj $staticdest" + $run eval "$install_prog \$staticobj \$staticdest" || exit $? + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext="" + case $file in + *.exe) + if test ! -f "$file"; then + file=`$echo $file|${SED} 's,.exe$,,'` + stripped_ext=".exe" + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin*|*mingw*) + wrapper=`$echo $file | ${SED} -e 's,.exe$,,'` + ;; + *) + wrapper=$file + ;; + esac + if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then + notinst_deplibs= + relink_command= + + # To insure that "foo" is sourced, and not "foo.exe", + # finese the cygwin/MSYS system by explicitly sourcing "foo." + # which disallows the automatic-append-.exe behavior. + case $build in + *cygwin* | *mingw*) wrapperdot=${wrapper}. ;; + *) wrapperdot=${wrapper} ;; + esac + # If there is no directory component, then add one. + case $file in + */* | *\\*) . ${wrapperdot} ;; + *) . ./${wrapperdot} ;; + esac + + # Check the variables that should have been set. + if test -z "$notinst_deplibs"; then + $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2 + exit $EXIT_FAILURE + fi + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + # If there is no directory component, then add one. + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + fi + libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 + finalize=no + fi + done + + relink_command= + # To insure that "foo" is sourced, and not "foo.exe", + # finese the cygwin/MSYS system by explicitly sourcing "foo." + # which disallows the automatic-append-.exe behavior. + case $build in + *cygwin* | *mingw*) wrapperdot=${wrapper}. ;; + *) wrapperdot=${wrapper} ;; + esac + # If there is no directory component, then add one. + case $file in + */* | *\\*) . ${wrapperdot} ;; + *) . ./${wrapperdot} ;; + esac + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + if test "$finalize" = yes && test -z "$run"; then + tmpdir="/tmp" + test -n "$TMPDIR" && tmpdir="$TMPDIR" + tmpdir="$tmpdir/libtool-$$" + save_umask=`umask` + umask 0077 + if $mkdir "$tmpdir"; then + umask $save_umask + else + umask $save_umask + $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2 + continue + fi + file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'` + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` + + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + ${rm}r "$tmpdir" + continue + fi + file="$outputname" + else + $echo "$modename: warning: cannot relink \`$file'" 1>&2 + fi + else + # Install the binary that we compiled earlier. + file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyways + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'` + ;; + esac + ;; + esac + $show "$install_prog$stripme $file $destfile" + $run eval "$install_prog\$stripme \$file \$destfile" || exit $? + test -n "$outputname" && ${rm}r "$tmpdir" + ;; + esac + done + + for file in $staticlibs; do + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + $show "$install_prog $file $oldlib" + $run eval "$install_prog \$file \$oldlib" || exit $? + + if test -n "$stripme" && test -n "$old_striplib"; then + $show "$old_striplib $oldlib" + $run eval "$old_striplib $oldlib" || exit $? + fi + + # Do each command in the postinstall commands. + cmds=$old_postinstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$future_libdirs"; then + $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 + fi + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + test -n "$run" && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi + ;; + + # libtool finish mode + finish) + modename="$modename: finish" + libdirs="$nonopt" + admincmds= + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for dir + do + libdirs="$libdirs $dir" + done + + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + cmds=$finish_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || admincmds="$admincmds + $cmd" + done + IFS="$save_ifs" + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $run eval "$cmds" || admincmds="$admincmds + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + test "$show" = : && exit $EXIT_SUCCESS + + $echo "----------------------------------------------------------------------" + $echo "Libraries have been installed in:" + for libdir in $libdirs; do + $echo " $libdir" + done + $echo + $echo "If you ever happen to want to link against installed libraries" + $echo "in a given directory, LIBDIR, you must either use libtool, and" + $echo "specify the full pathname of the library, or use the \`-LLIBDIR'" + $echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + $echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + $echo " during execution" + fi + if test -n "$runpath_var"; then + $echo " - add LIBDIR to the \`$runpath_var' environment variable" + $echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $echo " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + $echo " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + $echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + $echo + $echo "See any operating system documentation about shared libraries for" + $echo "more information, such as the ld(1) and ld.so(8) manual pages." + $echo "----------------------------------------------------------------------" + exit $EXIT_SUCCESS + ;; + + # libtool execute mode + execute) + modename="$modename: execute" + + # The first argument is the command name. + cmd="$nonopt" + if test -z "$cmd"; then + $echo "$modename: you must specify a COMMAND" 1>&2 + $echo "$help" + exit $EXIT_FAILURE + fi + + # Handle -dlopen flags immediately. + for file in $execute_dlfiles; do + if test ! -f "$file"; then + $echo "$modename: \`$file' is not a file" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + dir= + case $file in + *.la) + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Read the libtool library. + dlname= + library_names= + + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" + continue + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + + if test -f "$dir/$objdir/$dlname"; then + dir="$dir/$objdir" + else + $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 + exit $EXIT_FAILURE + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + ;; + + *) + $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -*) ;; + *) + # Do a test to see if this is really a libtool program. + if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` + args="$args \"$file\"" + done + + if test -z "$run"; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + if test "${save_LC_ALL+set}" = set; then + LC_ALL="$save_LC_ALL"; export LC_ALL + fi + if test "${save_LANG+set}" = set; then + LANG="$save_LANG"; export LANG + fi + + # Now prepare to actually exec the command. + exec_cmd="\$cmd$args" + else + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" + $echo "export $shlibpath_var" + fi + $echo "$cmd$args" + exit $EXIT_SUCCESS + fi + ;; + + # libtool clean and uninstall mode + clean | uninstall) + modename="$modename: $mode" + rm="$nonopt" + files= + rmforce= + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + for arg + do + case $arg in + -f) rm="$rm $arg"; rmforce=yes ;; + -*) rm="$rm $arg" ;; + *) files="$files $arg" ;; + esac + done + + if test -z "$rm"; then + $echo "$modename: you must specify an RM program" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + rmdirs= + + origobjdir="$objdir" + for file in $files; do + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + if test "X$dir" = "X$file"; then + dir=. + objdir="$origobjdir" + else + objdir="$dir/$origobjdir" + fi + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + test "$mode" = uninstall && objdir="$dir" + + # Remember objdir for removal later, being careful to avoid duplicates + if test "$mode" = clean; then + case " $rmdirs " in + *" $objdir "*) ;; + *) rmdirs="$rmdirs $objdir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if (test -L "$file") >/dev/null 2>&1 \ + || (test -h "$file") >/dev/null 2>&1 \ + || test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif test "$rmforce" = yes; then + continue + fi + + rmfiles="$file" + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + . $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + rmfiles="$rmfiles $objdir/$n" + done + test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" + test "$mode" = clean && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" + + if test "$mode" = uninstall; then + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + cmds=$postuninstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" + if test "$?" -ne 0 && test "$rmforce" != yes; then + exit_status=1 + fi + done + IFS="$save_ifs" + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + cmds=$old_postuninstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" + if test "$?" -ne 0 && test "$rmforce" != yes; then + exit_status=1 + fi + done + IFS="$save_ifs" + fi + # FIXME: should reinstall the best remaining shared library. + fi + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + + # Read the .lo file + . $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" \ + && test "$pic_object" != none; then + rmfiles="$rmfiles $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" \ + && test "$non_pic_object" != none; then + rmfiles="$rmfiles $dir/$non_pic_object" + fi + fi + ;; + + *) + if test "$mode" = clean ; then + noexename=$name + case $file in + *.exe) + file=`$echo $file|${SED} 's,.exe$,,'` + noexename=`$echo $name|${SED} 's,.exe$,,'` + # $file with .exe has already been added to rmfiles, + # add $file without .exe + rmfiles="$rmfiles $file" + ;; + esac + # Do a test to see if this is a libtool program. + if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + relink_command= + . $dir/$noexename + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" + if test "$fast_install" = yes && test -n "$relink_command"; then + rmfiles="$rmfiles $objdir/lt-$name" + fi + if test "X$noexename" != "X$name" ; then + rmfiles="$rmfiles $objdir/lt-${noexename}.c" + fi + fi + fi + ;; + esac + $show "$rm $rmfiles" + $run $rm $rmfiles || exit_status=1 + done + objdir="$origobjdir" + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + $show "rmdir $dir" + $run rmdir $dir >/dev/null 2>&1 + fi + done + + exit $exit_status + ;; + + "") + $echo "$modename: you must specify a MODE" 1>&2 + $echo "$generic_help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + if test -z "$exec_cmd"; then + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$generic_help" 1>&2 + exit $EXIT_FAILURE + fi +fi # test -z "$show_help" + +if test -n "$exec_cmd"; then + eval exec $exec_cmd + exit $EXIT_FAILURE +fi + +# We need to display help for each of the modes. +case $mode in +"") $echo \ +"Usage: $modename [OPTION]... [MODE-ARG]... + +Provide generalized library-building support services. + + --config show all configuration variables + --debug enable verbose shell tracing +-n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --finish same as \`--mode=finish' + --help display this help message and exit + --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] + --quiet same as \`--silent' + --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + --version print version information + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for +a more detailed description of MODE. + +Report bugs to ." + exit $EXIT_SUCCESS + ;; + +clean) + $echo \ +"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + +compile) + $echo \ +"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -prefer-pic try to building PIC objects only + -prefer-non-pic try to building non-PIC objects only + -static always build a \`.o' file suitable for static linking + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + +execute) + $echo \ +"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + +finish) + $echo \ +"Usage: $modename [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + +install) + $echo \ +"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + +link) + $echo \ +"Usage: $modename [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE Use a list of object files found in FILE to specify objects + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -static do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + +uninstall) + $echo \ +"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + +*) + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; +esac + +$echo +$echo "Try \`$modename --help' for more information about other modes." + +exit $EXIT_SUCCESS + +# The TAGs below are defined such that we never get into a situation +# in which we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) $echo no;; *) $echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/tags/gpgme-1.1.6/m4/ChangeLog b/tags/gpgme-1.1.6/m4/ChangeLog new file mode 100644 index 0000000..fadd952 --- /dev/null +++ b/tags/gpgme-1.1.6/m4/ChangeLog @@ -0,0 +1,35 @@ +2006-06-08 Marcus Brinkmann + + * pth.m4: Add --all to pth-config invocation. + +2006-02-22 Marcus Brinkmann + + * pth.m4: Fix code generation (required for Max OS X). + Submitted by Emanuele Giaquinta . + +2005-11-17 Marcus Brinkmann + + * glib-2.0.m4: New file. + +2004-12-28 Werner Koch + + * pth.m4: Changed quoting for use with automake 1.9. + +2004-09-14 Marcus Brinkmann + + * pth.m4: Disable _ac_pth_line, and don't fail if Pth is not + found. + + * glibc21.m4: New file. + * gpg-error.m4: New file. + * pth.m4: New file. + + Copyright 2004 g10 Code GmbH + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/tags/gpgme-1.1.6/m4/glib-2.0.m4 b/tags/gpgme-1.1.6/m4/glib-2.0.m4 new file mode 100644 index 0000000..d6413ff --- /dev/null +++ b/tags/gpgme-1.1.6/m4/glib-2.0.m4 @@ -0,0 +1,215 @@ +# Configure paths for GLIB +# Owen Taylor 1997-2001 + +dnl AM_PATH_GLIB_2_0([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]]) +dnl Test for GLIB, and define GLIB_CFLAGS and GLIB_LIBS, if gmodule, gobject or +dnl gthread is specified in MODULES, pass to pkg-config +dnl +AC_DEFUN([AM_PATH_GLIB_2_0], +[dnl +dnl Get the cflags and libraries from pkg-config +dnl +AC_ARG_ENABLE(glibtest, [ --disable-glibtest do not try to compile and run a test GLIB program], + , enable_glibtest=yes) + + pkg_config_args=glib-2.0 + for module in . $4 + do + case "$module" in + gmodule) + pkg_config_args="$pkg_config_args gmodule-2.0" + ;; + gmodule-no-export) + pkg_config_args="$pkg_config_args gmodule-no-export-2.0" + ;; + gobject) + pkg_config_args="$pkg_config_args gobject-2.0" + ;; + gthread) + pkg_config_args="$pkg_config_args gthread-2.0" + ;; + esac + done + + AC_PATH_PROG(PKG_CONFIG, pkg-config, no) + + no_glib="" + + if test x$PKG_CONFIG != xno ; then + if $PKG_CONFIG --atleast-pkgconfig-version 0.7 ; then + : + else + echo *** pkg-config too old; version 0.7 or better required. + no_glib=yes + PKG_CONFIG=no + fi + else + no_glib=yes + fi + + min_glib_version=ifelse([$1], ,2.0.0,$1) + AC_MSG_CHECKING(for GLIB - version >= $min_glib_version) + + if test x$PKG_CONFIG != xno ; then + ## don't try to run the test against uninstalled libtool libs + if $PKG_CONFIG --uninstalled $pkg_config_args; then + echo "Will use uninstalled version of GLib found in PKG_CONFIG_PATH" + enable_glibtest=no + fi + + if $PKG_CONFIG --atleast-version $min_glib_version $pkg_config_args; then + : + else + no_glib=yes + fi + fi + + if test x"$no_glib" = x ; then + GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0` + GOBJECT_QUERY=`$PKG_CONFIG --variable=gobject_query glib-2.0` + GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0` + + GLIB_CFLAGS=`$PKG_CONFIG --cflags $pkg_config_args` + GLIB_LIBS=`$PKG_CONFIG --libs $pkg_config_args` + glib_config_major_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + glib_config_minor_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + glib_config_micro_version=`$PKG_CONFIG --modversion glib-2.0 | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + if test "x$enable_glibtest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $GLIB_CFLAGS" + LIBS="$GLIB_LIBS $LIBS" +dnl +dnl Now check if the installed GLIB is sufficiently new. (Also sanity +dnl checks the results of pkg-config to some extent) +dnl + rm -f conf.glibtest + AC_TRY_RUN([ +#include +#include +#include + +int +main () +{ + int major, minor, micro; + char *tmp_version; + + system ("touch conf.glibtest"); + + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = g_strdup("$min_glib_version"); + if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_glib_version"); + exit(1); + } + + if ((glib_major_version != $glib_config_major_version) || + (glib_minor_version != $glib_config_minor_version) || + (glib_micro_version != $glib_config_micro_version)) + { + printf("\n*** 'pkg-config --modversion glib-2.0' returned %d.%d.%d, but GLIB (%d.%d.%d)\n", + $glib_config_major_version, $glib_config_minor_version, $glib_config_micro_version, + glib_major_version, glib_minor_version, glib_micro_version); + printf ("*** was found! If pkg-config was correct, then it is best\n"); + printf ("*** to remove the old version of GLib. You may also be able to fix the error\n"); + printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); + printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); + printf("*** required on your system.\n"); + printf("*** If pkg-config was wrong, set the environment variable PKG_CONFIG_PATH\n"); + printf("*** to point to the correct configuration files\n"); + } + else if ((glib_major_version != GLIB_MAJOR_VERSION) || + (glib_minor_version != GLIB_MINOR_VERSION) || + (glib_micro_version != GLIB_MICRO_VERSION)) + { + printf("*** GLIB header files (version %d.%d.%d) do not match\n", + GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION); + printf("*** library (version %d.%d.%d)\n", + glib_major_version, glib_minor_version, glib_micro_version); + } + else + { + if ((glib_major_version > major) || + ((glib_major_version == major) && (glib_minor_version > minor)) || + ((glib_major_version == major) && (glib_minor_version == minor) && (glib_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** An old version of GLIB (%d.%d.%d) was found.\n", + glib_major_version, glib_minor_version, glib_micro_version); + printf("*** You need a version of GLIB newer than %d.%d.%d. The latest version of\n", + major, minor, micro); + printf("*** GLIB is always available from ftp://ftp.gtk.org.\n"); + printf("***\n"); + printf("*** If you have already installed a sufficiently new version, this error\n"); + printf("*** probably means that the wrong copy of the pkg-config shell script is\n"); + printf("*** being found. The easiest way to fix this is to remove the old version\n"); + printf("*** of GLIB, but you can also set the PKG_CONFIG environment to point to the\n"); + printf("*** correct copy of pkg-config. (In this case, you will have to\n"); + printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); + printf("*** so that the correct libraries are found at run-time))\n"); + } + } + return 1; +} +],, no_glib=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_glib" = x ; then + AC_MSG_RESULT(yes (version $glib_config_major_version.$glib_config_minor_version.$glib_config_micro_version)) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "$PKG_CONFIG" = "no" ; then + echo "*** A new enough version of pkg-config was not found." + echo "*** See http://www.freedesktop.org/software/pkgconfig/" + else + if test -f conf.glibtest ; then + : + else + echo "*** Could not run GLIB test program, checking why..." + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $GLIB_CFLAGS" + LIBS="$LIBS $GLIB_LIBS" + AC_TRY_LINK([ +#include +#include +], [ return ((glib_major_version) || (glib_minor_version) || (glib_micro_version)); ], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding GLIB or finding the wrong" + echo "*** version of GLIB. If it is not finding GLIB, 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 that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means GLIB is incorrectly installed."]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + GLIB_CFLAGS="" + GLIB_LIBS="" + GLIB_GENMARSHAL="" + GOBJECT_QUERY="" + GLIB_MKENUMS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(GLIB_CFLAGS) + AC_SUBST(GLIB_LIBS) + AC_SUBST(GLIB_GENMARSHAL) + AC_SUBST(GOBJECT_QUERY) + AC_SUBST(GLIB_MKENUMS) + rm -f conf.glibtest +]) diff --git a/tags/gpgme-1.1.6/m4/glibc21.m4 b/tags/gpgme-1.1.6/m4/glibc21.m4 new file mode 100644 index 0000000..9c9f3db --- /dev/null +++ b/tags/gpgme-1.1.6/m4/glibc21.m4 @@ -0,0 +1,32 @@ +# glibc21.m4 serial 2 (fileutils-4.1.3, gettext-0.10.40) +dnl Copyright (C) 2000-2002 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +# Test for the GNU C Library, version 2.1 or newer. +# From Bruno Haible. + +AC_DEFUN([jm_GLIBC21], + [ + AC_CACHE_CHECK(whether we are using the GNU C Library 2.1 or newer, + ac_cv_gnu_library_2_1, + [AC_EGREP_CPP([Lucky GNU user], + [ +#include +#ifdef __GNU_LIBRARY__ + #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2) + Lucky GNU user + #endif +#endif + ], + ac_cv_gnu_library_2_1=yes, + ac_cv_gnu_library_2_1=no) + ] + ) + AC_SUBST(GLIBC21) + GLIBC21="$ac_cv_gnu_library_2_1" + ] +) diff --git a/tags/gpgme-1.1.6/m4/gpg-error.m4 b/tags/gpgme-1.1.6/m4/gpg-error.m4 new file mode 100644 index 0000000..e85f511 --- /dev/null +++ b/tags/gpgme-1.1.6/m4/gpg-error.m4 @@ -0,0 +1,65 @@ +# gpg-error.m4 - autoconf macro to detect libgpg-error. +# Copyright (C) 2002, 2003, 2004 g10 Code GmbH +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This file is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +dnl AM_PATH_GPG_ERROR([MINIMUM-VERSION, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl Test for libgpg-error and define GPG_ERROR_CFLAGS and GPG_ERROR_LIBS +dnl +AC_DEFUN([AM_PATH_GPG_ERROR], +[ AC_ARG_WITH(gpg-error-prefix, + AC_HELP_STRING([--with-gpg-error-prefix=PFX], + [prefix where GPG Error is installed (optional)]), + gpg_error_config_prefix="$withval", gpg_error_config_prefix="") + if test x$gpg_error_config_prefix != x ; then + if test x${GPG_ERROR_CONFIG+set} != xset ; then + GPG_ERROR_CONFIG=$gpg_error_config_prefix/bin/gpg-error-config + fi + fi + + AC_PATH_PROG(GPG_ERROR_CONFIG, gpg-error-config, no) + min_gpg_error_version=ifelse([$1], ,0.0,$1) + AC_MSG_CHECKING(for GPG Error - version >= $min_gpg_error_version) + ok=no + if test "$GPG_ERROR_CONFIG" != "no" ; then + req_major=`echo $min_gpg_error_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` + req_minor=`echo $min_gpg_error_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` + gpg_error_config_version=`$GPG_ERROR_CONFIG $gpg_error_config_args --version` + major=`echo $gpg_error_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` + minor=`echo $gpg_error_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` + if test "$major" -gt "$req_major"; then + ok=yes + else + if test "$major" -eq "$req_major"; then + if test "$minor" -ge "$req_minor"; then + ok=yes + fi + fi + fi + fi + if test $ok = yes; then + GPG_ERROR_CFLAGS=`$GPG_ERROR_CONFIG $gpg_error_config_args --cflags` + GPG_ERROR_LIBS=`$GPG_ERROR_CONFIG $gpg_error_config_args --libs` + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + GPG_ERROR_CFLAGS="" + GPG_ERROR_LIBS="" + AC_MSG_RESULT(no) + ifelse([$3], , :, [$3]) + fi + AC_SUBST(GPG_ERROR_CFLAGS) + AC_SUBST(GPG_ERROR_LIBS) +]) + diff --git a/tags/gpgme-1.1.6/m4/libtool.m4 b/tags/gpgme-1.1.6/m4/libtool.m4 new file mode 100644 index 0000000..7d30139 --- /dev/null +++ b/tags/gpgme-1.1.6/m4/libtool.m4 @@ -0,0 +1,5939 @@ +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +## Copyright 1996, 1997, 1998, 1999, 2000, 2001 +## Free Software Foundation, Inc. +## Originally by Gordon Matzigkeit , 1996 +## +## This program 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. +## +## This program 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. +## +## As a special exception to the GNU General Public License, if you +## distribute this file as part of a program that contains a +## configuration script generated by Autoconf, you may include it under +## the same distribution terms that you use for the rest of that program. + +# serial 47 AC_PROG_LIBTOOL +# Debian $Rev$ + + +# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) +# ----------------------------------------------------------- +# If this macro is not defined by Autoconf, define it here. +m4_ifdef([AC_PROVIDE_IFELSE], + [], + [m4_define([AC_PROVIDE_IFELSE], + [m4_ifdef([AC_PROVIDE_$1], + [$2], [$3])])]) + + +# AC_PROG_LIBTOOL +# --------------- +AC_DEFUN([AC_PROG_LIBTOOL], +[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl +dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX +dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX. + AC_PROVIDE_IFELSE([AC_PROG_CXX], + [AC_LIBTOOL_CXX], + [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX + ])]) +dnl And a similar setup for Fortran 77 support + AC_PROVIDE_IFELSE([AC_PROG_F77], + [AC_LIBTOOL_F77], + [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77 +])]) + +dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly. +dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run +dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both. + AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [ifdef([AC_PROG_GCJ], + [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([A][M_PROG_GCJ], + [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([LT_AC_PROG_GCJ], + [define([LT_AC_PROG_GCJ], + defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])]) +])])# AC_PROG_LIBTOOL + + +# _AC_PROG_LIBTOOL +# ---------------- +AC_DEFUN([_AC_PROG_LIBTOOL], +[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl +AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl +AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl +AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +# Prevent multiple expansion +define([AC_PROG_LIBTOOL], []) +])# _AC_PROG_LIBTOOL + + +# AC_LIBTOOL_SETUP +# ---------------- +AC_DEFUN([AC_LIBTOOL_SETUP], +[AC_PREREQ(2.50)dnl +AC_REQUIRE([AC_ENABLE_SHARED])dnl +AC_REQUIRE([AC_ENABLE_STATIC])dnl +AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_LD])dnl +AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl +AC_REQUIRE([AC_PROG_NM])dnl + +AC_REQUIRE([AC_PROG_LN_S])dnl +AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl +# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! +AC_REQUIRE([AC_OBJEXT])dnl +AC_REQUIRE([AC_EXEEXT])dnl +dnl + +AC_LIBTOOL_SYS_MAX_CMD_LEN +AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +AC_LIBTOOL_OBJDIR + +AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +_LT_AC_PROG_ECHO_BACKSLASH + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e s/^X//' +[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'] + +# Same as above, but do not quote variable references. +[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'] + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +# Constants: +rm="rm -f" + +# Global variables: +default_ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except M$VC, +# which needs '.lib'). +libext=a +ltmain="$ac_aux_dir/ltmain.sh" +ofile="$default_ofile" +with_gnu_ld="$lt_cv_prog_gnu_ld" + +AC_CHECK_TOOL(AR, ar, false) +AC_CHECK_TOOL(RANLIB, ranlib, :) +AC_CHECK_TOOL(STRIP, strip, :) + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru +test -z "$AS" && AS=as +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$LD" && LD=ld +test -z "$LN_S" && LN_S="ln -s" +test -z "$MAGIC_CMD" && MAGIC_CMD=file +test -z "$NM" && NM=nm +test -z "$SED" && SED=sed +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$RANLIB" && RANLIB=: +test -z "$STRIP" && STRIP=: +test -z "$ac_objext" && ac_objext=o + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds" + ;; + *) + old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +# Only perform the check for file, if the check method requires it +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + AC_PATH_MAGIC + fi + ;; +esac + +AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no) +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +enable_win32_dll=yes, enable_win32_dll=no) + +AC_ARG_ENABLE([libtool-lock], + [AC_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +AC_ARG_WITH([pic], + [AC_HELP_STRING([--with-pic], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [pic_mode="$withval"], + [pic_mode=default]) +test -z "$pic_mode" && pic_mode=default + +# Use C for the default configuration in the libtool script +tagname= +AC_LIBTOOL_LANG_C_CONFIG +_LT_AC_TAGCONFIG +])# AC_LIBTOOL_SETUP + + +# _LT_AC_SYS_COMPILER +# ------------------- +AC_DEFUN([_LT_AC_SYS_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_AC_SYS_COMPILER + + +# _LT_AC_SYS_LIBPATH_AIX +# ---------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX], +[AC_LINK_IFELSE(AC_LANG_PROGRAM,[ +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi],[]) +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi +])# _LT_AC_SYS_LIBPATH_AIX + + +# _LT_AC_SHELL_INIT(ARG) +# ---------------------- +AC_DEFUN([_LT_AC_SHELL_INIT], +[ifdef([AC_DIVERSION_NOTICE], + [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], + [AC_DIVERT_PUSH(NOTICE)]) +$1 +AC_DIVERT_POP +])# _LT_AC_SHELL_INIT + + +# _LT_AC_PROG_ECHO_BACKSLASH +# -------------------------- +# Add some code to the start of the generated configure script which +# will find an echo command which doesn't interpret backslashes. +AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH], +[_LT_AC_SHELL_INIT([ +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` + ;; +esac + +echo=${ECHO-echo} +if test "X[$]1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X[$]1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then + # Yippee, $echo works! + : +else + # Restart under the correct shell. + exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} +fi + +if test "X[$]1" = X--fallback-echo; then + # used as fallback echo + shift + cat </dev/null && + echo_test_string="`eval $cmd`" && + (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null + then + break + fi + done +fi + +if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : +else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for dir in $PATH /usr/ucb; do + IFS="$lt_save_ifs" + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$dir/echo" + break + fi + done + IFS="$lt_save_ifs" + + if test "X$echo" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + echo='print -r' + elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} + else + # Try using printf. + echo='printf %s\n' + if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + echo="$CONFIG_SHELL [$]0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$CONFIG_SHELL [$]0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do + if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "[$]0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} + else + # Oops. We lost completely, so just stick with echo. + echo=echo + fi + fi + fi + fi +fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +ECHO=$echo +if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then + ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" +fi + +AC_SUBST(ECHO) +])])# _LT_AC_PROG_ECHO_BACKSLASH + + +# _LT_AC_LOCK +# ----------- +AC_DEFUN([_LT_AC_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AC_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line __oline__ "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case "`/usr/bin/file conftest.o`" in + *32-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +[*-*-cygwin* | *-*-mingw* | *-*-pw32*) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; + ]) +esac + +need_locks="$enable_libtool_lock" + +])# _LT_AC_LOCK + + +# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], +[AC_REQUIRE([LT_AC_PROG_SED]) +AC_CACHE_CHECK([$1], [$2], + [$2=no + ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test ! -s conftest.err; then + $2=yes + fi + fi + $rm conftest* +]) + +if test x"[$]$2" = xyes; then + ifelse([$5], , :, [$5]) +else + ifelse([$6], , :, [$6]) +fi +])# AC_LIBTOOL_COMPILER_OPTION + + +# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ------------------------------------------------------------ +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], +[AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + else + $2=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" +]) + +if test x"[$]$2" = xyes; then + ifelse([$4], , :, [$4]) +else + ifelse([$5], , :, [$5]) +fi +])# AC_LIBTOOL_LINKER_OPTION + + +# AC_LIBTOOL_SYS_MAX_CMD_LEN +# -------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], +[# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + *) + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while (test "X"`$CONFIG_SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \ + = "XX$teststring") >/dev/null 2>&1 && + new_result=`expr "X$teststring" : ".*" 2>&1` && + lt_cv_sys_max_cmd_len=$new_result && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + teststring= + # Add a significant safety factor because C++ compilers can tack on massive + # amounts of additional arguments before passing them to the linker. + # It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + ;; + esac +]) +if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +])# AC_LIBTOOL_SYS_MAX_CMD_LEN + + +# _LT_AC_CHECK_DLFCN +# -------------------- +AC_DEFUN([_LT_AC_CHECK_DLFCN], +[AC_CHECK_HEADERS(dlfcn.h)dnl +])# _LT_AC_CHECK_DLFCN + + +# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ------------------------------------------------------------------ +AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "$cross_compiling" = yes; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + + exit (status); +}] +EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_unknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_AC_TRY_DLOPEN_SELF + + +# AC_LIBTOOL_DLOPEN_SELF +# ------------------- +AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + LDFLAGS="$LDFLAGS $link_static_flag" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +])# AC_LIBTOOL_DLOPEN_SELF + + +# AC_LIBTOOL_PROG_CC_C_O([TAGNAME]) +# --------------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler +AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test ! -s out/conftest.err; then + _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* +]) +])# AC_LIBTOOL_PROG_CC_C_O + + +# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME]) +# ----------------------------------------- +# Check to see if we can do hard links to lock some files if needed +AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], +[AC_REQUIRE([_LT_AC_LOCK])dnl + +hard_links="nottested" +if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS + + +# AC_LIBTOOL_OBJDIR +# ----------------- +AC_DEFUN([AC_LIBTOOL_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +])# AC_LIBTOOL_OBJDIR + + +# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME]) +# ---------------------------------------------- +# Check hardcoding attributes. +AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_AC_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \ + test -n "$_LT_AC_TAGVAR(runpath_var $1)" || \ + test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)"="Xyes" ; then + + # We can hardcode non-existant directories. + if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then + # Linking always hardcodes the temporary library directory. + _LT_AC_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_AC_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_AC_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)]) + +if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi +])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH + + +# AC_LIBTOOL_SYS_LIB_STRIP +# ------------------------ +AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP], +[striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) +fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +])# AC_LIBTOOL_SYS_LIB_STRIP + + +# AC_LIBTOOL_SYS_DYNAMIC_LINKER +# ----------------------------- +# PORTME Fill in your ld.so characteristics +AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER], +[AC_MSG_CHECKING([dynamic linker characteristics]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi4*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='$(test .$module = .yes && echo .so || echo .dylib)' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +kfreebsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +freebsd*) + objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + *) # from 3.2 on + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case "$host_cpu" in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`$SED -e 's/[:,\t]/ /g;s/=[^=]*$//;s/=[^= ]* / /g' /etc/ld.so.conf | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +knetbsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + need_lib_prefix=no + need_version=yes + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[[89]] | openbsd2.[[89]].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +sco3.2v5*) + version_type=osf + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test "$dynamic_linker" = no && can_build_shared=no +])# AC_LIBTOOL_SYS_DYNAMIC_LINKER + + +# _LT_AC_TAGCONFIG +# ---------------- +AC_DEFUN([_LT_AC_TAGCONFIG], +[AC_ARG_WITH([tags], + [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@], + [include additional configurations @<:@automatic@:>@])], + [tagnames="$withval"]) + +if test -f "$ltmain" && test -n "$tagnames"; then + if test ! -f "${ofile}"; then + AC_MSG_WARN([output file `$ofile' does not exist]) + fi + + if test -z "$LTCC"; then + eval "`$SHELL ${ofile} --config | grep '^LTCC='`" + if test -z "$LTCC"; then + AC_MSG_WARN([output file `$ofile' does not look like a libtool script]) + else + AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile']) + fi + fi + + # Extract list of available tagged configurations in $ofile. + # Note that this assumes the entire list is on one line. + available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` + + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for tagname in $tagnames; do + IFS="$lt_save_ifs" + # Check whether tagname contains only valid characters + case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in + "") ;; + *) AC_MSG_ERROR([invalid tag name: $tagname]) + ;; + esac + + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null + then + AC_MSG_ERROR([tag name \"$tagname\" already exists]) + fi + + # Update the list of available tags. + if test -n "$tagname"; then + echo appending configuration tag \"$tagname\" to $ofile + + case $tagname in + CXX) + if test -n "$CXX" && test "X$CXX" != "Xno"; then + AC_LIBTOOL_LANG_CXX_CONFIG + else + tagname="" + fi + ;; + + F77) + if test -n "$F77" && test "X$F77" != "Xno"; then + AC_LIBTOOL_LANG_F77_CONFIG + else + tagname="" + fi + ;; + + GCJ) + if test -n "$GCJ" && test "X$GCJ" != "Xno"; then + AC_LIBTOOL_LANG_GCJ_CONFIG + else + tagname="" + fi + ;; + + RC) + AC_LIBTOOL_LANG_RC_CONFIG + ;; + + *) + AC_MSG_ERROR([Unsupported tag name: $tagname]) + ;; + esac + + # Append the new tag name to the list of available tags. + if test -n "$tagname" ; then + available_tags="$available_tags $tagname" + fi + fi + done + IFS="$lt_save_ifs" + + # Now substitute the updated list of available tags. + if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then + mv "${ofile}T" "$ofile" + chmod +x "$ofile" + else + rm -f "${ofile}T" + AC_MSG_ERROR([unable to update list of available tagged configurations.]) + fi +fi +])# _LT_AC_TAGCONFIG + + +# AC_LIBTOOL_DLOPEN +# ----------------- +# enable checks for dlopen support +AC_DEFUN([AC_LIBTOOL_DLOPEN], + [AC_BEFORE([$0],[AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_DLOPEN + + +# AC_LIBTOOL_WIN32_DLL +# -------------------- +# declare package support for building win32 dll's +AC_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_BEFORE([$0], [AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_WIN32_DLL + + +# AC_ENABLE_SHARED([DEFAULT]) +# --------------------------- +# implement the --enable-shared flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_SHARED], +[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([shared], + [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_shared=]AC_ENABLE_SHARED_DEFAULT) +])# AC_ENABLE_SHARED + + +# AC_DISABLE_SHARED +# ----------------- +#- set the default shared flag to --disable-shared +AC_DEFUN([AC_DISABLE_SHARED], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_SHARED(no) +])# AC_DISABLE_SHARED + + +# AC_ENABLE_STATIC([DEFAULT]) +# --------------------------- +# implement the --enable-static flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_STATIC], +[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([static], + [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_static=]AC_ENABLE_STATIC_DEFAULT) +])# AC_ENABLE_STATIC + + +# AC_DISABLE_STATIC +# ----------------- +# set the default static flag to --disable-static +AC_DEFUN([AC_DISABLE_STATIC], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_STATIC(no) +])# AC_DISABLE_STATIC + + +# AC_ENABLE_FAST_INSTALL([DEFAULT]) +# --------------------------------- +# implement the --enable-fast-install flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_FAST_INSTALL], +[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([fast-install], + [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT) +])# AC_ENABLE_FAST_INSTALL + + +# AC_DISABLE_FAST_INSTALL +# ----------------------- +# set the default to --disable-fast-install +AC_DEFUN([AC_DISABLE_FAST_INSTALL], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_FAST_INSTALL(no) +])# AC_DISABLE_FAST_INSTALL + + +# AC_LIBTOOL_PICMODE([MODE]) +# -------------------------- +# implement the --with-pic flag +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +AC_DEFUN([AC_LIBTOOL_PICMODE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +pic_mode=ifelse($#,1,$1,default) +])# AC_LIBTOOL_PICMODE + + +# AC_PROG_EGREP +# ------------- +# This is predefined starting with Autoconf 2.54, so this conditional +# definition can be removed once we require Autoconf 2.54 or later. +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP], +[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep], + [if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi]) + EGREP=$ac_cv_prog_egrep + AC_SUBST([EGREP]) +])]) + + +# AC_PATH_TOOL_PREFIX +# ------------------- +# find a file program which can recognise shared library +AC_DEFUN([AC_PATH_TOOL_PREFIX], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="ifelse([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +])# AC_PATH_TOOL_PREFIX + + +# AC_PATH_MAGIC +# ------------- +# find a file program which can recognise a shared library +AC_DEFUN([AC_PATH_MAGIC], +[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# AC_PATH_MAGIC + + +# AC_PROG_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([AC_PROG_LD], +[AC_ARG_WITH([gnu-ld], + [AC_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no]) +AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case "$host_cpu" in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd* | knetbsd*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +nto-qnx*) + lt_cv_deplibs_check_method=unknown + ;; + +openbsd*) + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB shared object' + else + lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +sco3.2v5*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown +])# AC_DEPLIBS_CHECK_METHOD + + +# AC_PROG_NM +# ---------- +# find the pathname to a BSD-compatible name lister +AC_DEFUN([AC_PROG_NM], +[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/${ac_tool_prefix}nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + esac + fi + done + IFS="$lt_save_ifs" + test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm +fi]) +NM="$lt_cv_path_NM" +])# AC_PROG_NM + + +# AC_CHECK_LIBM +# ------------- +# check for math library +AC_DEFUN([AC_CHECK_LIBM], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM="-lm") + ;; +esac +])# AC_CHECK_LIBM + + +# AC_LIBLTDL_CONVENIENCE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl convenience library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-convenience to the configure arguments. Note that LIBLTDL +# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If +# DIRECTORY is not provided, it is assumed to be `libltdl'. LIBLTDL will +# be prefixed with '${top_builddir}/' and LTDLINCL will be prefixed with +# '${top_srcdir}/' (note the single quotes!). If your package is not +# flat and you're not using automake, define top_builddir and +# top_srcdir appropriately in the Makefiles. +AC_DEFUN([AC_LIBLTDL_CONVENIENCE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + case $enable_ltdl_convenience in + no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; + "") enable_ltdl_convenience=yes + ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; + esac + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_CONVENIENCE + + +# AC_LIBLTDL_INSTALLABLE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl installable library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-install to the configure arguments. Note that LIBLTDL +# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If +# DIRECTORY is not provided and an installed libltdl is not found, it is +# assumed to be `libltdl'. LIBLTDL will be prefixed with '${top_builddir}/' +# and LTDLINCL will be prefixed with '${top_srcdir}/' (note the single +# quotes!). If your package is not flat and you're not using automake, +# define top_builddir and top_srcdir appropriately in the Makefiles. +# In the future, this macro may have to be called after AC_PROG_LIBTOOL. +AC_DEFUN([AC_LIBLTDL_INSTALLABLE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + AC_CHECK_LIB(ltdl, lt_dlinit, + [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], + [if test x"$enable_ltdl_install" = xno; then + AC_MSG_WARN([libltdl not installed, but installation disabled]) + else + enable_ltdl_install=yes + fi + ]) + if test x"$enable_ltdl_install" = x"yes"; then + ac_configure_args="$ac_configure_args --enable-ltdl-install" + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + else + ac_configure_args="$ac_configure_args --enable-ltdl-install=no" + LIBLTDL="-lltdl" + LTDLINCL= + fi + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_INSTALLABLE + + +# AC_LIBTOOL_CXX +# -------------- +# enable support for C++ libraries +AC_DEFUN([AC_LIBTOOL_CXX], +[AC_REQUIRE([_LT_AC_LANG_CXX]) +])# AC_LIBTOOL_CXX + + +# _LT_AC_LANG_CXX +# --------------- +AC_DEFUN([_LT_AC_LANG_CXX], +[AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([AC_PROG_CXXCPP]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX]) +])# _LT_AC_LANG_CXX + + +# AC_LIBTOOL_F77 +# -------------- +# enable support for Fortran 77 libraries +AC_DEFUN([AC_LIBTOOL_F77], +[AC_REQUIRE([_LT_AC_LANG_F77]) +])# AC_LIBTOOL_F77 + + +# _LT_AC_LANG_F77 +# --------------- +AC_DEFUN([_LT_AC_LANG_F77], +[AC_REQUIRE([AC_PROG_F77]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77]) +])# _LT_AC_LANG_F77 + + +# AC_LIBTOOL_GCJ +# -------------- +# enable support for GCJ libraries +AC_DEFUN([AC_LIBTOOL_GCJ], +[AC_REQUIRE([_LT_AC_LANG_GCJ]) +])# AC_LIBTOOL_GCJ + + +# _LT_AC_LANG_GCJ +# --------------- +AC_DEFUN([_LT_AC_LANG_GCJ], +[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[], + [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])], + [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])], + [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ]) +])# _LT_AC_LANG_GCJ + + +# AC_LIBTOOL_RC +# -------------- +# enable support for Windows resource files +AC_DEFUN([AC_LIBTOOL_RC], +[AC_REQUIRE([LT_AC_PROG_RC]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC]) +])# AC_LIBTOOL_RC + + +# AC_LIBTOOL_LANG_C_CONFIG +# ------------------------ +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG]) +AC_DEFUN([_LT_AC_LANG_C_CONFIG], +[lt_save_CC="$CC" +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}\n' + +_LT_AC_SYS_COMPILER + +# +# Check for any special shared library compilation flags. +# +_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)= +if test "$GCC" = no; then + case $host_os in + sco3.2v5*) + _LT_AC_TAGVAR(lt_prog_cc_shlib, $1)='-belf' + ;; + esac +fi +if test -n "$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)"; then + AC_MSG_WARN([`$CC' requires `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to build shared libraries]) + if echo "$old_CC $old_CFLAGS " | grep "[[ ]]$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)[[ ]]" >/dev/null; then : + else + AC_MSG_WARN([add `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to the CC or CFLAGS env variable and reconfigure]) + _LT_AC_TAGVAR(lt_cv_prog_cc_can_build_shared, $1)=no + fi +fi + + +# +# Check to make sure the static flag actually works. +# +AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $_LT_AC_TAGVAR(lt_prog_compiler_static, $1) works], + _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1), + $_LT_AC_TAGVAR(lt_prog_compiler_static, $1), + [], + [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) + + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) +AC_LIBTOOL_SYS_LIB_STRIP +AC_LIBTOOL_DLOPEN_SELF($1) + +# Report which librarie types wil actually be built +AC_MSG_CHECKING([if libtool supports shared libraries]) +AC_MSG_RESULT([$can_build_shared]) + +AC_MSG_CHECKING([whether to build shared libraries]) +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case "$host_os" in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +aix4* | aix5*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + darwin* | rhapsody*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + case "$host_os" in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup' + ;; + esac + fi + ;; + esac + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; +esac +AC_MSG_RESULT([$enable_shared]) + +AC_MSG_CHECKING([whether to build static libraries]) +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +AC_MSG_RESULT([$enable_static]) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_C_CONFIG + + +# AC_LIBTOOL_LANG_CXX_CONFIG +# -------------------------- +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)]) +AC_DEFUN([_LT_AC_LANG_CXX_CONFIG], +[AC_LANG_PUSH(C++) +AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([AC_PROG_CXXCPP]) + +_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_AC_TAGVAR(allow_undefined_flag, $1)= +_LT_AC_TAGVAR(always_export_symbols, $1)=no +_LT_AC_TAGVAR(archive_expsym_cmds, $1)= +_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_direct, $1)=no +_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_AC_TAGVAR(hardcode_libdir_separator, $1)= +_LT_AC_TAGVAR(hardcode_minus_L, $1)=no +_LT_AC_TAGVAR(hardcode_automatic, $1)=no +_LT_AC_TAGVAR(module_cmds, $1)= +_LT_AC_TAGVAR(module_expsym_cmds, $1)= +_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown +_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_AC_TAGVAR(no_undefined_flag, $1)= +_LT_AC_TAGVAR(whole_archive_flag_spec, $1)= +_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Dependencies to place before and after the object being linked: +_LT_AC_TAGVAR(predep_objects, $1)= +_LT_AC_TAGVAR(postdep_objects, $1)= +_LT_AC_TAGVAR(predeps, $1)= +_LT_AC_TAGVAR(postdeps, $1)= +_LT_AC_TAGVAR(compiler_lib_search_path, $1)= + +# Source file extension for C++ test sources. +ac_ext=cc + +# Object file extension for compiled C++ test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_LD=$LD +lt_save_GCC=$GCC +GCC=$GXX +lt_save_with_gnu_ld=$with_gnu_ld +lt_save_path_LD=$lt_cv_path_LD +if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx +else + unset lt_cv_prog_gnu_ld +fi +if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX +else + unset lt_cv_path_LD +fi +test -z "${LDCXX+set}" || LD=$LDCXX +CC=${CXX-"c++"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'` + +# We don't want -fno-exception wen compiling C++ code, so set the +# no_builtin_flag separately +if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' +else + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= +fi + +if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + AC_PROG_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ + grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + +else + GXX=no + with_gnu_ld=no + wlarc= +fi + +# PORTME: fill in a description of your system's C++ link characteristics +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +_LT_AC_TAGVAR(ld_shlibs, $1)=yes +case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GXX" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # -bexpall does not export symbols beginning with underscore (_) + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' ' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds it's shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + darwin* | rhapsody*) + if test "$GXX" = yes; then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + case "$host_os" in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup' + ;; + esac + fi + ;; + esac + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + _LT_AC_TAGVAR(module_cmds, $1)='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + dgux*) + case $cc_basename in + ec++) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + freebsd[12]*) + # C++ shared libraries reported to be fairly broken before switch to ELF + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + freebsd-elf*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + freebsd* | kfreebsd*-gnu) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + ;; + gnu*) + ;; + hpux9*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[-]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + case "$host_cpu" in + hppa*64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + ;; + *) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + esac + fi + case "$host_cpu" in + hppa*64*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + ia64*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + *) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC) + case "$host_cpu" in + hppa*64*|ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case "$host_cpu" in + ia64*|hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + irix5* | irix6*) + case $cc_basename in + CC) + # SGI C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' + fi + fi + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + linux*) + case $cc_basename in + KCC) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc) + # Intel C++ + with_gnu_ld=yes + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + cxx) + # Compaq C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + esac + ;; + lynxos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + m88k*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + mvs*) + case $cc_basename in + cxx) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + netbsd* | knetbsd*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + osf3*) + case $cc_basename in + KCC) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + + ;; + RCC) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + osf4* | osf5*) + case $cc_basename in + KCC) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' + ;; + RCC) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry $objdir/so_locations -o $lib~ + $rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + psos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + sco*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + case $cc_basename in + CC) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + lcc) + # Lucid + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + solaris*) + case $cc_basename in + CC) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -nolib -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -nolib ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The C++ compiler is used as linker so we must use $wl + # flag to pass the commands to the underlying system + # linker. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep "\-[[LR]]"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if $CC --version | grep -v '^2\.7' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + fi + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + fi + ;; + esac + ;; + sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + tandem*) + case $cc_basename in + NCC) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + vxworks*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; +esac +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_AC_TAGVAR(GCC, $1)="$GXX" +_LT_AC_TAGVAR(LD, $1)="$LD" + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +AC_LIBTOOL_POSTDEP_PREDEP($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) +AC_LIBTOOL_SYS_LIB_STRIP +AC_LIBTOOL_DLOPEN_SELF($1) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC=$lt_save_CC +LDCXX=$LD +LD=$lt_save_LD +GCC=$lt_save_GCC +with_gnu_ldcxx=$with_gnu_ld +with_gnu_ld=$lt_save_with_gnu_ld +lt_cv_path_LDCXX=$lt_cv_path_LD +lt_cv_path_LD=$lt_save_path_LD +lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld +lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +])# AC_LIBTOOL_LANG_CXX_CONFIG + +# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME]) +# ------------------------ +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[ +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +ifelse([$1],[],[cat > conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext <> "$cfgfile" +ifelse([$1], [], +[#! $SHELL + +# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# +# This file is part of GNU Libtool: +# Originally by Gordon Matzigkeit , 1996 +# +# This program 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. +# +# This program 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. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="$SED -e s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi + +# The names of the tagged configurations supported by this script. +available_tags= + +# ### BEGIN LIBTOOL CONFIG], +[# ### BEGIN LIBTOOL TAG CONFIG: $tagname]) + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1) + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# A language-specific compiler. +CC=$lt_[]_LT_AC_TAGVAR(compiler, $1) + +# Is the compiler the GNU C compiler? +with_gcc=$_LT_AC_TAGVAR(GCC, $1) + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_[]_LT_AC_TAGVAR(LD, $1) + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) + +# Must we lock files when doing compilation ? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1) + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1) + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1) + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1) + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1) +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1) + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) + +# Commands used to build and install a shared archive. +archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1) +archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1) +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1) +module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1) + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1) + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1) + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1) + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1) + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1) + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1) + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1) + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1) + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1) + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1) + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1) + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1) + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)" + +# Set to yes if exported symbols are required. +always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1) + +# The commands to list exported symbols. +export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1) + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1) + +# Symbols that must always be exported. +include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1) + +ifelse([$1],[], +[# ### END LIBTOOL CONFIG], +[# ### END LIBTOOL TAG CONFIG: $tagname]) + +__EOF__ + +ifelse([$1],[], [ + case $host_os in + aix3*) + cat <<\EOF >> "$cfgfile" + +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || \ + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +]) +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi +])# AC_LIBTOOL_CONFIG + + +# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl + +_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + + AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI + + +# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +# --------------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], +[AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_NM]) +AC_REQUIRE([AC_OBJEXT]) +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Transform the above into a raw symbol and a C symbol. +symxfrm='\1 \2\3 \3' + +# Transform an extracted symbol line into a proper C declaration +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) # Its linker distinguishes data from code symbols + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + fi + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris* | sysv5*) + symcode='[[BDRT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Write the raw and C identifiers. + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext < $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if grep ' nm_test_var$' "$nlist" >/dev/null; then + if grep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' + + cat <> conftest.$ac_ext +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[[]] = +{ +EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext + cat <<\EOF >> conftest.$ac_ext + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -f conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi +]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE + + +# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME]) +# --------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC], +[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_static, $1)= + +AC_MSG_CHECKING([for $compiler option to produce PIC]) + ifelse([$1],[CXX],[ + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | os2* | pw32*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case "$host_cpu" in + hppa*64*|ia64*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix4* | aix5*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68) + # Green Hills C++ Compiler + # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + dgux*) + case $cc_basename in + ec++) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | kfreebsd*-gnu) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" + case "$host_cpu" in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux*) + case $cc_basename in + KCC) + # KAI C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + icpc) + # Intel C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + cxx) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd* | knetbsd*-gnu) + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC) + # Rational C++ 2.4.1 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx) + # Digital/Compaq C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + sco*) + case $cc_basename in + CC) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + *) + ;; + esac + ;; + solaris*) + case $cc_basename in + CC) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC) + # Sun C++ 4.x + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc) + # Lucid + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC) + # NonStop-UX NCC 3.20 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + unixware*) + ;; + vxworks*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case "$host_cpu" in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case "$host_cpu" in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + newsos6) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + linux*) + case $CC in + icc* | ecc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + ccc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + sco3.2v5*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-dn' + ;; + + solaris*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sunos4*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + uts4*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)]) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then + AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works], + _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1), + [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +case "$host_os" in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])" + ;; +esac +]) + + +# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME]) +# ------------------------------------ +# See if the linker supports building shared libraries. +AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS], +[AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +ifelse([$1],[CXX],[ + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in + aix4* | aix5*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + cygwin* | mingw*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + ;; + linux*) + _LT_AC_TAGVAR(link_all_deplibs, $1)=no + ;; + *) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +],[ + runpath_var= + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)= + _LT_AC_TAGVAR(archive_expsym_cmds, $1)= + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)= + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + _LT_AC_TAGVAR(thread_safe_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_minus_L, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown + _LT_AC_TAGVAR(hardcode_automatic, $1)=no + _LT_AC_TAGVAR(module_cmds, $1)= + _LT_AC_TAGVAR(module_expsym_cmds, $1)= + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_AC_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + else + ld_shlibs=no + fi + ;; + + netbsd* | knetbsd*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris* | sysv5*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sunos4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + linux*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_cmds, $1)="$tmp_archive_cmds" + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [01].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + if test $supports_anon_versioning = yes; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~ +cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ +$echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + else + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="$tmp_archive_cmds" + fi + _LT_AC_TAGVAR(link_all_deplibs, $1)=no + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = yes; then + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$link_static_flag"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # -bexpall does not export symbols beginning with underscore (_) + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' ' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds it's shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + # see comment about different semantics on the GNU ld section + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + bsdi4*) + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path='`cygpath -w "$srcfile"`' + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + darwin* | rhapsody*) + if test "$GXX" = yes ; then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + case "$host_os" in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup' + ;; + esac + fi + ;; + esac + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + _LT_AC_TAGVAR(module_cmds, $1)='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + dgux*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + freebsd1*) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | kfreebsd*-gnu) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + + hpux10* | hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case "$host_cpu" in + hppa*64*|ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case "$host_cpu" in + hppa*64*|ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + case "$host_cpu" in + hppa*64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + ;; + *) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + netbsd* | knetbsd*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + openbsd*) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + sco3.2v5*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ;; + + solaris*) + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4.2uw2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + hardcode_runpath_var=yes + runpath_var=LD_RUN_PATH + ;; + + sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z ${wl}text' + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + runpath_var='LD_RUN_PATH' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv5*) + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' + # $CC -shared without GNU ld will not create a library from C++ + # object files and a static libstdc++, better avoid it by now + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + ;; + + uts4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +# +# Do we need to explicitly link libc? +# +case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $_LT_AC_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_MSG_CHECKING([whether -lc should be explicitly linked in]) + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1) + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) + then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + else + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)]) + ;; + esac + fi + ;; +esac +])# AC_LIBTOOL_PROG_LD_SHLIBS + + +# _LT_AC_FILE_LTDLL_C +# ------------------- +# Be careful that the start marker always follows a newline. +AC_DEFUN([_LT_AC_FILE_LTDLL_C], [ +# /* ltdll.c starts here */ +# #define WIN32_LEAN_AND_MEAN +# #include +# #undef WIN32_LEAN_AND_MEAN +# #include +# +# #ifndef __CYGWIN__ +# # ifdef __CYGWIN32__ +# # define __CYGWIN__ __CYGWIN32__ +# # endif +# #endif +# +# #ifdef __cplusplus +# extern "C" { +# #endif +# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); +# #ifdef __cplusplus +# } +# #endif +# +# #ifdef __CYGWIN__ +# #include +# DECLARE_CYGWIN_DLL( DllMain ); +# #endif +# HINSTANCE __hDllInstance_base; +# +# BOOL APIENTRY +# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) +# { +# __hDllInstance_base = hInst; +# return TRUE; +# } +# /* ltdll.c ends here */ +])# _LT_AC_FILE_LTDLL_C + + +# _LT_AC_TAGVAR(VARNAME, [TAGNAME]) +# --------------------------------- +AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])]) + + +# old names +AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL]) +AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) +AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) +AC_DEFUN([AM_PROG_LD], [AC_PROG_LD]) +AC_DEFUN([AM_PROG_NM], [AC_PROG_NM]) + +# This is just to silence aclocal about the macro not being used +ifelse([AC_DISABLE_FAST_INSTALL]) + +AC_DEFUN([LT_AC_PROG_GCJ], +[AC_CHECK_TOOL(GCJ, gcj, no) + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS) +]) + +AC_DEFUN([LT_AC_PROG_RC], +[AC_CHECK_TOOL(RC, windres, no) +]) + +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +# LT_AC_PROG_SED +# -------------- +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +AC_DEFUN([LT_AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && break + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +SED=$lt_cv_path_SED +]) +AC_MSG_RESULT([$SED]) +]) diff --git a/tags/gpgme-1.1.6/m4/pkg.m4 b/tags/gpgme-1.1.6/m4/pkg.m4 new file mode 100644 index 0000000..c29b6c0 --- /dev/null +++ b/tags/gpgme-1.1.6/m4/pkg.m4 @@ -0,0 +1,157 @@ +# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +# +# Copyright © 2004 Scott James Remnant . +# +# This program 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. +# +# This program 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. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# PKG_PROG_PKG_CONFIG([MIN-VERSION]) +# ---------------------------------- +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi + +fi[]dnl +])# PKG_PROG_PKG_CONFIG + +# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# +# Check to see whether a particular set of modules exists. Similar +# to PKG_CHECK_MODULES(), but does not set variables or print errors. +# +# +# Similar to PKG_CHECK_MODULES, make sure that the first instance of +# this or PKG_CHECK_MODULES is called, or make sure to call +# PKG_CHECK_EXISTS manually +# -------------------------------------------------------------- +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_ifval([$2], [$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + + +# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +# --------------------------------------------- +m4_define([_PKG_CONFIG], +[if test -n "$PKG_CONFIG"; then + if test -n "$$1"; then + pkg_cv_[]$1="$$1" + else + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], + [pkg_failed=yes]) + fi +else + pkg_failed=untried +fi[]dnl +])# _PKG_CONFIG + +# _PKG_SHORT_ERRORS_SUPPORTED +# ----------------------------- +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])# _PKG_SHORT_ERRORS_SUPPORTED + + +# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +# [ACTION-IF-NOT-FOUND]) +# +# +# Note that if there is a possibility the first call to +# PKG_CHECK_MODULES might not happen, you should be sure to include an +# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +# +# +# -------------------------------------------------------------- +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + ifelse([$4], , [AC_MSG_ERROR(dnl +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT +])], + [AC_MSG_RESULT([no]) + $4]) +elif test $pkg_failed = untried; then + ifelse([$4], , [AC_MSG_FAILURE(dnl +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])], + [$4]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + ifelse([$3], , :, [$3]) +fi[]dnl +])# PKG_CHECK_MODULES diff --git a/tags/gpgme-1.1.6/m4/pth.m4 b/tags/gpgme-1.1.6/m4/pth.m4 new file mode 100644 index 0000000..b558f28 --- /dev/null +++ b/tags/gpgme-1.1.6/m4/pth.m4 @@ -0,0 +1,402 @@ +dnl ## +dnl ## GNU Pth - The GNU Portable Threads +dnl ## Copyright (c) 1999-2002 Ralf S. Engelschall +dnl ## +dnl ## This file is part of GNU Pth, a non-preemptive thread scheduling +dnl ## library which can be found at http://www.gnu.org/software/pth/. +dnl ## +dnl ## This library is free software; you can redistribute it and/or +dnl ## modify it under the terms of the GNU Lesser General Public +dnl ## License as published by the Free Software Foundation; either +dnl ## version 2.1 of the License, or (at your option) any later version. +dnl ## +dnl ## This library is distributed in the hope that it will be useful, +dnl ## but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl ## Lesser General Public License for more details. +dnl ## +dnl ## You should have received a copy of the GNU Lesser General Public +dnl ## License along with this library; if not, write to the Free Software +dnl ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +dnl ## USA, or contact Ralf S. Engelschall . +dnl ## +dnl ## pth.m4: Autoconf macro for locating GNU Pth from within +dnl ## configure.in of third-party software packages +dnl ## + +dnl ## +dnl ## Synopsis: +dnl ## AC_CHECK_PTH([MIN-VERSION [, # minimum Pth version, e.g. 1.2.0 +dnl ## DEFAULT-WITH-PTH [, # default value for --with-pth option +dnl ## DEFAULT-WITH-PTH-TEST [,# default value for --with-pth-test option +dnl ## EXTEND-VARS [, # whether CFLAGS/LDFLAGS/etc are extended +dnl ## ACTION-IF-FOUND [, # action to perform if Pth was found +dnl ## ACTION-IF-NOT-FOUND # action to perform if Pth was not found +dnl ## ]]]]]]) +dnl ## Examples: +dnl ## AC_CHECK_PTH(1.2.0) +dnl ## AC_CHECK_PTH(1.2.0,,,no,CFLAGS="$CFLAGS -DHAVE_PTH $PTH_CFLAGS") +dnl ## AC_CHECK_PTH(1.2.0,yes,yes,yes,CFLAGS="$CFLAGS -DHAVE_PTH") +dnl ## +dnl +dnl # auxilliary macros +AC_DEFUN([_AC_PTH_ERROR], [dnl +AC_MSG_RESULT([*FAILED*]) +dnl define(_ac_pth_line,dnl +dnl "+------------------------------------------------------------------------+") +dnl echo " _ac_pth_line" 1>&2 +cat <>/ /' 1>&2 +$1 +EOT +dnl echo " _ac_pth_line" 1>&2 +dnl undefine(_ac_pth_line) +exit 1 +]) +AC_DEFUN([_AC_PTH_VERBOSE], [dnl +if test ".$verbose" = .yes; then + AC_MSG_RESULT([ $1]) +fi +]) +dnl # the user macro +AC_DEFUN([AC_CHECK_PTH], [dnl +dnl +dnl # prerequisites +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_CPP])dnl +dnl +PTH_CPPFLAGS='' +PTH_CFLAGS='' +PTH_LDFLAGS='' +PTH_LIBS='' +AC_SUBST(PTH_CPPFLAGS) +AC_SUBST(PTH_CFLAGS) +AC_SUBST(PTH_LDFLAGS) +AC_SUBST(PTH_LIBS) +dnl # command line options +AC_MSG_CHECKING(for GNU Pth) +_AC_PTH_VERBOSE([]) +AC_ARG_WITH(pth,dnl +[ --with-pth[=ARG] Build with GNU Pth Library (default=]ifelse([$2],,yes,$2)[)],dnl +,dnl +with_pth="ifelse([$2],,yes,$2)" +)dnl +AC_ARG_WITH(pth-test,dnl +[ --with-pth-test Perform GNU Pth Sanity Test (default=]ifelse([$3],,yes,$3)[)],dnl +,dnl +with_pth_test="ifelse([$3],,yes,$3)" +)dnl +_AC_PTH_VERBOSE([+ Command Line Options:]) +_AC_PTH_VERBOSE([ o --with-pth=$with_pth]) +_AC_PTH_VERBOSE([ o --with-pth-test=$with_pth_test]) +dnl +dnl # configuration +if test ".$with_pth" != .no; then + _pth_subdir=no + _pth_subdir_opts='' + case "$with_pth" in + subdir:* ) + _pth_subdir=yes + changequote(, )dnl + _pth_subdir_opts=`echo $with_pth | sed -e 's/^subdir:[^ ]*[ ]*//'` + with_pth=`echo $with_pth | sed -e 's/^subdir:\([^ ]*\).*$/\1/'` + changequote([, ])dnl + ;; + esac + _pth_version="" + _pth_location="" + _pth_type="" + _pth_cppflags="" + _pth_cflags="" + _pth_ldflags="" + _pth_libs="" + if test ".$with_pth" = .yes; then + # via config script in $PATH + changequote(, )dnl + _pth_version=`(pth-config --version) 2>/dev/null |\ + sed -e 's/^.*\([0-9]\.[0-9]*[ab.][0-9]*\).*$/\1/'` + changequote([, ])dnl + if test ".$_pth_version" != .; then + _pth_location=`pth-config --prefix` + _pth_type='installed' + _pth_cppflags=`pth-config --cflags` + _pth_cflags=`pth-config --cflags` + _pth_ldflags=`pth-config --ldflags` + _pth_libs=`pth-config --libs --all` + fi + elif test -d "$with_pth"; then + with_pth=`echo $with_pth | sed -e 's;/*$;;'` + _pth_found=no + # via locally included source tree + if test ".$_pth_subdir" = .yes; then + _pth_location="$with_pth" + _pth_type='local' + _pth_cppflags="-I$with_pth" + _pth_cflags="-I$with_pth" + if test -f "$with_pth/ltconfig"; then + _pth_ldflags="-L$with_pth/.libs" + else + _pth_ldflags="-L$with_pth" + fi + _pth_libs="-lpth" + changequote(, )dnl + _pth_version=`grep '^const char PTH_Hello' $with_pth/pth_vers.c |\ + sed -e 's;^.*Version[ ]*\([0-9]*\.[0-9]*[.ab][0-9]*\)[ ].*$;\1;'` + changequote([, ])dnl + _pth_found=yes + ac_configure_args="$ac_configure_args --enable-subdir $_pth_subdir_opts" + with_pth_test=no + fi + # via config script under a specified directory + # (a standard installation, but not a source tree) + if test ".$_pth_found" = .no; then + for _dir in $with_pth/bin $with_pth; do + if test -f "$_dir/pth-config"; then + test -f "$_dir/pth-config.in" && continue # pth-config in source tree! + changequote(, )dnl + _pth_version=`($_dir/pth-config --version) 2>/dev/null |\ + sed -e 's/^.*\([0-9]\.[0-9]*[ab.][0-9]*\).*$/\1/'` + changequote([, ])dnl + if test ".$_pth_version" != .; then + _pth_location=`$_dir/pth-config --prefix` + _pth_type="installed" + _pth_cppflags=`$_dir/pth-config --cflags` + _pth_cflags=`$_dir/pth-config --cflags` + _pth_ldflags=`$_dir/pth-config --ldflags` + _pth_libs=`$_dir/pth-config --libs --all` + _pth_found=yes + break + fi + fi + done + fi + # in any subarea under a specified directory + # (either a special installation or a Pth source tree) + if test ".$_pth_found" = .no; then + changequote(, )dnl + _pth_found=0 + for _file in x `find $with_pth -name "pth.h" -type f -print`; do + test .$_file = .x && continue + _dir=`echo $_file | sed -e 's;[^/]*$;;' -e 's;\(.\)/$;\1;'` + _pth_version=`($_dir/pth-config --version) 2>/dev/null |\ + sed -e 's/^.*\([0-9]\.[0-9]*[ab.][0-9]*\).*$/\1/'` + if test ".$_pth_version" = .; then + _pth_version=`grep '^#define PTH_VERSION_STR' $_file |\ + sed -e 's;^#define[ ]*PTH_VERSION_STR[ ]*"\([0-9]*\.[0-9]*[.ab][0-9]*\)[ ].*$;\1;'` + fi + _pth_cppflags="-I$_dir" + _pth_cflags="-I$_dir" + _pth_found=`expr $_pth_found + 1` + done + for _file in x `find $with_pth -name "libpth.[aso]" -type f -print`; do + test .$_file = .x && continue + _dir=`echo $_file | sed -e 's;[^/]*$;;' -e 's;\(.\)/$;\1;'` + _pth_ldflags="-L$_dir" + _pth_libs="-lpth" + _pth_found=`expr $_pth_found + 1` + done + changequote([, ])dnl + if test ".$_pth_found" = .2; then + _pth_location="$with_pth" + _pth_type="uninstalled" + else + _pth_version='' + fi + fi + fi + _AC_PTH_VERBOSE([+ Determined Location:]) + _AC_PTH_VERBOSE([ o path: $_pth_location]) + _AC_PTH_VERBOSE([ o type: $_pth_type]) + if test ".$_pth_version" = .; then + with_pth=no + else +dnl if test ".$with_pth" != .yes; then +dnl _AC_PTH_ERROR([dnl +dnl Unable to locate GNU Pth under $with_pth. +dnl Please specify the correct path to either a GNU Pth installation tree +dnl (use --with-pth=DIR if you used --prefix=DIR for installing GNU Pth in +dnl the past) or to a GNU Pth source tree (use --with-pth=DIR if DIR is a +dnl path to a pth-X.Y.Z/ directory; but make sure the package is already +dnl built, i.e., the "configure; make" step was already performed there).]) +dnl else +dnl _AC_PTH_ERROR([dnl +dnl Unable to locate GNU Pth in any system-wide location (see \$PATH). +dnl Please specify the correct path to either a GNU Pth installation tree +dnl (use --with-pth=DIR if you used --prefix=DIR for installing GNU Pth in +dnl the past) or to a GNU Pth source tree (use --with-pth=DIR if DIR is a +dnl path to a pth-X.Y.Z/ directory; but make sure the package is already +dnl built, i.e., the "configure; make" step was already performed there).]) +dnl fi +dnl fi + dnl # + dnl # Check whether the found version is sufficiently new + dnl # + _req_version="ifelse([$1],,1.0.0,$1)" + for _var in _pth_version _req_version; do + eval "_val=\"\$${_var}\"" + _major=`echo $_val | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\([[ab.]]\)\([[0-9]]*\)/\1/'` + _minor=`echo $_val | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\([[ab.]]\)\([[0-9]]*\)/\2/'` + _rtype=`echo $_val | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\([[ab.]]\)\([[0-9]]*\)/\3/'` + _micro=`echo $_val | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\([[ab.]]\)\([[0-9]]*\)/\4/'` + case $_rtype in + "a" ) _rtype=0 ;; + "b" ) _rtype=1 ;; + "." ) _rtype=2 ;; + esac + _hex=`echo dummy | awk '{ printf("%d%02d%1d%02d", major, minor, rtype, micro); }' \ + "major=$_major" "minor=$_minor" "rtype=$_rtype" "micro=$_micro"` + eval "${_var}_hex=\"\$_hex\"" + done + _AC_PTH_VERBOSE([+ Determined Versions:]) + _AC_PTH_VERBOSE([ o existing: $_pth_version -> 0x$_pth_version_hex]) + _AC_PTH_VERBOSE([ o required: $_req_version -> 0x$_req_version_hex]) + _ok=0 + if test ".$_pth_version_hex" != .; then + if test ".$_req_version_hex" != .; then + if test $_pth_version_hex -ge $_req_version_hex; then + _ok=1 + fi + fi + fi + if test ".$_ok" = .0; then + _AC_PTH_ERROR([dnl + Found Pth version $_pth_version, but required at least version $_req_version. + Upgrade Pth under $_pth_location to $_req_version or higher first, please.]) + fi + dnl # + dnl # Perform Pth Sanity Compile Check + dnl # + if test ".$with_pth_test" = .yes; then + _ac_save_CPPFLAGS="$CPPFLAGS" + _ac_save_CFLAGS="$CFLAGS" + _ac_save_LDFLAGS="$LDFLAGS" + _ac_save_LIBS="$LIBS" + CPPFLAGS="$CPPFLAGS $_pth_cppflags" + CFLAGS="$CFLAGS $_pth_cflags" + LDFLAGS="$LDFLAGS $_pth_ldflags" + LIBS="$LIBS $_pth_libs" + _AC_PTH_VERBOSE([+ Test Build Environment:]) + _AC_PTH_VERBOSE([ o CPPFLAGS=\"$CPPFLAGS\"]) + _AC_PTH_VERBOSE([ o CFLAGS=\"$CFLAGS\"]) + _AC_PTH_VERBOSE([ o LDFLAGS=\"$LDFLAGS\"]) + _AC_PTH_VERBOSE([ o LIBS=\"$LIBS\"]) + cross_compile=no + define(_code1, [dnl + #include + #include + ]) + define(_code2, [dnl + FILE *fp; + if (!(fp = fopen("conftestval", "w"))) + exit(1); + fprintf(fp, "hmm"); + fclose(fp); + pth_init(); + pth_kill(); + if (!(fp = fopen("conftestval", "w"))) + exit(1); + fprintf(fp, "yes"); + fclose(fp); + exit(0); + ]) + _AC_PTH_VERBOSE([+ Performing Sanity Checks:]) + _AC_PTH_VERBOSE([ o pre-processor test]) + AC_TRY_CPP(_code1, _ok=yes, _ok=no) + if test ".$_ok" != .yes; then + _AC_PTH_ERROR([dnl + Found GNU Pth $_pth_version under $_pth_location, but + was unable to perform a sanity pre-processor check. This means + the GNU Pth header pth.h was not found. + We used the following build environment: + >> CPP="$CPP" + >> CPPFLAGS="$CPPFLAGS" + See config.log for possibly more details.]) + fi + _AC_PTH_VERBOSE([ o link check]) + AC_TRY_LINK(_code1, _code2, _ok=yes, _ok=no) + if test ".$_ok" != .yes; then + _AC_PTH_ERROR([dnl + Found GNU Pth $_pth_version under $_pth_location, but + was unable to perform a sanity linker check. This means + the GNU Pth library libpth.a was not found. + We used the following build environment: + >> CC="$CC" + >> CFLAGS="$CFLAGS" + >> LDFLAGS="$LDFLAGS" + >> LIBS="$LIBS" + See config.log for possibly more details.]) + fi + _AC_PTH_VERBOSE([ o run-time check]) + AC_TRY_RUN(AC_LANG_PROGRAM(_code1, _code2), _ok=`cat conftestval`, _ok=no, _ok=no) + if test ".$_ok" != .yes; then + if test ".$_ok" = .no; then + _AC_PTH_ERROR([dnl + Found GNU Pth $_pth_version under $_pth_location, but + was unable to perform a sanity execution check. This usually + means that the GNU Pth shared library libpth.so is present + but \$LD_LIBRARY_PATH is incomplete to execute a Pth test. + In this case either disable this test via --without-pth-test, + or extend \$LD_LIBRARY_PATH, or build GNU Pth as a static + library only via its --disable-shared Autoconf option. + We used the following build environment: + >> CC="$CC" + >> CFLAGS="$CFLAGS" + >> LDFLAGS="$LDFLAGS" + >> LIBS="$LIBS" + See config.log for possibly more details.]) + else + _AC_PTH_ERROR([dnl + Found GNU Pth $_pth_version under $_pth_location, but + was unable to perform a sanity run-time check. This usually + means that the GNU Pth library failed to work and possibly + caused a core dump in the test program. In this case it + is strongly recommended that you re-install GNU Pth and this + time make sure that it really passes its "make test" procedure. + We used the following build environment: + >> CC="$CC" + >> CFLAGS="$CFLAGS" + >> LDFLAGS="$LDFLAGS" + >> LIBS="$LIBS" + See config.log for possibly more details.]) + fi + fi + _extendvars="ifelse([$4],,yes,$4)" + if test ".$_extendvars" != .yes; then + CPPFLAGS="$_ac_save_CPPFLAGS" + CFLAGS="$_ac_save_CFLAGS" + LDFLAGS="$_ac_save_LDFLAGS" + LIBS="$_ac_save_LIBS" + fi + else + _extendvars="ifelse([$4],,yes,$4)" + if test ".$_extendvars" = .yes; then + if test ".$_pth_subdir" = .yes; then + CPPFLAGS="$CPPFLAGS $_pth_cppflags" + CFLAGS="$CFLAGS $_pth_cflags" + LDFLAGS="$LDFLAGS $_pth_ldflags" + LIBS="$LIBS $_pth_libs" + fi + fi + fi + PTH_CPPFLAGS="$_pth_cppflags" + PTH_CFLAGS="$_pth_cflags" + PTH_LDFLAGS="$_pth_ldflags" + PTH_LIBS="$_pth_libs" + AC_SUBST(PTH_CPPFLAGS) + AC_SUBST(PTH_CFLAGS) + AC_SUBST(PTH_LDFLAGS) + AC_SUBST(PTH_LIBS) + _AC_PTH_VERBOSE([+ Final Results:]) + _AC_PTH_VERBOSE([ o PTH_CPPFLAGS=\"$PTH_CPPFLAGS\"]) + _AC_PTH_VERBOSE([ o PTH_CFLAGS=\"$PTH_CFLAGS\"]) + _AC_PTH_VERBOSE([ o PTH_LDFLAGS=\"$PTH_LDFLAGS\"]) + _AC_PTH_VERBOSE([ o PTH_LIBS=\"$PTH_LIBS\"]) +fi +fi +if test ".$with_pth" != .no; then + AC_MSG_RESULT([version $_pth_version, $_pth_type under $_pth_location]) + ifelse([$5], , :, [$5]) +else + AC_MSG_RESULT([no]) + ifelse([$6], , :, [$6]) +fi +]) diff --git a/tags/gpgme-1.1.6/missing b/tags/gpgme-1.1.6/missing new file mode 100755 index 0000000..6a37006 --- /dev/null +++ b/tags/gpgme-1.1.6/missing @@ -0,0 +1,336 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. +# Copyright (C) 1996, 1997, 1999, 2000, 2002 Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# This program 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, or (at your option) +# any later version. + +# This program 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. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +case "$1" in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case "$1" in + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch]" + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing 0.4 - GNU automake" + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + + aclocal*) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case "$f" in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is needed, and you do not seem to have it handy on your + system. You might have modified some files without having the + proper tools for further handling them. + You can get \`$1Help2man' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` + test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` + fi + if [ -f "$file" ]; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit 1 + fi + ;; + + makeinfo) + if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then + # We have makeinfo, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` + fi + touch $file + ;; + + tar) + shift + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + fi + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar "$@" && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar "$@" && exit 0 + fi + firstarg="$1" + if shift; then + case "$firstarg" in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + case "$firstarg" in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and you do not seem to have it handy on your + system. You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequirements for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 diff --git a/tags/gpgme-1.1.6/mkinstalldirs b/tags/gpgme-1.1.6/mkinstalldirs new file mode 100755 index 0000000..d2d5f21 --- /dev/null +++ b/tags/gpgme-1.1.6/mkinstalldirs @@ -0,0 +1,111 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Public domain + +errstatus=0 +dirmode="" + +usage="\ +Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..." + +# process command line arguments +while test $# -gt 0 ; do + case $1 in + -h | --help | --h*) # -h for help + echo "$usage" 1>&2 + exit 0 + ;; + -m) # -m PERM arg + shift + test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } + dirmode=$1 + shift + ;; + --) # stop option processing + shift + break + ;; + -*) # unknown option + echo "$usage" 1>&2 + exit 1 + ;; + *) # first non-opt arg + break + ;; + esac +done + +for file +do + if test -d "$file"; then + shift + else + break + fi +done + +case $# in + 0) exit 0 ;; +esac + +case $dirmode in + '') + if mkdir -p -- . 2>/dev/null; then + echo "mkdir -p -- $*" + exec mkdir -p -- "$@" + fi + ;; + *) + if mkdir -m "$dirmode" -p -- . 2>/dev/null; then + echo "mkdir -m $dirmode -p -- $*" + exec mkdir -m "$dirmode" -p -- "$@" + fi + ;; +esac + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case $pathcomp in + -*) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + else + if test ! -z "$dirmode"; then + echo "chmod $dirmode $pathcomp" + lasterr="" + chmod "$dirmode" "$pathcomp" || lasterr=$? + + if test ! -z "$lasterr"; then + errstatus=$lasterr + fi + fi + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# End: +# mkinstalldirs ends here diff --git a/tags/gpgme-1.1.6/tests/ChangeLog b/tags/gpgme-1.1.6/tests/ChangeLog new file mode 100644 index 0000000..94aa576 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/ChangeLog @@ -0,0 +1,770 @@ +2008-01-04 Marcus Brinkmann + + * gpg/Makefile.am (CLEANFILES): Add pubring.kbx and dirmngr.conf. + + * Makefile.am (TESTS_ENVIRONMENT): Use absolute path for + GNUPGHOME. + * gpg/Makefile.am (TESTS_ENVIRONMENT): Use absolute path for + GNUPGHOME. + * gpgsm/Makefile.am (TESTS_ENVIRONMENT): Use absolute path for + GNUPGHOME. + * gpg/Makefile.am (TESTS): Add t-gpgconf. + t-gpgconf.c: New file. + +2007-11-23 Marcus Brinkmann + + * gpgsm/t-verify.c (show_auditlog): Check for GPG_ERR_ASS_UNKNOWN_CMD. + +2007-11-23 Werner Koch + + * gpgsm/t-verify.c (check_result): Don't exit on error but set a flag. + (main): Cosnult flag for return value. + (show_auditlog): New. + (main): Use it. + +2007-09-27 Marcus Brinkmann + + * t-engine-info.c (check_engine_info): Fix debug output. + * gpg/Makefile.am (tests_unix): New variable. + (TESTS): Use it. + * gpg/t-support.h (passphrase_cb) [HAVE_W32_SYSTEM]: Use WriteFile instead of write. + * gpg/t-wait.c [HAVE_W32_SYSTEM]: Define sleep as _sleep. + +2007-09-14 Marcus Brinkmann + + * gpgsm/t-verify.c (main): Release TEXT and SIG. + +2007-07-12 Marcus Brinkmann + + * gpgsm/Makefile.am (key_id): Change := into =. + +2007-07-12 Werner Koch + + * gpgsm/t-support.h (init_gpgme) [W32]: Do not init the locales as + the constants are not available. + +2007-02-26 Werner Koch + + * gpg/t-verify.c (double_plaintext_sig): New. + (main): Check it. + +2006-12-02 Marcus Brinkmann + + * gpgsm/t-keylist.c (main): Skip unknown keys. Newer versions of + GPGSM import more keys than older ones. + +2005-12-06 Werner Koch + + * gpg/t-keylist.c (main): Changed for that secondary keys now have + a fingerprint. + * gpg/t-keylist-sig.c (main): Ditto. + * gpgsm/t-keylist.c (main): Ditto. The test used to be wrong. + +2005-10-18 Werner Koch + + * gpg/pubdemo.asc, gpg/secdemo.asc: Add 2 expired subkeys to + Whisky. + * gpg/t-keylist.c: Reordered list to match new demo keyring. Add + arg for number of subkeys and for extra checking function. + (main): Enhanced a few error outputs. Changed subkey + counting. Call extra checking fucntion. + (check_whisky): New. + +2005-10-07 Marcus Brinkmann + + * gpgsm/t-keylist.c (main): Allow for an email address as a second + uid. + + * gpg/t-sig-notation.c: Change critical notation to something + GnuPG understands. + +2005-10-01 Marcus Brinkmann + + * gpg/Makefile.am (EXTRA_DIST): Remove gpg.conf. + (DISTCLEANFILES): Add gpg.conf. + (all-local): Add gpg.conf. + (./gpg.conf): New target. + * gpg/gpg.conf: Remove file. + + * gpg/Makefile.am (EXTRA_DIST): Add gpg.conf. + + * gpg/Makefile.am (TESTS): Add t-sig-notation. + * gpg/t-sig-notation.c (check_result): New file. + * gpg/t-verify.c (check_result): Also check the length of the + notation data. + * gpg/gpg.conf: New file. + +2005-09-30 Marcus Brinkmann + + * gpg/Makefile.am (TESTS): Add t-filename. + * gpg/t-filename.c: New file. + +2005-09-23 Werner Koch + + * gpg/t-support.h (init_gpgme) [W32]: Don't use LC_MESSAGES. + + * gpg/t-encrypt-large.c: New test. + * gpg/Makefile.am (TESTS): Add t-encrypt-large. + +2005-06-03 Marcus Brinkmann + + * gpg/Makefile.am (TESTS): Add t-wait. + * gpg/t-wait.c (main): New test. + +2004-12-07 Marcus Brinkmann + + * gpg/mkdemodirs: Add copyright notice. + + * gpgsm/Makefile.am, gpgsm/t-support.h, gpgsm/t-decrypt.c, + gpgsm/t-encrypt.c, gpgsm/t-export.c, gpgsm/t-genkey.c, + gpgsm/t-import.c, gpgsm/t-keylist.c, gpgsm/t-sign.c, + gpgsm/t-verify.c, gpg/Makefile.am, gpg/t-decrypt.c, + gpg/t-decrypt-verify.c, gpg/t-edit.c, gpg/t-encrypt.c, + gpg/t-encrypt-sign.c, gpg/t-encrypt-sym.c, gpg/t-eventloop.c, + gpg/t-export.c, gpg/t-genkey.c, gpg/t-import.c, gpg/t-keylist.c, + gpg/t-keylist-sig.c, gpg/t-sign.c, gpg/t-signers.c, + gpg/t-support.h, gpg/t-thread1.c, gpg/t-trustlist.c, + gpg/t-verify.c, Makefile.am, t-data.c, t-engine-info.c, + t-version.c: Change license to LGPL. + +2004-08-17 Marcus Brinkmann + + * gpgsm/t-keylist.c (struct): Add new fields VALIDITY and + KEY_LENGTH. + (main): Use them. + * gpgsm/t-import.c (check_result): New argument total_stat. + (main): Pass this argument. Reduce number of total considered + keys to 1 for the second test. + +2004-04-05 Werner Koch + + * gpgsm/Makefile.am: Changed the faked system time to 20011213T12000. + +2004-03-07 Marcus Brinkmann + + * gpgsm/t-keylist.c: Add chain IDs. + +2004-03-03 Werner Koch + + * gpgsm/t-export.c (main): Also check exporting 2 certificates. + +2004-02-17 Werner Koch + + * gpgsm/t-import.c (check_result): gpgsm does now return info in + the result->imports; adjust for that. + + * gpgsm/Makefile.am (TESTS_ENVIRONMENT): Reset the GPG_AGENT_INFO. + + Include config.h at the top of each C source. This is required + due to LFS support. + + * gpg/t-keylist-sig.c (main): s/class/sig_class/. + * gpg/t-signers.c (check_result): Ditto. + * gpg/t-sign.c (check_result): Ditto. + * gpg/t-encrypt-sign.c (check_result): Ditto. + * gpgsm/t-sign.c (check_result): Ditto. + +2004-01-12 Werner Koch + + * gpg/t-keylist-sig.c (main): Temporary disabled one test due top + gpg 1.3.4 problems. + * gpg/t-import.c (check_result): Likewise. + +2003-11-19 Werner Koch + + * gpg/t-support.h (DIM): Added. + + * gpg/t-verify.c (check_result): Rewrote test for notations + because the order of notaions is not guaranteed. + + * gpgsm/t-support.h (fail_if_err): Also print the numeric values. + +2003-10-06 Marcus Brinkmann + + * gpg/t-eventloop.c: Include for old systems. + + * gpgsm/Makefile.am (DISTCLEANFILES): Add random_seed. + + * gpg/t-thread1.c (thread_one): Do not call initialize_gpgme. + Likewise. + +2003-09-14 Marcus Brinkmann + + * gpg/t-thread1.c (main): Call init_gpgme here. + (initialize_gpgme): Function removed. + + * gpg/t-thread1.c: New file. + * gpg/Makefile.am (TESTS): Add t-thread1.c. + (t_thread1_LDADD): New variable. + (LDADD): Remove GPG Error lib. + * gpgsm/Makefile.am (LDADD): Likewise. + + * gpg/t-import.c (main): Likewise. + * gpg/t-keylist-sig.c (main): Likewise. + * gpg/t-keylist.c (main): Likewise. + * gpg/t-sign.c (main): Likewise. + * gpg/t-signers.c (main): Likewise. + * gpg/t-trustlist.c (main): Likewise. + * gpgsm/t-support.h: Include and . + (init_gpgme): New function. + * gpg/t-support.h: Likewise. + * gpgsm/t-verify.c (main): Call init_gpgme. + * gpgsm/t-decrypt.c (main): Likewise. + * gpgsm/t-encrypt.c (main): Likewise. + * gpgsm/t-export.c (main): Likewise. + * gpgsm/t-genkey.c (main): Likewise. + * gpgsm/t-import.c (main): Likewise. + * gpgsm/t-keylist.c (main): Likewise. + * gpgsm/t-sign.c (main): Likewise. + * gpg/t-verify.c (main): Call init_gpgme. + * gpg/t-decrypt-verify.c (main): Likewise. + * gpg/t-decrypt.c (main): Likewise. + * gpg/t-edit.c (main): Likewise. + * gpg/t-encrypt-sign.c (main): Likewise. + * gpg/t-encrypt-sym.c (main): Likewise. + * gpg/t-encrypt.c (main): Likewise. + * gpg/t-eventloop.c (main): Likewise. + * gpg/t-export.c (main): Likewise. + * gpg/t-genkey.c (main): Likewise. + +2003-08-14 Marcus Brinkmann + + * gpg/t-sign.c (check_result): Change output format for signature + class to unsigned int. + * gpg/t-signers.c (check_result): Likewise. + * gpg/t-encrypt-sign.c (check_result): Likewise. + * gpgsm/t-sign.c (check_result): Likewise. + +2003-07-31 Marcus Brinkmann + + * gpg/t-verify.c (check_result): Change type of SUMMARY to + unsigned int. + * gpg/t-decrypt-verify.c (check_verify_result): Likewise. + * gpg/t-keylist-sig.c (keys): Change type of member CLASS to + unsigned int. + * t-data.c (read_cb): Change type of AMOUNT to unsigned int. + * t-version.c (version): Remove unused variable. + +2003-07-22 Marcus Brinkmann + + * Makefile.am (AM_CPPFLAGS): New variable. + (LDADD): Add @GPG_ERROR_LIBS@. + * gpg/Makefile.am (AM_CPPFLAGS): New variable. + (LDADD): Add @GPG_ERROR_LIBS@. + * gpgsm/Makefile.am (AM_CPPFLAGS): New variable. + (LDADD): Add @GPG_ERROR_LIBS@. + +2003-06-06 Marcus Brinkmann + + Everywhere: Use libgpg-error error codes. + + * gpg/Makefile.am (noinst_HEADERS): New variable. + * gpg/t-support.h: New file. + * gpgsm/Makefile.am (noinst_HEADERS): New variable. + * gpgsm/t-support.h: New file. + +2003-05-29 Marcus Brinkmann + + * gpg/t-encrypt-sym.c (main): Adapt to new syntax. + * gpg/t-encrypt.c (main): Likewise. + * gpg/t-eventloop.c (main): Likewise. + * gpg/t-encrypt-sign.c (main): Likewise. + * gpgsm/t-export.c (main): Likewise. + * gpgsm/t-encrypt.c (main): Likewise. + +2003-05-28 Marcus Brinkmann + + * gpg/t-eventloop.c (main): Rewrite recipient management. + * gpg/t-encrypt-sign.c (main): Likewise. + * gpg/t-encrypt.c (main): Likewise. + * gpg/t-export.c (main): Likewise. + * gpgsm/t-encrypt.c (main): Likewise. + * gpgsm/t-export.c (main): Likewise. + +2003-05-27 Marcus Brinkmann + + * gpg/Makefile.am (TESTS): Order t-keylist and t-keylist-sig after + t-import. + * gpg/t-edit.c (edit_fnc): Fix primary UID for keylisting tests. + * gpg/t-keylist.c: Change order of user IDs. + * gpg/t-keylist-sig.c: Likewise. + * gpg/t-import.c: Add support for gpg in CVS. + +2003-05-27 Marcus Brinkmann + + * t-data.c: Remove TEST_OUT_CB. + (main): Likewise. + * gpg/t-trustlist.c (main): Access ITEM directly. + + * (t-decrypt-verify.c, t-decrypt.c, t-edit.c, t-encrypt-sign.c, + t-encrypt-sym.c, t-sign.c, t-signers.c): Include . + (passphrase_cb): Rewritten. + * t-edit.c (edit_fnc): Rewritten. + +2003-05-04 Marcus Brinkmann + + * gpg/t-keylist-sig.c (main): Remove timestamp check. + + * gpgsm/t-keylist.c: Add check for timestamp. + + * gpg/Makefile.am (TESTS): Add t-keylist-sig. + * gpg/t-keylist-sig.c: New file. + +2003-04-30 Marcus Brinkmann + + * gpg/t-eventloop.c (main): Do not call print_op_info. + (print_op_info): Function removed. + + * gpg/t-keylist.c: Rewritten. + * gpgsm/t-keylist.c (main): Rewritten. + * gpg/t-edit.c (main): Do not use gpgme_key_get_as_xml. Use + gpgme_key_unref instead gpgme_key_release. + * gpg/t-signers.c (main): Use gpgme_key_unref instead + gpgme_key_release. + +2003-04-29 Marcus Brinkmann + + * gpg/t-trustlist.c: Rewritten. + + * gpg/t-verify.c (main): Rewritten. + * gpg/t-decrypt-verify.c: Rewritten. + * gpgsm/t-verify.c (main): Rewritten. + +2003-04-28 Marcus Brinkmann + + * gpgsm/t-decrypt.c (main): Rewritten. + + * gpg/t-decrypt.c: Rewritten. + + * gpg/t-signers.c: Rewritten. + +2003-04-27 Marcus Brinkmann + + * gpg/t-encrypt-sign.c (check_result): Rewritten. + + * gpg/t-sign.c: Rewritten. + * gpgsm/t-sign.c: Rewritten. + * gpg/t-encrypt.c: Check for invalid recipients. + * gpgsm/t-encrypt.c: Likewise. + + * gpg/t-import.c (check_result): Really use FPR. + * gpgsm/t-import.c (check_result): Rewritten. + +2003-04-25 Marcus Brinkmann + + * gpg/t-import.c: Rewritten. + + * gpgsm/t-genkey.c: Rewritten. + * gpgsm/Makefile.am (noinst_PROGRAMS): Add t-genkey. + * gpg/t-genkey.c: Include . + (main): Check result->fpr before checking its length. + +2003-04-24 Marcus Brinkmann + + * gpg/t-genkey.c: Rewritten to match new semantics. + +2003-02-06 Marcus Brinkmann + + * gpg/t-decrypt.c (passphrase_cb): Fix to new prototype. + * gpg/t-decrypt-verify.c (passphrase_cb): Likewise. + * gpg/t-edit.c (passphrase_cb): Likewise. + * gpg/t-encrypt-sign.c (passphrase_cb): Likewise. + * gpg/t-encrypt-sym.c (passphrase_cb): Likewise. + * gpg/t-sign.c (passphrase_cb): Likewise. + * gpg/t-signers.c (passphrase_cb): Likewise. + +2003-01-30 Marcus Brinkmann + + * t-engine-info.c: Use file_name instead path throughout. + + * Makefile.am (TESTS): Add t-engine-info. + * t-engine-info.c: New file. + * gpg/t-encrypt.c (main): Don't print engine info. + * gpg/t-eventloop.c (main): Likewise. + * gpg/t-encrypt-sign.c (main): Likewise. + * gpgsm/t-encrypt.c (main): Likewise. + +2002-12-24 Marcus Brinkmann + + * gpgsm/t-verify.c (main): Adjust caller of gpgme_op_verify. + * gpg/t-verify.c (main): Likewise. + * gpg/t-decrypt-verify.c (main): Likewise for + gpgme_op_decrypt_verify. + +2002-12-23 Marcus Brinkmann + + * gpgsm/Makefile.am (./gpgsm.conf): Add a faked system time to + avoid certification's expiry. + * gpgsm/t-encrypt.c (main): Use the short certification name. + +2002-11-19 Marcus Brinkmann + + * gpg/t-genkey.c (main): Add missing argument to gpgme_op_genkey + invocation. + +2002-10-09 Marcus Brinkmann + + * gpg/t-decrypt.c (print_data): Update to new gpgme_data_read + interface, and use gpgme_engine_check_version instead + gpgme_check_version. + * gpg/t-decrypt-verify.c (print_data): Likewise. + * gpg/t-edit.c (main): Likewise. + * gpg/t-encrypt.c (print_data): Likewise. + * gpg/t-encrypt-sign.c (print_data): Likewise. + * gpg/t-encrypt-sym.c (print_data): Likewise. + * gpg/t-eventloop.c (print_data): Likewise. + * gpg/t-export.c (print_data): Likewise. + * gpg/t-sign.c (print_data): Likewise. + * gpg/t-signers.c (print_data): Likewise. + * gpgsm/t-decrypt.c (print_data): Likewise. + * gpgsm/t-encrypt.c (print_data): Likewise. + * gpgsm/t-export.c (print_data): Likewise. + * gpgsm/t-sign.c (print_data): Likewise. + * gpg/t-verify.c (main): Likewise for gpgme_op_verify. + * gpgsm/t-verify.c (main): Likewise for gpgme_op_verify. + * t-data.c (read_once_test): Likewise. + (write_test): Update for new behaviour of data objects. + (main): Remove type test. + +2002-09-30 Werner Koch + + * gpgsm/t-keylist.c (doit): Add arg SECRET. + (main): Add option --secret. + +2002-09-28 Marcus Brinkmann + + * t-version.c: Include . Reported by Stéphane Corthésy. + +2002-09-02 Marcus Brinkmann + + * gpg/t-keylist.c (main): Test PATTERN for NULL before printing. + Reported by Dr. Stefan Dalibor . + +2002-08-01 Marcus Brinkmann + + * gpg/t-edit.c: Also add a test for the expire command (testing + the passphrase callback). + +2002-07-28 Marcus Brinkmann + + * gpg/t-edit.c: New file. + * gpg/Makefile (TESTS): Add t-edit. + +2002-07-25 Marcus Brinkmann + + * gpg/t-encrypt-sym.c (main): Change type of I to size_t and + rename to LEN. + * gpg/t-verify.c (main): Likewise. Submitted by Stéphane + Corthésy. + +2002-07-03 Marcus Brinkmann + + * gpg/t-eventloop.c: New file. + * gpg/Makefile (TESTS): Add t-eventloop. + +2002-06-26 Werner Koch + + * gpgsm/t-import.c (print_op_info): New. + (main): Print operation info. + +2002-06-25 Werner Koch + + * gpgsm/Makefile.am (DISTCLEANFILES): new. + +2002-06-25 Marcus Brinkmann + + * gpgsm/Makefile.am (TESTS): Add t-export. + gpgsm/t-export.c: New file. + +2002-06-20 Werner Koch + + * gpgsm/t-sign.c (main): Also test a normal signature. + + * gpg/Makefile (TESTS_ENVIRONMENT): Set GPG_AGENT_INFO empty. + * gpg/t-signers.c, gpg/t-sign.c, gpg/t-encrypt-sym.c + * gpg/t-encrypt-sign.c, gpg/t-decrypt.c + * gpg/t-decrypt-verify.c (main): Changed the GPG_AGENT_INFO check to + match the one in ../../gpgme/rungpg.c. + +2002-06-12 Werner Koch + + * gpgsm/t-keylist.c (doit): Print operation info if available. + +2002-06-10 Werner Koch + + * gpgsm/t-verify.c (print_sig_stat): Print the error token. + +2002-06-04 Werner Koch + + * gpgsm/t-encrypt.c (main): Add a simple option parser and allow + to specify an encryption key. + +2002-05-26 Marcus Brinkmann + + * gpg/Makefile.am (all-local): Remove dependency on ./secring.gpg. + (./secring.gpg): Remove target, and move all rules for this target + to ... + (./pubring.gpg): ... here. This was necessary because GnuPG 1.0.7 + does create an empty secring.gpg file when importing public keys. + +2002-05-08 Marcus Brinkmann + + * gpgsm/t-verify.c (validity_string): New. + (print_sig_stat): Print expire time and validity. + (status_string): Add new exipred stati. + +2002-05-03 Werner Koch + + * gpg/t-verify.c (validity_string): New. + (print_sig_stat): Print expire time and validity. + (status_string): Add new exipred stati. + +2002-04-05 Marcus Brinkmann + + * gpgsm/Makefile.am (./trustlist.txt): Put more into this file to + prevent use of gpg-agent. + (./gpg-agent.conf): Remove target. + (all-local): Remove ./gpg-agent.conf. + +2002-04-05 Marcus Brinkmann + + * gpgsm/t-keylist.c (main): Use gpgme_engine_check_version instead + gpgme_check_engine. + * gpgsm/t-encrypt.c (main): Likewise. + +2002-03-06 Marcus Brinkmann + + * gpg/t-encrypt-sym.c: New file. + * gpg/Makefile.am (TESTS): Add t-encrypt-sym. + +2002-03-05 Marcus Brinkmann + + * gpg/Makefile.am (CLEANFILES): Remove random_seed, which is now + in DISTCLEANFILES. + +2002-03-04 Werner Koch + + * gpg/Makefile.am (DISTCLEANFILES): Added. + +2002-03-03 Marcus Brinkmann + + * gpg/t-verify.c (main): Add a few more sanity checks, and a check + for normal signatures. + +2002-02-26 Marcus Brinkmann + + * gpg/t-encrypt-sign.c: New file. + * gpg/Makefile.am (TESTS): Add t-encrypt-sign. + +2002-02-13 Werner Koch + + * gpgsm/Makefile.am (private-keys-v1.d): Don't + fail when the directory already exists. + +2002-02-12 Marcus Brinkmann + + * gpg/Makefile.am (CLEANFILES): New target. + (distclean-local): Rename to ... + (clean-local): ... this. + +2002-02-09 Marcus Brinkmann + + * gpgsm/Makefile.am (./private-keys-v1.d/$(key_id).key): Fix rule. + +2002-02-09 Marcus Brinkmann + + * gpgsm/t-genkey.c: New file (not added to Makefile.am because of + gpg-agent bug). + +2002-02-08 Marcus Brinkmann + + * gpgsm/Makefile.am (key_id): Update value. + (all-local): Add .key to keyid filename. + (./private-keys-v1.d/$(key_id)): Renamed to ... + (./private-keys-v1.d/$(key_id).key): ... this. + (all-local): Add ./gpgsm.conf, ./trustlist.txt. + (./gpgsm.conf, ./trustlist.txt): New target. + * gpgsm/567064FE6D14A17B2D811ABB407728BC558AA455: Renamed to ... + * gpgsm/32100C27173EF6E9C4E9A25D3D69F86D37A4F939: ... this. + +2002-01-30 Marcus Brinkmann + + * gpg/t-import.c (print_op_info): New function. + (main): Use it. + +2002-01-22 Marcus Brinkmann + + * gpg/t-signers.c (passphrase_cb): Change type of r_hd to void**. + * gpg/t-sign.c (passphrase_cb): Likewise. + * gpg/t-decrypt-verify.c (passphrase_cb): Likewise. + * gpg/t-decrypt.c (passphrase_cb): Likewise. + +2001-12-19 Marcus Brinkmann + + * gpg/t-decrypt-verify.c: Don't include `mcheck.h'. Reported by + Stéphane Corthésy. + +2001-12-19 Marcus Brinkmann + + * gpg/Makefile.am (EXTRA_DIST): Add missing line continuation. + +2001-12-19 Marcus Brinkmann + + * gpgsm/Makefile.am (EXTRA_DIST): Add $(key_id). + +2001-12-16 Marcus Brinkmann + + * gpgsm/Makefile: Rename `pubcerts.kbx' to `pubring.kbx'. + +2001-12-15 Marcus Brinkmann + + * gpgsm/t-keylist.c (check_two_contexts): Set protocols. + +2001-12-14 Marcus Brinkmann + + * gpgsm/t-sign.c: New file. + * gpgsm/Makefile.am (TESTS): Add t-sign. + +2001-12-14 Marcus Brinkmann + + * gpgsm/t-decrypt.c: New file. + * gpgsm/567064FE6D14A17B2D811ABB407728BC558AA455: Likewise. + * gpgsm/Makefile.am (TESTS): Add t-decrypt. + (key_id): New variable. + (all-local): New target ./private-keys-v1.d/$(key_id) added. + (./private-keys-v1.d/$(key_id)): New target. + +2001-12-14 Marcus Brinkmann + + * gpgsm/t-verify.c: New file. + * gpgsm/Makefile.am (TESTS): Add t-verify. + +2001-12-14 Marcus Brinkmann + + * gpg/Makefile.am (GPG): Set to @GPG_PATH@. + (./pubring.gpg): Use $(GPG) instead gpg. + (./secring.gpg): Likewise. + + * gpgsm/t-import.c (main): Remove third test case. + * gpgsm/Makefile.am (GPGSM): Set to @GPGSM@. + (all-local): New target. + (./pubcerts.kbx): Likewise. + * gpgsm/t-encrypt.c: New file. + * gpgsm/Makefile.am (TESTS): Add t-encrypt. + +2001-12-14 Marcus Brinkmann + + * gpgsm/t-keylist.c: New file. + * gpgsm/Makefile.am (TESTS): Add t-keylist. + +2001-12-13 Marcus Brinkmann + + * gpgsm/cert_dfn_pca01.der: New file. + * gpgsm/cert_dfn_pca15.der: Likewise. + * gpgsm/cert_g10code_test1.der: Likewise. + * gpgsm/t-import.c: Likewise. + * gpgsm/Makefile.am (EXTRADIST): Add new files. + (TESTS): Add t-import. + +2001-11-22 Marcus Brinkmann + + * gpg/: New directory. + * Makefile.am, t-verify.c, t-encrypt.c, t-signers.c, t-trustlist.c, + t-sign.c, t-keylist.c, t-import.c, t-genkey.c, t-export.c, + t-decrypt-verify.c, t-decrypt.c, t-version.c, t-data.c, mkdemodirs. + cipher-1.asc, cipher-2.asc, geheim.txt, pubdemo.asc, pubkey-1.asc, + secdemo.asc, seckey-1.asc): Move to sub directory gpg/. + + * gpg/Makefile.am (INCLUDES): Include gpgme/, not include/ and + intl/. + (LDD): Correct relative path to gpgme library. + (TESTS): Remove t-version and t-data. + * gpg/t-verify.c, gpg/t-encrypt.c, gpg/t-signers.c, gpg/t-trustlist.c, + gpg/t-sign.c, gpg/t-keylist.c, gpg/t-import.c, gpg/t-genkey.c, + gpg/t-export.c, gpg/t-decrypt-verify.c, gpg/t-decrypt.c, + t-version.c, t-data.c): Include gpgme.h, not "../gpgme/gpgme.h". + + * Makefile.am: New file. + * gpgsm/: New directory. + * gpgsm/Makefile.am: New file. + +2001-11-16 Marcus Brinkmann + + * Makefile.am (TESTS): Add t-decrypt-verify. + * t-decrypt-verify.c: New file. + * cipher-2.asc: Likewise. + +2001-11-02 Marcus Brinkmann + + * t-data.c: Include stddef.h. + (read_once_test): Change type of READ to size_t. + (read_test): Likewise. + (write_test): Likewise. + +2001-10-29 Marcus Brinkmann + + * t-signers.c: New file. + * Makefile.am (TESTS): Add t-signers. + +2001-10-22 Marcus Brinkmann + + * Makefile.am (TEST_ENVIRONMENT): Revert last change. + +2001-10-22 Marcus Brinkmann + + * Makefile.am (TEST_ENVIRONMENT): Set environment to $(srcdir), + not current directory. + +2001-10-22 Marcus Brinkmann + + * t-data.c (write_test): New function. + (main): Invoke write_test for all rounds except TEST_OUT_CB. + +2001-10-22 Marcus Brinkmann + + * Makefile.am (INCLUDES): Remove spurious duplicate to silence + automake. + +2001-10-16 Marcus Brinkmann + + * t-version.c: New file. + * t-data.c: Likewise. + * t-data-1.txt: Likewise. + * t-data-2.txt: Likewise. + * Makefile.am (TESTS): Add t-version, t-data. + +2001-09-17 Werner Koch + + * t-keylist.c (check_two_contexts): New. + +2001-09-03 Werner Koch + + * t-encrypt.c (print_op_info): New and use it after each operation.. + +2001-08-28 Werner Koch + + * t-sign.c (print_op_info): New and use it after each operation. + +2001-03-15 Werner Koch + + * t-keylist.c (doit): List subkeys too, show caps. + +2001-02-13 Werner Koch + + * t-verify.c (print_sig_stat): Repaled ulong by unsigned long + because we don't use the config stuff here. + +2001-02-12 Werner Koch + + * tests/t-verify.c (print_sig_stat): Print info about the keys. + + + Copyright 2001, 2004 g10 Code GmbH + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/tags/gpgme-1.1.6/tests/Makefile.am b/tags/gpgme-1.1.6/tests/Makefile.am new file mode 100644 index 0000000..ceabc99 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/Makefile.am @@ -0,0 +1,48 @@ +# Makefile.am - Makefile for GPGME tests. +# Copyright (C) 2000 Werner Koch (dd9jn) +# Copyright (C) 2001, 2004 g10 Code GmbH +# +# This file is part of GPGME. +# +# GPGME is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser 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 + +## Process this file with automake to produce Makefile.in + +TESTS_ENVIRONMENT = GNUPGHOME=$(abs_builddir) + +TESTS = t-version t-data t-engine-info + +EXTRA_DIST = t-data-1.txt t-data-2.txt + +INCLUDES = -I$(top_srcdir)/gpgme + +AM_CPPFLAGS = @GPG_ERROR_CFLAGS@ +LDADD = ../gpgme/libgpgme.la @GPG_ERROR_LIBS@ + +noinst_PROGRAMS = $(TESTS) + +if RUN_GPG_TESTS +gpgtests = gpg +else +gpgtests = +endif + +if RUN_GPGSM_TESTS +gpgsmtests = gpgsm +else +gpgsmtests = +endif + +SUBDIRS = ${gpgtests} ${gpgsmtests} diff --git a/tags/gpgme-1.1.6/tests/gpg/Makefile.am b/tags/gpgme-1.1.6/tests/gpg/Makefile.am new file mode 100644 index 0000000..3ce6592 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/Makefile.am @@ -0,0 +1,70 @@ +# Copyright (C) 2000 Werner Koch (dd9jn) +# Copyright (C) 2001, 2004, 2005 g10 Code GmbH +# +# This file is part of GPGME. +# +# GPGME is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser 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 + +## Process this file with automake to produce Makefile.in + +GPG = @GPG@ + +TESTS_ENVIRONMENT = GNUPGHOME=$(abs_builddir) GPG_AGENT_INFO= + +# The keylist tests must come after the import and the edit test. +noinst_HEADERS = t-support.h + +if HAVE_W32_SYSTEM +tests_unix = +else +tests_unix = t-eventloop t-thread1 +endif + +TESTS = t-encrypt t-encrypt-sym t-encrypt-sign t-sign t-signers \ + t-decrypt t-verify t-decrypt-verify t-sig-notation t-export \ + t-import t-trustlist t-edit t-keylist t-keylist-sig t-wait \ + t-encrypt-large t-file-name t-gpgconf $(tests_unix) + +CLEANFILES = secring.gpg pubring.gpg pubring.kbx trustdb.gpg dirmngr.conf +DISTCLEANFILES = pubring.gpg~ random_seed gpg.conf + +EXTRA_DIST = mkdemodirs pubdemo.asc secdemo.asc cipher-1.asc cipher-2.asc \ + geheim.txt pubkey-1.asc seckey-1.asc + +INCLUDES = -I$(top_srcdir)/gpgme + +AM_CPPFLAGS = @GPG_ERROR_CFLAGS@ +LDADD = ../../gpgme/libgpgme.la +t_thread1_LDADD = ../../gpgme/libgpgme-pthread.la + +# We don't run t-genkey in the test suite, because it takes too long +noinst_PROGRAMS = $(TESTS) t-genkey + +clean-local: + $(srcdir)/mkdemodirs --clean + +all-local: ./pubring.gpg ./gpg.conf + +./pubring.gpg: $(srcdir)/pubdemo.asc ./Alpha/Secret.gpg + $(GPG) --homedir . --import $(srcdir)/pubdemo.asc + $(GPG) --homedir . --allow-secret-key-import \ + --import Alpha/Secret.gpg Zulu/Secret.gpg + +./Alpha/Secret.gpg: secdemo.asc + srcdir=$(srcdir) $(srcdir)/mkdemodirs + +./gpg.conf: +# This is required for t-sig-notations. + echo no-force-v3-sigs > ./gpg.conf diff --git a/tags/gpgme-1.1.6/tests/gpg/cipher-1.asc b/tags/gpgme-1.1.6/tests/gpg/cipher-1.asc new file mode 100644 index 0000000..f0a8ca4 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/cipher-1.asc @@ -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----- diff --git a/tags/gpgme-1.1.6/tests/gpg/cipher-2.asc b/tags/gpgme-1.1.6/tests/gpg/cipher-2.asc new file mode 100644 index 0000000..210f3e9 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/cipher-2.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP MESSAGE----- +Version: GnuPG v1.0.6 (GNU/Linux) +Comment: Weitere Infos: siehe http://www.gnupg.org + +hQEOA++dwnahcsiBEAP9HgkC1ElQwZRX1X/MBF54Q28dpXKr84IviO4QcbnnhmYk +2IlaNe6mr8R7kNM1aqJFK3fnobqnSWwM/VBObMqqYnzZSfclCNsy66sojQJxwXcz +DKQKi69BLaC6aTMnX048tOl8pJpR72fkffUOUa5ywDHVVVUClDG3XkIrfM1du3YD +/A6vFSrRylupKhQBxdtSUx5IDmpDYwG2vqqbYKoMaQ4pPSKLYV2zskU+pQWRlk6y +nwPGY5h9eGz0xYHMPxhe9VnwljeTEDwz5U4CHF3wQ8h5WBxOVx5QN/H/UyjpmoJT +ddrIu+8GgajhBVKVYAOqr577exkiSDA60/JrYbKZBvzL0sAJAUu+HoeMPJ+5/RYF +pLSdz/3MbVDRJJqzV2TJnEBvFtPa6urzx99P0u4xr+RJMFmR9/99YXhYz7+Y6d/B +44F6B3YouYxiK39IoOUcYPZTwb5kaudD5a3mU3XxEhSDUpnyvowPiKQO1T8CPd2u +2HsD3KeaOc2VFE0gnvqECvUTQfSCZCk/kil8XVAMHZrEA0bWAYiaHfHEOB8SRCy8 +rW0wsON4uDXmZpUkfOjFoYZdpJI7fDKkb5uYUzFZDasharEaXb1X/5xSAclx +=+eYk +-----END PGP MESSAGE----- diff --git a/tags/gpgme-1.1.6/tests/gpg/geheim.txt b/tags/gpgme-1.1.6/tests/gpg/geheim.txt new file mode 100644 index 0000000..99a5478 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/geheim.txt @@ -0,0 +1,2 @@ +Wenn Sie dies lesen können, ist es wohl nicht +geheim genug. diff --git a/tags/gpgme-1.1.6/tests/gpg/mkdemodirs b/tags/gpgme-1.1.6/tests/gpg/mkdemodirs new file mode 100755 index 0000000..ab2c568 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/mkdemodirs @@ -0,0 +1,55 @@ +#!/bin/sh +# Copyright (C) 2004 g10 Code GmbH +# +# This file is part of GPGME. +# +# GPGME is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser 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 + +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 || true + 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 diff --git a/tags/gpgme-1.1.6/tests/gpg/pubdemo.asc b/tags/gpgme-1.1.6/tests/gpg/pubdemo.asc new file mode 100644 index 0000000..be600c7 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/pubdemo.asc @@ -0,0 +1,586 @@ +26 demo keys [2005-10-18] + +pub 1024D/68697734 1999-03-08 Alpha Test (demo key) +uid Alice (demo key) +uid Alfa Test (demo key) +sub 1024g/46A871F8 1999-03-08 +pub 1024D/A9E3B0B2 1999-03-08 Bravo Test (demo key) +uid Bob (demo key) +sub 1024g/E29BA37F 1999-03-08 +pub 1024D/1AFDAB6C 1999-03-08 Charlie Test (demo key) +sub 1024g/BC43DA60 1999-03-08 +pub 1024D/EB9DC9E6 1999-03-08 Delta Test (demo key) +sub 1024g/B0C45424 1999-03-08 +pub 1024D/FAEF6D1B 1999-03-08 Echo Test (demo key) +uid Eve (demo key) +uid Echelon (demo key) +sub 1024g/7272144D 1999-03-08 +pub 1024D/7372E243 1999-03-08 Foxtrot Test (demo key) +sub 1024g/EE45198E 1999-03-08 +pub 1024D/8FC282E6 1999-03-08 Golf Test (demo key) +sub 1024g/9DCAD354 1999-03-08 +pub 1024D/34C6E3F1 1999-03-08 Hotel Test (demo key) +sub 1024g/D622AD0A 1999-03-08 +pub 1024D/04259677 1999-03-08 India Test (demo key) +sub 1024g/61F76C73 1999-03-08 +pub 1024D/D2699313 1999-03-08 Juliet Test (demo key) +sub 1024g/35F8F136 1999-03-08 +pub 1024D/43C2D0C7 1999-03-08 Kilo Test (demo key) +sub 1024g/9AF64D02 1999-03-08 +pub 1024D/B79103F8 1999-03-08 Lima Test (demo key) +sub 1024g/FE56350C 1999-03-08 +pub 1024D/BE5CF886 1999-03-08 Mike Test (demo key) +uid Mallory (demo key) +sub 1024g/4F31EAE8 1999-03-08 +pub 1024D/30CEC684 1999-03-08 November Test (demo key) +sub 1024g/8B70E472 1999-03-08 +pub 1024D/6D9732AC 1999-03-08 Oscar Test (demo key) +sub 1024g/2681619F 1999-03-08 +pub 1024D/3FF13206 1999-03-08 Papa test (demo key) +sub 1024g/63330D9C 1999-03-08 +pub 1024D/3C661C84 1999-03-08 Quebec Test (demo key) +sub 1024g/A029ACF4 1999-03-08 +pub 1024D/777FBED3 1999-03-08 Romeo Test (demo key) +sub 1024g/11D102EA 1999-03-08 +pub 1024D/A3AE3EA1 1999-03-08 Sierra Test (demo key) +sub 1024g/0F1B50B4 1999-03-08 +pub 1024D/85A81F38 1999-03-08 Tango Test (demo key) +sub 1024g/101C0402 1999-03-08 +pub 1024D/653244D6 1999-03-08 Uniform Test (demo key) +sub 1024g/5522BDB9 1999-03-08 +pub 1024D/61F04784 1999-03-08 Victor Test (demo key) +sub 1024g/07287134 1999-03-08 +pub 1024D/EC67DBDE 1999-03-08 Whisky Test (demo key) +sub 1024g/FD6E27F6 1999-03-08 +sub 1024D/E51987C9 2005-10-18 [expires: 2005-10-18] +sub 1024R/40DB9D43 2005-10-18 [expires: 2005-10-18] +pub 1024D/567FB34A 1999-03-08 XRay Test (demo key) +sub 1024g/41E408BE 1999-03-08 +pub 1024D/4B11B25F 1999-03-08 Yankee Test (demo key) +sub 1024g/F7B080AD 1999-03-08 +pub 1024D/54ACD246 1999-03-08 Zulu Test (demo key) +sub 1024g/A172C881 1999-03-08 + +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQGiBDbjjp4RBAC2ZbFDX0wmJI8yLDYQdIiZeAuHLmfyHsqXaLGUMZtWiAvn/hNp +ctwahmzKm5oXinHUvUkLOQ0s8rOlu15nhw4azc30rTP1LsIkn5zORNnFdgYC6RKy +hOeim/63+/yGtdnTm49lVfaCqwsEmBCEkXaeWDGq+ie1b89J89T6n/JquwCgoQkj +VeVGG+B/SzJ6+yifdHWQVkcD/RXDyLXX4+WHGP2aet51XlKojWGwsZmc9LPPYhwU +/RcUO7ce1QQb0XFlUVFBhY0JQpM/ty/kNi+aGWFzigbQ+HAWZkUvA8+VIAVneN+p ++SHhGIyLTXKpAYTq46AwvllZ5Cpvf02Cp/+W1aVyA0qnBWMyeIxXmR9HOi6lxxn5 +cjajA/9VZufOXWqCXkBvz4Oy3Q5FbjQQ0/+ty8rDn8OTaiPi41FyUnEi6LO+qyBS +09FjnZj++PkcRcXW99SNxmEJRY7MuNHt5wIvEH2jNEOJ9lszzZFBDbuwsjXHK35+ +lPbGEy69xCP26iEafysKKbRXJhE1C+tk8SnK+Gm62sivmK/5arQpQWxwaGEgVGVz +dCAoZGVtbyBrZXkpIDxhbHBoYUBleGFtcGxlLm5ldD6IVQQTEQIAFQUCNuOOngML +CgMDFQMCAxYCAQIXgAAKCRAtcnzHaGl3NDl4AKCBLmRplv/8ZfSqep5IjqEAuaXv +WwCgl6NEzT+/WewPTGcwZY+pLkycLv20EEFsaWNlIChkZW1vIGtleSmIVQQTEQIA +FQUCNuO2qwMLCgMDFQMCAxYCAQIXgAAKCRAtcnzHaGl3NCeMAJ9MeUVrago5Jc6P +dwdeN5OMwby37QCghW65cZTQlD1bBlIq/QM8bz9AN4G0J0FsZmEgVGVzdCAoZGVt +byBrZXkpIDxhbGZhQGV4YW1wbGUubmV0PohVBBMRAgAVBQI247hYAwsKAwMVAwID +FgIBAheAAAoJEC1yfMdoaXc0t8IAoJPwa6j+Vm5Vi3Nvuo8JZri4PJ/DAJ9dqbma +JdB8FdJnHfGh1rXK3y/JcrkBDQQ2448PEAQAnI3XH1f0uyN9fZnw72zsHMw706g7 +EW29nD4UDQG4OzRZViSrUa5n39eI7QrfTO+1meVvs0y8F/PvFst5jH68rPLnGSrX +z4sTl1T4cop1FBkquvCAKwPLy0lE7jjtCyItOSwIOo8xoTfY4JEEXmcqsbm+KHv9 +yYSF/YK4Cf7bIzcAAwcD/Rnl5jKxoucDA96pD2829TKsLFQSau+Xiy8bvOSSDdly +ABsOkNBSaeKO3eAQEKgDM7dzjVNTnAlpQ0EQ8Y9Z8pxOWYEQYlaMrnRBC4DZ2Iad +zEhLlIOz5BVp/jfhrr8oVVBwKZXsrz9PZLz+e4Yn+siUUvlei9boD9L2ZgSOHakP +iEYEGBECAAYFAjbjjw8ACgkQLXJ8x2hpdzQgqQCfcDXmD8uNVdKg/C9vqI3JSndq +knsAnRxzVeHi/iJ73OCKtvFrHbV9GogqmQGiBDbjouIRBACKncc4Ueec7dWaVARy +2SmNVufeSenYs4AsIPP0v59jEl7JI0rb+4JbIJoAzW/hcm26GS/UbbpQwig8/PgM +UV5QfBST4CEOlf7/x2a4HKk9tDV4An7q2aNr1beW+twxfUGWWV5I0o1b/iKVk/Li +QRiaMr8pJXY266m6/2Pn9LmDtwCg+Iqfx8gsK2PZCWv87uEKAOLzHXsD/1eRxLqC +t1hT98gdDLykRTlI3kMq6EK3I+z/8pDIMDuPIJq1eM68YdFZr8s7i1ye1QpDltPY +HgWnUC733ujAKANdyybm3HrA3TSBjEAhNfcu8nkrVorvASQUDCLJatWRWJTUVrPH ++GXIXMA/Oi6LDsgNDOJanwzzvDCCm8hWQqW9A/4xYAZ4NVFrQq8gtQPJWuMIfSFS +vpZWNgQgYZntiXSUGYOVs28T/87RoRx02tsVDw2PA8z68q/XRuM9NdetxbUXQHB9 +eszFLi3W1idsXhd/C4SyiTgEFXG8Y8s94Eadgk1PAYHN6Gd3SY7jmevqYGVLmBp7 +qfj5Y9XSM5SE0Th+fLQpQnJhdm8gVGVzdCAoZGVtbyBrZXkpIDxicmF2b0BleGFt +cGxlLm5ldD6IVQQTEQIAFQUCNuOi4gMLCgMDFQMCAxYCAQIXgAAKCRD+GAsdqeOw +svruAJ4iU4M5s1xsZiXa0wLnX4FBBl9abgCfflNpwyEp6KEhKCPWwPRG9WJc0qi0 +DkJvYiAoZGVtbyBrZXkpiFUEExECABUFAjbjtzsDCwoDAxUDAgMWAgECF4AACgkQ +/hgLHanjsLIa4QCgityK8zajBOqAN0ZZTq8fOzgiEYIAn1ZEfjX+jefZUuY+4zFz +rpO/fX0OuQENBDbjowcQBACVSdXxUWlz81FjqHgR4b1EtmhmW89CmpsHfKlSwlYv +BtbB/y7TFIfvAr4ZFbpuqew6JvtjIEZoXvolTWwHVPEFkuG0LAa03olaYpzC6ZBD +uLkb09RukCD4zdY6xwbAMRsOzZgv597LZXtOLLLnmOyTpsjRDLztWsuNglm5rffO +TwADBwP/SyVZvFEdEVn5/dQTp7eAtXdrbZEM379ctCJ2663RbTZd55lIBev1fTnK +QkvDTY2e58yIQ4E+Nzr99qg9Cyf6e3OhErTUqEBOhusBge4/7E5LrIVMvo6AFU9q +gn0Sgsnu/ww2txVw3XEjqL8Hgl+4Q/57YRvJOe+q29Ye9LL8eaiIRgQYEQIABgUC +NuOjBwAKCRD+GAsdqeOwsjK5AJ9pek7H6yt3ZHAJ+7nn7sGmxYxb5ACg1INFN4AM +zqEUjbZ51KTVdAvyKlSZAaIENuOQZxEEAL8MJC6eA7aInuP372p3ZyuMFTwr4CZC +GzbskGQmq0BsL/EWqQcGwDU+LxlvpMtr84KbY9tcWIznHTTCISdUo3O4Y7NTy4cH +qTBa0uPz5XtU5Y6RIMS2eVMXq7TL0k6+zsbAO+o4zkLdAfstr7Oc14C7XnbsePqX +RcZIDPK+n42TAKCeS1TXVUWkpIh2imVkFrI307NPywP8DBz/z3R+JIxZg0ajj6fo +gfGGMEEz2Uv4MB7VG0IS3BRJY2sawjEWcNGQzG8ylpPga6wb4M+FpN12sMFLIWII +vEoMFiAxtI7rBD2DrNYQSHVkxMxVT9qSvzUM4QKiVef9/dDixGPEjeG7bPy2NV7A +A81O5YRNDqIcehWp2mQrhoAEAJ9syud8rpO6PFKz3Ux8oFZ9jHLD2GMzr5VXxwkl +0NeKF4wrNZytV5zCBhjO6SY2Kc7/8FGZByzXB1+LlR18cs0UOKDD3pJ3JmkfH7v2 +CEPc2oObNhqShEigMpxkAisCOB+XmJ/q8iIDhzUuOFJ1xVMGxLKJz+aSTTUSDO1Y +pjRptC1DaGFybGllIFRlc3QgKGRlbW8ga2V5KSA8Y2hhcmxpZUBleGFtcGxlLm5l +dD6IVQQTEQIAFQUCNuOQZwMLCgMDFQMCAxYCAQIXgAAKCRBBP0rzGv2rbD5EAJ9f +cDAXA+7n6av9/VJr9a/Sb1PnuACfVMEihQSsyol6FBm7vc3S73d+pIq5AQ0ENuOQ +ghAEAKFjw1K+7qwrSngPQBUGxHPyJVdiptGVFNkAdLgsJfDH+LwWZ90hedo0s6jK +Ljhiu5IKeVl2Hhhaq4LHaaDLAbnz0DNwWFqGaoSU1spvubgX/8QYhkrTNOBbXe1D +Ab2FNc6Fh6pyGc45oMPA8QrUav7aj/kA2qGquKfRMUUFYuB3AAMHA/9HTT2zrVf8 +WRRQCHzDhO5rqqd03/YaypezI9iN0XkTeASsryMNwMueI4eqSzBXXtskbzVzMJET +klxUUstZAmD1yl6hOk/5hwX6b3CG2zBo4n8s+vHzzyL86aW5IPzVU/7rMGGFNRul +rN8sR23ddzOlbsI101vKIRyBP7oKv5bYZohGBBgRAgAGBQI245CCAAoJEEE/SvMa +/atsta0AnA21IY9iNt6wtJN5HAoYDl99mIUOAJ9M8Loj5fIZq+McmtodOBL9tII3 +Q5kBogQ246OHEQQA3mc7VzzWMKaCH+gX6nqSJmaoVXdql7mQSZxL8GhaAJe3q+Nq +V1y2YViLu/4Fjg33MjcbFCoDG3kPp1jto3XGULbfoJkQBpdReS28bD+mkcON1uzw +JG5mID2ObWP3YYBRj+abqFfZoYo6RXCv3I3oOsDYJo7hLAr/AReRV+P6drMAoMJo +HMfPBKSRd/xA605OP/F6+mfPBAC/fSVoJ5dMNkzYj/U93OZrVXXGLN9p7SR/Nk4k +ENC0dAO80WOa7qIzWQvS7E4beSuvQCWpKwwPxbuZq9sWKBSXFuG+66XilMv8GIn3 +joWGOU9jQ2L2mZ0CV2ejvJRixYAMQpp2RDeCERWoSrP4AJhvOnenwr7kq6IUmb0P +i7K9OgQAhU+LY37i+jGdFYbApcXgT58tgDNdPmwwzOXjpeTgyzfTcX/kkbuQHSKI +89jqg/SXeeVqG6VFxs0yPtINt+t+iLibh+1RghfdpxcJI3SA25UaKmDwLCUZDIgu +BZEWnqhdA6YCWnGEgZx3WN2HeyPnL4JCu6AY804lP2bOYWQHivG0KURlbHRhIFRl +c3QgKGRlbW8ga2V5KSA8ZGVsdGFAZXhhbXBsZS5uZXQ+iFUEExECABUFAjbjo4cD +CwoDAxUDAgMWAgECF4AACgkQ66nyQOudyeauJgCgl0HAxcZVFMWV/DW7heKYJE9U +VE0An1YVfKzHS6BZohosne3I1lAdagBGuQENBDbjo6oQBACPtZ1o4mPMk2zYbyu+ +sNm8P+5oAtD0+129gCn8OunvEwflPrb4opOUp07ezwhAE+K4Whwk2Kvmy3+ebxeX +6Bw5k6+2vjlz9yXnh8Y7WA6MFk5+BuR0FUr8szC5BYh5srioJmcA6UMtg0ZVSC4Y +ucRAFJ+eGGSCHRYDSSq3t9i+lwADBQP/dw4So+Ux1h4ucYQbjA/G3JUhyHAY6/Rh +FblqlvPZ907ui2PUAVQ3lbMXDQDn5YfNrU4hSGDnRlyjoefArHoX4ttnlo5zfsQC +9oWA+4zEF+RpZhqAKh/eMEXQJtNZRdX8Pn90WYh64ZO5Qw2wZUf45IxbaEE3/v5o +krksscv6HOmIRgQYEQIABgUCNuOjqgAKCRDrqfJA653J5nNNAKCaviZP/A83ammD +nHvkTdxefqoHbwCfaE7+GAg+R/+tJLJ0DvZllz8xYzqZAaIENuORzREEAIrOxkw6 +rRDOpbqKenlrMRYvfqoVFafTekvsZW8M0GVQOBYwqn9VUfSV/H8Iy3nJsU+cU4UF +XEaoHhVWgspMtjYHvxXBTD2UHmj+Y7+RkVnOT7x/UsPKbxjkweeleGXkeHECwwZu +QhebSrtQQllqtjCx33Le013ukAs2SnI83cPLAKDfVb6yjfhG0Avkx83VmlFqXXH1 +pwQAhVhMi1T06SNYzbKAmdNBfBWrv9m2l5PJnUTpSWUum6ueJLHzkEM0XgVnHt+Y +dFuzXgUafsnqEn+2N4tI0zuJqzoi/9DQnEvKijZxihtYq3S3rN6UIQ2aXFHthvVt +xZxocZeluYaWHPeedJlI9h9yObZn0mLFXFY6TUiHQYs8RNgD/0iNbequyxzEKdId +zD0Ns+3WjIVBlYl51Zdvqyo2+U+270hXVdIssrsqKr1DwRlsCRSwMY+nrB0ZUOlv +LaIB7qCQke3C9myu/fJoGDhMZOYAXsatVR0EGTdXnSuCxqNhEiqwlbZGMAcwFO+o +WBSgGyjFPHTMSOw0XS42d73UNxTatCdFY2hvIFRlc3QgKGRlbW8ga2V5KSA8ZWNo +b0BleGFtcGxlLm5ldD6IVQQTEQIAFQUCNuOkfwMLCgMDFQMCAxYCAQIXgAAKCRAx +jB+u+u9tG2cDAKCzaFoiAm79QSmYISeiM7XMKhoHDACaA8CU1j8+20C7rNipOHYz +3KfUMhe0DkV2ZSAoZGVtbyBrZXkpiFUEExECABUFAjbjuAADCwoDAxUDAgMWAgEC +F4AACgkQMYwfrvrvbRsg3QCeOMf0g3znbc8IBiTrIPUgUz9p3WoAoJ6eRZTZk7z+ +hTyx4JDceReQbYlGtBJFY2hlbG9uIChkZW1vIGtleSmIVQQTEQIAFQUCNuO4HwML +CgMDFQMCAxYCAQIXgAAKCRAxjB+u+u9tG16mAJ46lQbmtWRZUldQtp4ZnOptP7ZJ +tQCfceYMZfMAnqUKJiHk2tMhvwDvAh25AQ0ENuOR/xAEALSl7SaNEf8mYovea5tJ +NEwoZx3vv6XymyXga1wDqKo2PeDrnRDbHGBb5BvWIv1J6Igk/wq4R+Pq989Upkcq +REB+yOeluE3zPPtZBrbLySSaqiMegYiHnAAPc0TqjH7UPZa+fJKZTUk64BCUQN9E +LkL2FKtAGQ7RNQJYvbCq4O/XAAMFBACXdO4a3ZIK5hJejhHZ01mkHa6Sqoc6Pued +NC7tlWiLU62BljGiv/DvzcbMsnvk991AxJ3pP4ZvKr5CClqIG+WZa1zmtwXdmCfG +Jb2fbNSVD4zp16e5slPr8Cp+fvIv2/SyvwruROs+oAzSVvoMAzAGSk3yj5nT5oik +bn+M62fC5IhGBBgRAgAGBQI245H/AAoJEDGMH676720bj5AAnRH+1me1/iHDnS5l +tXysOdl24/BMAKCPThApQ7lJe8LYr61+lXUUwr1TKZkBogQ246UmEQQA3Vs5XdZc +g1g6hj0sxjrHoV8k0mtKTn1Uy3JKSaQ6RK3J/I0vHCq15FVKMCO0pWYT0ZmCPuaa +hmhuRWeVSXdU3ylooXOzviQx6Ct8mpjp4ejhUBT2VBdflpQBohVy3Pljg824DkjM +v/MlwOp9M3vr93reZ/Ss4m97Axo8OQzJomMAoJlMJ6H6rJB1b9UurQ4NPJlwCyij +BACFRsn/Yo9wczW9H1WBlDi1NO56kN0aTUD2irT0KQaG0ZJ0P2Unc7ogC3AgfkOu +uH9XChgPjoLZtC/39cVJikVt60/ZczLXAsupHLnQiNjh5v4DnD8yqo4+aJ6Q/OH4 +EeAXW7HoU/Prq5sRYiv2xRSOngtS+XnQUHES7O0xdo2N0gQAnV8vch4Oog0yYcrL +0e1Li1hP9bPcrIq4WYD29L8iBcB30czPegGCD6S2a/475Kw2sE8WBnxiGa4+1Mhn +j7u0QnhUVVV+eQenrzb93wKm5sENRh01+1hwjXQJD9O8k8Wf8J2bnTwM0MEZBH2d +/U3XHGzoR3x72790TUNFcW1rUFK0LUZveHRyb3QgVGVzdCAoZGVtbyBrZXkpIDxm +b3h0cm90QGV4YW1wbGUubmV0PohVBBMRAgAVBQI246UmAwsKAwMVAwIDFgIBAheA +AAoJENS/V/NzcuJDdy0An2YZaL/VMei6H3kreYNoVYow3V9IAJ0XO2nYsUNoaaa7 ++LzaCr5rphfw+LkBDQQ246VQEAQA31Qj2MGefTCoF0x+D+9UMxZ6RuBPzI6gzX1t +zcUPWYy38NIq+lNYBg7hLFkUfn0uTsAm33h2Q8z4/DGT7jmQWpoIg7yNTr6681L/ +gYo5FhhC+qERZ1iPMyfMwwD7rrz9bthUGTqChV2h6NiPUPM7ic/D9rxJICXy8dso +j0dQ6dsAAwUD/0ggimQTUCGmNHHypor/GY0XAAL4Vy8jAsC0FH1UaqDVTrTDH1qW +LRnS9uxEsOJIGSLMSdxC0FZEYq4jCm7CYjTOHTHvvYDbhs9QhvW9r4VD2efbERFS +EYMiH69ASQLGDp/O5kOZTgQOvl5oxzvsrOMaRFSWcn66uUAMORmHKz1giEYEGBEC +AAYFAjbjpVAACgkQ1L9X83Ny4kOO+QCglWbqVGzF6vcsNNzN+EUvWE/TMykAn1IB +XfhZ/PcalODsIPzEM2JS63lJmQGiBDbjktERBAC5tQ53QHtwXMkcXm+jk3CIxnUl +c+PI2ovY5YT9d9p4mIHnmgyZUQ+YrUkXr3BTtkGmjWXg8QhZw/tZEyq8EQWX7wud +6VGRJb3mTAWvcPxNGdqtnLeR+IEXW3fd2eRVNpljEIMo4F1n9mJG8trqBn8oeEhN +/NpLuHfobYxsCUaWPwCgpA8WwQ+MHIph3Hvabn/Ym7/h3iMD+gI0Apokfs3xjccu +KzVKGGnK0k/XIL0YmO15ze6DNhILtEpXc0lwF4JfiibcqGINI3phhUgJ/jB2rPpM +Chyio/NHa3sXPr66nEiCHlYaecKzZ7u47V5dQJJc41+IMQPNEoZNCOR2/AWj7zzQ +OSIaWf+qZGtwgsDnrx3A2c6sGKjlA/91uSlQGGoYOvYtyGmShjJCWrNu9SlcnXGV +9mKbWN+uZ1+yTzd0TeIHO+ZPwHIhlwyioMQeKX3kuYmnerDXJV4Ck/9lZH7ReIEs +QX0aFwA5zmKEfYAJJctaJFenIyYrb96tO9NfdCQByqhDVwVYLA00KuWDJwHzgd2b +kZd1qOntwLQnR29sZiBUZXN0IChkZW1vIGtleSkgPGdvbGZAZXhhbXBsZS5uZXQ+ +iFUEExECABUFAjbjktEDCwoDAxUDAgMWAgECF4AACgkQFoQQpI/CguYi4wCfbbaA +ruJvA5fMgp3+Bk/T0kL/f54AoI56Vqqpio01uS7SADzj47t3WQyquQENBDbjkvwQ +BAC2wan9ScDXLgCqN7CWSRM5B68vC3PCbemYsuOXZjdN8afw2LSHxZ3buRXfYxRn +JNo1pm4PGkMQ7ZpQikZZVCZa+WoIVXYXRnYAjxHhvHW0LaQPvnyFS9H5LaGf2Urs +TWVA+695zYsSaX669XFb9WbiIMGB4yUiXPvQwUL0tSd+kwADBQP8C3sKWjsPh02T +jcEy+FDxWAn4g3LfsOPw8dfawJln+0h9LA0hTebbKBJWt5OUMqjjTq/pCZ5+z+b1 +0f2WwET/xAvjQSTdJjrFX9DNNU3jhCCelEpal9oxsbNYlVd5zOU2RN4hlmj+eEOb +5oy5wy797sQpsbrgGetCTsvPotIpvbGIRgQYEQIABgUCNuOS/AAKCRAWhBCkj8KC +5vfsAKCJwKTpe9OoS/fhFdVKSF/4RwMc4wCfeSuo9zll5IkZrtF9FxWGblC1y/KZ +AaIENuOl2hEEAKeOL2pIdZ+zQtehxdL9l/uDBFSTuN9rLb8DgLiw8Z9j8U5CEH/M +38WzH1nHKKlZKjGVZYiyhRfAG83wvHnT83lq+Ad0lgaZTR4z6nrd5ViOlHPlfqo4 +RPZPzPe+uF7EfDl792sJerXGAasLosmKnxKAyJyVjh7eZcjTS/hUhO9zAKDVyLHJ +/gQlMYk8vE5XYL7Pw4d28wP/VsKVkjlxsXpcrCQIoKeDXgKNVv9L+0Pebspzr2WO +ah8iBN1QOkbtexIKCbb9mmviEnJU0FFx5MIw4mipvY4EpCaH3McGwJpCzWmdzID8 +Z6oISUyKsuP7PXjmASbogV6Iqy2m/2RDtfbIlbwotfbiOT9Tr3IPbH+tHAZByMRy +vxID/RN90WOPSpODxr9AH9btmeJD0BfNt99116+qdwvWrTofcbkBgzvB34vLLDaM +KVIyinxz2lYyC7aSpA3uzjZvoPvPrQJFLE0dx7DSkUTtWbQGByRabpyrXYdKZzsF +XLb+LSTWwF3sQLax0C4cYT7OLPlxjDVq/A0jgztaZVWa37IYtClIb3RlbCBUZXN0 +IChkZW1vIGtleSkgPGhvdGVsQGV4YW1wbGUubmV0PohVBBMRAgAVBQI246XaAwsK +AwMVAwIDFgIBAheAAAoJEBPbllU0xuPx7NQAoMhUK7d8mW1F45Qpwtpbn/EdSuqN +AJ94+GVY6GrtMbA8yrZHeD8zSAedrrkBDQQ246YdEAQAzpO6UuCWWpP9up5GVhLP +oSCBfSIA9JWm5Ap6/hjQ5hia7CcS8E41PjaGl6Pkh5lj2qkSUBa892SXyQMYqMqE +q/h7+BW7+n62SCRMtYOHRYZPA4hvs0d7jznGQlMsltx7qamoVNP0XF+ws1wHLjyQ +l3qMnkrAQ8lAJP+jg7P5Hq8AAwcD/A61qQLRXsSFr7LMBnaUSR0o6+4/HCdh8t+m +nAeQBDAkne5DTPiwqzqsjoYekX6JK7wk+mbsJTd/Zw55Jkq9xVm6nEUo/JIbN7cP +lMqfCLaoS+ttbxZ9fNCO3WTNdWxAr/mGZZiBfy9yTcxUfo5qTg0ffWy40CNHaVKk ++iIcktGziEYEGBECAAYFAjbjph0ACgkQE9uWVTTG4/EmaACfU+XRhr/UgvgCfMlO +thY327vlI30AoJypWeGLup2DqouZIGkY8bmpDrz9mQGiBDbjlLERBADIbiZFRBlq +CMOCXTECdpJssJDnAmpir+yfAKX4hsOVdygepdA071Ams8rApABS/c2+Tuaplad8 +w+iyQs4BKuzqeQK/YWj0DDqyY2LM7qJbvFd6nC/GOGjiEucTTSgY8IOFScBTTks7 +alMGjHAdWzSjq+1ppWJeTSzp04UKhV1/0wCguOIaUr/cMVahSuoiK4Tdot+CR10E +AKunWycnUG2IaGYqO3sCfpChzktWdTjUn9ESJAjKK1QUC89f5+KrMPITdUPypf++ +9MumBkJi+8R0GVJ8zwhwKfX9CHhrD0kfO68pCDxZyW+dDzOr/tFX0nuH9pL8oiEM +kikaGLph+N+N1Ip8thh+vdLhNUr3EPRlrcAfv+WtOpbyA/9+kpa7x8nIn2SofJis +j+PjKS3lAoGPe0eOoK/sVBvgVjy3Gc3d8vMG29r+2WRIpGwuhuLGNlQYX65BHV1M +K/TjYvFnpoRSqtTK3GpRzTmkJIC8RlXxtfYf/n66VLB3EoTOzWHY29JMCJnnjPMo +aMc2YSK10Bo8P/27nF0CKo8XEbQpSW5kaWEgVGVzdCAoZGVtbyBrZXkpIDxpbmRp +YUBleGFtcGxlLm5ldD6IVQQTEQIAFQUCNuOUsQMLCgMDFQMCAxYCAQIXgAAKCRAf +6PxvBCWWd1pYAKCVZ7DfK+i/YZGyEu18DnWq0ixligCghGwDoMGgLnenSjyShMZ+ +1Ecekia5AQ0ENuOVEhAEAIMMgk/e8lsV/KEkd4/jNK4yFj5iy/Faon800I3GUzET +uQA2AT3getR+GuV4pbZWE/80b9hnNW50UJGiP1+SXfVtY5vT8p/gNFwn5d0O/pq3 +bpgFRJmoawTzx8SFDwCVPHEcwOHE2j5LvfrvRBOyKU32tr976ri+Uowt0+92LuA7 +AAMFA/0Yo9dDqhjR2UoNcYfEZwWhRHaaJenP3z3QbzjJkASb5H84xCTEpv0dqEtV +TJUoIo8Lh5VjbiCwok4QPLVSbQFeHqTKb7N96PjevkZ1Co6OrLCNOcPRvXxgCwSG +buuLMkQJEutnXLu0DOKquY94KXXh79La7lTgjReE/1Wzbgc1+ohGBBgRAgAGBQI2 +45USAAoJEB/o/G8EJZZ3CXgAoI5oimsZs8ZKmLb5sPB4AZzngCyzAJ9og9spt3EY +XAB95XmfzqgJBRv04ZkBogQ246f/EQQAl65ub9rEKS7XsXwNkvGtj1K7gnql2H1b +J5GF9bGCWhWmB8WFtsAy9XUeC3WbrcuWFgTsbtTfXZ5I7j7HSG6ukf6Ycusb+bA1 +IoT+GAQGWpFeWoXe16wXZFl0pEc2iUnx9ThtoQF0fO5YlbvHJPEQ3kvoqcdb52WO +OfOuCAJxc6sAoNqo5w0YxgJ9jkj7J4cmR+OFUEKXA/wO0jrvYE7eiZeFUjGNiRot +xzhTzh53rxtz2/DWG3D+IBFOt4qqxxp3WCSNO5SnBZWUW50hDkhTxS7jSmsfPBmC +inmQ6EF5FaFPyLQBq0uKwhMaWficdrQS9syXFlPuzQ5jOS3kVAxOmtDd7CMTC889 +2dj02qzAE46QNNUI91kZXAP+PINfoJ8hV2zvlGZ9tVlo+Lgsl1BOvxvEgmYV14gy +TmMWga5sNq7TdMdWi8Fz0Vy7sI4S+RMJ96rMws2iTzWLi2jGO44itoWttCwqmGJm +lSWurRsvYhSBgvNCLXFGGaQn5ncO1tqKnWSDf625UnAipsgW8P4Agd5qJZiwXfJ6 +7Hi0K0p1bGlldCBUZXN0IChkZW1vIGtleSkgPGp1bGlldEBleGFtcGxlLm5ldD6I +VQQTEQIAFQUCNuOn/wMLCgMDFQMCAxYCAQIXgAAKCRAMggxx0mmTE0D2AKCkQfBM +tzcuk2imhqC9hjRUBMDNTACdFm5StEnEim5tQTftoXw5pikZIL25AQ0ENuOoKhAE +AJHZUiWH04mR/wpH1fLZ4SOiA8/koImSnJ3hAZzvoQCaLbQERgKI3W1EZTiHmakQ +oCqXU1wSuzHRwM+EShZwAFzwwWYAOavgqKp+fNLfzvwChm/JCp/Z+ds/ZQvAOSpx +2kQLDilcj0yFOb6uhS5rFpjAeeYs/Nug5PZDIVe5pnUHAAQNBACPCatyZ6n9B6qm +l+wmbjShyYGoNeG02gcNJ4mStCkgehQac4rRKMrLeSQTwpdGskBMNB5+I4WQKnGc +myP/6QtQjUAQTuO1VItMtVFYxMbWjZplsboM5M1hx8eFpslrAkMBjeAfa4lMLOIN +3YAtNO5fmqJys4+UBKNV4ojDUxRZj4hGBBgRAgAGBQI246gqAAoJEAyCDHHSaZMT +j64AoL6wmTv08Y6txelPb8XUKpayw4FyAJ4neVj62ZIfdX94DPkF00H5qvVeEZkB +ogQ245UlEQQAnKdAaILozJ04V6Z+FIwQEY/aF4EFrJJIc+uewF7ukZl/7uUZqSxq +mzZjbqigyMFGybJSMa6TpwN0BKG5CJe04R/mVCIRsz1Jx5YXezN3UFsNVNE36R8l +8dxWG+wgj2m60gu4VlodcpVMc/kRiSUgKUfg/xmPnRe3SJZSlG2lBm8AoNc/r5DW +86om3MHWK8AoyhvVXhWvA/wOcjx6gfTTKftzpQBhOF0U0fC3npQC6bvjLjTBhQjC +3WX5rfwJqMmrudRbEO1sFqzTOQPtb9xatMeVqTcOi6+x2zfXes4nTfi9Lgq1z8Hh +E/LnktwxZxyPeOXqXu9N023IyQTv7mC59C1xMZk4POOv9WZUGz4C85s2/9iTJCfk +MwP+MRW0S9mHmisruCY6TDVFc12KIFMIPSmWav6gW6bCAA+wIHfmcSyR6MHiLV2g +tJ0vQuqgyWfeTiaxPof07dg9pZsV7Hk1ZUhEmloeOcfZmwtHkRhWGEbEsd89IWMD +JlwNJ7Y9JZ3QvK7vB42bQVvyhdFQdEXH0slvlvsgKtCcaOa0J0tpbG8gVGVzdCAo +ZGVtbyBrZXkpIDxraWxvQGV4YW1wbGUubmV0PohVBBMRAgAVBQI245UlAwsKAwMV +AwIDFgIBAheAAAoJEK0bD61DwtDH1RIAn1kxWuxGwCS1+i7Fp1cFzzZCHycLAJwJ +q+RG7ux9sQEmop2V2mKdjBZmkrkBDQQ245VIEAQAuZli0/vYbs6h1HhF9HbvRHFM +ePjQ99Sk8h/dTx7PI7eSqMHXYh0PZghchlbrMSPnemxfwMbJrmdK9WN0Wh9BJUe2 +ycH8ftUcGRo5CdESgiceziF6Vg4PQz9FlxtEhvrl7q8R6y7O+j03QAJKUGwBdt54 +0oZ8YYKiDvgZUZxnoecAAwcD/1b2fYzAnuWrQZXhXQQ4cNVxMBVFKHScH24oFVbu +EWLgM/tdgF+CPw2Vtzba8ySR1K80VSgsQfs6n2wyCVd+II8lKHTZT/pfICFcPJlH +Ks4ge+JNn1IcxBAiq0QRNW5hGTO9KdJ8MFWrWn2Bbp5k32roAzuCagoielFo4MVF +ZTsNiEYEGBECAAYFAjbjlUgACgkQrRsPrUPC0MeO/QCfaGt8NeCm0zbssmOrXZ6v +9zFk8xEAnj3SpjLTyqemniHSJ9KEzIKJCdiDmQGiBDbjqN0RBADBWmbmmByw+u1J +TAixxj5NXRXQJ9zLtkxRQ1GHxLQPyQzojWWnD4kEme8yvsFXuulbPX8zZMnl6qcC +8wt+b5E8dCtZuvQL3vS51yGe9M76VRC/1HgriE0YqHMTYJT4J+HciftldHFid+jR +nGZpLwVtLxiLaWAm6SBi82FTn4lVGwCgtjc3u/SMsPgylPRyN/QeH8/OZ5MD/R2y +G/c+ZF4kWcgmlzjJxQUN2wGYeDoOWUMXS8mf6yF+DLtwxo6oOlLaLHVTR6+qH2Vh +z1zaqk1Ir6FJjkuUGvHbVFt2BmvL26StTjJ4zC4UFSWYP3qLvfbPThT+RoD4ea+V +cPxGEGeqs0umImJ6s0reS3KJS9vgHtGo11Is4nP1A/9EzV7QkX5EuEnlUpGV2q29 +aGYx3RpcOhDYixogNHuW+K9KwcluBEEBmT74NwxVzI6qdJVVZn5lxT4IC5G0z/ki +df1Rkgv8Eqj5DIikgnp0asB8FiHSsb+39d4cnk2V0ez/LmknXUl2mpKpk/fb+qXW +TqPDbFUE8dz8zyqRFXIjwbQnTGltYSBUZXN0IChkZW1vIGtleSkgPGxpbWFAZXhh +bXBsZS5uZXQ+iFUEExECABUFAjbjqN0DCwoDAxUDAgMWAgECF4AACgkQN8q1H7eR +A/iKXACgkZY9/w96yK2Oiq/MUs/A74SzJ2MAniQ2eSHT5CQ4G8PPvYfPZueNI9PT +uQENBDbjqPUQBACn8JyfkTPFcgaWMpUpnk+nTEkDe4GhAG9fO7alTgdT6+aDCdfX +fXfH7gGwdURvDv6V/KEqcMPRNLAgAeP/F4T6OtoJNTxfWLB7j14DJNpYXjBPJPN1 +kpD2at8GcWB1aVGMsAtxMwlo4TZlqyfzCAAQeCLhBbIE9LWKX5oUTqiLOwADBgP9 +Gm8md+/xWp9sLE5i3uZ4t9Muu9w+UY3Ke/WcSA2CNthEYhHNtcMPP6PBwtz0x425 +mC1pe9RuxDyzRfV0/q+rjdWZBNA+VTVNDHXSj5hifvem3KFvA6TIgMabJ/q4WE7T +4Hn8xjQpEsLGjSXAzG9WRg13qTzTilIk+rC6xYGbZHSIRgQYEQIABgUCNuOo9QAK +CRA3yrUft5ED+P5vAJ9dQMc2nMpcKuH28xwKl8r7MP3pygCfWHGKFHWIDkUt8RfH +AB9geauEQSKZAaIENuOqZBEEAKLUF5GqBMWJQtBs1t1Sp+NIOGuMLgJOhINbMU6t +k2jzeUt6ooNd+c8P0TexsbSETwhrU4ntpvIISb7I8Twhcled7bi5KCABJOzz7Fw+ +Ydxo5Yjm1DQH7+gEtPx3n4AjZUfRAN0nqcFizDpRYPqVaN1QYiGWn9yPF3pubQhV +n8zzAKCpx1LUlQl2e5t1YJhmom2qy38EeQP+IB45FBfDf5KKtyS64alQ0vHYIssU +p806PQorw/ZOuoiscUQj/WeZ4vn7rCdu60uR1EuHpGp7n0t7igEgAOcxDjrxJmpg +SdD79V+oJAFLATo2msj1IklVvJeI7ZsImyPchIU1lqn/GvpAam9N+FiIB1KUMFqT +Jzc6zUn1Qqag1w0EAIiRHPYRW8ojd9Uh4Ed3X0daAnClyMWL82t2bj/bJRmhupQn +4aVJ5D0pFB9izTiJEWciHpqiMdsi/zExYYIDS1Zu94+WFbNIxyMFfHrJ5fUQtAqL +b7E5LrlxZONUnrRwshqR4X2TmW2mz1Wop542eUQ1UWp4Gr3VlH6giswY0CnQtCdN +aWtlIFRlc3QgKGRlbW8ga2V5KSA8bWlrZUBleGFtcGxlLm5ldD6IVQQTEQIAFQUC +NuOqZAMLCgMDFQMCAxYCAQIXgAAKCRC+eUhSvlz4hvEjAJsEfDLAxH49s9lf0nql +F4tcflpr/wCeJKCP6iVwvhGIdCu+Dbvf6z8/sI60Ek1hbGxvcnkgKGRlbW8ga2V5 +KYhVBBMRAgAVBQI247e3AwsKAwMVAwIDFgIBAheAAAoJEL55SFK+XPiGmdUAoKhr +c+z524neflMpRwJ+NG8KVxOxAJsFZqm7bBtYllrdcTqNqMk49LfBObkBDQQ246p+ +EAQApnvWjY5rMvw9Ly8xFL49pGjAYFb9zFijvgG4tMirI3T9EBLflKLJ8m4KWoRo +T2eNmy/JGLHyZjveaVh8TerDV+uxZkEGvv702nz8NOElQTjHWHoy0n6poci6Fxhf +Jd1bnOjDK2mZEufEQNSn2PhA46gjCLRTAPuwLpitSSL5ubsAAwYD/ij9KRO69/Jx +3+W9DZQxWIQBiKnYHVr1us2WpdpTV4jpCqJOCOgB/hlBmCY1C1/tpsAj1A3ZZamJ +RWVZoNokkReItZLXfGacprGbmmjcg89gFM5V3nEUNCU/mm2BQWp58h4NOCv60dGr +5GAqHDxAStPk388zbxEdyFs57CPQ4ZJtiEYEGBECAAYFAjbjqn4ACgkQvnlIUr5c ++IaRMgCfdcoqwoaTU7rNH0BWaYUfCrQ6TnIAniN+yQaBbwZHMbSaDTBRndjLglsK +mQGiBDbjquMRBACteKaHZ7pcM7Quj8Ec8Sx0fJ3u0NdLso5xn9Ek4FWMLBu6jw7b +/5KjB2WtXOZSWKHOzeTfUAx79NMKJrD9jZW/0kEAFVeZpwZF1l8fBsRELR9cxAaj +E3RvFkgCYAhXsF1Jno+qiU5TNvadGU4SzmP4vOnnjrIWTy83mtZiwoFIcwCggaaa +ClE8Q41NyIfVtjS3f+Nm8x0D/icH9uwM3vpB2QV29IIBqazgaFr7vBoogFoAllaC +QbPLiyHX1Mk3kEZg5xewmDS/tU4rGqj7UcL9OlZx1ICD8cp80yNYfoI7K5XM6sYO +MmfJORGOEsqMtoYbo3lluDgDkg26DZNynUeFHZRrIWz2cKqTuaB3dw09m8sJNus3 +poEtA/9Q1KDsjKPi8+2kUzJoK3V61QglXAVDlfzK6B5KOEZ6GR/gX9M5uyyLjREy +bFSSNPlvLR11+mV4GR5AcrVQOmE0QpFyo1Mr+uDsbqwkzERvRq1r5pOyqM5WPXhl +Xa5oo4na1fBEX76IEzK6xIVG07GnNnaY+dlPgsLq4I8+A20ZG7QvTm92ZW1iZXIg +VGVzdCAoZGVtbyBrZXkpIDxub3ZlbWJlckBleGFtcGxlLm5ldD6IVQQTEQIAFQUC +NuOq4wMLCgMDFQMCAxYCAQIXgAAKCRAlsA/UMM7GhJjYAJ49ENMfPwK1U1ESEYQS +5Yts3SRcAgCdG65G3ZW0dnhnjQAhf/vk+EteMfK5AQ0ENuOrHBAEAOGceVg3PC6F +tgrZrnofohzWnui6FVBzeai1DZ5MMKmdN6/QMv1eeHoMOb33fbfhwA51n+kPuhap +r6QqTzx62RGA/gK1m7vjU2OfYxSO65GN/rSUXN/kE83jR7Hux4MocRXZ+/8ngqL7 +JAjw1LZdJyOniJpeRvrckPNC/bKaua77AAMFA/95VjAjJIAU/gOMwtbqTgV+cmHe +52Aa1CJEalV88yKG86nnqHuL4xxUTTZljyjbbKleJD/Ah7R1BxBhSEDy8WuTuonE +VHVxTcL9Yig4pZ/OzYZf5fkl1eLNaSLb8XZMT0JbP02b//OMpAr29lcaga1o1RtW +vrlUyIYOTm2RcTxkf4hGBBgRAgAGBQI246scAAoJECWwD9QwzsaEIOcAnjt0vZDn +9+3cTNpCuV1ZKIu2t410AJ0Y3CnFBUFBOKk6zkOJnaArwVN3ZZkBogQ246tbEQQA +lWieyQhDso2ZnD2wb+gq6aqk1rRUhcwdBwCTbiE1aLAsnuMl8nLH4fvhaTz2V/Ae +joL00e28duA5or9JiBfmVblrpTAIGWsu0AU6uEQsWgZwRdso3NH/KfH8Z5lxwJtk +Z/hlAiEHohmGoD38mJNsgnm63RXadUH76irO6McvWlcAoONeH7i25AcrMol4O7BZ +wqGq25ibA/9IRhK7AFhfgaRrDTz84PaIssxp1dWKalRruMJYGQK2LDuEl53Q+d1r +nYBPliPbjWr/9Gkjx3K4B0CfWWQC0sUl77bNRFqr8FXkjRZcvkCoxxHG7PIFG77r +Ld2SiQ+eS+dp5QijuuMC8skkvQuuxS6eIk0g+jjGlNhjuu97Ya6xeQP/Zxek37p8 +P1u9TTmN7nPtlzGXGrfKVi9DtJ31E805ruXFqTuoFfcOBRrtfY+DOebX8RxIwQV/ +TEmyxwoXdmkv03EYwD6AJSmx3WuVi5/revcH9nfSEHDy7sFC8CBp4aavAFRQNrho +mSB9lSm5clGLZiD4nljF1EFABwQFch7HhlO0KU9zY2FyIFRlc3QgKGRlbW8ga2V5 +KSA8b3NjYXJAZXhhbXBsZS5uZXQ+iFUEExECABUFAjbjq1sDCwoDAxUDAgMWAgEC +F4AACgkQX2NWum2XMqywLwCbBT6UT+lNWMh/jxFu/m5Dy2qMwpMAmwePBu7USi6T +WKaXYRSL2yywJR0HuQENBDbjq44QBACdC1XRPM9CMFrgVUvioU7SShffLnjgWBZ3 +hqbOYrsgtXfuQdv6lAixnNPdnk/k4mjL8w1pqbjUmfmbppVDxzsiiUQlJatzGDfU +1gDc7ksnXpF/vzghbucy8HNO0SHi3uM/GXC574iZ1oxa/A14fKnCVYT1ThqUa1us +C5YQXHm4IwADBQP/f4LZgN3dbL4jLqXHDNpAIEjiTbKXxDKHOnAof//4SE0mpaNV +HLu3nxI57CtXfSI2kMQSm/3pqpTKzaBlM/CbMAJUanhmlLPARDcJ/hQcDtBsF5nF +G7zfLfe0SBwgsM1HxL968Vva7WsbYpSa98+3HSDuy9VwphFp7i4HbnCbSK6IRgQY +EQIABgUCNuOrjgAKCRBfY1a6bZcyrA3hAJ0erCoxKtpc184iLkp5kpXQakDGHgCe +K2WXA5gTOULftladXZn8tNoXM6CZAaIENuOsQxEEAIQRmJhsJniNi/bRff/YGrZ9 +aFWt81G93W8WhV51qq+ntUHgUNY55Yyos4XLOa2tS+K8zP6X15FesVBPYIQa5BIC +10mAsLfJ+1rbnGJPuNBA2U2MoEaRxo/JtXQ//5jiTRlYwLDRnBzuaMCPdsirveu+ +JBw53ytRwjwe7m/D1PPvAKCp2dj1FtDjubTN7kCF0o2KzPwE0wP7BimQxXyPwSzG +qLaHXSEBsh84OQTxPI98BXgq0195/A1B1/pPs356euKlqoefUTHYhbjiMYbjZT+A +6juudf7A2Ucy03G8HDZ4k1f1vmzrj24+6ygGBcxTVr0BaweiC1DwG3LjQoJ1cuFx +RQ8BYJDGIwPrUW5JdlnzW2bJWfdyXOoD/0S7iEVN9txkSKildOeP1YcDCD8MM3hv +F9kUc+1hbmir8SOZ/IYJAyQN+j+mYWsLuKtZ/F9pqiBNTXH2jWCTqldOD/ZYxHVJ +AARnkiVG6yckMLsxHi2LPPBK8xack0y92mKe7za/7fhVgCRSs7M/rzUbzUhyInHS +yxr2SYb+8lbutCdQYXBhIHRlc3QgKGRlbW8ga2V5KSA8cGFwYUBleGFtcGxlLm5l +dD6IVQQTEQIAFQUCNuOsQwMLCgMDFQMCAxYCAQIXgAAKCRBdFeAdP/EyBgb6AJsE +NGQmK4nUrwcbtZ7+av5GDQ2T4wCfYJaV2rBtTR9aWTRQfZOQoIkNF8+5AQ0ENuOs +cRAEAN5hO+fEhqW2pX71oSUqW/TRHWSbybNc5brQ1tzgTbheHiG/LQJ1lHjtZoZQ +syW3H/efEuNARwryo4IjvK0nmiQsqZUR1795XTIbo/waPN08QujC26uWbL1pYL5y +QarwbKOoyAst4jgE1NpZVc/r1+WUp7NuEapicVjvFNzkiVCLAAMGBACWQJYr+h0o +zr7JQ/BqI8vTKuVXb+DIBQjuSzN7LvaiIqMqb9ZdfNNmZ1Atvklo2Ce2VMyliQzV +STZuHJQbfrDTBXBf+Q+AINiHdZEAodzBvDv6p7vsTnoP+A2bS8l6xrWObKt3Ky9+ +GUDkqW3WuagcUKogQgEb/FKec+GegwSgUYhGBBgRAgAGBQI246xxAAoJEF0V4B0/ +8TIGk4cAn1I/jmu7FSgglh9aPmVYAw7HWQMAAJ9PAPPXfqtwza6I8ttGPLYNvEAm +AZkBogQ246zREQQAgcIj/Eo8PrIhEaxKcjc9dNb9/0BZ3BxBk7x9a7HKm6o0/vcf +LH2XFjFxB4Ddfe+O1PC9KNUqIi6GTafGbyqS47XsnOJs5nvsrgmVpUUzAd7p0dxc +c2tJodwhkH4GtOP4i4P9XBrxngQrWQ0ju333EPF6wLWi7qkVyGENCfsvktMAoKYg +M+XYh9UQe7/HX0GiCnk3ExVnA/4ryBxdyBihj02i6s8vAe5mlTrwv85ugouSB95X +EX8GPfvaWIW/TpUWQ6a7o8YzU/kIPa7YzETYX8e/FVr2Zd33HAfeLUNp3OS0NvEb +YJlGDfW7/X7qLVv1o5WCjCHUhK8DCf9Ax9b4z7CbRHptxSE4U79NCCOsXQsObV28 +qlGsFQP+IIaCh7dTqADw/nBmfuXxepPKXS6Xdi0to79LfQtr+TUtJOEVGIbqqQBs +gESFiT5qR0W7qhOnl47TIQyPQnt/V994QwyAGtIgtM5qYFRW70g1FkyDRX57PzTM +uU2BjVI6mHkaUkLaLujbRXiQFm8IXJ4rf297GppKuSgvNcr7Rmq0K1F1ZWJlYyBU +ZXN0IChkZW1vIGtleSkgPHF1ZWJlY0BleGFtcGxlLm5ldD6IVQQTEQIAFQUCNuOs +0QMLCgMDFQMCAxYCAQIXgAAKCRAcZ+wTPGYchNG4AJ98zSyvQ3Rt+Y+AVfawyEoo +sFG5KwCgmMyj4RYhRlXKWCPORBxAfCOYMtW5AQ0ENuOs5BAEAJGi4T/jrY5BtRTM +0psAneQytzzFgH4+LigUXAAb0QDAOkyGNfWHrfHJIS7A3Nc9pMWAdOjWgSKbYyrz +ra0SQ75/SkI5+/S5ev2Fpki+HYo7cNgVXnbCJrIY7k4DAMunqPJ9JCUXc88WxGvK +V5b45htqCPnV2Pgq+AEIKD5aGfLjAAMFA/9+O6ttUbeY2bQHRdThl4HUxQw4lgYN +7stgGZsbHCc0y6ln1HF9vlE4Tl6HI/NR/8OauQrXt8988dh039QNZsOdAeRWTk4P +gSuXq6VDG5WNw6B9bvRPKXe5yeVmNNl6KESBzMcq87kANZWZ68vKJ2JihxPHRAyf +xwGr2JKkVF0S+YhGBBgRAgAGBQI246zkAAoJEBxn7BM8ZhyEiJcAoJTy/pFHvd9y +xAYZBYp7qLG2lUIOAJ9Rlpbjou3wb81vE+Qev1+GQGpaVZkBogQ24644EQQAlNDo +1aAt9iof3VI1z3TehyLrBIR4XmKRSM2Bx02CZhQRIwY/QsK6WBoxlJqfgUtsBUuf +cztjJaUBixq5qPmBgXYqN9/B8HZvG2nknHdiqKrvqFpAqATJtlccW0tzPJKtKaTb +tkORBDv6hssFa1aXwTN7IjN5nLI1Wh8lsvk9SKsAoP5Z4IDSK/mM9h6FPRsAsAYv +d99ZA/40UwQLl06u7wBtmxqSdF/86kjC0kWX8J2Y9vIceiNEiE9MmVNcYIKwIM0m +wduF50EksVjEdgWUJrqT3RztJfMT5+Sgm2KOAvvfmbKa8RF4NPSrVXDDrFeqk6uN +DT0jnUUTQFYTjk4Pxg9Kl+a/c7Qee6qXn5qeDX8ubZqN0noX0QP/Y5HSgi62UbBP +5B+e5BqE+ZLeJ7yVtl909NwTCr7KVZt1o3Za0dCYtMosPT9ObAjCanhSnuEWa3hu +outOgorWaUSEW6Y3zBKvN/M4FA7+1Rhe86gnnWLt+rHqX5M8Y/7JTcrugNtR04DF +sYga5A16CLsTDxSmM2Rgvpwh14FtrqG0KVJvbWVvIFRlc3QgKGRlbW8ga2V5KSA8 +cm9tZW9AZXhhbXBsZS5uZXQ+iFUEExECABUFAjbjrjgDCwoDAxUDAgMWAgECF4AA +CgkQO9vtsXd/vtOr4ACgllMIBb4leDKz61LQiA4TGWQp9+QAn0gF7rrvXtHdEc9k +FQxgfASZH4RZuQENBDbjrmYQBACJ5res4tXRZj36s7P4KZWUf0YC8mtLxxeNEXe5 +ckAtn8gMfcSQJ4Mei4O1EBvrKZ9Dz28Emv0FmDd66DUd4ybRIk1PN8kWry9UuGLA +f/VBAkMIyXhYCEnB7wRsNj4kF5DhYiytep2wekPocZO2GAUoIyY2yMNb2m2g2K8U +nK2QBwADBQP+Ixih3o+++i02Xwi4wOe7aro2xSeBmH9b8nEaJ8v8RVLRO0AgoR4G +LzKeTOfv57FU48tlY7sxth6FOxeJaQkS1nD1LRpb3GUDZr7qM/yOGYp0WhdRgGW+ +c0eYa32g5ajq2zn3+H1L4yrmRSZM4nmZ5ZXe9ijkGs0UNYqmi0gBYxqIRgQYEQIA +BgUCNuOuZgAKCRA72+2xd3++00nRAKCX6f3/mVnEreWCgorUdZh8hg1LEgCg7FUW +Ctn3HWOwgOwxxKzOs/rQm+CZAaIENuOvBBEEAMUtk4AJiXP3jaKpIhbi3B73S2SZ +67rKzBkicjelpwWk6LndsCrbLsIWsDf8fNtih0r9As+2arfApkNlwuCGq1ZlPGGG +Ef18OqPxFvnghVEbDdcosP4bIm3k6G2sgFbMl68xAGnTtkS5Gfz43uTuznPzdZnG +bIjP0uBmPfZk6GW7AKDhi4htuxr3Y+ud9lx1bWM9KqUtAwQAiRYHm605RZVBkdzl +fYx1Iwgn/l8Chq3MsPrfBMslapBnq1an2/nEQPmuIde9C6ALN1t03DHpKonx2Xgj +YVz8pgty2FU7txSSm2EE+975dXp3ov4TfD1KxksOl770PAzixLfNhPW1q4A2cEru +GgO74qEX3/fAa1J0nRKDgmA/mgYD/2TSZKCaFHoc3IHQnkygmGzzZNpVZV2+1kIB +8Z2hNo9V81PYpzlYV8SlG51ajW1G3ePcti7JOIP6MquNUbYR4TOzZy1Dq4+VqqZC +B6fOeIKL40IKKAoMMDYFNLp9zcT+s6+6DTPH27eE1WEt+NQjBgr2ofC/4iAU/nmA +Ymo4xn7YtCtTaWVycmEgVGVzdCAoZGVtbyBrZXkpIDxzaWVycmFAZXhhbXBsZS5u +ZXQ+iFUEExECABUFAjbjrwQDCwoDAxUDAgMWAgECF4AACgkQpeZ/f6OuPqGvfwCg +oevUn2afCdW1bLwbcRs5kYrM1GwAn04Y4r15A7ytYdO2PaxSkSJ4gn5NuQENBDbj +r4AQBAC4cckdPiWgQNkGvAm3q8FxzRLog68/jffvj8Mvt++XQ4NikO0VJ8ezYkVd ++vG3v5RoHTISynmMWZZjT56aFDSDZPOkQs2G0qZgAEgTpzCUBdlnUC8ZrHSTSQjC +n7HtR2cpYCCUBliPtatDvS3Me1XdRfBhXib04TB0ci6DrzFQkwADBQQAje0R1INm +9GkZKAzTECi+lVei7wbXkn4JF6n9r1KL5oULVF8aGHNEJ1Twj7kuq2kacYjc/Di4 +KdESRTZN9szlZnNruvAd9JKHIgbeysene3yRhy+YFaqXm1MtWCdwwaDiDoHDASpl +55RtuCKxz6uW77qhrZ8E6GRDrhI92R88DbmIRgQYEQIABgUCNuOvgAAKCRCl5n9/ +o64+oWsJAJ0XijmoDUP1Iu6lhsSlmGOiNO/l4QCff5G6w6Vkq8d86Ev2IwS9Wf4u +NmaZAaIENuOwChEEAJDhTfBph5G51alEDUaIfFvD0K+oXDXqDB7hDg3stVIpZR99 +d2bo/dPOuVWorwXFBDJeK0c7iJEQrMWKlxdqbRGkH8paFSnL5XWo4xMjknqnJzYu +3gb734ioFHTC4WDM2/voTGuFpLw+eirW+wl12wusHpnNkWxMEIWt2HoGTerfAKD3 +JUBraePb8gHKnXFzyEu8RLp3swP/XaAKje+NAYeqhcAqxv2SEPUj8EMgtX7SDkky +Dv8wuRfcNwMAt4XwHYnnM3bpUwWj2JcDGE9rsNna/HuFAjz/2lrhUKncH0Cywvjh +Ytt1t92j0cPZaeR3pY8R/bm8Ns20tiP7uxVlj+szI2Pf5KiUHhiWHJ2RTXGE2pUm +T6UFhc0D/juyZvINKwkbUSSwpKvsoi15d6e4Wx5PZ2mArT5y+ULitBx4WKIsXV6U +VVaEBNaBe63k9cFGdPEba/HflSd76kLmcSdy+Fr73d3TMIrmwAKMVdKjRAEc3l87 +YaPd2/LdT+TWzCQw33EotexJ7yZzZA2SJx27/jyIgXkWtwvn5UCMtClUYW5nbyBU +ZXN0IChkZW1vIGtleSkgPHRhbmdvQGV4YW1wbGUubmV0PohVBBMRAgAVBQI247AK +AwsKAwMVAwIDFgIBAheAAAoJEFjLmkyFqB84JOIAni+c3CDhA3k2Pp2CWgBSFcsT +A59CAJ4gy1+t/Pwk/095y1T6g3rwRbE0zbkBDQQ247CeEAQAnr0w2OcvlUX7E8u2 +C8dJGIj7wRU5qDazxh0tw55/ybJ3/KyhCFfsr2dZ2E7Zw6Yvc1u3WTTf82nH4S+/ +IJFSI+qBi3TrcwVtt8Xa3Po7cIzNvS0bBhqfmOOXJc4ihUlADR2Jukm/QC+f6bO8 +IZBDWr/7LnT4SwEPhPoZNMFb63sAAwYEAJ2kiP3e1zM+zEo2i2jkOny1Igyn0sRi +uw0OXQ9B656zp02G5qtDN+IXhgLdfQqgqyWckP4BLDJ4NtQoEM/Mr2/7oj3h01Xp +bU86R1QFQOXmoWw3q7yqEWIwfOBqClSF0A14sXdjQwadyabTFsW4m8Zn5jLW+1sH +4PrVjHoNEz4CiEYEGBECAAYFAjbjsJ4ACgkQWMuaTIWoHzgImwCfYJ4NGyH/snAB +xoxryuVciL3Cyu8AoMtIZ222A8al4XK0DrQqJAnIZlF+mQGiBDbjsakRBADettZo +8gTOTr1nJXbk5sJfuVSQaMmbgLpZpMs3Q7C+gAX0XX+Q/vcuHp+wV2Nq0S4v+w5K ++sxDF4A8UDf+q+GmNKMA5U27hkcDQvE48EYUghcdWKjWeFwmmJOb0KMoatdeh4iP +T4j8ocGw+i0z6o/e0y0OVWsUvIqp4iZP3UlnOwCggOq5GfPJMq3K3cND3nU7GOR8 +e1EEAMcgH09o68Hbjbwpw+ejPuKwVFa37COX/65FF8PONeleq7Mr3Y8yKqbLIsIW +DaxrlflpbyMz/ShuDdNU8gh+msfwh0+RNzdEPmpJCCVJOdZO46cudgbyAQriH7Py +sSbi7AbmpnMl7kQruhAZWXLtnH1e1kKovB43a3ph8wF4kotyA/45A8bLKEmJvpq/ +amY6VjDnGsxkDjjw2OoVbt8sLdGjpganj3fvy5KRhWeWLKhmtq44tH97m4YDmGCH +Va/Iic4aDPMMvUPWdaY5DyCeerVOb3JN1qLC7o5x2HBt8RE7cXnPJl5VKxc4qzys +5bqQEYYt2dP4cJqKk3OjjCbl6TJ+8bQtVW5pZm9ybSBUZXN0IChkZW1vIGtleSkg +PHVuaWZvcm1AZXhhbXBsZS5uZXQ+iFUEExECABUFAjbjsakDCwoDAxUDAgMWAgEC +F4AACgkQqUwPdWUyRNYzWwCeMxscN9idLHgH2DP2U6tP0tNR0T0An3lfFgidO+z8 +ZeHXzuOM9TAS+jz6uQENBDbjscMQBAC1u+09NP46dPnn6RJtczL3LEroyrcPmHOk +3FbiNfJ8YMnFBeST+U++chi/kKzm+N4y8TZE8sHwGqnkeIBtJX2YmQJFhKi2RR9A +tVn2HV1ZTBYT1q/P7MpZTPMI9EODlCEPJTvX+MdtP8xh0Gsj1i1wujQOJAiXdrqs +Pxen4Sch5wADBQP+NRROzLFq4kBUpgoTyvWzJl96Gdykf+O0AhbTlZ7ix9KtQLfx +Grqzgo0hwDjb2QzeWHfjVhaaaSc5UWNMuIQyHRcsj9x4n25XGE0HUyOVSD46IOAj +fZF+beXOa/NbYcR+zzORfXr1qyW2g4oV8LN4s4uV4dPamQ3l98Lkg8lhWCeIRgQY +EQIABgUCNuOxwwAKCRCpTA91ZTJE1s6YAJ9ZgYjqQ3rScmCwhc3Ihzt2ATANbwCd +FuVgvD2Yh8lsuiWswLDFrNsDk5WZAaIENuOzmhEEAKMDGobMDqPX3SKI3/W8m9Lm +NgtDUffHGHNd1npnGM8mSyVfWjEWoEg2GPMEmdX3/tvUUV7nTz02IJwZRVlrbEPd +W76eItMAY1NB43LpjQTrAR++mVAslulUY6a5V5nJKEc0IqOuxkW1LWavujX1JRvl +BZLeBkdpsVNuaGJtwUFfAKDfqoZUCcZxnO+dRMalHLfGOn7O4QP/apMk2mc+GJwp +KSxXBvoQkVcfuZBJmXJuUCc4BUUzHX0ZSKNbgxY/kVR1xN3krMgOCR6dEsGukIsg +VWRDj9to/+E6IIs6YKhG7fGcXKhE8z8mf3hDLcmjbCKDCSFBT7PI5TkLzlAEP1y2 +Rtin/Sa71unGZhNyEfAPW/d1dRcRVqMD/2WcTPUaIjRvAqmbxUpenRhg/mF5rwmH +l81VvVBbZCoZ35c0edEZKpfmyYbKuz7GhjEPz6O/UWGYZpK/7r6f4kFUrhO5atCl +nRyBkvmNmdfbtM5hd5jh3lgqAT7tk7ntPAIh8X8/qm5+Uab63kZwXCPiSR+iEwRp +42GbVL7F/b2rtCtWaWN0b3IgVGVzdCAoZGVtbyBrZXkpIDx2aWN0b3JAZXhhbXBs +ZS5vcmc+iFUEExECABUFAjbjs5oDCwoDAxUDAgMWAgECF4AACgkQR69LaWHwR4TM +SQCgwD4p9j1sDwR1+9bBrzNQzVIyzmsAoNL7pfcdW4Jou1XHNc6hv4MpsHtvuQEN +BDbjs74QBACHkUCB29pMkveMEZyNiKImizF5NZ/cv91Rj319k3xHf0NJWhQp/1G3 +8SxLkPLBdWcoB4mJRNjDyVsxFUXvRWFIMekwL0q1sHSWTcJwCpQs+LKKtPmD3LA3 +bhbuTSdpYgmKy21SH4epubqBzk/P0193mWXzHgSGLeUoTo3N7eBQ0wADBQP8C1Q3 +WGrBZNOmFVly0erclpQRv1qCa785yx/bj9ur2LxHwVozAEXh8jmoiKZyoAz7YFnp +29kR2qtVplH1oePNyFweZqIjtmZbiCaT4scUVZ/3LuYbxgMoUFeRoG4mnEVvUUh8 +mmZovMmZFrvp0uojcDsfYTx0VBr8waxgJrg2YguIRQQYEQIABgUCNuOzvgAKCRBH +r0tpYfBHhFPdAKCcyVECIa28vmUPgZ2jkXQoQ/nNkQCUDpGL1aZn1eKrDlHcGyD4 +CzywnpkBogQ247Q0EQQAvVX9TJEynPJEsX3X2fGPPDiQK+oB7D1INI9bfID5NKto +o8qybivOLo85i5m7RUiEyhX3E9lUg9buKmtIhas0sJ8sLURmCndIKtXjIWg3Kd0p +mjE8q2zyd7ChQ3ffJ20875wNbR4GQhSO1WTuxwRoL53ft+9JTULJxkQRf71Azm8A +oJZQYphKeLWrLtFjb2WKbYxst54tBACS7C/Vu40euIevp2TZHTtY0U+ObFvJr8jD +rdQZMkUFSuhti7rfO/bf7qTwmCvv6IVmn905ACh9bnKwZvcR5T1yR2b6CAN267fz +riZhu6/FG+9Ddr62ZnV2rP8Oa7uxAXCnoovaafKYupopvHV0z0tUf2+wasrQdHZT +vc0pfY+56AP/WOVJ0KGzP6k9bYjYSRJ1MJb70wdVFiHdlIlEd5P3jQsXOyHVMrWp +6qH10sQLto8gweWJr9aHem0QjTNSTVpzp6laBHf7tnLEwCJGeX5f5BOh87akRjwf +h9J9zW+DBrtpqS6vjlDYU5y6RGbGRl6ndtXhV5FpE4cbLax/pGFWEq20K1doaXNr +eSBUZXN0IChkZW1vIGtleSkgPHdoaXNreUBleGFtcGxlLm5ldD6IVQQTEQIAFQUC +NuO0NAMLCgMDFQMCAxYCAQIXgAAKCRDe8Pe47Gfb3qJqAJ9MbluIqs8qjd1lOkj5 +8xC5K482bACgjeYJadH5StXmbJMGw2ZD29yevzOIVQQTEQIAFQUCNuO0NAMLCgMD +FQMCAxYCAQIXgAAKCRDe8Pe47Gfb3qJqAJ9KLOBiv3gbMisxZtzofWFruAU5fgCf +ah6JSqX0OheC+mHzYBQa2a/1O5G5AQ0ENuO0VhAEAM9X7EMxDw3OSqgnI76WuIBS +sI0gF/UptzpT8g8AY6gQPVhU9fgQHbu7cr8SZFV3dyUVLTzkNq7msUivd3/Fecuf +77CpKBCrQlzst+UykiPQ/bT3+gq3owGi9MBCfeU2l5yZZ3yjGIqg8/XnxmCbuItw +69FNyz7+nQoDM28ci9B3AAMFA/wJBLjxXXqWFY5JdXq7ck66Qx5YHDpPH7szUKrI +GKGZHxk2UXoU8G9WRfQ0VVQfaomfnKvo+bFDFJGcLfIITI8FrjzGoh2K3PKcxsQi +Q1SsVlMT3XmuvST0yvDM8a4t9o+2v8yLLgEjR2dn/lTiGjE/ANunRo9TBGpvz5P0 +85NmzohGBBgRAgAGBQI247RWAAoJEN7w97jsZ9ve/yAAn18Lg2NXAdY6HW0LEurh +0Xcv8zlWAJ9ePiLMYxpoW5nv4g4nuOAWoL/KLLkBogRDVOPaEQQA0vZ86nCVajqp +71XSCfin8OI+gHAAbVA2t0JAH94SELIUTqhU3KDiqg481GoI0g5sbn83VOOnV06H +yfCoS3hVAw+qPIJ5B9hOT7YSd078qI5N6H6mV6vXhC4mFn+Q71t1ZIjZM2grgXBK +8gBa9XyIZPrtdI1K6H7PAaWitfJCLTcAoKRwVDiGrW2eio0bD3ri1TZKY6o5A/0f +KN6cxEMJuAX6hI9QBkdwCdQBYTfnaw6RgZOiU3Yfq/IhwLJe4GDm9JdBLSv8N9Xj +pkcsvDDu29ByeL8c2Mer7WQwFnx51MKKaHisWUafcO9QgLAFiS59nTCQimlbd/Wc +hiuLkJesLf5KjTcs+y4I1ryjpjZDseGhC49nK4BMAQP9FZ6uNXhULndYmA8WRs9G +GF95IzlbwixmZNkoviIF9Pv4nGT+xJPrMj89OzHt8KCLx2YyVelrLhwOCSxfjPMw +2Je1qRwcDXGKnF3/Nb1Mw9/3TQoRexGz7+SuV4v5EEvu53CY6sYbvRkuWHopzmdJ +3nIXNbywNRCse/EzhN+1H2uIlwQYEQIADwUCQ1Tj2gIbAgUJAAAAPABSCRDe8Pe4 +7Gfb3kcgBBkRAgAGBQJDVOPbAAoJEGX0CIjlGYfJ12EAoJ48RmJso+koefTCqbqS +zIEK2tGjAJ4+2Ur67Vye4z0tH6ArbYhPx8mRS6EYAJ0bOtXgxXzLucJLCaBqpYK7 +xbtZKwCfUQ/sT2tTaBwe+dAwzeIS1tsyDl+4iwRDVOQFAQQAykNkLQNR34cKEes6 +UcssN7IDzXup4UoNQVt+YBJwMI7rsI8jtaUeBZxxBmFOAp1dp3JQTUgv1CxWQZk8 +S/fuKOK3D7+NnDyZIBITsPF4IyE6qLkuFtEsxLnOPjf2gmWT1wk2AX1UQmRgXcp4 ++4jnIk2B5Rh3+FnM7dc+8CaCCc8ABimITwQYEQIADwUCQ1TkBQIbDAUJAAAARgAK +CRDe8Pe47Gfb3vVeAKCSwHVbYSnEz9o3AOWcJleQA8IL6wCfRnVu8NlqzIBcstTX +TimrHUIM/k2ZAaIENuO03BEEAK1KlG4lUzMSYafGwOLzFwMwri48rOAOOAxPrkRW +/QBrGU5sPxUzxEzu4lP9365cmMk4CLyNswxdUsB1xtOihd8iLvCxejgjNDdJOypy +qcPDNrZD4k/g/ADax1OXde/Hr85uND8jQ8isUhjZSBtTeDCChbTXTJWoS77vdZBt +OFnrAKCz2ucyEr7F/hMPeTNaOELYvImB2wP+MK/nmEcsD9+Xm/xeVfWzi1oVphA8 +8OCh10O1fjieyQ+Z+OEuSizysCKIKIQ5T5q8Q0wCf2ALpAKVCLXd9JK9FKt+EIBZ +LQLKoAj+wuShDNU08VNuU3LOKI1B6A8jI9eBArokwj9GRUSlIr6KYI4EYRUyl1VV +k8kpENIPUg2iE0oD/2tBclzEFGCY7gexgOq+FOkJyB7MUuca0IJLIW+LadjFVjIa +pYbHzi2o9VmfqHtA8SsNDt2Ckx/xAM5jXpSnDG7U3IpS2iHSOZfmJWpv22Xu0L2z +drO9ip9j2Y7WKjt1M6sNeG6gCUZdHpJXjHWUTDMwLKLq/ojVTx55aHV50NoMtCdY +UmF5IFRlc3QgKGRlbW8ga2V5KSA8eHJheUBleGFtcGxlLm5ldD6IVQQTEQIAFQUC +NuO03AMLCgMDFQMCAxYCAQIXgAAKCRCJeabFVn+zSrdPAJ9D0aoYjMxfi9+w8r3G +lZftM0q5mwCdHy/vA+Ra3KdZt2LQTKaPo+XbIni5AQ0ENuO1BRAEAMbhpQb6qA5M +YSA4BWc3RyTvoCcpveM4Ehh5AZgSAX+UNhtjt85De0iBDSNesoPXMcu85E2wbvTz +IM1Hv1LkKL/WemFys049Yy6M6xnZYyjnFuWEb5Ym6O3ilw1JEr0/l+idQTiFXsZd +OWODXJn+6LTQ63tvUHyvIBgTv23UHey/AAQLA/0eDavyUGr+P+3eRE7jGXXTwMVe +JAp2Puxe6CYBwyiYXicbePazbX10sQWVLCfT+l4a+OnwkU99ww9T/EclJpkt/3SZ +ex/6kdwNa6MeBUD1gLpOFhobH0l75WZxViiYQvE2cxYrI4l48NThWIheEwK8Y/Q+ +3f3BxCiIuN67Xn6X/ohGBBgRAgAGBQI247UFAAoJEIl5psVWf7NK7JAAnihkYWPn +xhbWi9SUMaB3Qz0SfsLvAJsEGrvruaT2XPVKwa9FFfqRj6WPnpkBogQ247VREQQA +3VAGc4T+vuvVXcka4ETaLaLlL1xOiPIdJMWRWWQ60CZqWXDVpFBw6oG2AyfUZiHh +LlmTZssz8UhXLw/URsPSpiGbtpGWKiLs4OCqjslN0lHzcnGqxGWCZJixMgZa5DcW +ZJjwqdXEbDChgm4ULP/7+iKvIenTQNhFoCXr9MtdoHMAoLpNCmSKlTu1H5GlWmYT +K9AndWrfA/47ip0VYgzIvUhI0iWcG95sNfshApzPL6zPgKBqACogs/5/DfRn9g07 +BcuMihLJD0PLNPVnOXqQRaN4Da7jLuJA53XtLgpogxG08M6XUimTucfcovu29/bg +jZIKA5c8KJ2lzXSJ9jZxSoy+O051f7yhXbUmYC1vdNr8GBk69QKy/wQAiHMfU3cb +CfTTMmig+zBHCkHjqzqr/zKtR8RT5AwSOIU2aUIiHdV08apCelBw8PbEf077TuWC +q2YyDZJmgWRYh5cdaMgdAd7ul1FS1yHPZYshcofWjgXUJHR4I8iPCs5OmdHo2HK3 +uU2OM36ZQGSpFA5WN1NEm9GtMSBoYKN2ERC0K1lhbmtlZSBUZXN0IChkZW1vIGtl +eSkgPHlhbmtlZUBleGFtcGxlLm5ldD6IVQQTEQIAFQUCNuO1UQMLCgMDFQMCAxYC +AQIXgAAKCRCe7zTNSxGyX0kEAKCUUXvVByh4l9ohXM16up6769DYSwCffVvyOW9v +9kENNcHvItZnEmD1o+O5AQ0ENuO1ZxAEAJriuUXEtM08l6eko1tvlnkCKSZyQ35S +9PogXv/90gA79NalJsN41jALsRvgnAgKZLJddtlfZ6RB4iwuENgOva6C0bG8SgT3 +m7rLX2nSyaFWKj7L456wZWn3uRnKxT5ymxNMFemV8f06f3kg4kJYneJVs+Sfs/5j +eyoRwDc6EQG7AAMGBACTuX5AknTcJIrBV83irJVsZvWKHtUzqLoklddYXsdI/eB6 +c+cBlhFxe8/hWw6vuFdFKhpCsWhEbJehzFjZCJo+ezf/YdQtWA34ik4poObWaSpn +oV7ZXaVhgjQ2axNEWrKxQihDVYRTIaXOJAJ8eq2wNPi4UbyZL5HcWO6SlP/2mYhG +BBgRAgAGBQI247VnAAoJEJ7vNM1LEbJf9FwAn337iOCEu3IIdDzYIa/9L9y/zYZ3 +AKCTcLrZje5JL/Z/6D6pAcsy8b2beJkBogQ247XLEQQAgQyThl/Qv8cQlWTT+jh8 ++nC+bzNz4plAIVfvRwFVT0FYk5xSq5GD0kMkX1s4zlPETtU6eQh8++O6Dm+o/T++ +Mh9bsu/MhYOFLoVwVop4bgiiquCCFsCZAigRa9VPH7vGumOjXI6ogwNCphkSazD5 +l3p15CaRRhxu/K1LzYvSDH8AoLoMzSC4f912QmVPgVD2Hly/p1ABBACA12YY9bxV +x4IvZZooyg4yaHBAaGpjf7WkMujsdUUQ+h7XwD2OUxEdZ+8ZvYTMxPjr9SCqR/xP +O9kYWtartb+3jmunk7jVhdDb5kkfeeX63kbDbkfCTSG+krSNhEfacwVH48pAvaYN +sD3gu8KUCSBfUxfiWtQbxtiPoWtsSe/OgAP7BxFLwDrHOfGGz5WyD8qdiXRB7100 +U9jSElUbkzELIPL1ffZzGEdglIdu9Lj8stsWWg/5GHCff9Z4GOwvaW2zVqFe9D5B +DDv6o+uziFYllT81ISHVEaK26RobnN6Ac1MToImpeyGyEj0SLQ4INqGaGOIaskDc +fAo9mWQMw6TNrwq0J1p1bHUgVGVzdCAoZGVtbyBrZXkpIDx6dWx1QGV4YW1wbGUu +bmV0PohVBBMRAgAVBQI247XLAwsKAwMVAwIDFgIBAheAAAoJEGvEd4BUrNJGQOsA +niVMkc7hW7GdLkLpb6YDiEUy0yrHAKC3dyJ1RI9tKXk1EOW9jTopkl5ysbkBDQQ2 +47XyEAQAzHzwwUKDM7+djJo2/EnWmCijc6g3fStaGNoXDEovi3B2oPiiRTsigX90 +qB5nFP7whDfi8k4JY2Eig5hH+MGdvni36hYEnQSadsZueYofvQh14N3V8fUmx4hi +QiMXyWiLJzc91ZiRjww4wZWn/4Y5f+0mb0fjCaVSxTxo4+7joU8AAwUD/0oL9Gm3 +gl1XVV8BhJoXVdFQ6PN9yEEXUbtcrfkC51kTBk2NaEGqbB+kC8GEmXwyZcW7AQN7 +X6ikraUUm3RjTU7CvkSHobBnXYt7FhqZURpuV7eSqZGP5nP7SxWmCTTKgIH1kHCp +WRwaexKFjIIkYgyVFqtEx9cEQ6D2kXPh+RnaiEYEGBECAAYFAjbjtfIACgkQa8R3 +gFSs0kZ9YwCguRqebBzPbFnWXjOqn7ueBdjsDEAAn042F36TAKQETj5I4YRTah9H +fMeR +=oe6c +-----END PGP PUBLIC KEY BLOCK----- + diff --git a/tags/gpgme-1.1.6/tests/gpg/pubkey-1.asc b/tags/gpgme-1.1.6/tests/gpg/pubkey-1.asc new file mode 100644 index 0000000..bed1da3 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/pubkey-1.asc @@ -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----- diff --git a/tags/gpgme-1.1.6/tests/gpg/secdemo.asc b/tags/gpgme-1.1.6/tests/gpg/secdemo.asc new file mode 100644 index 0000000..1a697f8 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/secdemo.asc @@ -0,0 +1,699 @@ +26 demo keys (passphrase is "abc") [2005-10-18] + +sec 1024D/68697734 1999-03-08 Alpha Test (demo key) +uid Alice (demo key) +uid Alfa Test (demo key) +ssb 1024g/46A871F8 1999-03-08 +sec 1024D/A9E3B0B2 1999-03-08 Bravo Test (demo key) +uid Bob (demo key) +ssb 1024g/E29BA37F 1999-03-08 +sec 1024D/1AFDAB6C 1999-03-08 Charlie Test (demo key) +ssb 1024g/BC43DA60 1999-03-08 +sec 1024D/EB9DC9E6 1999-03-08 Delta Test (demo key) +ssb 1024g/B0C45424 1999-03-08 +sec 1024D/FAEF6D1B 1999-03-08 Echo Test (demo key) +uid Eve (demo key) +uid Echelon (demo key) +ssb 1024g/7272144D 1999-03-08 +sec 1024D/7372E243 1999-03-08 Foxtrot Test (demo key) +ssb 1024g/EE45198E 1999-03-08 +sec 1024D/8FC282E6 1999-03-08 Golf Test (demo key) +ssb 1024g/9DCAD354 1999-03-08 +sec 1024D/34C6E3F1 1999-03-08 Hotel Test (demo key) +ssb 1024g/D622AD0A 1999-03-08 +sec 1024D/04259677 1999-03-08 India Test (demo key) +ssb 1024g/61F76C73 1999-03-08 +sec 1024D/D2699313 1999-03-08 Juliet Test (demo key) +ssb 1024g/35F8F136 1999-03-08 +sec 1024D/43C2D0C7 1999-03-08 Kilo Test (demo key) +ssb 1024g/9AF64D02 1999-03-08 +sec 1024D/B79103F8 1999-03-08 Lima Test (demo key) +ssb 1024g/FE56350C 1999-03-08 +sec 1024D/BE5CF886 1999-03-08 Mike Test (demo key) +uid Mallory (demo key) +ssb 1024g/4F31EAE8 1999-03-08 +sec 1024D/30CEC684 1999-03-08 November Test (demo key) +ssb 1024g/8B70E472 1999-03-08 +sec 1024D/6D9732AC 1999-03-08 Oscar Test (demo key) +ssb 1024g/2681619F 1999-03-08 +sec 1024D/3FF13206 1999-03-08 Papa test (demo key) +ssb 1024g/63330D9C 1999-03-08 +sec 1024D/3C661C84 1999-03-08 Quebec Test (demo key) +ssb 1024g/A029ACF4 1999-03-08 +sec 1024D/777FBED3 1999-03-08 Romeo Test (demo key) +ssb 1024g/11D102EA 1999-03-08 +sec 1024D/A3AE3EA1 1999-03-08 Sierra Test (demo key) +ssb 1024g/0F1B50B4 1999-03-08 +sec 1024D/85A81F38 1999-03-08 Tango Test (demo key) +ssb 1024g/101C0402 1999-03-08 +sec 1024D/653244D6 1999-03-08 Uniform Test (demo key) +ssb 1024g/5522BDB9 1999-03-08 +sec 1024D/61F04784 1999-03-08 Victor Test (demo key) +ssb 1024g/07287134 1999-03-08 +sec 1024D/EC67DBDE 1999-03-08 Whisky Test (demo key) +ssb 1024g/FD6E27F6 1999-03-08 +ssb 1024D/E51987C9 2005-10-18 +ssb 1024R/40DB9D43 2005-10-18 +sec 1024D/567FB34A 1999-03-08 XRay Test (demo key) +ssb 1024g/41E408BE 1999-03-08 +sec 1024D/4B11B25F 1999-03-08 Yankee Test (demo key) +ssb 1024g/F7B080AD 1999-03-08 +sec 1024D/54ACD246 1999-03-08 Zulu Test (demo key) +ssb 1024g/A172C881 1999-03-08 + + +-----BEGIN PGP PRIVATE KEY BLOCK----- + +lQHOBDbjjp4RBAC2ZbFDX0wmJI8yLDYQdIiZeAuHLmfyHsqXaLGUMZtWiAvn/hNp +ctwahmzKm5oXinHUvUkLOQ0s8rOlu15nhw4azc30rTP1LsIkn5zORNnFdgYC6RKy +hOeim/63+/yGtdnTm49lVfaCqwsEmBCEkXaeWDGq+ie1b89J89T6n/JquwCgoQkj +VeVGG+B/SzJ6+yifdHWQVkcD/RXDyLXX4+WHGP2aet51XlKojWGwsZmc9LPPYhwU +/RcUO7ce1QQb0XFlUVFBhY0JQpM/ty/kNi+aGWFzigbQ+HAWZkUvA8+VIAVneN+p ++SHhGIyLTXKpAYTq46AwvllZ5Cpvf02Cp/+W1aVyA0qnBWMyeIxXmR9HOi6lxxn5 +cjajA/9VZufOXWqCXkBvz4Oy3Q5FbjQQ0/+ty8rDn8OTaiPi41FyUnEi6LO+qyBS +09FjnZj++PkcRcXW99SNxmEJRY7MuNHt5wIvEH2jNEOJ9lszzZFBDbuwsjXHK35+ +lPbGEy69xCP26iEafysKKbRXJhE1C+tk8SnK+Gm62sivmK/5av8EAQNuYiCeVh4Q +pF3i4v6LDa82cNBI92zOHLJAu1nbeJ6bl86f/lrm6DuHtClBbHBoYSBUZXN0IChk +ZW1vIGtleSkgPGFscGhhQGV4YW1wbGUubmV0PohVBBMRAgAVBQI2446eAwsKAwMV +AwIDFgIBAheAAAoJEC1yfMdoaXc0OXgAniui4cH4ukKQ2LkLn2McRrWRsA3MAKCZ +122s1KPXI/JMLBTBGCE9SiYQJLQQQWxpY2UgKGRlbW8ga2V5KYhVBBMRAgAVBQI2 +47arAwsKAwMVAwIDFgIBAheAAAoJEC1yfMdoaXc0J4wAn0x5RWtqCjklzo93B143 +k4zBvLftAKCFbrlxlNCUPVsGUir9AzxvP0A3gbQnQWxmYSBUZXN0IChkZW1vIGtl +eSkgPGFsZmFAZXhhbXBsZS5uZXQ+iFUEExECABUFAjbjuFgDCwoDAxUDAgMWAgEC +F4AACgkQLXJ8x2hpdzS3wgCgk/BrqP5WblWLc2+6jwlmuLg8n8MAn12puZol0HwV +0mcd8aHWtcrfL8lynQGlBDbjjw8QBACcjdcfV/S7I319mfDvbOwczDvTqDsRbb2c +PhQNAbg7NFlWJKtRrmff14jtCt9M77WZ5W+zTLwX8+8Wy3mMfrys8ucZKtfPixOX +VPhyinUUGSq68IArA8vLSUTuOO0LIi05LAg6jzGhN9jgkQReZyqxub4oe/3JhIX9 +grgJ/tsjNwADBwP9GeXmMrGi5wMD3qkPbzb1MqwsVBJq75eLLxu85JIN2XIAGw6Q +0FJp4o7d4BAQqAMzt3ONU1OcCWlDQRDxj1nynE5ZgRBiVoyudEELgNnYhp3MSEuU +g7PkFWn+N+GuvyhVUHApleyvP09kvP57hif6yJRS+V6L1ugP0vZmBI4dqQ//BAED +bmIgnlYeEKRd4uL+iw2vNnOO9Y3cRSExyy8unuzNvx5GFG6KNtxoFCDzMMzUa0ED +H1x/QJA3CgqMpS282nLdk/5O+AphiEVeGv8+c6pL/t7falIfSgKZ0j2nvCKH12So +bwiNflTGJB+jLnnesjqYJD7h0SVLjToP/vtKPYlXOU1ZpKzDwP5YcQQuRhF9Tj8S +UxScIIhGBBgRAgAGBQI2448PAAoJEC1yfMdoaXc0IKkAoJ/NQGlvFv5clcDIf1AX +jLlTFG9uAJ9rs8IOzHfNWuUSNxdhRvO+O7fYF5UBzgQ246LiEQQAip3HOFHnnO3V +mlQEctkpjVbn3knp2LOALCDz9L+fYxJeySNK2/uCWyCaAM1v4XJtuhkv1G26UMIo +PPz4DFFeUHwUk+AhDpX+/8dmuBypPbQ1eAJ+6tmja9W3lvrcMX1BllleSNKNW/4i +lZPy4kEYmjK/KSV2Nuupuv9j5/S5g7cAoPiKn8fILCtj2Qlr/O7hCgDi8x17A/9X +kcS6grdYU/fIHQy8pEU5SN5DKuhCtyPs//KQyDA7jyCatXjOvGHRWa/LO4tcntUK +Q5bT2B4Fp1Au997owCgDXcsm5tx6wN00gYxAITX3LvJ5K1aK7wEkFAwiyWrVkViU +1Fazx/hlyFzAPzouiw7IDQziWp8M87wwgpvIVkKlvQP+MWAGeDVRa0KvILUDyVrj +CH0hUr6WVjYEIGGZ7Yl0lBmDlbNvE//O0aEcdNrbFQ8NjwPM+vKv10bjPTXXrcW1 +F0BwfXrMxS4t1tYnbF4XfwuEsok4BBVxvGPLPeBGnYJNTwGBzehnd0mO45nr6mBl +S5gae6n4+WPV0jOUhNE4fnz/BAEDZ+eT3rtPNfpwG0QtNEjpDuT92icLuwCL1zfT +YKyXVFu00JkCvnB8k7QpQnJhdm8gVGVzdCAoZGVtbyBrZXkpIDxicmF2b0BleGFt +cGxlLm5ldD6IVQQTEQIAFQUCNuOi4wMLCgMDFQMCAxYCAQIXgAAKCRD+GAsdqeOw +smzHAJ4/wZXBeYHYY/IbohYo5IGWYv2IAACg8aZj+CQpLM/lDyrEPFG7bkz26T20 +DkJvYiAoZGVtbyBrZXkpiFUEExECABUFAjbjtzsDCwoDAxUDAgMWAgECF4AACgkQ +/hgLHanjsLIa4QCgityK8zajBOqAN0ZZTq8fOzgiEYIAn1ZEfjX+jefZUuY+4zFz +rpO/fX0OnQGlBDbjowcQBACVSdXxUWlz81FjqHgR4b1EtmhmW89CmpsHfKlSwlYv +BtbB/y7TFIfvAr4ZFbpuqew6JvtjIEZoXvolTWwHVPEFkuG0LAa03olaYpzC6ZBD +uLkb09RukCD4zdY6xwbAMRsOzZgv597LZXtOLLLnmOyTpsjRDLztWsuNglm5rffO +TwADBwP/SyVZvFEdEVn5/dQTp7eAtXdrbZEM379ctCJ2663RbTZd55lIBev1fTnK +QkvDTY2e58yIQ4E+Nzr99qg9Cyf6e3OhErTUqEBOhusBge4/7E5LrIVMvo6AFU9q +gn0Sgsnu/ww2txVw3XEjqL8Hgl+4Q/57YRvJOe+q29Ye9LL8eaj/BAEDZ+eT3rtP +NfpwG0QtNEjpDueclWEU7qldXMk8f3YzKKAvQfYWIlwPJHFJ/0Tt4c7R1RRkmEFm +DYThgT3vha1BX2Osoxnkva5SykN6Ghgq+qb2WHSAXc5LVvkyLQz2JkWmgUyqwcPI +5nHLJ+8ZxK4lXIJEk0zHe9OiPHAiEIf4iojOaRWRjz4IUD5+qWkui/snT9GTZYhG +BBgRAgAGBQI246MHAAoJEP4YCx2p47CyMrkAnRZD571KWLq1aD44YNacOFM7mlWM +AJ0Tm/dzklD/T2cX+F1ScBylNj5wlJUBzgQ245BnEQQAvwwkLp4Dtoie4/fvandn +K4wVPCvgJkIbNuyQZCarQGwv8RapBwbANT4vGW+ky2vzgptj21xYjOcdNMIhJ1Sj +c7hjs1PLhwepMFrS4/Ple1TljpEgxLZ5UxertMvSTr7OxsA76jjOQt0B+y2vs5zX +gLtedux4+pdFxkgM8r6fjZMAoJ5LVNdVRaSkiHaKZWQWsjfTs0/LA/wMHP/PdH4k +jFmDRqOPp+iB8YYwQTPZS/gwHtUbQhLcFEljaxrCMRZw0ZDMbzKWk+BrrBvgz4Wk +3XawwUshYgi8SgwWIDG0jusEPYOs1hBIdWTEzFVP2pK/NQzhAqJV5/390OLEY8SN +4bts/LY1XsADzU7lhE0Oohx6FanaZCuGgAQAn2zK53yuk7o8UrPdTHygVn2McsPY +YzOvlVfHCSXQ14oXjCs1nK1XnMIGGM7pJjYpzv/wUZkHLNcHX4uVHXxyzRQ4oMPe +kncmaR8fu/YIQ9zag5s2GpKESKAynGQCKwI4H5eYn+ryIgOHNS44UnXFUwbEsonP +5pJNNRIM7VimNGn/BAEDIklsjKh5E70pJ77zKAq/uP+EnBQq0tCcyqQgQiG1n28i +MQy45N5zv7QtQ2hhcmxpZSBUZXN0IChkZW1vIGtleSkgPGNoYXJsaWVAZXhhbXBs +ZS5uZXQ+iFUEExECABUFAjbjkGcDCwoDAxUDAgMWAgECF4AACgkQQT9K8xr9q2w+ +RACghpiwPnn7F3HJsm9VXM8SwBjWThIAnjHZulQw9Tee9XDT5STui+ZG+WN3nQGl +BDbjkIIQBAChY8NSvu6sK0p4D0AVBsRz8iVXYqbRlRTZAHS4LCXwx/i8FmfdIXna +NLOoyi44YruSCnlZdh4YWquCx2mgywG589AzcFhahmqElNbKb7m4F//EGIZK0zTg +W13tQwG9hTXOhYeqchnOOaDDwPEK1Gr+2o/5ANqhqrin0TFFBWLgdwADBwP/R009 +s61X/FkUUAh8w4Tua6qndN/2GsqXsyPYjdF5E3gErK8jDcDLniOHqkswV17bJG81 +czCRE5JcVFLLWQJg9cpeoTpP+YcF+m9whtswaOJ/LPrx888i/OmluSD81VP+6zBh +hTUbpazfLEdt3XczpW7CNdNbyiEcgT+6Cr+W2Gb/BAEDIklsjKh5E70pJ77zKAq/ +uPsbfaq2h50JWrb/wQiufxaUrYRvo5FjMBLnoUE+L/yG/Hp2ZRZuA5EzBpZ3ON5L +aFadahL98oQe/W3IXFZwxyYfGCtVrV16zx6cFTJQK/iIqp3TNp/fA6TRE3syS1FQ +ZIZMiFLvgSy4Tsu4vAadP290Tc62LP9ivC3PiIxt3aqW2l/NLohGBBgRAgAGBQI2 +45CCAAoJEEE/SvMa/atsta0An3ZMmv9EVWVwEvf/Rwf7nbFsgGhuAJ0bP+lAOCRS +YziWSIDf+BJ9F19H3ZUBzgQ246OHEQQA3mc7VzzWMKaCH+gX6nqSJmaoVXdql7mQ +SZxL8GhaAJe3q+NqV1y2YViLu/4Fjg33MjcbFCoDG3kPp1jto3XGULbfoJkQBpdR +eS28bD+mkcON1uzwJG5mID2ObWP3YYBRj+abqFfZoYo6RXCv3I3oOsDYJo7hLAr/ +AReRV+P6drMAoMJoHMfPBKSRd/xA605OP/F6+mfPBAC/fSVoJ5dMNkzYj/U93OZr +VXXGLN9p7SR/Nk4kENC0dAO80WOa7qIzWQvS7E4beSuvQCWpKwwPxbuZq9sWKBSX +FuG+66XilMv8GIn3joWGOU9jQ2L2mZ0CV2ejvJRixYAMQpp2RDeCERWoSrP4AJhv +Onenwr7kq6IUmb0Pi7K9OgQAhU+LY37i+jGdFYbApcXgT58tgDNdPmwwzOXjpeTg +yzfTcX/kkbuQHSKI89jqg/SXeeVqG6VFxs0yPtINt+t+iLibh+1RghfdpxcJI3SA +25UaKmDwLCUZDIguBZEWnqhdA6YCWnGEgZx3WN2HeyPnL4JCu6AY804lP2bOYWQH +ivH/BAEDYa6EPLwGsFGwSRgJuxOczaFyt5cvcleOf0qIVWQ8zg7zpaOi1spi6rQp +RGVsdGEgVGVzdCAoZGVtbyBrZXkpIDxkZWx0YUBleGFtcGxlLm5ldD6IVQQTEQIA +FQUCNuOjhwMLCgMDFQMCAxYCAQIXgAAKCRDrqfJA653J5q4mAKC2XzshPCkG6gim +QNpS28Zwl69htQCgp1gHi/+kS47sk+3XRt6nfoIBJwedAaUENuOjqhAEAI+1nWji +Y8yTbNhvK76w2bw/7mgC0PT7Xb2AKfw66e8TB+U+tviik5SnTt7PCEAT4rhaHCTY +q+bLf55vF5foHDmTr7a+OXP3JeeHxjtYDowWTn4G5HQVSvyzMLkFiHmyuKgmZwDp +Qy2DRlVILhi5xEAUn54YZIIdFgNJKre32L6XAAMFA/93DhKj5THWHi5xhBuMD8bc +lSHIcBjr9GEVuWqW89n3Tu6LY9QBVDeVsxcNAOflh82tTiFIYOdGXKOh58Csehfi +22eWjnN+xAL2hYD7jMQX5GlmGoAqH94wRdAm01lF1fw+f3RZiHrhk7lDDbBlR/jk +jFtoQTf+/miSuSyxy/oc6f8EAQNhroQ8vAawUbBJGAm7E5zNohCGfow8evYur7Yi +tpkufrndPvf1xHdX6BzF6AcqIU7CXlL28F7wLuxbw3X66Kt1xr0o2fnM0zCHpMwW +2EcQvqT2BDTbgZ/3ui0ykA+KFVvrkGHD2seQL2XkebZvUT8bkNRGDQJh0djhLZhO +M0m6hra57Kf2tPe20wp5sR+j7ENfR0rHiEYEGBECAAYFAjbjo6oACgkQ66nyQOud +yeZzTQCfUnuDgUMiEoBukTDNnuvn62NNR/sAniZp9Uhila1p2XiARI/o0eTkgDAw +lQHOBDbjkc0RBACKzsZMOq0QzqW6inp5azEWL36qFRWn03pL7GVvDNBlUDgWMKp/ +VVH0lfx/CMt5ybFPnFOFBVxGqB4VVoLKTLY2B78VwUw9lB5o/mO/kZFZzk+8f1LD +ym8Y5MHnpXhl5HhxAsMGbkIXm0q7UEJZarYwsd9y3tNd7pALNkpyPN3DywCg31W+ +so34RtAL5MfN1ZpRal1x9acEAIVYTItU9OkjWM2ygJnTQXwVq7/ZtpeTyZ1E6Ull +LpurniSx85BDNF4FZx7fmHRbs14FGn7J6hJ/tjeLSNM7ias6Iv/Q0JxLyoo2cYob +WKt0t6zelCENmlxR7Yb1bcWcaHGXpbmGlhz3nnSZSPYfcjm2Z9JixVxWOk1Ih0GL +PETYA/9IjW3qrsscxCnSHcw9DbPt1oyFQZWJedWXb6sqNvlPtu9IV1XSLLK7Kiq9 +Q8EZbAkUsDGPp6wdGVDpby2iAe6gkJHtwvZsrv3yaBg4TGTmAF7GrVUdBBk3V50r +gsajYRIqsJW2RjAHMBTvqFgUoBsoxTx0zEjsNF0uNne91DcU2v8EAQP7HKVodZwE +5NkEJ3i6Lo0iwuRAu/m4Vbrq1Zgq9zYA8B7ygrGHlgyntCdFY2hvIFRlc3QgKGRl +bW8ga2V5KSA8ZWNob0BleGFtcGxlLm5ldD6IVQQTEQIAFQUCNuOkfwMLCgMDFQMC +AxYCAQIXgAAKCRAxjB+u+u9tG2cDAKCzaFoiAm79QSmYISeiM7XMKhoHDACaA8CU +1j8+20C7rNipOHYz3KfUMhe0DkV2ZSAoZGVtbyBrZXkpiFUEExECABUFAjbjuAAD +CwoDAxUDAgMWAgECF4AACgkQMYwfrvrvbRsg3QCeOMf0g3znbc8IBiTrIPUgUz9p +3WoAoJ6eRZTZk7z+hTyx4JDceReQbYlGtBJFY2hlbG9uIChkZW1vIGtleSmIVQQT +EQIAFQUCNuO4HwMLCgMDFQMCAxYCAQIXgAAKCRAxjB+u+u9tG16mAJ46lQbmtWRZ +UldQtp4ZnOptP7ZJtQCfceYMZfMAnqUKJiHk2tMhvwDvAh2dAaUENuOR/xAEALSl +7SaNEf8mYovea5tJNEwoZx3vv6XymyXga1wDqKo2PeDrnRDbHGBb5BvWIv1J6Igk +/wq4R+Pq989UpkcqREB+yOeluE3zPPtZBrbLySSaqiMegYiHnAAPc0TqjH7UPZa+ +fJKZTUk64BCUQN9ELkL2FKtAGQ7RNQJYvbCq4O/XAAMFBACXdO4a3ZIK5hJejhHZ +01mkHa6Sqoc6PuedNC7tlWiLU62BljGiv/DvzcbMsnvk991AxJ3pP4ZvKr5CClqI +G+WZa1zmtwXdmCfGJb2fbNSVD4zp16e5slPr8Cp+fvIv2/SyvwruROs+oAzSVvoM +AzAGSk3yj5nT5oikbn+M62fC5P8EAQP7HKVodZwE5NkEJ3i6Lo0iwYcZv7GfkzxH +BBuVK1coW7Tsa6CI42qeo2AH6zLC3Wi2fh0VRaj/gXMnO8S0FDoSNyFYBUqhViPk +fsTE4/gEo0M1v0l87O70i0eTxO9DlfsehX+v14zSLoxHM06W9yEHU/cePDhrY+Pp +PCkQEZm65ip7XhQAY+VSMdKf4u6G0akTTrO5iEYEGBECAAYFAjbjkf8ACgkQMYwf +rvrvbRuPkACfZP1v+fVPYJNr5DmgYosCwEhyB4YAn2QLgRNZ9jyK1qvLvt0qbJUl +62CXlQHOBDbjpSYRBADdWzld1lyDWDqGPSzGOsehXyTSa0pOfVTLckpJpDpErcn8 +jS8cKrXkVUowI7SlZhPRmYI+5pqGaG5FZ5VJd1TfKWihc7O+JDHoK3yamOnh6OFQ +FPZUF1+WlAGiFXLc+WODzbgOSMy/8yXA6n0ze+v3et5n9Kzib3sDGjw5DMmiYwCg +mUwnofqskHVv1S6tDg08mXALKKMEAIVGyf9ij3BzNb0fVYGUOLU07nqQ3RpNQPaK +tPQpBobRknQ/ZSdzuiALcCB+Q664f1cKGA+Ogtm0L/f1xUmKRW3rT9lzMtcCy6kc +udCI2OHm/gOcPzKqjj5onpD84fgR4BdbsehT8+urmxFiK/bFFI6eC1L5edBQcRLs +7TF2jY3SBACdXy9yHg6iDTJhysvR7UuLWE/1s9ysirhZgPb0vyIFwHfRzM96AYIP +pLZr/jvkrDawTxYGfGIZrj7UyGePu7RCeFRVVX55B6evNv3fAqbmwQ1GHTX7WHCN +dAkP07yTxZ/wnZudPAzQwRkEfZ39TdccbOhHfHvbv3RNQ0VxbWtQUv8EAQO595ah +JXcubqawgYCOwcKTNBJVjftg9mvS4BJQhejHk5xuGHGpqOBmtC1Gb3h0cm90IFRl +c3QgKGRlbW8ga2V5KSA8Zm94dHJvdEBleGFtcGxlLm5ldD6IVQQTEQIAFQUCNuOl +JgMLCgMDFQMCAxYCAQIXgAAKCRDUv1fzc3LiQ3ctAJ9QF57VC7tHkxX6KiI9oCKE +Uepf5ACdFSF2rDZ+XDAug7Xbh/wpdwQhVtudAaUENuOlUBAEAN9UI9jBnn0wqBdM +fg/vVDMWekbgT8yOoM19bc3FD1mMt/DSKvpTWAYO4SxZFH59Lk7AJt94dkPM+Pwx +k+45kFqaCIO8jU6+uvNS/4GKORYYQvqhEWdYjzMnzMMA+668/W7YVBk6goVdoejY +j1DzO4nPw/a8SSAl8vHbKI9HUOnbAAMFA/9IIIpkE1AhpjRx8qaK/xmNFwAC+Fcv +IwLAtBR9VGqg1U60wx9ali0Z0vbsRLDiSBkizEncQtBWRGKuIwpuwmI0zh0x772A +24bPUIb1va+FQ9nn2xERUhGDIh+vQEkCxg6fzuZDmU4EDr5eaMc77KzjGkRUlnJ+ +urlADDkZhys9YP8EAQO595ahJXcubqawgYCOwcKTMLJiwDbUjYSnvlZhZLzfZrMp +pGf18gON07NxKYCP0aD9geBkvS8rggtugxKhp7GrbPvsmnv8A6Fs9ZjPbauFHDC+ +IUhyG2ZxtjhGQyIrtauWktSNu1HloQPPqj4T6LMPXCd2N7ECIHSBIiswHX7I4ZhO +/GkqZY4Rpxbpk1b/af5QjbgBiEYEGBECAAYFAjbjpVAACgkQ1L9X83Ny4kOO+QCf +WgIpdCqnp6C84k3sRHHNhJxZkbsAnRI8ATqCRceqpbSDP7SXMakYu6rtlQHOBDbj +ktERBAC5tQ53QHtwXMkcXm+jk3CIxnUlc+PI2ovY5YT9d9p4mIHnmgyZUQ+YrUkX +r3BTtkGmjWXg8QhZw/tZEyq8EQWX7wud6VGRJb3mTAWvcPxNGdqtnLeR+IEXW3fd +2eRVNpljEIMo4F1n9mJG8trqBn8oeEhN/NpLuHfobYxsCUaWPwCgpA8WwQ+MHIph +3Hvabn/Ym7/h3iMD+gI0Apokfs3xjccuKzVKGGnK0k/XIL0YmO15ze6DNhILtEpX +c0lwF4JfiibcqGINI3phhUgJ/jB2rPpMChyio/NHa3sXPr66nEiCHlYaecKzZ7u4 +7V5dQJJc41+IMQPNEoZNCOR2/AWj7zzQOSIaWf+qZGtwgsDnrx3A2c6sGKjlA/91 +uSlQGGoYOvYtyGmShjJCWrNu9SlcnXGV9mKbWN+uZ1+yTzd0TeIHO+ZPwHIhlwyi +oMQeKX3kuYmnerDXJV4Ck/9lZH7ReIEsQX0aFwA5zmKEfYAJJctaJFenIyYrb96t +O9NfdCQByqhDVwVYLA00KuWDJwHzgd2bkZd1qOntwP8EAQMzOMJjiSv9DeOHKJqc +uHe89G2I204zUEBdWXIIWswBYzjC93U29DM6tCdHb2xmIFRlc3QgKGRlbW8ga2V5 +KSA8Z29sZkBleGFtcGxlLm5ldD6IVQQTEQIAFQUCNuOS0QMLCgMDFQMCAxYCAQIX +gAAKCRAWhBCkj8KC5iLjAKCZdUQInKOR+kkkFN0bMKOFSrg3+wCfcKC7DVHitfTf +3V7WkBS7Izg6wWedAaUENuOS/BAEALbBqf1JwNcuAKo3sJZJEzkHry8Lc8Jt6Ziy +45dmN03xp/DYtIfFndu5Fd9jFGck2jWmbg8aQxDtmlCKRllUJlr5aghVdhdGdgCP +EeG8dbQtpA++fIVL0fktoZ/ZSuxNZUD7r3nNixJpfrr1cVv1ZuIgwYHjJSJc+9DB +QvS1J36TAAMFA/wLewpaOw+HTZONwTL4UPFYCfiDct+w4/Dx19rAmWf7SH0sDSFN +5tsoEla3k5QyqONOr+kJnn7P5vXR/ZbARP/EC+NBJN0mOsVf0M01TeOEIJ6USlqX +2jGxs1iVV3nM5TZE3iGWaP54Q5vmjLnDLv3uxCmxuuAZ60JOy8+i0im9sf8EAQMz +OMJjiSv9DeOHKJqcuHe88M29HoyPcFtrcllVBMqQ95IHdcEmBDyyzOdky/GU10Y+ +XpI6WkFg9yZS6ja7r19L4tTOrEzS6eMsL9ZFE9avlALKDeQkVelnkNyx1dQ+KR9p +EPhda5U9NK1y7s0LdhG35A3TLiZ1p1kyNIDAzIeD+ipkcXoegr9MDllNUc2VpuP7 +M2nJiEYEGBECAAYFAjbjkv0ACgkQFoQQpI/CguZK5QCdFyMPKuMhs4IORB8Kuk+9 +uqIehAwAoJhITUNWoGT5GVVSnxG4+aC/MgoLlQHOBDbjpdoRBACnji9qSHWfs0LX +ocXS/Zf7gwRUk7jfay2/A4C4sPGfY/FOQhB/zN/Fsx9ZxyipWSoxlWWIsoUXwBvN +8Lx50/N5avgHdJYGmU0eM+p63eVYjpRz5X6qOET2T8z3vrhexHw5e/drCXq1xgGr +C6LJip8SgMiclY4e3mXI00v4VITvcwCg1cixyf4EJTGJPLxOV2C+z8OHdvMD/1bC +lZI5cbF6XKwkCKCng14CjVb/S/tD3m7Kc69ljmofIgTdUDpG7XsSCgm2/Zpr4hJy +VNBRceTCMOJoqb2OBKQmh9zHBsCaQs1pncyA/GeqCElMirLj+z145gEm6IFeiKst +pv9kQ7X2yJW8KLX24jk/U69yD2x/rRwGQcjEcr8SA/0TfdFjj0qTg8a/QB/W7Zni +Q9AXzbffddevqncL1q06H3G5AYM7wd+Lyyw2jClSMop8c9pWMgu2kqQN7s42b6D7 +z60CRSxNHcew0pFE7Vm0BgckWm6cq12HSmc7BVy2/i0k1sBd7EC2sdAuHGE+ziz5 +cYw1avwNI4M7WmVVmt+yGP8EAQOGra5cBw9i1UFlvGlJ9eyL42cZ6dmeRJuqta7M +7bO5va1wr/nylBRftClIb3RlbCBUZXN0IChkZW1vIGtleSkgPGhvdGVsQGV4YW1w +bGUubmV0PohVBBMRAgAVBQI246XaAwsKAwMVAwIDFgIBAheAAAoJEBPbllU0xuPx +7NQAnRTmLEOKTUnU/YK3YZjjVyl4FUc5AKCJm5Qv4sEbYt/8mfC43NLRHOB0z50B +pQQ246YdEAQAzpO6UuCWWpP9up5GVhLPoSCBfSIA9JWm5Ap6/hjQ5hia7CcS8E41 +PjaGl6Pkh5lj2qkSUBa892SXyQMYqMqEq/h7+BW7+n62SCRMtYOHRYZPA4hvs0d7 +jznGQlMsltx7qamoVNP0XF+ws1wHLjyQl3qMnkrAQ8lAJP+jg7P5Hq8AAwcD/A61 +qQLRXsSFr7LMBnaUSR0o6+4/HCdh8t+mnAeQBDAkne5DTPiwqzqsjoYekX6JK7wk ++mbsJTd/Zw55Jkq9xVm6nEUo/JIbN7cPlMqfCLaoS+ttbxZ9fNCO3WTNdWxAr/mG +ZZiBfy9yTcxUfo5qTg0ffWy40CNHaVKk+iIcktGz/wQBA4atrlwHD2LVQWW8aUn1 +7IvgBwLos11Jv+dIDqgz5/fwL4EJz88YHle9TmlM1Cr2RFSAuwPHjW5i16KDNynO +qaWlTstZegVTXBwPogHRDpxi/XuOjQC8Bc/gx67drpmNm2p77epGMlqgoZ6er55P +DuAg/Lnyp0OHN830rpevbrlAPpeHuWRvFeclKIpEz+5G+/+z0jKIRgQYEQIABgUC +NuOmHQAKCRAT25ZVNMbj8SZoAJ488ZCSBKz8PYif1pS7+ILz2PyISwCfVke9uQJi +IzxHvGKoTX8eW/lWvQqVAc4ENuOUsREEAMhuJkVEGWoIw4JdMQJ2kmywkOcCamKv +7J8ApfiGw5V3KB6l0DTvUCazysCkAFL9zb5O5qmVp3zD6LJCzgEq7Op5Ar9haPQM +OrJjYszuolu8V3qcL8Y4aOIS5xNNKBjwg4VJwFNOSztqUwaMcB1bNKOr7WmlYl5N +LOnThQqFXX/TAKC44hpSv9wxVqFK6iIrhN2i34JHXQQAq6dbJydQbYhoZio7ewJ+ +kKHOS1Z1ONSf0RIkCMorVBQLz1/n4qsw8hN1Q/Kl/770y6YGQmL7xHQZUnzPCHAp +9f0IeGsPSR87rykIPFnJb50PM6v+0VfSe4f2kvyiIQySKRoYumH4343Uiny2GH69 +0uE1SvcQ9GWtwB+/5a06lvID/36SlrvHycifZKh8mKyP4+MpLeUCgY97R46gr+xU +G+BWPLcZzd3y8wbb2v7ZZEikbC6G4sY2VBhfrkEdXUwr9ONi8WemhFKq1MrcalHN +OaQkgLxGVfG19h/+frpUsHcShM7NYdjb0kwImeeM8yhoxzZhIrXQGjw//bucXQIq +jxcR/wQBAwmIVrocZ3iWL9mYXF6ltdajZSzt7R3+EFj2DmfW0QoZtFM1uQkYpPG0 +KUluZGlhIFRlc3QgKGRlbW8ga2V5KSA8aW5kaWFAZXhhbXBsZS5uZXQ+iFUEExEC +ABUFAjbjlLEDCwoDAxUDAgMWAgECF4AACgkQH+j8bwQllndaWACeJb8gwlf5faF5 +CTszXhi9w3+bvO4An1puRe2LCIYvj0ewVWnxVAbFk8PrnQGlBDbjlRIQBACDDIJP +3vJbFfyhJHeP4zSuMhY+YsvxWqJ/NNCNxlMxE7kANgE94HrUfhrleKW2VhP/NG/Y +ZzVudFCRoj9fkl31bWOb0/Kf4DRcJ+XdDv6at26YBUSZqGsE88fEhQ8AlTxxHMDh +xNo+S73670QTsilN9ra/e+q4vlKMLdPvdi7gOwADBQP9GKPXQ6oY0dlKDXGHxGcF +oUR2miXpz9890G84yZAEm+R/OMQkxKb9HahLVUyVKCKPC4eVY24gsKJOEDy1Um0B +Xh6kym+zfej43r5GdQqOjqywjTnD0b18YAsEhm7rizJECRLrZ1y7tAziqrmPeCl1 +4e/S2u5U4I0XhP9Vs24HNfr/BAEDCYhWuhxneJYv2ZhcXqW11qA65iKv4k3bInmf +WEWAPqyeDgbW9rI6ldi+lmDTqnNqg0o/UAyESfMog8rAP+GIrq/lDQakbSUBq6Ho +A1xuPjR7LnZ1cxl2kLIBKgI2fT2RLbKxH/A/PTXmdN8kBZAF0N5/mgn+vY5mrv2H +9mAF+w/G65MYEKdzwlHDoBr/BD6Pa/gHkYhGBBgRAgAGBQI245USAAoJEB/o/G8E +JZZ3CXgAmgKk+ky+Dd4BtpS0Dc1eoDHf6d3YAJ9v9phIBW9wpKK1sHVvvsH/2E4X +tJUBzgQ246f/EQQAl65ub9rEKS7XsXwNkvGtj1K7gnql2H1bJ5GF9bGCWhWmB8WF +tsAy9XUeC3WbrcuWFgTsbtTfXZ5I7j7HSG6ukf6Ycusb+bA1IoT+GAQGWpFeWoXe +16wXZFl0pEc2iUnx9ThtoQF0fO5YlbvHJPEQ3kvoqcdb52WOOfOuCAJxc6sAoNqo +5w0YxgJ9jkj7J4cmR+OFUEKXA/wO0jrvYE7eiZeFUjGNiRotxzhTzh53rxtz2/DW +G3D+IBFOt4qqxxp3WCSNO5SnBZWUW50hDkhTxS7jSmsfPBmCinmQ6EF5FaFPyLQB +q0uKwhMaWficdrQS9syXFlPuzQ5jOS3kVAxOmtDd7CMTC8892dj02qzAE46QNNUI +91kZXAP+PINfoJ8hV2zvlGZ9tVlo+Lgsl1BOvxvEgmYV14gyTmMWga5sNq7TdMdW +i8Fz0Vy7sI4S+RMJ96rMws2iTzWLi2jGO44itoWttCwqmGJmlSWurRsvYhSBgvNC +LXFGGaQn5ncO1tqKnWSDf625UnAipsgW8P4Agd5qJZiwXfJ67Hj/BAEDu6tMael+ +rX7E/usFH0MyFQczfHWCg6VkC9TYfdLwbBVtdcq/lugvQLQrSnVsaWV0IFRlc3Qg +KGRlbW8ga2V5KSA8anVsaWV0QGV4YW1wbGUubmV0PohVBBMRAgAVBQI246f/AwsK +AwMVAwIDFgIBAheAAAoJEAyCDHHSaZMTQPYAnj5F4su5N516+dcXYBl7cLVDPp1J +AJ9d2mO76rlmINaaTtH5lhApIjQjEZ0BpQQ246gqEAQAkdlSJYfTiZH/CkfV8tnh +I6IDz+SgiZKcneEBnO+hAJottARGAojdbURlOIeZqRCgKpdTXBK7MdHAz4RKFnAA +XPDBZgA5q+Coqn580t/O/AKGb8kKn9n52z9lC8A5KnHaRAsOKVyPTIU5vq6FLmsW +mMB55iz826Dk9kMhV7mmdQcABA0EAI8Jq3Jnqf0HqqaX7CZuNKHJgag14bTaBw0n +iZK0KSB6FBpzitEoyst5JBPCl0ayQEw0Hn4jhZAqcZybI//pC1CNQBBO47VUi0y1 +UVjExtaNmmWxugzkzWHHx4WmyWsCQwGN4B9riUws4g3dgC007l+aonKzj5QEo1Xi +iMNTFFmP/wQBA7urTGnpfq1+xP7rBR9DMhUEbuQV+5mF3JEYDt0dr9Ej9Ccl8GT/ +tOi0QsPNbtaWED6pY70iZMVJSk0TG7pZ47FNx8UHI2bJKWWjCF1nuXV+mW/xLMM1 +GgFMwK44bX2IsEJVqFjB7alBd/uj0ugnj2feFeTao2xDuSQ71IjGy/lFtOkcdJOo +v7L4tNh2/8ag6bbuZKiIRgQYEQIABgUCNuOoKgAKCRAMggxx0mmTE4+uAJ4+Jbld +pmIpRDEuE8tFCnHacQr0/QCeLU0G5RaI4jZI+QUKtYiXq0ITUnGVAc4ENuOVJREE +AJynQGiC6MydOFemfhSMEBGP2heBBaySSHPrnsBe7pGZf+7lGaksaps2Y26ooMjB +RsmyUjGuk6cDdAShuQiXtOEf5lQiEbM9SceWF3szd1BbDVTRN+kfJfHcVhvsII9p +utILuFZaHXKVTHP5EYklIClH4P8Zj50Xt0iWUpRtpQZvAKDXP6+Q1vOqJtzB1ivA +KMob1V4VrwP8DnI8eoH00yn7c6UAYThdFNHwt56UAum74y40wYUIwt1l+a38CajJ +q7nUWxDtbBas0zkD7W/cWrTHlak3Douvsds313rOJ034vS4Ktc/B4RPy55LcMWcc +j3jl6l7vTdNtyMkE7+5gufQtcTGZODzjr/VmVBs+AvObNv/YkyQn5DMD/jEVtEvZ +h5orK7gmOkw1RXNdiiBTCD0plmr+oFumwgAPsCB35nEskejB4i1doLSdL0LqoMln +3k4msT6H9O3YPaWbFex5NWVIRJpaHjnH2ZsLR5EYVhhGxLHfPSFjAyZcDSe2PSWd +0Lyu7weNm0Fb8oXRUHRFx9LJb5b7ICrQnGjm/wQBA3NCmZyGwaocX3hYb9Uj7Whi +UDisj8phP8MH7MdcGq4iXYpmhRF5vJu0J0tpbG8gVGVzdCAoZGVtbyBrZXkpIDxr +aWxvQGV4YW1wbGUubmV0PohVBBMRAgAVBQI245UlAwsKAwMVAwIDFgIBAheAAAoJ +EK0bD61DwtDH1RIAniwQsiPwhnGW+TCqaYQxe2bWQiFCAJ9kSky1OmRFtP6sQcyy +x6LvYkmL450BpQQ245VIEAQAuZli0/vYbs6h1HhF9HbvRHFMePjQ99Sk8h/dTx7P +I7eSqMHXYh0PZghchlbrMSPnemxfwMbJrmdK9WN0Wh9BJUe2ycH8ftUcGRo5CdES +giceziF6Vg4PQz9FlxtEhvrl7q8R6y7O+j03QAJKUGwBdt540oZ8YYKiDvgZUZxn +oecAAwcD/1b2fYzAnuWrQZXhXQQ4cNVxMBVFKHScH24oFVbuEWLgM/tdgF+CPw2V +tzba8ySR1K80VSgsQfs6n2wyCVd+II8lKHTZT/pfICFcPJlHKs4ge+JNn1IcxBAi +q0QRNW5hGTO9KdJ8MFWrWn2Bbp5k32roAzuCagoielFo4MVFZTsN/wQBA3NCmZyG +waocX3hYb9Uj7WhhNmbxLh2adi8RjvsHqFo8xA3mcKO5up8cYYgwnFFEb8gfNerS +02Lh+6ygsgu1VtSC1r73i7OCeytQmplt+bCsh33pTnacbzZkyEulfjWVn90tmi4K +v+Mw7S68X5ZgyM7Th98F9yc2R5C/SntYMfTNlmO4nRqhTAEz3HFTeVhODOVpmLyI +RgQYEQIABgUCNuOVSAAKCRCtGw+tQ8LQx479AJ41i0UNeuvbU1mUu7Q58B6U8Ezn +UACgqCWi5kbR/j2yb20eDUZz+fCPPOGVAc4ENuOo3REEAMFaZuaYHLD67UlMCLHG +Pk1dFdAn3Mu2TFFDUYfEtA/JDOiNZacPiQSZ7zK+wVe66Vs9fzNkyeXqpwLzC35v +kTx0K1m69Ave9LnXIZ70zvpVEL/UeCuITRiocxNglPgn4dyJ+2V0cWJ36NGcZmkv +BW0vGItpYCbpIGLzYVOfiVUbAKC2Nze79Iyw+DKU9HI39B4fz85nkwP9HbIb9z5k +XiRZyCaXOMnFBQ3bAZh4Og5ZQxdLyZ/rIX4Mu3DGjqg6UtosdVNHr6ofZWHPXNqq +TUivoUmOS5Qa8dtUW3YGa8vbpK1OMnjMLhQVJZg/eou99s9OFP5GgPh5r5Vw/EYQ +Z6qzS6YiYnqzSt5LcolL2+Ae0ajXUizic/UD/0TNXtCRfkS4SeVSkZXarb1oZjHd +Glw6ENiLGiA0e5b4r0rByW4EQQGZPvg3DFXMjqp0lVVmfmXFPggLkbTP+SJ1/VGS +C/wSqPkMiKSCenRqwHwWIdKxv7f13hyeTZXR7P8uaSddSXaakqmT99v6pdZOo8Ns +VQTx3PzPKpEVciPB/wQBA3B94sZ4BXVUUYZFifR1y3VNINM8s1ZkPHDNwxOmQwK5 +PkcxqfpPpGu0J0xpbWEgVGVzdCAoZGVtbyBrZXkpIDxsaW1hQGV4YW1wbGUubmV0 +PohVBBMRAgAVBQI246jdAwsKAwMVAwIDFgIBAheAAAoJEDfKtR+3kQP4ilwAn2q9 +qdnkpFPi1neWFi0OEOr5le7lAJ40e+wQHgKIE+Fn7sjYQ0Liwn7oip0BpQQ246j1 +EAQAp/Ccn5EzxXIGljKVKZ5Pp0xJA3uBoQBvXzu2pU4HU+vmgwnX1313x+4BsHVE +bw7+lfyhKnDD0TSwIAHj/xeE+jraCTU8X1iwe49eAyTaWF4wTyTzdZKQ9mrfBnFg +dWlRjLALcTMJaOE2Zasn8wgAEHgi4QWyBPS1il+aFE6oizsAAwYD/RpvJnfv8Vqf +bCxOYt7meLfTLrvcPlGNynv1nEgNgjbYRGIRzbXDDz+jwcLc9MeNuZgtaXvUbsQ8 +s0X1dP6vq43VmQTQPlU1TQx10o+YYn73ptyhbwOkyIDGmyf6uFhO0+B5/MY0KRLC +xo0lwMxvVkYNd6k804pSJPqwusWBm2R0/wQBA3B94sZ4BXVUUYZFifR1y3VOfk4w +3PRZvIRE/y8bsqADpUHOrpzhg45mVJx0XUD9jUsufCzZg7wHdE3KlnZW2cJ+HHoh +up28Ie38bbaUVgfofuur31BiAVojpu8KhTncGAMb64oNfdRJapHzzBcuUigQ9ETt +6OPgUE/thuHws+GpxQe8KhGQcVfJwuRernhyJhW+BEeIRgQYEQIABgUCNuOo9gAK +CRA3yrUft5ED+PJaAKCkicGM/NGxdTvpyHhtVSSkTRV/6gCgsnKOr6ziNIo/Bbdf +RfYDd1dL4lOVAc4ENuOqZBEEAKLUF5GqBMWJQtBs1t1Sp+NIOGuMLgJOhINbMU6t +k2jzeUt6ooNd+c8P0TexsbSETwhrU4ntpvIISb7I8Twhcled7bi5KCABJOzz7Fw+ +Ydxo5Yjm1DQH7+gEtPx3n4AjZUfRAN0nqcFizDpRYPqVaN1QYiGWn9yPF3pubQhV +n8zzAKCpx1LUlQl2e5t1YJhmom2qy38EeQP+IB45FBfDf5KKtyS64alQ0vHYIssU +p806PQorw/ZOuoiscUQj/WeZ4vn7rCdu60uR1EuHpGp7n0t7igEgAOcxDjrxJmpg +SdD79V+oJAFLATo2msj1IklVvJeI7ZsImyPchIU1lqn/GvpAam9N+FiIB1KUMFqT +Jzc6zUn1Qqag1w0EAIiRHPYRW8ojd9Uh4Ed3X0daAnClyMWL82t2bj/bJRmhupQn +4aVJ5D0pFB9izTiJEWciHpqiMdsi/zExYYIDS1Zu94+WFbNIxyMFfHrJ5fUQtAqL +b7E5LrlxZONUnrRwshqR4X2TmW2mz1Wop542eUQ1UWp4Gr3VlH6giswY0CnQ/wQB +A5YOFNcg/BY3BMnzmbEa9r4DVqdF0faqHCAPM1GU/o1rZ++VSNJruLO0J01pa2Ug +VGVzdCAoZGVtbyBrZXkpIDxtaWtlQGV4YW1wbGUubmV0PohVBBMRAgAVBQI246pk +AwsKAwMVAwIDFgIBAheAAAoJEL55SFK+XPiG8SMAmQEeRej4CyoP+wmpdhNm+c9f +amN9AJ9nKsCqRWJ/ufezi0YqAcbgbaNQ5rQSTWFsbG9yeSAoZGVtbyBrZXkpiFUE +ExECABUFAjbjt7cDCwoDAxUDAgMWAgECF4AACgkQvnlIUr5c+IaZ1QCgqGtz7Pnb +id5+UylHAn40bwpXE7EAmwVmqbtsG1iWWt1xOo2oyTj0t8E5nQGlBDbjqn4QBACm +e9aNjmsy/D0vLzEUvj2kaMBgVv3MWKO+Abi0yKsjdP0QEt+UosnybgpahGhPZ42b +L8kYsfJmO95pWHxN6sNX67FmQQa+/vTafPw04SVBOMdYejLSfqmhyLoXGF8l3Vuc +6MMraZkS58RA1KfY+EDjqCMItFMA+7AumK1JIvm5uwADBgP+KP0pE7r38nHf5b0N +lDFYhAGIqdgdWvW6zZal2lNXiOkKok4I6AH+GUGYJjULX+2mwCPUDdllqYlFZVmg +2iSRF4i1ktd8ZpymsZuaaNyDz2AUzlXecRQ0JT+abYFBannyHg04K/rR0avkYCoc +PEBK0+TfzzNvER3IWznsI9Dhkm3/BAEDlg4U1yD8FjcEyfOZsRr2vgAw2DSsek1W +QcJVSrTcrl4DmC6JoYKNZxcZxkz+azXGMzU6P/gruBQX4ldaWq8ObvjrdF+g032G +Xju9Olh9Wx82E+lc4O2K5kwNe0fveQQG7vFrmajyXnIB4myEx8jSGNcEUcl/6pMm +wjzIOMcU1lPVYNkZU8cFQpZHJ2dY0OO9MXpawIhGBBgRAgAGBQI246p+AAoJEL55 +SFK+XPiGkTIAnj6CpWQaP+vvx+HhzcjTcL/VKlZQAJ9Nk+d40+pCqkNEZDcV/xO6 +vXHbbZUBzgQ246rjEQQArXimh2e6XDO0Lo/BHPEsdHyd7tDXS7KOcZ/RJOBVjCwb +uo8O2/+SowdlrVzmUlihzs3k31AMe/TTCiaw/Y2Vv9JBABVXmacGRdZfHwbERC0f +XMQGoxN0bxZIAmAIV7BdSZ6PqolOUzb2nRlOEs5j+Lzp546yFk8vN5rWYsKBSHMA +oIGmmgpRPEONTciH1bY0t3/jZvMdA/4nB/bsDN76QdkFdvSCAams4Gha+7waKIBa +AJZWgkGzy4sh19TJN5BGYOcXsJg0v7VOKxqo+1HC/TpWcdSAg/HKfNMjWH6COyuV +zOrGDjJnyTkRjhLKjLaGG6N5Zbg4A5INug2Tcp1HhR2UayFs9nCqk7mgd3cNPZvL +CTbrN6aBLQP/UNSg7Iyj4vPtpFMyaCt1etUIJVwFQ5X8yugeSjhGehkf4F/TObss +i40RMmxUkjT5by0ddfpleBkeQHK1UDphNEKRcqNTK/rg7G6sJMxEb0ata+aTsqjO +Vj14ZV2uaKOJ2tXwRF++iBMyusSFRtOxpzZ2mPnZT4LC6uCPPgNtGRv/BAEDsc7Y +SdD9O4gyqEDz+24vfhBH5b1jnJJ9MOulZipNjfbpG+Tocn1wYbQvTm92ZW1iZXIg +VGVzdCAoZGVtbyBrZXkpIDxub3ZlbWJlckBleGFtcGxlLm5ldD6IVQQTEQIAFQUC +NuOq4wMLCgMDFQMCAxYCAQIXgAAKCRAlsA/UMM7GhJjYAJ96+gRNnRtFX68Wbsix +2VqHsXeLugCfVbbEonL55bC9BBQ89XY+6AFNSgGdAaUENuOrHBAEAOGceVg3PC6F +tgrZrnofohzWnui6FVBzeai1DZ5MMKmdN6/QMv1eeHoMOb33fbfhwA51n+kPuhap +r6QqTzx62RGA/gK1m7vjU2OfYxSO65GN/rSUXN/kE83jR7Hux4MocRXZ+/8ngqL7 +JAjw1LZdJyOniJpeRvrckPNC/bKaua77AAMFA/95VjAjJIAU/gOMwtbqTgV+cmHe +52Aa1CJEalV88yKG86nnqHuL4xxUTTZljyjbbKleJD/Ah7R1BxBhSEDy8WuTuonE +VHVxTcL9Yig4pZ/OzYZf5fkl1eLNaSLb8XZMT0JbP02b//OMpAr29lcaga1o1RtW +vrlUyIYOTm2RcTxkf/8EAQOxzthJ0P07iDKoQPP7bi9+FNgB92LCXMeilHSPeArG +JblD4lyK8pp+jwjSCaWJrWQO/OJJOzhTh6Betn6H6C6bapoEaQ8TuKbHEnOMUfax +tx/yzDtWu4EWGMyG9sSPjXRr/lChDsi5OMcYnrxK3foQYMEHBMb1fIqqtRZmqWPc +FixNLKLjBalB2cMRuYaY8o2V3ZyKiEYEGBECAAYFAjbjqxwACgkQJbAP1DDOxoQg +5wCfbgzOK8WkgR8iruUOQagMIqwMr6gAn1iBQ2TJM5znLHzYgLX+D0k5IG/plQHO +BDbjq1sRBACVaJ7JCEOyjZmcPbBv6CrpqqTWtFSFzB0HAJNuITVosCye4yXycsfh +++FpPPZX8B6OgvTR7bx24Dmiv0mIF+ZVuWulMAgZay7QBTq4RCxaBnBF2yjc0f8p +8fxnmXHAm2Rn+GUCIQeiGYagPfyYk2yCebrdFdp1QfvqKs7oxy9aVwCg414fuLbk +BysyiXg7sFnCoarbmJsD/0hGErsAWF+BpGsNPPzg9oiyzGnV1YpqVGu4wlgZArYs +O4SXndD53WudgE+WI9uNav/0aSPHcrgHQJ9ZZALSxSXvts1EWqvwVeSNFly+QKjH +Ecbs8gUbvust3ZKJD55L52nlCKO64wLyySS9C67FLp4iTSD6OMaU2GO673thrrF5 +A/9nF6Tfunw/W71NOY3uc+2XMZcat8pWL0O0nfUTzTmu5cWpO6gV9w4FGu19j4M5 +5tfxHEjBBX9MSbLHChd2aS/TcRjAPoAlKbHda5WLn+t69wf2d9IQcPLuwULwIGnh +pq8AVFA2uGiZIH2VKblyUYtmIPieWMXUQUAHBAVyHseGU/8EAQMb786noBSUDw4m +7xGDnWduktairbapLv/ColtFylU7mo8tzwPJ9N6MtClPc2NhciBUZXN0IChkZW1v +IGtleSkgPG9zY2FyQGV4YW1wbGUubmV0PohVBBMRAgAVBQI246tbAwsKAwMVAwID +FgIBAheAAAoJEF9jVrptlzKssC8An32a3EYMFU3dvYtqymOZk1G6qdElAJ9XrILy +cL0GM22u75KkQfVlZReszp0BpQQ246uOEAQAnQtV0TzPQjBa4FVL4qFO0koX3y54 +4FgWd4amzmK7ILV37kHb+pQIsZzT3Z5P5OJoy/MNaam41Jn5m6aVQ8c7IolEJSWr +cxg31NYA3O5LJ16Rf784IW7nMvBzTtEh4t7jPxlwue+ImdaMWvwNeHypwlWE9U4a +lGtbrAuWEFx5uCMAAwUD/3+C2YDd3Wy+Iy6lxwzaQCBI4k2yl8QyhzpwKH//+EhN +JqWjVRy7t58SOewrV30iNpDEEpv96aqUys2gZTPwmzACVGp4ZpSzwEQ3Cf4UHA7Q +bBeZxRu83y33tEgcILDNR8S/evFb2u1rG2KUmvfPtx0g7svVcKYRae4uB25wm0iu +/wQBAxvvzqegFJQPDibvEYOdZ26Rt9GjNyo0jdE5rAxUvk0VBw7TW+V6uxtqp+fK +rP3W/ewR4mUXo1jq29kicdAtO/nI0uEWiMuascrL4lCWWcrEK2n4AX7KbzJ9W3HD +upQhHHwYga7LFg+ZAc+6m9k+cn6M8SycsbQt90IMqon/jpYnSialNZilcMpFfYCn +qBDTVKpBReiIRgQYEQIABgUCNuOrjgAKCRBfY1a6bZcyrA3hAKCPwFgK2ukTx/0R +6o/BN6HFJh7Y+ACeIB2LqEi2uOknmyef7JveVqldPTyVAc4ENuOsQxEEAIQRmJhs +JniNi/bRff/YGrZ9aFWt81G93W8WhV51qq+ntUHgUNY55Yyos4XLOa2tS+K8zP6X +15FesVBPYIQa5BIC10mAsLfJ+1rbnGJPuNBA2U2MoEaRxo/JtXQ//5jiTRlYwLDR +nBzuaMCPdsirveu+JBw53ytRwjwe7m/D1PPvAKCp2dj1FtDjubTN7kCF0o2KzPwE +0wP7BimQxXyPwSzGqLaHXSEBsh84OQTxPI98BXgq0195/A1B1/pPs356euKlqoef +UTHYhbjiMYbjZT+A6juudf7A2Ucy03G8HDZ4k1f1vmzrj24+6ygGBcxTVr0Bawei +C1DwG3LjQoJ1cuFxRQ8BYJDGIwPrUW5JdlnzW2bJWfdyXOoD/0S7iEVN9txkSKil +dOeP1YcDCD8MM3hvF9kUc+1hbmir8SOZ/IYJAyQN+j+mYWsLuKtZ/F9pqiBNTXH2 +jWCTqldOD/ZYxHVJAARnkiVG6yckMLsxHi2LPPBK8xack0y92mKe7za/7fhVgCRS +s7M/rzUbzUhyInHSyxr2SYb+8lbu/wQBA3vncg3S/0EKhZRFb/E5MzbPjleeF5fQ +n4SvP7U30kDoHyI3LH6KymC0J1BhcGEgdGVzdCAoZGVtbyBrZXkpIDxwYXBhQGV4 +YW1wbGUubmV0PohVBBMRAgAVBQI246xEAwsKAwMVAwIDFgIBAheAAAoJEF0V4B0/ +8TIG4YwAn2L7BGoJE1q7g/ePfsIhAc0nacGKAJ4iBZV69HtWtOryudH1sG7zEoaR +KZ0BpQQ246xxEAQA3mE758SGpbalfvWhJSpb9NEdZJvJs1zlutDW3OBNuF4eIb8t +AnWUeO1mhlCzJbcf958S40BHCvKjgiO8rSeaJCyplRHXv3ldMhuj/Bo83TxC6MLb +q5ZsvWlgvnJBqvBso6jICy3iOATU2llVz+vX5ZSns24RqmJxWO8U3OSJUIsAAwYE +AJZAliv6HSjOvslD8Gojy9Mq5Vdv4MgFCO5LM3su9qIioypv1l1802ZnUC2+SWjY +J7ZUzKWJDNVJNm4clBt+sNMFcF/5D4Ag2Id1kQCh3MG8O/qnu+xOeg/4DZtLyXrG +tY5sq3crL34ZQOSpbda5qBxQqiBCARv8Up5z4Z6DBKBR/wQBA3vncg3S/0EKhZRF +b/E5MzbLEL6CTR0ywkrjR5f4P+KFRNbVixP74rOGEYga1Uy8PrUOMDBIjbtKVWQy +6ly4hnMv7ZPtIZSJFpeofg7k/kTNJB0W0BcJhWfg5CbiWncJYH+IZT6+/0aJfmhe +y7gMlkoXOqH7y1MlLXHLriVzNOpapAK4Q7vwzzfRL8kXP8zC+u1noiuIRgQYEQIA +BgUCNuOscgAKCRBdFeAdP/EyBhuTAJ4zaeXrBSUA3s0m0MV04WJxDDGwWgCeKwYd +KMH/CO2Eaetd28XWxnxJHO6VAc4ENuOs0REEAIHCI/xKPD6yIRGsSnI3PXTW/f9A +WdwcQZO8fWuxypuqNP73Hyx9lxYxcQeA3X3vjtTwvSjVKiIuhk2nxm8qkuO17Jzi +bOZ77K4JlaVFMwHe6dHcXHNrSaHcIZB+BrTj+IuD/Vwa8Z4EK1kNI7t99xDxesC1 +ou6pFchhDQn7L5LTAKCmIDPl2IfVEHu/x19Bogp5NxMVZwP+K8gcXcgYoY9NourP +LwHuZpU68L/OboKLkgfeVxF/Bj372liFv06VFkOmu6PGM1P5CD2u2MxE2F/HvxVa +9mXd9xwH3i1DadzktDbxG2CZRg31u/1+6i1b9aOVgowh1ISvAwn/QMfW+M+wm0R6 +bcUhOFO/TQgjrF0LDm1dvKpRrBUD/iCGgoe3U6gA8P5wZn7l8XqTyl0ul3YtLaO/ +S30La/k1LSThFRiG6qkAbIBEhYk+akdFu6oTp5eO0yEMj0J7f1ffeEMMgBrSILTO +amBUVu9INRZMg0V+ez80zLlNgY1SOph5GlJC2i7o20V4kBZvCFyeK39vexqaSrko +LzXK+0Zq/wQBA0GK22cdg+tRJk3gYcN/JjZjdGbyparZK4zFc6L9X+dZtsC9gBVh +D2i0K1F1ZWJlYyBUZXN0IChkZW1vIGtleSkgPHF1ZWJlY0BleGFtcGxlLm5ldD6I +VQQTEQIAFQUCNuOs0QMLCgMDFQMCAxYCAQIXgAAKCRAcZ+wTPGYchNG4AKCjSqAG +ZAKs7NstyNXe0qmxdjqhgACfUIFuQ0RAvRxngnEfGZJiTL7vHBmdAaUENuOs5BAE +AJGi4T/jrY5BtRTM0psAneQytzzFgH4+LigUXAAb0QDAOkyGNfWHrfHJIS7A3Nc9 +pMWAdOjWgSKbYyrzra0SQ75/SkI5+/S5ev2Fpki+HYo7cNgVXnbCJrIY7k4DAMun +qPJ9JCUXc88WxGvKV5b45htqCPnV2Pgq+AEIKD5aGfLjAAMFA/9+O6ttUbeY2bQH +RdThl4HUxQw4lgYN7stgGZsbHCc0y6ln1HF9vlE4Tl6HI/NR/8OauQrXt8988dh0 +39QNZsOdAeRWTk4PgSuXq6VDG5WNw6B9bvRPKXe5yeVmNNl6KESBzMcq87kANZWZ +68vKJ2JihxPHRAyfxwGr2JKkVF0S+f8EAQNBittnHYPrUSZN4GHDfyY2YCjm88Cd +mfBmhTozr+i8fBZaKPsQQkAz4Ybhdf+dCkGOyQjOvI9qUX4wNF1n9/2af6a9A9TJ +NYGpdQ3AQUyyH1AXIfYLeZhAKR8oHgP3r5L4DDGmyAG/I47Ziko9nyyRjEkT5B17 +n0HedUtHH0+v6vtjNc4OA0XtbY0SCvuFMpLRF9guiEYEGBECAAYFAjbjrOQACgkQ +HGfsEzxmHISIlwCfZ8SYKvVQnWcUbLR4pdAC/SDm0XwAnAqTsdVw9qkF0c5EwGns +st/qiAqalQHOBDbjrjgRBACU0OjVoC32Kh/dUjXPdN6HIusEhHheYpFIzYHHTYJm +FBEjBj9CwrpYGjGUmp+BS2wFS59zO2MlpQGLGrmo+YGBdio338Hwdm8baeScd2Ko +qu+oWkCoBMm2VxxbS3M8kq0ppNu2Q5EEO/qGywVrVpfBM3siM3mcsjVaHyWy+T1I +qwCg/lnggNIr+Yz2HoU9GwCwBi9331kD/jRTBAuXTq7vAG2bGpJ0X/zqSMLSRZfw +nZj28hx6I0SIT0yZU1xggrAgzSbB24XnQSSxWMR2BZQmupPdHO0l8xPn5KCbYo4C ++9+ZsprxEXg09KtVcMOsV6qTq40NPSOdRRNAVhOOTg/GD0qX5r9ztB57qpefmp4N +fy5tmo3SehfRA/9jkdKCLrZRsE/kH57kGoT5kt4nvJW2X3T03BMKvspVm3WjdlrR +0Ji0yiw9P05sCMJqeFKe4RZreG6i606CitZpRIRbpjfMEq838zgUDv7VGF7zqCed +Yu36sepfkzxj/slNyu6A21HTgMWxiBrkDXoIuxMPFKYzZGC+nCHXgW2uof8EAQOP +MKazZfwtUoJ7eB74i789uCp+H+yM1KROCEcmSW/T7ago8wfbaRdCtClSb21lbyBU +ZXN0IChkZW1vIGtleSkgPHJvbWVvQGV4YW1wbGUubmV0PohVBBMRAgAVBQI24644 +AwsKAwMVAwIDFgIBAheAAAoJEDvb7bF3f77Tq+AAn10WjJmAMcn1pBFwE28eIqtU +z5bsAKCoNi7oa/HFVQZRypKR7SChjez90p0BpQQ2465mEAQAiea3rOLV0WY9+rOz ++CmVlH9GAvJrS8cXjRF3uXJALZ/IDH3EkCeDHouDtRAb6ymfQ89vBJr9BZg3eug1 +HeMm0SJNTzfJFq8vVLhiwH/1QQJDCMl4WAhJwe8EbDY+JBeQ4WIsrXqdsHpD6HGT +thgFKCMmNsjDW9ptoNivFJytkAcAAwUD/iMYod6PvvotNl8IuMDnu2q6NsUngZh/ +W/JxGifL/EVS0TtAIKEeBi8ynkzn7+exVOPLZWO7MbYehTsXiWkJEtZw9S0aW9xl +A2a+6jP8jhmKdFoXUYBlvnNHmGt9oOWo6ts59/h9S+Mq5kUmTOJ5meWV3vYo5BrN +FDWKpotIAWMa/wQBA48wprNl/C1Sgnt4HviLvz27SydCgapMV/zUfdQL64nYYQj/ +00crVG3e1cAN2iOPRNsjnczkYXjFfSxTxoVvQEOvScRoOF1LQ6doAGGSJmSkyIGZ +wxb4VLD8GhqmCX30XxOcTRG6EiLq9+kDGL5gAnBUTviRF6Tc+y9N79L+nxc4lawj +36d0ZXeIG2fm8RycxA2E4ICIRgQYEQIABgUCNuOuZgAKCRA72+2xd3++00nRAKCQ +vRyQt5pNoWbpj8btfqGK00jpOACgjSITGzCNURjHPCPEBAPqgOVDh4CVAc4ENuOv +BBEEAMUtk4AJiXP3jaKpIhbi3B73S2SZ67rKzBkicjelpwWk6LndsCrbLsIWsDf8 +fNtih0r9As+2arfApkNlwuCGq1ZlPGGGEf18OqPxFvnghVEbDdcosP4bIm3k6G2s +gFbMl68xAGnTtkS5Gfz43uTuznPzdZnGbIjP0uBmPfZk6GW7AKDhi4htuxr3Y+ud +9lx1bWM9KqUtAwQAiRYHm605RZVBkdzlfYx1Iwgn/l8Chq3MsPrfBMslapBnq1an +2/nEQPmuIde9C6ALN1t03DHpKonx2XgjYVz8pgty2FU7txSSm2EE+975dXp3ov4T +fD1KxksOl770PAzixLfNhPW1q4A2cEruGgO74qEX3/fAa1J0nRKDgmA/mgYD/2TS +ZKCaFHoc3IHQnkygmGzzZNpVZV2+1kIB8Z2hNo9V81PYpzlYV8SlG51ajW1G3ePc +ti7JOIP6MquNUbYR4TOzZy1Dq4+VqqZCB6fOeIKL40IKKAoMMDYFNLp9zcT+s6+6 +DTPH27eE1WEt+NQjBgr2ofC/4iAU/nmAYmo4xn7Y/wQBAw1YC6sO6OK1YqygeAug +0cwEFM97WACPFwv/yo59kPUn2OPV90GqWcO0K1NpZXJyYSBUZXN0IChkZW1vIGtl +eSkgPHNpZXJyYUBleGFtcGxlLm5ldD6IVQQTEQIAFQUCNuOvBAMLCgMDFQMCAxYC +AQIXgAAKCRCl5n9/o64+oa9/AKCaJbj4sc17CLwMOuvFVejk4mwUQQCfcrpQGZox +97B60MgQRs/wklSEVWedAaUENuOvgBAEALhxyR0+JaBA2Qa8CberwXHNEuiDrz+N +9++Pwy+375dDg2KQ7RUnx7NiRV368be/lGgdMhLKeYxZlmNPnpoUNINk86RCzYbS +pmAASBOnMJQF2WdQLxmsdJNJCMKfse1HZylgIJQGWI+1q0O9Lcx7Vd1F8GFeJvTh +MHRyLoOvMVCTAAMFBACN7RHUg2b0aRkoDNMQKL6VV6LvBteSfgkXqf2vUovmhQtU +XxoYc0QnVPCPuS6raRpxiNz8OLgp0RJFNk32zOVmc2u68B30kociBt7Kx6d7fJGH +L5gVqpebUy1YJ3DBoOIOgcMBKmXnlG24IrHPq5bvuqGtnwToZEOuEj3ZHzwNuf8E +AQMNWAurDujitWKsoHgLoNHMAI9CpJsg3p5r1/2dTbN+h0CJ+lqHoo70wkoAb+ga +M+7jq/FWce/7mNExPIYobdgkvZ2rbKJPx8o0zJqu77IkMLTb/eh8z+dEaC9X0S/u +YgN6AUJl/DsEU+XwOd+JY8Es0wJda+M0qvSGaH6+kTYy4pO5QD1BrfdPTOVNxcFn +a7HAItZPiEYEGBECAAYFAjbjr4EACgkQpeZ/f6OuPqEzHwCgo3fuvctqBR1zM+lG +iitaCcoRH98AoM2iZsG2q1yiU3MebUWDxcPCiuRMlQHOBDbjsAoRBACQ4U3waYeR +udWpRA1GiHxbw9CvqFw16gwe4Q4N7LVSKWUffXdm6P3TzrlVqK8FxQQyXitHO4iR +EKzFipcXam0RpB/KWhUpy+V1qOMTI5J6pyc2Lt4G+9+IqBR0wuFgzNv76ExrhaS8 +Pnoq1vsJddsLrB6ZzZFsTBCFrdh6Bk3q3wCg9yVAa2nj2/IByp1xc8hLvES6d7MD +/12gCo3vjQGHqoXAKsb9khD1I/BDILV+0g5JMg7/MLkX3DcDALeF8B2J5zN26VMF +o9iXAxhPa7DZ2vx7hQI8/9pa4VCp3B9AssL44WLbdbfdo9HD2Wnkd6WPEf25vDbN +tLYj+7sVZY/rMyNj3+SolB4YlhydkU1xhNqVJk+lBYXNA/47smbyDSsJG1EksKSr +7KIteXenuFseT2dpgK0+cvlC4rQceFiiLF1elFVWhATWgXut5PXBRnTxG2vx35Un +e+pC5nEncvha+93d0zCK5sACjFXSo0QBHN5fO2Gj3dvy3U/k1swkMN9xKLXsSe8m +c2QNkicdu/48iIF5FrcL5+VAjP8EAQOkqTnVSVlDNyanmeWCbHT5y1XDf7flXnKw +AlPvRhV71WMkqrgQyZSOtClUYW5nbyBUZXN0IChkZW1vIGtleSkgPHRhbmdvQGV4 +YW1wbGUubmV0PohVBBMRAgAVBQI247AKAwsKAwMVAwIDFgIBAheAAAoJEFjLmkyF +qB84JOIAn1w8JVmBDp+6A35ia9SqWpt52ZiiAKCIHwczU5eSjSlPSm5W8C7dlk+B +CZ0BpQQ247CeEAQAnr0w2OcvlUX7E8u2C8dJGIj7wRU5qDazxh0tw55/ybJ3/Kyh +CFfsr2dZ2E7Zw6Yvc1u3WTTf82nH4S+/IJFSI+qBi3TrcwVtt8Xa3Po7cIzNvS0b +BhqfmOOXJc4ihUlADR2Jukm/QC+f6bO8IZBDWr/7LnT4SwEPhPoZNMFb63sAAwYE +AJ2kiP3e1zM+zEo2i2jkOny1Igyn0sRiuw0OXQ9B656zp02G5qtDN+IXhgLdfQqg +qyWckP4BLDJ4NtQoEM/Mr2/7oj3h01XpbU86R1QFQOXmoWw3q7yqEWIwfOBqClSF +0A14sXdjQwadyabTFsW4m8Zn5jLW+1sH4PrVjHoNEz4C/wQBA6SpOdVJWUM3JqeZ +5YJsdPnICDfLPDsLTp+mSJOvz8ZkqbdjjI/q3Kptusm2FbDk07+WCtgfeKcaeJZH +FNDb0PYRG9S22OGNlhDTmZluNPmUG5syMkoyycBX+4RTirp7LNS+VBIOHa6d1wD1 +k8lANIjD/ilD8pW0pAyqN5oJLDgGD9892G7eeE9Vy4XGRmBB6TbFMF2IRgQYEQIA +BgUCNuOwngAKCRBYy5pMhagfOAibAKCS4dbgdlteoklBNH9XU3+trecmqgCg4u4N +x5RLyPVJoOlZhb87WTBcW5+VAc4ENuOxqREEAN621mjyBM5OvWclduTmwl+5VJBo +yZuAulmkyzdDsL6ABfRdf5D+9y4en7BXY2rRLi/7Dkr6zEMXgDxQN/6r4aY0owDl +TbuGRwNC8TjwRhSCFx1YqNZ4XCaYk5vQoyhq116HiI9PiPyhwbD6LTPqj97TLQ5V +axS8iqniJk/dSWc7AKCA6rkZ88kyrcrdw0PedTsY5Hx7UQQAxyAfT2jrwduNvCnD +56M+4rBUVrfsI5f/rkUXw8416V6rsyvdjzIqpssiwhYNrGuV+WlvIzP9KG4N01Ty +CH6ax/CHT5E3N0Q+akkIJUk51k7jpy52BvIBCuIfs/KxJuLsBuamcyXuRCu6EBlZ +cu2cfV7WQqi8HjdremHzAXiSi3ID/jkDxssoSYm+mr9qZjpWMOcazGQOOPDY6hVu +3ywt0aOmBqePd+/LkpGFZ5YsqGa2rji0f3ubhgOYYIdVr8iJzhoM8wy9Q9Z1pjkP +IJ56tU5vck3WosLujnHYcG3xETtxec8mXlUrFzirPKzlupARhi3Z0/hwmoqTc6OM +JuXpMn7x/wQBAwH5EiW2ICr1W3T/Rx6Cb3eG3/JG8Sjo3rpEYlaApMS+d4oM/9V8 +3kq0LVVuaWZvcm0gVGVzdCAoZGVtbyBrZXkpIDx1bmlmb3JtQGV4YW1wbGUubmV0 +PohVBBMRAgAVBQI247GpAwsKAwMVAwIDFgIBAheAAAoJEKlMD3VlMkTWM1sAn0ei +deyWSJxrd/trrimzJpapYrQPAJ99nNzMTsSCQwsfLaq0E7kkkS7KtZ0BpQQ247HD +EAQAtbvtPTT+OnT55+kSbXMy9yxK6Mq3D5hzpNxW4jXyfGDJxQXkk/lPvnIYv5Cs +5vjeMvE2RPLB8Bqp5HiAbSV9mJkCRYSotkUfQLVZ9h1dWUwWE9avz+zKWUzzCPRD +g5QhDyU71/jHbT/MYdBrI9YtcLo0DiQIl3a6rD8Xp+EnIecAAwUD/jUUTsyxauJA +VKYKE8r1syZfehncpH/jtAIW05We4sfSrUC38Rq6s4KNIcA429kM3lh341YWmmkn +OVFjTLiEMh0XLI/ceJ9uVxhNB1MjlUg+OiDgI32Rfm3lzmvzW2HEfs8zkX169asl +toOKFfCzeLOLleHT2pkN5ffC5IPJYVgn/wQBAwH5EiW2ICr1W3T/Rx6Cb3eFuP+I +vpNCP9FJtq/cHx/aNtVczSNEk2ParqkEbsZoGgIF0fZStEWeTda8b2/P8dt8E/hZ +L8YE86A6y26jjzhIQBnThCdlxYXCI+f3rwXSdBJYBu6jvOA6Cp7VJkBGBUknV3c2 +6VN6mF0tq2xw8EdB0Z94SBwIObsUJxUXGSx6F9n/BIaIRgQYEQIABgUCNuOxwwAK +CRCpTA91ZTJE1s6YAJ90NN6PZ4hYojIqGPHLsoXLX4ZQqwCeNI8dzekcdK9ZkqXR +xIfFj4cQH5+VAc4ENuOzmhEEAKMDGobMDqPX3SKI3/W8m9LmNgtDUffHGHNd1npn +GM8mSyVfWjEWoEg2GPMEmdX3/tvUUV7nTz02IJwZRVlrbEPdW76eItMAY1NB43Lp +jQTrAR++mVAslulUY6a5V5nJKEc0IqOuxkW1LWavujX1JRvlBZLeBkdpsVNuaGJt +wUFfAKDfqoZUCcZxnO+dRMalHLfGOn7O4QP/apMk2mc+GJwpKSxXBvoQkVcfuZBJ +mXJuUCc4BUUzHX0ZSKNbgxY/kVR1xN3krMgOCR6dEsGukIsgVWRDj9to/+E6IIs6 +YKhG7fGcXKhE8z8mf3hDLcmjbCKDCSFBT7PI5TkLzlAEP1y2Rtin/Sa71unGZhNy +EfAPW/d1dRcRVqMD/2WcTPUaIjRvAqmbxUpenRhg/mF5rwmHl81VvVBbZCoZ35c0 +edEZKpfmyYbKuz7GhjEPz6O/UWGYZpK/7r6f4kFUrhO5atClnRyBkvmNmdfbtM5h +d5jh3lgqAT7tk7ntPAIh8X8/qm5+Uab63kZwXCPiSR+iEwRp42GbVL7F/b2r/wQB +A+smNbHH+mT2ogDvwebUEYQ5u7AjqZvUWkfnZPKAVQwghkIrT1Vq21u0K1ZpY3Rv +ciBUZXN0IChkZW1vIGtleSkgPHZpY3RvckBleGFtcGxlLm9yZz6IVQQTEQIAFQUC +NuOzmgMLCgMDFQMCAxYCAQIXgAAKCRBHr0tpYfBHhMxJAJ91JH/X2uIsYSrKJmI/ +S1Zgwoz1/wCfdQoDeGHzNwPI5NaxIZH0XYr+O22dAaUENuOzvhAEAIeRQIHb2kyS +94wRnI2IoiaLMXk1n9y/3VGPfX2TfEd/Q0laFCn/UbfxLEuQ8sF1ZygHiYlE2MPJ +WzEVRe9FYUgx6TAvSrWwdJZNwnAKlCz4soq0+YPcsDduFu5NJ2liCYrLbVIfh6m5 +uoHOT8/TX3eZZfMeBIYt5ShOjc3t4FDTAAMFA/wLVDdYasFk06YVWXLR6tyWlBG/ +WoJrvznLH9uP26vYvEfBWjMAReHyOaiIpnKgDPtgWenb2RHaq1WmUfWh483IXB5m +oiO2ZluIJpPixxRVn/cu5hvGAyhQV5GgbiacRW9RSHyaZmi8yZkWu+nS6iNwOx9h +PHRUGvzBrGAmuDZiC/8EAQPrJjWxx/pk9qIA78Hm1BGEOtrTuBDDiXmHnTN7vG9T +7F+vQT/JusPW4EJHYO4E2e1J6gyPEGOqrAsLW97WTEN+LW1bdTdY7dhM4jSI+Unv +ZqZ71xW06WXE2lxGD4ayXuzP6Q0KQT7YcMnrkqBluRJTfGKdjX0RPXt/5+KWd7H3 +VEst836l75/lYfLrbWxaArFjztISiEYEGBECAAYFAjbjs74ACgkQR69LaWHwR4RT +3QCfcsKGxTTd4f5S/liM5MfnCtlAU9QAnia0uQcnuH/aodTQqspKUGN3Z04+lQHO +BDbjtDQRBAC9Vf1MkTKc8kSxfdfZ8Y88OJAr6gHsPUg0j1t8gPk0q2ijyrJuK84u +jzmLmbtFSITKFfcT2VSD1u4qa0iFqzSwnywtRGYKd0gq1eMhaDcp3SmaMTyrbPJ3 +sKFDd98nbTzvnA1tHgZCFI7VZO7HBGgvnd+370lNQsnGRBF/vUDObwCgllBimEp4 +tasu0WNvZYptjGy3ni0EAJLsL9W7jR64h6+nZNkdO1jRT45sW8mvyMOt1BkyRQVK +6G2Lut879t/upPCYK+/ohWaf3TkAKH1ucrBm9xHlPXJHZvoIA3brt/OuJmG7r8Ub +70N2vrZmdXas/w5ru7EBcKeii9pp8pi6mim8dXTPS1R/b7BqytB0dlO9zSl9j7no +A/9Y5UnQobM/qT1tiNhJEnUwlvvTB1UWId2UiUR3k/eNCxc7IdUytanqofXSxAu2 +jyDB5Ymv1od6bRCNM1JNWnOnqVoEd/u2csTAIkZ5fl/kE6HztqRGPB+H0n3Nb4MG +u2mpLq+OUNhTnLpEZsZGXqd21eFXkWkThxstrH+kYVYSrf8EAQMsrHk/oVe3Xf3i +4RPIB3bwsBoWGrA4kRK7mm5a6M/pBLavd6wy89rvtCtXaGlza3kgVGVzdCAoZGVt +byBrZXkpIDx3aGlza3lAZXhhbXBsZS5uZXQ+iFUEExECABUFAjbjtDQDCwoDAxUD +AgMWAgECF4AACgkQ3vD3uOxn296iagCfSizgYr94GzIrMWbc6H1ha7gFOX4An2oe +iUql9DoXgvph82AUGtmv9TuRnQGlBDbjtFYQBADPV+xDMQ8NzkqoJyO+lriAUrCN +IBf1Kbc6U/IPAGOoED1YVPX4EB27u3K/EmRVd3clFS085Dau5rFIr3d/xXnLn++w +qSgQq0Jc7LflMpIj0P209/oKt6MBovTAQn3lNpecmWd8oxiKoPP158Zgm7iLcOvR +Tcs+/p0KAzNvHIvQdwADBQP8CQS48V16lhWOSXV6u3JOukMeWBw6Tx+7M1CqyBih +mR8ZNlF6FPBvVkX0NFVUH2qJn5yr6PmxQxSRnC3yCEyPBa48xqIditzynMbEIkNU +rFZTE915rr0k9MrwzPGuLfaPtr/Miy4BI0dnZ/5U4hoxPwDbp0aPUwRqb8+T9POT +Zs7/BAEDLKx5P6FXt1394uETyAd28LN6Abjx+ozpGMN36+SHvBm1QBbee0EWJ9LY +natmavOGPgEn7HZFbgk/QaUQiMRMNQIEykHjoKU1C5uWEDR+P/wuEYX0+pQ1UhUU +Z8v+/wZjAC+X5WymJmjKW2l4LXfq0RpOU3DedzHl5+zcuhfZN03MhxX4mcTHdGNS +LqWzikj/1HWl3ohGBBgRAgAGBQI247RWAAoJEN7w97jsZ9ve/yAAnROeKraABkL+ +JUAzQwMcNm+0JCezAJ0Uz6p+tN5wt6ywyH09JfENI3F77Z0B4QRDVOPaEQQA0vZ8 +6nCVajqp71XSCfin8OI+gHAAbVA2t0JAH94SELIUTqhU3KDiqg481GoI0g5sbn83 +VOOnV06HyfCoS3hVAw+qPIJ5B9hOT7YSd078qI5N6H6mV6vXhC4mFn+Q71t1ZIjZ +M2grgXBK8gBa9XyIZPrtdI1K6H7PAaWitfJCLTcAoKRwVDiGrW2eio0bD3ri1TZK +Y6o5A/0fKN6cxEMJuAX6hI9QBkdwCdQBYTfnaw6RgZOiU3Yfq/IhwLJe4GDm9JdB +LSv8N9XjpkcsvDDu29ByeL8c2Mer7WQwFnx51MKKaHisWUafcO9QgLAFiS59nTCQ +imlbd/WchiuLkJesLf5KjTcs+y4I1ryjpjZDseGhC49nK4BMAQP9FZ6uNXhULndY +mA8WRs9GGF95IzlbwixmZNkoviIF9Pv4nGT+xJPrMj89OzHt8KCLx2YyVelrLhwO +CSxfjPMw2Je1qRwcDXGKnF3/Nb1Mw9/3TQoRexGz7+SuV4v5EEvu53CY6sYbvRku +WHopzmdJ3nIXNbywNRCse/EzhN+1H2v+AwMCeQ0GPAUFo8VgGOz57mojjJX8F4Vl +X7IYjOVab40guLzkSGqxQCsps8UmWL/mKfAoBYRgpPDRozfnxSSIlwQYEQIADwUC +Q1Tj2wIbAgUJAAAAPABSCRDe8Pe47Gfb3kcgBBkRAgAGBQJDVOPbAAoJEGX0CIjl +GYfJ12EAnRuCm61Ypk5bbynrSpZu5nd7Kf6YAJ0aBGUQSyDxdieKqY+f/U1NwDmi +ZmXsAJ4hJCAMBP1TqRBM2D61RwrUTpVcOgCgi3v4j/k7ojLKcZtv3L62YETM3RSd +AfwEQ1TkBQEEAMpDZC0DUd+HChHrOlHLLDeyA817qeFKDUFbfmAScDCO67CPI7Wl +HgWccQZhTgKdXadyUE1IL9QsVkGZPEv37ijitw+/jZw8mSASE7DxeCMhOqi5LhbR +LMS5zj439oJlk9cJNgF9VEJkYF3KePuI5yJNgeUYd/hZzO3XPvAmggnPAAYp/gMD +ArwKKdoDxBLOYIbNlJluk4MFdM8VaglnHWRAhSJ7aWgD3qbp+p2AgQkuijQxJT9o +wKVsPdRePwc7I4ffXuESOQmOjNF1dLwaJKAr+s8hRw9HCOTUlkBIhqtWnKjegKZL +ZClgnA8M4/91wowP877+Lz5ABGGbMAhvTfPXqzWy8eiGB0FhJe5k5GNaw/jKfqH4 +A12FYeWqLMcl26Yxd8G3w9rYcR6vRvbBf/LqMoRkG0XYF+YCDcBDGTgBvuxG2JKP +UHSRoV4VRXn1onyZkRBG5xdNGC2RPripX/4sVPXBjIGty1xk455XpE5Q0DkiwRfP +IhjZr2Zzv5wFb9bTO1PKlGshS41b0SsWS+ULDYSw6rqXbk3F9aGU0YcwkYhIMPde +tmAuRKmmSlo4b305yr5W62Kn1jKtiJuKjsczpZt3us+vXKCtikb0fyTC4A9dWTEY +EAacZP+vhaLgGEMWr0vfJlB4KhjM4Zk3lLWVFQVFiE8EGBECAA8FAkNU5AUCGwwF +CQAAAEYACgkQ3vD3uOxn2971XgCeL6JojSxB+GBZD6VXXdt5i+8EbXwAn3iwQfIp +Di5nPVvcM/kbD0eIfix2lQHOBDbjtNwRBACtSpRuJVMzEmGnxsDi8xcDMK4uPKzg +DjgMT65EVv0AaxlObD8VM8RM7uJT/d+uXJjJOAi8jbMMXVLAdcbTooXfIi7wsXo4 +IzQ3STsqcqnDwza2Q+JP4PwA2sdTl3Xvx6/ObjQ/I0PIrFIY2UgbU3gwgoW010yV +qEu+73WQbThZ6wCgs9rnMhK+xf4TD3kzWjhC2LyJgdsD/jCv55hHLA/fl5v8XlX1 +s4taFaYQPPDgoddDtX44nskPmfjhLkos8rAiiCiEOU+avENMAn9gC6QClQi13fSS +vRSrfhCAWS0CyqAI/sLkoQzVNPFTblNyziiNQegPIyPXgQK6JMI/RkVEpSK+imCO +BGEVMpdVVZPJKRDSD1INohNKA/9rQXJcxBRgmO4HsYDqvhTpCcgezFLnGtCCSyFv +i2nYxVYyGqWGx84tqPVZn6h7QPErDQ7dgpMf8QDOY16Upwxu1NyKUtoh0jmX5iVq +b9tl7tC9s3azvYqfY9mO1io7dTOrDXhuoAlGXR6SV4x1lEwzMCyi6v6I1U8eeWh1 +edDaDP8EAQPfoYwMXoA+NvOy9Qr7KTriHrsU72UPiLQWJcATcO1+IErNiHeMRXW6 +tCdYUmF5IFRlc3QgKGRlbW8ga2V5KSA8eHJheUBleGFtcGxlLm5ldD6IVQQTEQIA +FQUCNuO03AMLCgMDFQMCAxYCAQIXgAAKCRCJeabFVn+zSrdPAKCetSLKBzw2Y/8Q +OyAc7B4vLn6gxQCgkLPtL1D/V/ZfvFdT1ezbGRoprO+dAaUENuO1BRAEAMbhpQb6 +qA5MYSA4BWc3RyTvoCcpveM4Ehh5AZgSAX+UNhtjt85De0iBDSNesoPXMcu85E2w +bvTzIM1Hv1LkKL/WemFys049Yy6M6xnZYyjnFuWEb5Ym6O3ilw1JEr0/l+idQTiF +XsZdOWODXJn+6LTQ63tvUHyvIBgTv23UHey/AAQLA/0eDavyUGr+P+3eRE7jGXXT +wMVeJAp2Puxe6CYBwyiYXicbePazbX10sQWVLCfT+l4a+OnwkU99ww9T/EclJpkt +/3SZex/6kdwNa6MeBUD1gLpOFhobH0l75WZxViiYQvE2cxYrI4l48NThWIheEwK8 +Y/Q+3f3BxCiIuN67Xn6X/v8EAQPfoYwMXoA+NvOy9Qr7KTriHeTVwSrlVprhmm/M +2bFHEQQxJP5csnuV5EXOeAUzsIksQ17f5lOppLt339rSn2hxXA/Y0c4FMtJSIqLw +9pxTeq2vkDv0zYC1SuWfAlxriimd4EsmA0YkvJEay/pYRas9nU+FHu/pKRR+PyND +9PNvWWPoOk4ClkUf18e/lu0tT4khNNH6iEYEGBECAAYFAjbjtQUACgkQiXmmxVZ/ +s0rskACdGiy9dMrQlMOeDzuRqJcsBPe3YfwAn3nDC2nXHR4/itw7jnJSyAYihahT +lQHOBDbjtVERBADdUAZzhP6+69VdyRrgRNotouUvXE6I8h0kxZFZZDrQJmpZcNWk +UHDqgbYDJ9RmIeEuWZNmyzPxSFcvD9RGw9KmIZu2kZYqIuzg4KqOyU3SUfNycarE +ZYJkmLEyBlrkNxZkmPCp1cRsMKGCbhQs//v6Iq8h6dNA2EWgJev0y12gcwCguk0K +ZIqVO7UfkaVaZhMr0Cd1at8D/juKnRViDMi9SEjSJZwb3mw1+yECnM8vrM+AoGoA +KiCz/n8N9Gf2DTsFy4yKEskPQ8s09Wc5epBFo3gNruMu4kDnde0uCmiDEbTwzpdS +KZO5x9yi+7b39uCNkgoDlzwonaXNdIn2NnFKjL47TnV/vKFdtSZgLW902vwYGTr1 +ArL/BACIcx9TdxsJ9NMyaKD7MEcKQeOrOqv/Mq1HxFPkDBI4hTZpQiId1XTxqkJ6 +UHDw9sR/TvtO5YKrZjINkmaBZFiHlx1oyB0B3u6XUVLXIc9liyFyh9aOBdQkdHgj +yI8Kzk6Z0ejYcre5TY4zfplAZKkUDlY3U0Sb0a0xIGhgo3YREP8EAQMT5FnbWGWP +2cVRAqQN/YTcRPzxcHeXQzVsLEK/ZQB8an6kRJZsVmwGtCtZYW5rZWUgVGVzdCAo +ZGVtbyBrZXkpIDx5YW5rZWVAZXhhbXBsZS5uZXQ+iFUEExECABUFAjbjtVIDCwoD +AxUDAgMWAgECF4AACgkQnu80zUsRsl9XsQCgkAArOB5EfjSD6bXFfll8/pCcJygA +oJtNkxKjQfv2DpmfbBlt0RUbCaP6nQGlBDbjtWcQBACa4rlFxLTNPJenpKNbb5Z5 +AikmckN+UvT6IF7//dIAO/TWpSbDeNYwC7Eb4JwICmSyXXbZX2ekQeIsLhDYDr2u +gtGxvEoE95u6y19p0smhVio+y+OesGVp97kZysU+cpsTTBXplfH9On95IOJCWJ3i +VbPkn7P+Y3sqEcA3OhEBuwADBgQAk7l+QJJ03CSKwVfN4qyVbGb1ih7VM6i6JJXX +WF7HSP3genPnAZYRcXvP4VsOr7hXRSoaQrFoRGyXocxY2QiaPns3/2HULVgN+IpO +KaDm1mkqZ6Fe2V2lYYI0NmsTRFqysUIoQ1WEUyGlziQCfHqtsDT4uFG8mS+R3Fju +kpT/9pn/BAEDE+RZ21hlj9nFUQKkDf2E3EecwSh+NU1+ETQkC/cpMlFkc4JvMKQ7 +4PEqBxIixlVImLPO52ZUthtBYwpzTKQC9smi3iTo+A2JbBTJjwfFCzQX7lhi1CQy +zxV0hA17P7kTZEKgH5V+VRWriqFZTFcHvfuZpQSxJzbbTJ4SPTifn06U8gtv4D9e +/CgIT8X6QJB2VLsEDYhGBBgRAgAGBQI247VnAAoJEJ7vNM1LEbJf9FwAn1fc3Y8+ +VfQp43FQd5+qak9gMXoaAJ9mbIL86WuaZK6Uno0AfGJA1PgP9pUBzgQ247XLEQQA +gQyThl/Qv8cQlWTT+jh8+nC+bzNz4plAIVfvRwFVT0FYk5xSq5GD0kMkX1s4zlPE +TtU6eQh8++O6Dm+o/T++Mh9bsu/MhYOFLoVwVop4bgiiquCCFsCZAigRa9VPH7vG +umOjXI6ogwNCphkSazD5l3p15CaRRhxu/K1LzYvSDH8AoLoMzSC4f912QmVPgVD2 +Hly/p1ABBACA12YY9bxVx4IvZZooyg4yaHBAaGpjf7WkMujsdUUQ+h7XwD2OUxEd +Z+8ZvYTMxPjr9SCqR/xPO9kYWtartb+3jmunk7jVhdDb5kkfeeX63kbDbkfCTSG+ +krSNhEfacwVH48pAvaYNsD3gu8KUCSBfUxfiWtQbxtiPoWtsSe/OgAP7BxFLwDrH +OfGGz5WyD8qdiXRB7100U9jSElUbkzELIPL1ffZzGEdglIdu9Lj8stsWWg/5GHCf +f9Z4GOwvaW2zVqFe9D5BDDv6o+uziFYllT81ISHVEaK26RobnN6Ac1MToImpeyGy +Ej0SLQ4INqGaGOIaskDcfAo9mWQMw6TNrwr/BAEDcZMUKY/bw+Whlbt8d72KlAfR +OQf7KnYhddFY0eOFxs6vCS/v6N50dbQnWnVsdSBUZXN0IChkZW1vIGtleSkgPHp1 +bHVAZXhhbXBsZS5uZXQ+iFUEExECABUFAjbjtcsDCwoDAxUDAgMWAgECF4AACgkQ +a8R3gFSs0kZA6wCeOBSNOP3/J4LLMGDC7YWzVnYcH1oAoJh1THc6xw3dCapVWt7e +nBljkaZInQGlBDbjtfIQBADMfPDBQoMzv52Mmjb8SdaYKKNzqDd9K1oY2hcMSi+L +cHag+KJFOyKBf3SoHmcU/vCEN+LyTgljYSKDmEf4wZ2+eLfqFgSdBJp2xm55ih+9 +CHXg3dXx9SbHiGJCIxfJaIsnNz3VmJGPDDjBlaf/hjl/7SZvR+MJpVLFPGjj7uOh +TwADBQP/Sgv0abeCXVdVXwGEmhdV0VDo833IQRdRu1yt+QLnWRMGTY1oQapsH6QL +wYSZfDJlxbsBA3tfqKStpRSbdGNNTsK+RIehsGddi3sWGplRGm5Xt5KpkY/mc/tL +FaYJNMqAgfWQcKlZHBp7EoWMgiRiDJUWq0TH1wRDoPaRc+H5Gdr/BAEDcZMUKY/b +w+Whlbt8d72KlASOyif5HwnRxkXE7wHaToVqzUKku8/w/Q11MjKK1qIFRq0gYMjw +3bYjqap6WlZmlMplnKasMp7SfyH6tM2pvS4i3wVH7r/WoWcvWTcT/5DGpLtUaRHP +rGdP6Vrs5Wt7FfPXzKdum/Mkw97ZIA/Kpj5FLNbB/ln9uAz4D9+00V8R6dyfsohG +BBgRAgAGBQI247XyAAoJEGvEd4BUrNJGfWMAmwXfO7BnT2jtPTJk2bjNZxEZm+14 +AKCugutV1S43Ft0SWUfgFty8UHTrMA== +=+vvt +-----END PGP PRIVATE KEY BLOCK----- diff --git a/tags/gpgme-1.1.6/tests/gpg/seckey-1.asc b/tags/gpgme-1.1.6/tests/gpg/seckey-1.asc new file mode 100644 index 0000000..3934804 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/seckey-1.asc @@ -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----- diff --git a/tags/gpgme-1.1.6/tests/gpg/t-decrypt-verify.c b/tags/gpgme-1.1.6/tests/gpg/t-decrypt-verify.c new file mode 100644 index 0000000..697d383 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/t-decrypt-verify.c @@ -0,0 +1,141 @@ +/* t-decrypt-verify.c - Regression test. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include + +#include "t-support.h" + + +static void +check_verify_result (gpgme_verify_result_t result, unsigned int summary, + char *fpr, gpgme_error_t status) +{ + gpgme_signature_t sig; + + sig = result->signatures; + if (!sig || sig->next) + { + fprintf (stderr, "%s:%i: Unexpected number of signatures\n", + __FILE__, __LINE__); + exit (1); + } + if (sig->summary != summary) + { + fprintf (stderr, "%s:%i: Unexpected signature summary: 0x%x\n", + __FILE__, __LINE__, sig->summary); + exit (1); + } + if (strcmp (sig->fpr, fpr)) + { + fprintf (stderr, "%s:%i: Unexpected fingerprint: %s\n", + __FILE__, __LINE__, sig->fpr); + exit (1); + } + if (gpg_err_code (sig->status) != status) + { + fprintf (stderr, "%s:%i: Unexpected signature status: %s\n", + __FILE__, __LINE__, gpgme_strerror (sig->status)); + exit (1); + } + if (sig->notations) + { + fprintf (stderr, "%s:%i: Unexpected notation data\n", + __FILE__, __LINE__); + exit (1); + } + if (sig->wrong_key_usage) + { + fprintf (stderr, "%s:%i: Unexpectedly wrong key usage\n", + __FILE__, __LINE__); + exit (1); + } + if (sig->validity != GPGME_VALIDITY_UNKNOWN) + { + fprintf (stderr, "%s:%i: Unexpected validity: %i\n", + __FILE__, __LINE__, sig->validity); + exit (1); + } + if (gpg_err_code (sig->validity_reason) != GPG_ERR_NO_ERROR) + { + fprintf (stderr, "%s:%i: Unexpected validity reason: %s\n", + __FILE__, __LINE__, gpgme_strerror (sig->validity_reason)); + exit (1); + } +} + + +int +main (int argc, char *argv[]) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_data_t in, out; + gpgme_decrypt_result_t decrypt_result; + gpgme_verify_result_t verify_result; + const char *cipher_2_asc = make_filename ("cipher-2.asc"); + char *agent_info; + + init_gpgme (GPGME_PROTOCOL_OpenPGP); + + err = gpgme_new (&ctx); + fail_if_err (err); + + agent_info = getenv("GPG_AGENT_INFO"); + if (!(agent_info && strchr (agent_info, ':'))) + gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL); + + err = gpgme_data_new_from_file (&in, cipher_2_asc, 1); + fail_if_err (err); + err = gpgme_data_new (&out); + fail_if_err (err); + + err = gpgme_op_decrypt_verify (ctx, in, out); + fail_if_err (err); + decrypt_result = gpgme_op_decrypt_result (ctx); + if (decrypt_result->unsupported_algorithm) + { + fprintf (stderr, "%s:%i: unsupported algorithm: %s\n", + __FILE__, __LINE__, decrypt_result->unsupported_algorithm); + exit (1); + } + print_data (out); + verify_result = gpgme_op_verify_result (ctx); + check_verify_result (verify_result, 0, + "A0FF4590BB6122EDEF6E3C542D727CC768697734", + GPG_ERR_NO_ERROR); + + gpgme_data_release (in); + gpgme_data_release (out); + gpgme_release (ctx); + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpg/t-decrypt.c b/tags/gpgme-1.1.6/tests/gpg/t-decrypt.c new file mode 100644 index 0000000..2a2f4d7 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/t-decrypt.c @@ -0,0 +1,79 @@ +/* t-decrypt.c - Regression test. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include + +#include "t-support.h" + + +int +main (int argc, char *argv[]) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_data_t in, out; + gpgme_decrypt_result_t result; + const char *cipher_1_asc = make_filename ("cipher-1.asc"); + char *agent_info; + + init_gpgme (GPGME_PROTOCOL_OpenPGP); + + err = gpgme_new (&ctx); + fail_if_err (err); + + agent_info = getenv("GPG_AGENT_INFO"); + if (!(agent_info && strchr (agent_info, ':'))) + gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL); + + 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); + result = gpgme_op_decrypt_result (ctx); + if (result->unsupported_algorithm) + { + fprintf (stderr, "%s:%i: unsupported algorithm: %s\n", + __FILE__, __LINE__, result->unsupported_algorithm); + exit (1); + } + print_data (out); + + gpgme_data_release (in); + gpgme_data_release (out); + gpgme_release (ctx); + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpg/t-edit.c b/tags/gpgme-1.1.6/tests/gpg/t-edit.c new file mode 100644 index 0000000..f2f406d --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/t-edit.c @@ -0,0 +1,152 @@ +/* t-edit.c - Regression test. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "t-support.h" + + +static void +flush_data (gpgme_data_t dh) +{ + char buf[100]; + int ret; + + ret = gpgme_data_seek (dh, 0, SEEK_SET); + if (ret) + fail_if_err (gpg_error_from_errno (errno)); + while ((ret = gpgme_data_read (dh, buf, 100)) > 0) + fwrite (buf, ret, 1, stdout); + if (ret < 0) + fail_if_err (gpg_error_from_errno (errno)); +} + + +gpgme_error_t +edit_fnc (void *opaque, gpgme_status_code_t status, const char *args, int fd) +{ + char *result = NULL; + gpgme_data_t out = (gpgme_data_t) opaque; + + fputs ("[-- Response --]\n", stdout); + flush_data (out); + + fprintf (stdout, "[-- Code: %i, %s --]\n", status, args); + + if (fd >= 0) + { + if (!strcmp (args, "keyedit.prompt")) + { + static int step = 0; + + switch (step) + { + case 0: + result = "fpr"; + break; + case 1: + result = "expire"; + break; + + /* This fixes the primary user ID so the keylisting + tests will have predictable output. */ + case 2: + result = "1"; + break; + case 3: + result = "primary"; + break; + + default: + result = "quit"; + break; + } + step++; + } + else if (!strcmp (args, "keyedit.save.okay")) + result = "Y"; + else if (!strcmp (args, "keygen.valid")) + result = "0"; + } + + if (result) + { + write (fd, result, strlen (result)); + write (fd, "\n", 1); + } + return 0; +} + + +int +main (int argc, char **argv) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_data_t out = NULL; + gpgme_key_t key = NULL; + const char *pattern = "Alpha"; + char *agent_info; + + init_gpgme (GPGME_PROTOCOL_OpenPGP); + + err = gpgme_new (&ctx); + fail_if_err (err); + err = gpgme_data_new (&out); + fail_if_err (err); + + agent_info = getenv("GPG_AGENT_INFO"); + if (!(agent_info && strchr (agent_info, ':'))) + gpgme_set_passphrase_cb (ctx, passphrase_cb, 0); + + err = gpgme_op_keylist_start (ctx, pattern, 0); + fail_if_err (err); + err = gpgme_op_keylist_next (ctx, &key); + fail_if_err (err); + err = gpgme_op_keylist_end (ctx); + fail_if_err (err); + + err = gpgme_op_edit (ctx, key, edit_fnc, out, out); + fail_if_err (err); + + fputs ("[-- Last response --]\n", stdout); + flush_data (out); + + gpgme_data_release (out); + gpgme_key_unref (key); + gpgme_release (ctx); + + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpg/t-encrypt-large.c b/tags/gpgme-1.1.6/tests/gpg/t-encrypt-large.c new file mode 100644 index 0000000..6cc6138 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/t-encrypt-large.c @@ -0,0 +1,143 @@ +/* t-encrypt-large.c - Regression test for large amounts of data. + Copyright (C) 2005 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +#include "t-support.h" + + +struct cb_parms +{ + size_t bytes_to_send; + size_t bytes_received; +}; + + + +/* The read callback used by GPGME to read data. */ +static ssize_t +read_cb (void *handle, void *buffer, size_t size) +{ + struct cb_parms *parms = handle; + char *p = buffer; + + for (; size && parms->bytes_to_send; size--, parms->bytes_to_send--) + *p++ = rand (); + + return (p - (char*)buffer); +} + +/* The write callback used by GPGME to write data. */ +static ssize_t +write_cb (void *handle, const void *buffer, size_t size) +{ + struct cb_parms *parms = handle; + + parms->bytes_received += size; + + return size; +} + + +static void +progress_cb (void *opaque, const char *what, int type, int current, int total) +{ + /* This is just a dummy. */ +} + + + + + +int +main (int argc, char *argv[]) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + struct gpgme_data_cbs cbs; + gpgme_data_t in, out; + gpgme_key_t key[3] = { NULL, NULL, NULL }; + gpgme_encrypt_result_t result; + size_t nbytes; + struct cb_parms parms; + + if (argc > 1) + nbytes = atoi (argv[1]); + else + nbytes = 100000; + + init_gpgme (GPGME_PROTOCOL_OpenPGP); + + memset (&cbs, 0, sizeof cbs); + cbs.read = read_cb; + cbs.write = write_cb; + memset (&parms, 0, sizeof parms); + parms.bytes_to_send = nbytes; + + err = gpgme_new (&ctx); + fail_if_err (err); + gpgme_set_armor (ctx, 0); + + /* Install a progress handler to enforce a bit of more work to the + gpgme i/o system. */ + gpgme_set_progress_cb (ctx, progress_cb, NULL); + + err = gpgme_data_new_from_cbs (&in, &cbs, &parms); + fail_if_err (err); + + err = gpgme_data_new_from_cbs (&out, &cbs, &parms); + fail_if_err (err); + + err = gpgme_get_key (ctx, "A0FF4590BB6122EDEF6E3C542D727CC768697734", + &key[0], 0); + fail_if_err (err); + err = gpgme_get_key (ctx, "D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", + &key[1], 0); + fail_if_err (err); + + err = gpgme_op_encrypt (ctx, key, GPGME_ENCRYPT_ALWAYS_TRUST, in, out); + fail_if_err (err); + result = gpgme_op_encrypt_result (ctx); + if (result->invalid_recipients) + { + fprintf (stderr, "Invalid recipient encountered: %s\n", + result->invalid_recipients->fpr); + exit (1); + } + printf ("plaintext=%u bytes, ciphertext=%u bytes\n", + (unsigned int)nbytes, (unsigned int)parms.bytes_received); + + gpgme_key_unref (key[0]); + gpgme_key_unref (key[1]); + gpgme_data_release (in); + gpgme_data_release (out); + gpgme_release (ctx); + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpg/t-encrypt-sign.c b/tags/gpgme-1.1.6/tests/gpg/t-encrypt-sign.c new file mode 100644 index 0000000..9da5ff0 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/t-encrypt-sign.c @@ -0,0 +1,139 @@ +/* t-encrypt-sign.c - Regression test. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include + +#include "t-support.h" + + +static void +check_result (gpgme_sign_result_t result, gpgme_sig_mode_t type) +{ + if (result->invalid_signers) + { + fprintf (stderr, "Invalid signer found: %s\n", + result->invalid_signers->fpr); + exit (1); + } + if (!result->signatures || result->signatures->next) + { + fprintf (stderr, "Unexpected number of signatures created\n"); + exit (1); + } + if (result->signatures->type != type) + { + fprintf (stderr, "Wrong type of signature created\n"); + exit (1); + } + if (result->signatures->pubkey_algo != GPGME_PK_DSA) + { + fprintf (stderr, "Wrong pubkey algorithm reported: %i\n", + result->signatures->pubkey_algo); + exit (1); + } + if (result->signatures->hash_algo != GPGME_MD_SHA1) + { + fprintf (stderr, "Wrong hash algorithm reported: %i\n", + result->signatures->hash_algo); + exit (1); + } + if (result->signatures->sig_class != 0) + { + fprintf (stderr, "Wrong signature class reported: %u\n", + result->signatures->sig_class); + exit (1); + } + if (strcmp ("A0FF4590BB6122EDEF6E3C542D727CC768697734", + result->signatures->fpr)) + { + fprintf (stderr, "Wrong fingerprint reported: %s\n", + result->signatures->fpr); + exit (1); + } +} + + +int +main (int argc, char **argv) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_data_t in, out; + gpgme_key_t key[3] = { NULL, NULL, NULL }; + gpgme_encrypt_result_t result; + gpgme_sign_result_t sign_result; + char *agent_info; + + init_gpgme (GPGME_PROTOCOL_OpenPGP); + + err = gpgme_new (&ctx); + fail_if_err (err); + gpgme_set_textmode (ctx, 1); + gpgme_set_armor (ctx, 1); + + agent_info = getenv("GPG_AGENT_INFO"); + if (!(agent_info && strchr (agent_info, ':'))) + gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL); + + 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_get_key (ctx, "A0FF4590BB6122EDEF6E3C542D727CC768697734", + &key[0], 0); + fail_if_err (err); + err = gpgme_get_key (ctx, "D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", + &key[1], 0); + fail_if_err (err); + + err = gpgme_op_encrypt_sign (ctx, key, GPGME_ENCRYPT_ALWAYS_TRUST, in, out); + fail_if_err (err); + result = gpgme_op_encrypt_result (ctx); + if (result->invalid_recipients) + { + fprintf (stderr, "Invalid recipient encountered: %s\n", + result->invalid_recipients->fpr); + exit (1); + } + sign_result = gpgme_op_sign_result (ctx); + check_result (sign_result, GPGME_SIG_MODE_NORMAL); + print_data (out); + + gpgme_key_unref (key[0]); + gpgme_key_unref (key[1]); + gpgme_data_release (in); + gpgme_data_release (out); + gpgme_release (ctx); + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpg/t-encrypt-sym.c b/tags/gpgme-1.1.6/tests/gpg/t-encrypt-sym.c new file mode 100644 index 0000000..51a3fc1 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/t-encrypt-sym.c @@ -0,0 +1,98 @@ +/* t-encrypt-sym.c - Regression test. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include + +#include "t-support.h" + + +int +main (int argc, char *argv[]) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_data_t plain, cipher; + const char *text = "Hallo Leute\n"; + char *text2; + char *p; + size_t len; + + init_gpgme (GPGME_PROTOCOL_OpenPGP); + + err = gpgme_new (&ctx); + fail_if_err (err); + gpgme_set_armor (ctx, 1); + + p = getenv("GPG_AGENT_INFO"); + if (!(p && strchr (p, ':'))) + gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL); + + err = gpgme_data_new_from_mem (&plain, text, strlen (text), 0); + fail_if_err (err); + + err = gpgme_data_new (&cipher); + fail_if_err (err); + + err = gpgme_op_encrypt (ctx, 0, 0, plain, cipher); + fail_if_err (err); + + fflush (NULL); + fputs ("Begin Result Encryption:\n", stdout); + print_data (cipher); + fputs ("End Result.\n", stdout); + + gpgme_data_seek (cipher, 0, SEEK_SET); + + gpgme_data_release (plain); + err = gpgme_data_new (&plain); + fail_if_err (err); + + err = gpgme_op_decrypt (ctx, cipher, plain); + fail_if_err (err); + + fputs ("Begin Result Decryption:\n", stdout); + print_data (plain); + fputs ("End Result.\n", stdout); + + text2 = gpgme_data_release_and_get_mem (plain, &len); + if (strncmp (text, text2, len)) + { + fprintf (stderr, "%s:%d: Wrong plaintext\n", __FILE__, __LINE__); + exit (1); + } + + gpgme_data_release (cipher); + gpgme_release (ctx); + + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpg/t-encrypt.c b/tags/gpgme-1.1.6/tests/gpg/t-encrypt.c new file mode 100644 index 0000000..264f31a --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/t-encrypt.c @@ -0,0 +1,82 @@ +/* t-encrypt.c - Regression test. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +#include "t-support.h" + + +int +main (int argc, char *argv[]) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_data_t in, out; + gpgme_key_t key[3] = { NULL, NULL, NULL }; + gpgme_encrypt_result_t result; + + init_gpgme (GPGME_PROTOCOL_OpenPGP); + + err = gpgme_new (&ctx); + fail_if_err (err); + gpgme_set_armor (ctx, 1); + + 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_get_key (ctx, "A0FF4590BB6122EDEF6E3C542D727CC768697734", + &key[0], 0); + fail_if_err (err); + err = gpgme_get_key (ctx, "D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", + &key[1], 0); + fail_if_err (err); + + err = gpgme_op_encrypt (ctx, key, GPGME_ENCRYPT_ALWAYS_TRUST, in, out); + fail_if_err (err); + result = gpgme_op_encrypt_result (ctx); + if (result->invalid_recipients) + { + fprintf (stderr, "Invalid recipient encountered: %s\n", + result->invalid_recipients->fpr); + exit (1); + } + print_data (out); + + gpgme_key_unref (key[0]); + gpgme_key_unref (key[1]); + gpgme_data_release (in); + gpgme_data_release (out); + gpgme_release (ctx); + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpg/t-eventloop.c b/tags/gpgme-1.1.6/tests/gpg/t-eventloop.c new file mode 100644 index 0000000..bf1ab4e --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/t-eventloop.c @@ -0,0 +1,225 @@ +/* t-eventloop.c - Regression test. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "t-support.h" + + +/* Stripped down version of gpgme/wait.c. */ + +struct op_result +{ + int done; + gpgme_error_t err; +}; + +struct op_result op_result; + +struct one_fd +{ + int fd; + int dir; + gpgme_io_cb_t fnc; + void *fnc_data; +}; + +#define FDLIST_MAX 32 +struct one_fd fdlist[FDLIST_MAX]; + +gpgme_error_t +add_io_cb (void *data, int fd, int dir, gpgme_io_cb_t fnc, void *fnc_data, + void **r_tag) +{ + struct one_fd *fds = data; + int i; + + for (i = 0; i < FDLIST_MAX; i++) + { + if (fds[i].fd == -1) + { + fds[i].fd = fd; + fds[i].dir = dir; + fds[i].fnc = fnc; + fds[i].fnc_data = fnc_data; + break; + } + } + if (i == FDLIST_MAX) + return gpg_err_make (GPG_ERR_SOURCE_USER_1, GPG_ERR_GENERAL); + *r_tag = &fds[i]; + return 0; +} + +void +remove_io_cb (void *tag) +{ + struct one_fd *fd = tag; + + fd->fd = -1; +} + +void +io_event (void *data, gpgme_event_io_t type, void *type_data) +{ + struct op_result *result = data; + + if (type == GPGME_EVENT_DONE) + { + result->done = 1; + result->err = * (gpgme_error_t *) type_data; + } +} + + +int +do_select (void) +{ + fd_set rfds; + fd_set wfds; + int i, n; + int any = 0; + + FD_ZERO (&rfds); + FD_ZERO (&wfds); + for (i = 0; i < FDLIST_MAX; i++) + if (fdlist[i].fd != -1) + FD_SET (fdlist[i].fd, fdlist[i].dir ? &rfds : &wfds); + + do + { + n = select (FD_SETSIZE, &rfds, &wfds, NULL, 0); + } + while (n < 0 && errno == EINTR); + + if (n < 0) + return n; /* Error or timeout. */ + + for (i = 0; i < FDLIST_MAX && n; i++) + { + if (fdlist[i].fd != -1) + { + if (FD_ISSET (fdlist[i].fd, fdlist[i].dir ? &rfds : &wfds)) + { + assert (n); + n--; + any = 1; + (*fdlist[i].fnc) (fdlist[i].fnc_data, fdlist[i].fd); + } + } + } + return any; +} + +int +my_wait (void) +{ + int n; + + do + { + n = do_select (); + } + while (n >= 0 && !op_result.done); + return 0; +} + + +struct gpgme_io_cbs io_cbs = + { + add_io_cb, + fdlist, + remove_io_cb, + io_event, + &op_result + }; + + +int +main (int argc, char *argv[]) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_data_t in, out; + gpgme_key_t key[3] = { NULL, NULL, NULL }; + int i; + + init_gpgme (GPGME_PROTOCOL_OpenPGP); + + for (i = 0; i < FDLIST_MAX; i++) + fdlist[i].fd = -1; + + err = gpgme_engine_check_version (GPGME_PROTOCOL_OpenPGP); + fail_if_err (err); + + err = gpgme_new (&ctx); + fail_if_err (err); + gpgme_set_armor (ctx, 1); + gpgme_set_io_cbs (ctx, &io_cbs); + op_result.done = 0; + + 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_get_key (ctx, "A0FF4590BB6122EDEF6E3C542D727CC768697734", + &key[0], 0); + fail_if_err (err); + err = gpgme_get_key (ctx, "D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", + &key[1], 0); + fail_if_err (err); + + err = gpgme_op_encrypt_start (ctx, key, GPGME_ENCRYPT_ALWAYS_TRUST, in, out); + fail_if_err (err); + + my_wait (); + fail_if_err (op_result.err); + fail_if_err (err); + + fflush (NULL); + fputs ("Begin Result:\n", stdout); + print_data (out); + fputs ("End Result.\n", stdout); + + gpgme_key_unref (key[0]); + gpgme_key_unref (key[1]); + gpgme_data_release (in); + gpgme_data_release (out); + gpgme_release (ctx); + + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpg/t-export.c b/tags/gpgme-1.1.6/tests/gpg/t-export.c new file mode 100644 index 0000000..f469843 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/t-export.c @@ -0,0 +1,67 @@ +/* t-export.c - Regression test. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include + +#include "t-support.h" + + +int +main (int argc, char **argv) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_data_t out; + const char *pattern[] = { "Alpha", "Bob", NULL }; + + init_gpgme (GPGME_PROTOCOL_OpenPGP); + + err = gpgme_new (&ctx); + fail_if_err (err); + + err = gpgme_data_new (&out); + fail_if_err (err); + + gpgme_set_armor (ctx, 1); + err = gpgme_op_export_ext (ctx, pattern, 0, out); + fail_if_err (err); + + fflush (NULL); + fputs ("Begin Result:\n", stdout); + print_data (out); + fputs ("End Result.\n", stdout); + + gpgme_data_release (out); + gpgme_release (ctx); + + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpg/t-file-name.c b/tags/gpgme-1.1.6/tests/gpg/t-file-name.c new file mode 100644 index 0000000..eb20fc0 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/t-file-name.c @@ -0,0 +1,99 @@ +/* t-file-name.c - Regression test. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +#include "t-support.h" + +#define TESTNAME "abcde12345" + + +int +main (int argc, char *argv[]) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_data_t in, out; + gpgme_key_t key[2] = { NULL, NULL }; + gpgme_decrypt_result_t result; + char *agent_info; + + init_gpgme (GPGME_PROTOCOL_OpenPGP); + + err = gpgme_new (&ctx); + fail_if_err (err); + gpgme_set_armor (ctx, 1); + + agent_info = getenv("GPG_AGENT_INFO"); + if (!(agent_info && strchr (agent_info, ':'))) + gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL); + + err = gpgme_data_new_from_mem (&in, "Hallo Leute\n", 12, 0); + fail_if_err (err); + + err = gpgme_data_set_file_name (in, TESTNAME); + fail_if_err (err); + + err = gpgme_data_new (&out); + fail_if_err (err); + + err = gpgme_get_key (ctx, "A0FF4590BB6122EDEF6E3C542D727CC768697734", + &key[0], 0); + fail_if_err (err); + + err = gpgme_op_encrypt (ctx, key, GPGME_ENCRYPT_ALWAYS_TRUST, in, out); + fail_if_err (err); + + gpgme_data_release (in); + err = gpgme_data_new (&in); + fail_if_err (err); + + err = gpgme_data_seek (out, 0, SEEK_SET); + fail_if_err (err); + + err = gpgme_op_decrypt (ctx, out, in); + fail_if_err (err); + result = gpgme_op_decrypt_result (ctx); + + if (strcmp (TESTNAME, result->file_name)) + { + fprintf (stderr, "%s:%i: Unexpected result file name: %s\n", + __FILE__, __LINE__, + result->file_name ? "(null)" : result->file_name); + exit (1); + } + + gpgme_key_unref (key[0]); + gpgme_data_release (in); + gpgme_data_release (out); + gpgme_release (ctx); + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpg/t-genkey.c b/tags/gpgme-1.1.6/tests/gpg/t-genkey.c new file mode 100644 index 0000000..407824f --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/t-genkey.c @@ -0,0 +1,122 @@ +/* t-genkey.c - Regression test. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +#include "t-support.h" + + +/* True if progress function printed something on the screen. */ +static int progress_called; + +static void +progress (void *self, const char *what, int type, int current, int total) +{ + if (!strcmp (what, "primegen") && !current && !total + && (type == '.' || type == '+' || type == '!' + || type == '^' || type == '<' || type == '>')) + { + printf ("%c", type); + fflush (stdout); + progress_called = 1; + } + else + { + fprintf (stderr, "unknown progress `%s' %d %d %d\n", what, type, + current, total); + exit (1); + } +} + + +int +main (int argc, char **argv) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + const char *parms = "\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)\n" + "Name-Email: joe@foo.bar\n" + "Expire-Date: 0\n" + "Passphrase: abc\n" + "\n"; + gpgme_genkey_result_t result; + + init_gpgme (GPGME_PROTOCOL_OpenPGP); + + err = gpgme_new (&ctx); + fail_if_err (err); + + gpgme_set_progress_cb (ctx, progress, NULL); + + err = gpgme_op_genkey (ctx, parms, NULL, NULL); + fail_if_err (err); + + result = gpgme_op_genkey_result (ctx); + if (!result) + { + fprintf (stderr, "%s:%d: gpgme_op_genkey_result returns NULL\n", + __FILE__, __LINE__); + exit (1); + } + if (progress_called) + printf ("\n"); + + printf ("Generated key: %s (%s)\n", result->fpr ? result->fpr : "none", + result->primary ? (result->sub ? "primary, sub" : "primary") + : (result->sub ? "sub" : "none")); + + if (result->fpr && strlen (result->fpr) != 40) + { + fprintf (stderr, "%s:%d: generated key has unexpected fingerprint\n", + __FILE__, __LINE__); + exit (1); + } + if (!result->primary) + { + fprintf (stderr, "%s:%d: primary key was not generated\n", + __FILE__, __LINE__); + exit (1); + } + if (!result->sub) + { + fprintf (stderr, "%s:%d: sub key was not generated\n", + __FILE__, __LINE__); + exit (1); + } + gpgme_release (ctx); + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpg/t-gpgconf.c b/tags/gpgme-1.1.6/tests/gpg/t-gpgconf.c new file mode 100644 index 0000000..458bbe7 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/t-gpgconf.c @@ -0,0 +1,305 @@ +/* t-gpgconf.c - Regression test. + Copyright (C) 2001, 2004, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#ifdef HAVE_W32_SYSTEM +#include +#endif + +#include + + +#define fail_if_err(err) \ + do \ + { \ + if (err) \ + { \ + fprintf (stderr, "%s:%d: %s: %s\n", \ + __FILE__, __LINE__, gpgme_strsource (err), \ + gpgme_strerror (err)); \ + exit (1); \ + } \ + } \ + while (0) + + +void +init_gpgme (gpgme_protocol_t proto) +{ + gpgme_error_t err; + + gpgme_check_version (NULL); + setlocale (LC_ALL, ""); + gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL)); +#ifndef HAVE_W32_SYSTEM + gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL)); +#endif + + err = gpgme_engine_check_version (proto); + fail_if_err (err); +} + + +static char * +spaces (char *str, int extra) +{ + static char buf[80]; + int len = str ? strlen (str) : 0; + int n; + +#define TABSTOP 30 + n = TABSTOP - len - extra; + + memset (buf, ' ', sizeof (buf)); + if (n < 1 || n > (sizeof (buf) - 1)) + { + buf[0] = '\n'; + n = TABSTOP + 1; + } + + buf[n] = '\0'; + return buf; +} + + +void +dump_arg (int type, gpgme_conf_arg_t arg) +{ + if (!arg) + { + printf ("(none)"); + return; + } + + while (arg) + { + switch (type) + { + case GPGME_CONF_STRING: + case GPGME_CONF_PATHNAME: + case GPGME_CONF_LDAP_SERVER: + printf ("%s", arg->value.string); + break; + + case GPGME_CONF_UINT32: + printf ("%u", arg->value.uint32); + break; + + case GPGME_CONF_INT32: + printf ("%i", arg->value.int32); + break; + + case GPGME_CONF_NONE: + printf ("%i (times)", arg->value.count); + break; + + default: + printf ("(unknown type)"); + } + + arg = arg->next; + if (arg) + printf (" "); + } +} + + +void +dump_opt (gpgme_conf_opt_t opt) +{ + char level; + char runtime = (opt->flags & GPGME_CONF_RUNTIME) ? 'r' : ' '; + + switch (opt->level) + { + case GPGME_CONF_BASIC: + level = 'b'; + break; + case GPGME_CONF_ADVANCED: + level = 'a'; + break; + case GPGME_CONF_EXPERT: + level = 'e'; + break; + case GPGME_CONF_INVISIBLE: + level = 'i'; + break; + case GPGME_CONF_INTERNAL: + level = '#'; + break; + default: + level = '?'; + } + + if (opt->flags & GPGME_CONF_GROUP) + { + printf ("\n"); + printf ("%c%c [%s]%s%s\n", level, runtime, opt->name, spaces (opt->name, 5), + opt->description + ? opt->description : ""); + } + else + { + if (opt->argname) + { + char *more = (opt->flags & GPGME_CONF_LIST) ? "..." : ""; + + if (opt->flags & GPGME_CONF_OPTIONAL) + { + printf ("%c%c --%s [%s%s] %s", level, runtime, opt->name, opt->argname, more, + spaces (opt->name, 9 + strlen (opt->argname) + strlen (more))); + } + else + { + printf ("%c%c --%s %s%s %s", level, runtime, opt->name, opt->argname, more, + spaces (opt->name, 7 + strlen (opt->argname) + strlen (more))); + } + } + else + printf ("%c%c --%s%s", level, runtime, opt->name, spaces (opt->name, 5)); + + if (opt->description) + printf ("%s", opt->description); + printf ("\n"); + + if (opt->flags & GPGME_CONF_DEFAULT) + { + printf ("%s%s = ", spaces (NULL, 0), opt->argname ? opt->argname : "(default)"); + dump_arg (opt->type, opt->default_value); + printf ("\n"); + } + else if (opt->flags & GPGME_CONF_DEFAULT_DESC) + printf ("%s%s = %s\n", spaces (NULL, 0), opt->argname ? opt->argname : "(default)", + opt->default_description); + + if (opt->no_arg_value) + { + printf ("%sNo Arg Def = ", spaces (NULL, 0)); + dump_arg (opt->type, opt->no_arg_value); + printf ("\n"); + } + if (opt->value) + { + printf ("%sCurrent = ", spaces (NULL, 0)); + dump_arg (opt->type, opt->value); + printf ("\n"); + } + } + +#if 0 + arg = comp->options; + while (opt) + { + dump_opt (opt); + opt = opt->next; + } +#endif +} + + +void +dump_comp (gpgme_conf_comp_t comp) +{ + gpgme_conf_opt_t opt; + + printf ("COMPONENT\n"); + printf ("=========\n"); + printf (" Name: %s\n", comp->name); + if (comp->description) + printf (" Desc: %s\n", comp->description); + if (comp->program_name) + printf (" Path: %s\n", comp->program_name); + printf ("\n"); + + opt = comp->options; + while (opt) + { + dump_opt (opt); + opt = opt->next; + } +} + + +int +main (int argc, char **argv) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_conf_comp_t conf; + gpgme_conf_comp_t comp; + int first; + init_gpgme (GPGME_PROTOCOL_GPGCONF); + + err = gpgme_new (&ctx); + fail_if_err (err); + + err = gpgme_op_conf_load (ctx, &conf); + fail_if_err (err); + + comp = conf; + first = 1; + while (comp) + { + if (!first) + printf ("\n"); + else + first = 0; + dump_comp (comp); + comp = comp->next; + } + +#if 1 + /* Now change something. */ + { + unsigned int count = 1; + gpgme_conf_arg_t arg; + gpgme_conf_opt_t opt; + + err = gpgme_conf_arg_new (&arg, GPGME_CONF_NONE, &count); + fail_if_err (err); + + comp = conf; + while (comp && strcmp (comp->name, "dirmngr")) + comp = comp->next; + opt = comp->options; + while (opt && strcmp (opt->name, "verbose")) + opt = opt->next; + + err = gpgme_conf_opt_change (opt, 0, arg); + fail_if_err (err); + + err = gpgme_op_conf_save (ctx, comp); + fail_if_err (err); + } +#endif + + gpgme_conf_release (conf); + + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpg/t-import.c b/tags/gpgme-1.1.6/tests/gpg/t-import.c new file mode 100644 index 0000000..db5f925 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/t-import.c @@ -0,0 +1,241 @@ +/* t-import.c - Regression test. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include + +#include "t-support.h" + + +void +check_result (gpgme_import_result_t result, char *fpr, int secret) +{ + if (result->considered != 1) + { + fprintf (stderr, "Unexpected number of considered keys %i\n", + result->considered); + exit (1); + } + if (result->no_user_id != 0) + { + fprintf (stderr, "Unexpected number of user ids %i\n", + result->no_user_id); + exit (1); + } + if ((secret && result->imported != 0) + || (!secret && (result->imported != 0 && result->imported != 1))) + { + fprintf (stderr, "Unexpected number of imported keys %i\n", + result->imported); + exit (1); + } + if (result->imported_rsa != 0) + { + fprintf (stderr, "Unexpected number of imported RSA keys %i\n", + result->imported_rsa); + exit (1); + } + if ((secret && result->unchanged != 0) + || (!secret && ((result->imported == 0 && result->unchanged != 1) + || (result->imported == 1 && result->unchanged != 0)))) + { + fprintf (stderr, "Unexpected number of unchanged keys %i\n", + result->unchanged); + exit (1); + } + if (result->new_user_ids != 0) + { + fprintf (stderr, "Unexpected number of new user IDs %i\n", + result->new_user_ids); + exit (1); + } + if (result->new_sub_keys != 0) + { + fprintf (stderr, "Unexpected number of new sub keys %i\n", + result->new_sub_keys); + exit (1); + } + if ((secret + && ((result->secret_imported == 0 && result->new_signatures != 0) + || (result->secret_imported == 1 && result->new_signatures > 1))) + || (!secret && result->new_signatures != 0)) + { + fprintf (stderr, "Unexpected number of new signatures %i\n", + result->new_signatures); + if (result->new_signatures == 2) + fprintf (stderr, "### ignored due to gpg 1.3.4 problems\n"); + else + exit (1); + } + if (result->new_revocations != 0) + { + fprintf (stderr, "Unexpected number of new revocations %i\n", + result->new_revocations); + exit (1); + } + if ((secret && result->secret_read != 1) + || (!secret && result->secret_read != 0)) + { + fprintf (stderr, "Unexpected number of secret keys read %i\n", + result->secret_read); + exit (1); + } + if ((secret && result->secret_imported != 0 && result->secret_imported != 1) + || (!secret && result->secret_imported != 0)) + { + fprintf (stderr, "Unexpected number of secret keys imported %i\n", + result->secret_imported); + exit (1); + } + if ((secret + && ((result->secret_imported == 0 && result->secret_unchanged != 1) + || (result->secret_imported == 1 && result->secret_unchanged != 0))) + || (!secret && result->secret_unchanged != 0)) + { + fprintf (stderr, "Unexpected number of secret keys unchanged %i\n", + result->secret_unchanged); + exit (1); + } + if (result->not_imported != 0) + { + fprintf (stderr, "Unexpected number of secret keys not imported %i\n", + result->not_imported); + exit (1); + } + if (secret) + { + if (!result->imports + || (result->imports->next && result->imports->next->next)) + { + fprintf (stderr, "Unexpected number of status reports\n"); + exit (1); + } + } + else + { + if (!result->imports || result->imports->next) + { + fprintf (stderr, "Unexpected number of status reports\n"); + exit (1); + } + } + if (strcmp (fpr, result->imports->fpr)) + { + fprintf (stderr, "Unexpected fingerprint %s\n", + result->imports->fpr); + exit (1); + } + if (result->imports->next && strcmp (fpr, result->imports->next->fpr)) + { + fprintf (stderr, "Unexpected fingerprint on second status %s\n", + result->imports->next->fpr); + exit (1); + } + if (result->imports->result != 0) + { + fprintf (stderr, "Unexpected status result %s\n", + gpgme_strerror (result->imports->result)); + exit (1); + } + if (secret) + { + if (result->secret_imported == 0) + { + if (result->imports->status != GPGME_IMPORT_SECRET) + { + fprintf (stderr, "Unexpected status %i\n", + result->imports->status); + exit (1); + } + } + else + { + if (result->imports->status + != (GPGME_IMPORT_SECRET | GPGME_IMPORT_NEW) + || (result->imports->next + && result->imports->next->status != GPGME_IMPORT_SIG)) + { + fprintf (stderr, "Unexpected status %i\n", + result->imports->status); + exit (1); + } + } + } + else + { + if ((result->imported == 0 && result->imports->status != 0) + || (result->imported == 1 + && result->imports->status != GPGME_IMPORT_NEW)) + { + fprintf (stderr, "Unexpected status %i\n", + result->imports->status); + exit (1); + } + } +} + + +int +main (int argc, char *argv[]) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_data_t in; + gpgme_import_result_t result; + const char *pubkey_1_asc = make_filename ("pubkey-1.asc"); + const char *seckey_1_asc = make_filename ("seckey-1.asc"); + + init_gpgme (GPGME_PROTOCOL_OpenPGP); + + 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); + result = gpgme_op_import_result (ctx); + check_result (result, "ADAB7FCC1F4DE2616ECFA402AF82244F9CD9FD55", 0); + 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); + result = gpgme_op_import_result (ctx); + check_result (result, "ADAB7FCC1F4DE2616ECFA402AF82244F9CD9FD55", 1); + gpgme_data_release (in); + + gpgme_release (ctx); + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpg/t-keylist-sig.c b/tags/gpgme-1.1.6/tests/gpg/t-keylist-sig.c new file mode 100644 index 0000000..b89ba33 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/t-keylist-sig.c @@ -0,0 +1,635 @@ +/* t-keylist-sig.c - Regression test. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +#include "t-support.h" + + +struct +{ + char *fpr; + char *sec_keyid; + struct + { + char *name; + char *comment; + char *email; + struct + { + gpgme_pubkey_algo_t algo; + char *keyid; + char *name; + char *comment; + char *email; + unsigned int sig_class; + int exportable; + } sig; + } uid[3]; +} +keys[] = + { + { "A0FF4590BB6122EDEF6E3C542D727CC768697734", "6AE6D7EE46A871F8", + { { "Alfa Test", "demo key", "alfa@example.net", + { GPGME_PK_DSA, "2D727CC768697734", + "Alfa Test", "demo key", "alfa@example.net", 19, 1 } }, + { "Alpha Test", "demo key", "alpha@example.net", + { GPGME_PK_DSA, "2D727CC768697734", + "Alfa Test", "demo key", "alfa@example.net", 19, 1 } }, + { "Alice", "demo key", NULL, + { GPGME_PK_DSA, "2D727CC768697734", + "Alfa Test", "demo key", "alfa@example.net", 19, 1 } } } }, + { NULL } + }; + + +int +main (int argc, char **argv) +{ + gpgme_error_t err; + gpgme_ctx_t ctx; + gpgme_key_t key; + gpgme_keylist_result_t result; + int mode; + int i = 0; + + init_gpgme (GPGME_PROTOCOL_OpenPGP); + + err = gpgme_new (&ctx); + fail_if_err (err); + + mode = gpgme_get_keylist_mode (ctx); + mode |= GPGME_KEYLIST_MODE_SIGS; + err = gpgme_set_keylist_mode (ctx, mode); + fail_if_err (err); + + err = gpgme_op_keylist_start (ctx, "Alpha", 0); + fail_if_err (err); + + while (!(err = gpgme_op_keylist_next (ctx, &key))) + { + if (!keys[i].fpr) + { + fprintf (stderr, "More keys returned than expected\n"); + exit (1); + } + + /* Global key flags. */ + if (key->revoked) + { + fprintf (stderr, "Key unexpectedly revoked\n"); + exit (1); + } + if (key->expired) + { + fprintf (stderr, "Key unexpectedly expired\n"); + exit (1); + } + if (key->disabled) + { + fprintf (stderr, "Key unexpectedly disabled\n"); + exit (1); + } + if (key->invalid) + { + fprintf (stderr, "Key unexpectedly invalid\n"); + exit (1); + } + if (!key->can_encrypt) + { + fprintf (stderr, "Key unexpectedly unusable for encryption\n"); + exit (1); + } + if (!key->can_sign) + { + fprintf (stderr, "Key unexpectedly unusable for signing\n"); + exit (1); + } + if (!key->can_certify) + { + fprintf (stderr, "Key unexpectedly unusable for certifications\n"); + exit (1); + } + if (key->secret) + { + fprintf (stderr, "Key unexpectedly secret\n"); + exit (1); + } + if (key->protocol != GPGME_PROTOCOL_OpenPGP) + { + fprintf (stderr, "Key has unexpected protocol: %s\n", + gpgme_get_protocol_name (key->protocol)); + exit (1); + } + if (key->issuer_serial) + { + fprintf (stderr, "Key unexpectedly carries issuer serial: %s\n", + key->issuer_serial); + exit (1); + } + if (key->issuer_name) + { + fprintf (stderr, "Key unexpectedly carries issuer name: %s\n", + key->issuer_name); + exit (1); + } + if (key->chain_id) + { + fprintf (stderr, "Key unexpectedly carries chain ID: %s\n", + key->chain_id); + exit (1); + } + if (key->owner_trust != GPGME_VALIDITY_UNKNOWN) + { + fprintf (stderr, "Key has unexpected owner trust: %i\n", + key->owner_trust); + exit (1); + } + if (!key->subkeys || !key->subkeys->next || key->subkeys->next->next) + { + fprintf (stderr, "Key has unexpected number of subkeys\n"); + exit (1); + } + + /* Primary key. */ + if (key->subkeys->revoked) + { + fprintf (stderr, "Primary key unexpectedly revoked\n"); + exit (1); + } + if (key->subkeys->expired) + { + fprintf (stderr, "Primary key unexpectedly expired\n"); + exit (1); + } + if (key->subkeys->disabled) + { + fprintf (stderr, "Primary key unexpectedly disabled\n"); + exit (1); + } + if (key->subkeys->invalid) + { + fprintf (stderr, "Primary key unexpectedly invalid\n"); + exit (1); + } + if (key->subkeys->can_encrypt) + { + fprintf (stderr, "Primary key unexpectedly usable for encryption\n"); + exit (1); + } + if (!key->subkeys->can_sign) + { + fprintf (stderr, "Primary key unexpectedly unusable for signing\n"); + exit (1); + } + if (!key->subkeys->can_certify) + { + fprintf (stderr, "Primary key unexpectedly unusable for certifications\n"); + exit (1); + } + if (key->subkeys->secret) + { + fprintf (stderr, "Primary key unexpectedly secret\n"); + exit (1); + } + if (key->subkeys->pubkey_algo != GPGME_PK_DSA) + { + fprintf (stderr, "Primary key has unexpected public key algo: %s\n", + gpgme_pubkey_algo_name (key->subkeys->pubkey_algo)); + exit (1); + } + if (key->subkeys->length != 1024) + { + fprintf (stderr, "Primary key has unexpected length: %i\n", + key->subkeys->length); + exit (1); + } + if (strcmp (key->subkeys->keyid, &keys[i].fpr[40 - 16])) + { + fprintf (stderr, "Primary key has unexpected key ID: %s\n", + key->subkeys->keyid); + exit (1); + } + if (strcmp (key->subkeys->fpr, keys[i].fpr)) + { + fprintf (stderr, "Primary key has unexpected fingerprint: %s\n", + key->subkeys->fpr); + exit (1); + } + if (key->subkeys->expires) + { + fprintf (stderr, "Primary key unexpectedly expires: %lu\n", + key->subkeys->expires); + exit (1); + } + + /* Secondary key. */ + if (key->subkeys->next->revoked) + { + fprintf (stderr, "Secondary key unexpectedly revoked\n"); + exit (1); + } + if (key->subkeys->next->expired) + { + fprintf (stderr, "Secondary key unexpectedly expired\n"); + exit (1); + } + if (key->subkeys->next->disabled) + { + fprintf (stderr, "Secondary key unexpectedly disabled\n"); + exit (1); + } + if (key->subkeys->next->invalid) + { + fprintf (stderr, "Secondary key unexpectedly invalid\n"); + exit (1); + } + if (!key->subkeys->next->can_encrypt) + { + fprintf (stderr, "Secondary key unexpectedly unusable for encryption\n"); + exit (1); + } + if (key->subkeys->next->can_sign) + { + fprintf (stderr, "Secondary key unexpectedly usable for signing\n"); + exit (1); + } + if (key->subkeys->next->can_certify) + { + fprintf (stderr, "Secondary key unexpectedly usable for certifications\n"); + exit (1); + } + if (key->subkeys->next->secret) + { + fprintf (stderr, "Secondary key unexpectedly secret\n"); + exit (1); + } + if (key->subkeys->next->pubkey_algo != GPGME_PK_ELG_E) + { + fprintf (stderr, "Secondary key has unexpected public key algo: %s\n", + gpgme_pubkey_algo_name (key->subkeys->next->pubkey_algo)); + exit (1); + } + if (key->subkeys->next->length != 1024) + { + fprintf (stderr, "Secondary key has unexpected length: %i\n", + key->subkeys->next->length); + exit (1); + } + if (strcmp (key->subkeys->next->keyid, keys[i].sec_keyid)) + { + fprintf (stderr, "Secondary key has unexpected key ID: %s\n", + key->subkeys->next->keyid); + exit (1); + } + if (!key->subkeys->next->fpr) + { + fprintf (stderr, "Secondary key has unexpectedly no fingerprint\n"); + exit (1); + } + if (key->subkeys->next->expires) + { + fprintf (stderr, "Secondary key unexpectedly expires: %lu\n", + key->subkeys->next->expires); + exit (1); + } + + /* FIXME: The below test will crash if we want to check for a + name, comment or email that doesn't exist in the key's user + IDs. */ + if (!((!keys[i].uid[0].name && !key->uids) + || (keys[i].uid[0].name && !keys[i].uid[1].name + && key->uids && !key->uids->next) + || (keys[i].uid[0].name && keys[i].uid[1].name + && !keys[i].uid[2].name + && key->uids && key->uids->next && !key->uids->next->next) + || (keys[i].uid[0].name && keys[i].uid[1].name + && keys[i].uid[2].name + && key->uids && key->uids->next && key->uids->next->next + && !key->uids->next->next->next))) + { + fprintf (stderr, "Key has unexpected number of user IDs\n"); + exit (1); + } + if (key->uids && key->uids->revoked) + { + fprintf (stderr, "First user ID unexpectedly revoked\n"); + exit (1); + } + if (key->uids && key->uids->invalid) + { + fprintf (stderr, "First user ID unexpectedly invalid\n"); + exit (1); + } + if (key->uids && key->uids->validity != GPGME_VALIDITY_UNKNOWN) + { + fprintf (stderr, "First user ID has unexpectedly validity: %i\n", + key->uids->validity); + exit (1); + } + if (keys[i].uid[0].name + && strcmp (keys[i].uid[0].name, key->uids->name)) + { + fprintf (stderr, "Unexpected name in first user ID: %s\n", + key->uids->name); + exit (1); + } + if (keys[i].uid[0].comment + && strcmp (keys[i].uid[0].comment, key->uids->comment)) + { + fprintf (stderr, "Unexpected comment in first user ID: %s\n", + key->uids->comment); + exit (1); + } + if (keys[i].uid[0].email + && strcmp (keys[i].uid[0].email, key->uids->email)) + { + fprintf (stderr, "Unexpected email in first user ID: %s\n", + key->uids->email); + exit (1); + } + if (key->uids && (!key->uids->signatures || key->uids->signatures->next)) + { + fprintf (stderr, "First user ID unexpected number of signatures\n"); + exit (1); + } + if (keys[i].uid[0].sig.algo != key->uids->signatures->pubkey_algo) + { + fprintf (stderr, "Unexpected algorithm in first user ID sig: %s\n", + gpgme_pubkey_algo_name (key->uids->signatures->pubkey_algo)); + exit (1); + } + if (strcmp (keys[i].uid[0].sig.keyid, key->uids->signatures->keyid)) + { + fprintf (stderr, "Unexpected key ID in first user ID sig: %s\n", + key->uids->signatures->keyid); + exit (1); + } + if (strcmp (keys[i].uid[0].sig.name, key->uids->signatures->name)) + { + fprintf (stderr, "Unexpected name in first user ID sig: %s\n", + key->uids->signatures->name); + exit (1); + } + if (strcmp (keys[i].uid[0].sig.comment, key->uids->signatures->comment)) + { + fprintf (stderr, "Unexpected comment in first user ID sig: %s\n", + key->uids->signatures->comment); + exit (1); + } + if (strcmp (keys[i].uid[0].sig.email, key->uids->signatures->email)) + { + fprintf (stderr, "Unexpected email in first user ID sig: %s\n", + key->uids->signatures->email); + exit (1); + } + if (keys[i].uid[0].sig.sig_class != key->uids->signatures->sig_class) + { + fprintf (stderr, "Unexpected class in first user ID sig: %i\n", + key->uids->signatures->sig_class); + exit (1); + } + if (keys[i].uid[0].sig.exportable != key->uids->signatures->exportable) + { + fprintf (stderr, "Unexpected exportable stat in first user ID sig: %i\n", + key->uids->signatures->exportable); + exit (1); + } + + if (key->uids && key->uids->next && key->uids->next->revoked) + { + fprintf (stderr, "Second user ID unexpectedly revoked\n"); + exit (1); + } + if (key->uids && key->uids->next && key->uids->next->invalid) + { + fprintf (stderr, "Second user ID unexpectedly invalid\n"); + exit (1); + } + if (key->uids && key->uids->next + && key->uids->next->validity != GPGME_VALIDITY_UNKNOWN) + { + fprintf (stderr, "Second user ID has unexpectedly validity: %i\n", + key->uids->next->validity); + exit (1); + } + if (keys[i].uid[1].name + && strcmp (keys[i].uid[1].name, key->uids->next->name)) + { + fprintf (stderr, "Unexpected name in second user ID: %s\n", + key->uids->next->name); + exit (1); + } + if (keys[i].uid[1].comment + && strcmp (keys[i].uid[1].comment, key->uids->next->comment)) + { + fprintf (stderr, "Unexpected comment in second user ID: %s\n", + key->uids->next->comment); + exit (1); + } + if (keys[i].uid[1].email + && strcmp (keys[i].uid[1].email, key->uids->next->email)) + { + fprintf (stderr, "Unexpected email in second user ID: %s\n", + key->uids->next->email); + exit (1); + } + /*FIXME: There is a bug in gpg 1.3.4 which duplicates a signaure + after importing the secret key. We disable this test for + now. */ +#ifdef __GNUC__ +#warning test disabled due to problems with gpg 1.3.4 generated key +#endif + if (key->uids && (!key->uids->next->signatures /*|| key->uids->next->signatures->next*/)) + { + fprintf (stderr, "Second user ID unexpected number of signatures\n"); + exit (1); + } + if (keys[i].uid[1].sig.algo != key->uids->next->signatures->pubkey_algo) + { + fprintf (stderr, "Unexpected algorithm in second user ID sig: %s\n", + gpgme_pubkey_algo_name (key->uids->next->signatures->pubkey_algo)); + exit (1); + } + if (strcmp (keys[i].uid[1].sig.keyid, key->uids->next->signatures->keyid)) + { + fprintf (stderr, "Unexpected key ID in second user ID sig: %s\n", + key->uids->next->signatures->keyid); + exit (1); + } + if (strcmp (keys[i].uid[1].sig.name, key->uids->next->signatures->name)) + { + fprintf (stderr, "Unexpected name in second user ID sig: %s\n", + key->uids->next->signatures->name); + exit (1); + } + if (strcmp (keys[i].uid[1].sig.comment, key->uids->next->signatures->comment)) + { + fprintf (stderr, "Unexpected comment in second user ID sig: %s\n", + key->uids->next->signatures->comment); + exit (1); + } + if (strcmp (keys[i].uid[1].sig.email, key->uids->next->signatures->email)) + { + fprintf (stderr, "Unexpected email in second user ID sig: %s\n", + key->uids->next->signatures->email); + exit (1); + } + if (keys[i].uid[1].sig.sig_class != key->uids->next->signatures->sig_class) + { + fprintf (stderr, "Unexpected class in second user ID sig: %i\n", + key->uids->next->signatures->sig_class); + exit (1); + } + if (keys[i].uid[1].sig.exportable != key->uids->next->signatures->exportable) + { + fprintf (stderr, "Unexpected exportable stat in second user ID sig: %i\n", + key->uids->next->signatures->exportable); + exit (1); + } + + if (key->uids && key->uids->next && key->uids->next->next + && key->uids->next->next->revoked) + { + fprintf (stderr, "Third user ID unexpectedly revoked\n"); + exit (1); + } + if (key->uids && key->uids->next && key->uids->next->next + && key->uids->next->next->invalid) + { + fprintf (stderr, "Third user ID unexpectedly invalid\n"); + exit (1); + } + if (key->uids && key->uids->next && key->uids->next->next + && key->uids->next->next->validity != GPGME_VALIDITY_UNKNOWN) + { + fprintf (stderr, "Third user ID has unexpectedly validity: %i\n", + key->uids->next->next->validity); + exit (1); + } + if (keys[i].uid[2].name + && strcmp (keys[i].uid[2].name, key->uids->next->next->name)) + { + fprintf (stderr, "Unexpected name in third user ID: %s\n", + key->uids->next->next->name); + exit (1); + } + if (keys[i].uid[2].comment + && strcmp (keys[i].uid[2].comment, key->uids->next->next->comment)) + { + fprintf (stderr, "Unexpected comment in third user ID: %s\n", + key->uids->next->next->comment); + exit (1); + } + if (keys[i].uid[2].email + && strcmp (keys[i].uid[2].email, key->uids->next->next->email)) + { + fprintf (stderr, "Unexpected email in third user ID: %s\n", + key->uids->next->next->email); + exit (1); + } + if (key->uids && (!key->uids->next->next->signatures + || key->uids->next->next->signatures->next)) + { + fprintf (stderr, "Third user ID unexpected number of signatures\n"); + exit (1); + } + if (keys[i].uid[2].sig.algo != key->uids->next->next->signatures->pubkey_algo) + { + fprintf (stderr, "Unexpected algorithm in third user ID sig: %s\n", + gpgme_pubkey_algo_name (key->uids->next->next->signatures->pubkey_algo)); + exit (1); + } + if (strcmp (keys[i].uid[2].sig.keyid, key->uids->next->next->signatures->keyid)) + { + fprintf (stderr, "Unexpected key ID in third user ID sig: %s\n", + key->uids->next->next->signatures->keyid); + exit (1); + } + if (strcmp (keys[i].uid[2].sig.name, key->uids->next->next->signatures->name)) + { + fprintf (stderr, "Unexpected name in third user ID sig: %s\n", + key->uids->next->next->signatures->name); + exit (1); + } + if (strcmp (keys[i].uid[2].sig.comment, key->uids->next->next->signatures->comment)) + { + fprintf (stderr, "Unexpected comment in third user ID sig: %s\n", + key->uids->next->next->signatures->comment); + exit (1); + } + if (strcmp (keys[i].uid[2].sig.email, key->uids->next->next->signatures->email)) + { + fprintf (stderr, "Unexpected email in third user ID sig: %s\n", + key->uids->next->next->signatures->email); + exit (1); + } + if (keys[i].uid[2].sig.sig_class != key->uids->next->next->signatures->sig_class) + { + fprintf (stderr, "Unexpected class in third user ID sig: %i\n", + key->uids->next->next->signatures->sig_class); + exit (1); + } + if (keys[i].uid[2].sig.exportable != key->uids->next->next->signatures->exportable) + { + fprintf (stderr, "Unexpected exportable stat in third user ID sig: %i\n", + key->uids->next->next->signatures->exportable); + exit (1); + } + + + + + + gpgme_key_unref (key); + i++; + } + if (gpg_err_code (err) != GPG_ERR_EOF) + fail_if_err (err); + err = gpgme_op_keylist_end (ctx); + fail_if_err (err); + + result = gpgme_op_keylist_result (ctx); + if (result->truncated) + { + fprintf (stderr, "Key listing unexpectedly truncated\n"); + exit (1); + } + + if (keys[i].fpr) + { + fprintf (stderr, "Less keys returned than expected\n"); + exit (1); + } + + gpgme_release (ctx); + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpg/t-keylist.c b/tags/gpgme-1.1.6/tests/gpg/t-keylist.c new file mode 100644 index 0000000..c8c71d0 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/t-keylist.c @@ -0,0 +1,579 @@ +/* t-keylist.c - regression test + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +#include "t-support.h" + + +struct key_info_s +{ + char *fpr; + char *sec_keyid; + struct + { + char *name; + char *comment; + char *email; + } uid[3]; + int n_subkeys; + void (*misc_check)(struct key_info_s *keyinfo, gpgme_key_t key); +}; + + +static void check_whisky (struct key_info_s *keyinfo, gpgme_key_t key); + + + +struct key_info_s keys[] = + { + { "A0FF4590BB6122EDEF6E3C542D727CC768697734", "6AE6D7EE46A871F8", + { { "Alfa Test", "demo key", "alfa@example.net" }, + { "Alpha Test", "demo key", "alpha@example.net" }, + { "Alice", "demo key", NULL } }, 1 }, + { "D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", "5381EA4EE29BA37F", + { { "Bob", "demo key", NULL }, + { "Bravo Test", "demo key", "bravo@example.net" } }, 1 }, + { "61EE841A2A27EB983B3B3C26413F4AF31AFDAB6C", "E71E72ACBC43DA60", + { { "Charlie Test", "demo key", "charlie@example.net" } }, 1 }, + { "6560C59C43D031C54D7C588EEBA9F240EB9DC9E6", "06F22880B0C45424", + { { "Delta Test", "demo key", "delta@example.net" } }, 1 }, + { "3531152DE293E26A07F504BC318C1FAEFAEF6D1B", "B5C79E1A7272144D", + { { "Echelon", "demo key", NULL }, + { "Echo Test", "demo key", "echo@example.net" }, + { "Eve", "demo key", NULL } }, 1 }, + { "56D33268F7FE693FBB594762D4BF57F37372E243", "0A32EE79EE45198E", + { { "Foxtrot Test", "demo key", "foxtrot@example.net" } }, 1 }, + { "C9C07DCC6621B9FB8D071B1D168410A48FC282E6", "247491CC9DCAD354", + { { "Golf Test", "demo key", "golf@example.net" } }, 1 }, + { "9E91CBB11E4D4135583EF90513DB965534C6E3F1", "76E26537D622AD0A", + { { "Hotel Test", "demo key", "hotel@example.net" } }, 1 }, + { "CD538D6CC9FB3D745ECDA5201FE8FC6F04259677", "C1C8EFDE61F76C73", + { { "India Test", "demo key", "india@example.net" } }, 1 }, + { "F8F1EDC73995AB739AD54B380C820C71D2699313", "BD0B108735F8F136", + { { "Juliet Test", "demo key", "juliet@example.net" } }, 1 }, + { "3FD11083779196C2ECDD9594AD1B0FAD43C2D0C7", "86CBB34A9AF64D02", + { { "Kilo Test", "demo key", "kilo@example.net" } }, 1 }, + { "1DDD28CEF714F5B03B8C246937CAB51FB79103F8", "0363B449FE56350C", + { { "Lima Test", "demo key", "lima@example.net" } }, 1 }, + { "2686AA191A278013992C72EBBE794852BE5CF886", "5F600A834F31EAE8", + { { "Mallory", "demo key", NULL }, + { "Mike Test", "demo key", "mike@example.net" } }, 1 }, + { "5AB9D6D7BAA1C95B3BAA3D9425B00FD430CEC684", "4C1D63308B70E472", + { { "November Test", "demo key", "november@example.net" } }, 1 }, + { "43929E89F8F79381678CAE515F6356BA6D9732AC", "FF0785712681619F", + { { "Oscar Test", "demo key", "oscar@example.net" } }, 1 }, + { "6FAA9C201E5E26DCBAEC39FD5D15E01D3FF13206", "2764E18263330D9C", + { { "Papa test", "demo key", "papa@example.net" } }, 1 }, + { "A7969DA1C3297AA96D49843F1C67EC133C661C84", "6CDCFC44A029ACF4", + { { "Quebec Test", "demo key", "quebec@example.net" } }, 1 }, + { "38FBE1E4BF6A5E1242C8F6A13BDBEDB1777FBED3", "9FAB805A11D102EA", + { { "Romeo Test", "demo key", "romeo@example.net" } }, 1 }, + { "045B2334ADD69FC221076841A5E67F7FA3AE3EA1", "93B88B0F0F1B50B4", + { { "Sierra Test", "demo key", "sierra@example.net" } }, 1 }, + { "ECAC774F4EEEB0620767044A58CB9A4C85A81F38", "97B60E01101C0402", + { { "Tango Test", "demo key", "tango@example.net" } }, 1 }, + { "0DBCAD3F08843B9557C6C4D4A94C0F75653244D6", "93079B915522BDB9", + { { "Uniform Test", "demo key", "uniform@example.net" } }, 1 }, + { "E8143C489C8D41124DC40D0B47AF4B6961F04784", "04071FB807287134", + { { "Victor Test", "demo key", "victor@example.org" } }, 1 }, + { "E8D6C90B683B0982BD557A99DEF0F7B8EC67DBDE", "D7FBB421FD6E27F6", + { { "Whisky Test", "demo key", "whisky@example.net" } }, 3, + check_whisky }, + { "04C1DF62EFA0EBB00519B06A8979A6C5567FB34A", "5CC6F87F41E408BE", + { { "XRay Test", "demo key", "xray@example.net" } }, 1 }, + { "ED9B316F78644A58D042655A9EEF34CD4B11B25F", "5ADFD255F7B080AD", + { { "Yankee Test", "demo key", "yankee@example.net" } }, 1 }, + { "23FD347A419429BACCD5E72D6BC4778054ACD246", "EF9DC276A172C881", + { { "Zulu Test", "demo key", "zulu@example.net" } }, 1 }, + { "ADAB7FCC1F4DE2616ECFA402AF82244F9CD9FD55", "087DD7E0381701C4", + { { "Joe Random Hacker", "test key with passphrase \"x\"", + "joe@setq.org" } }, 1 }, + { NULL } + }; + + +int +main (int argc, char **argv) +{ + gpgme_error_t err; + gpgme_ctx_t ctx; + gpgme_key_t key; + gpgme_keylist_result_t result; + int i = 0; + int n; + gpgme_subkey_t subkey; + + init_gpgme (GPGME_PROTOCOL_OpenPGP); + + err = gpgme_new (&ctx); + fail_if_err (err); + + err = gpgme_op_keylist_start (ctx, NULL, 0); + fail_if_err (err); + + while (!(err = gpgme_op_keylist_next (ctx, &key))) + { + if (!keys[i].fpr) + { + fprintf (stderr, "More keys returned than expected\n"); + exit (1); + } + + /* Global key flags. */ + if (key->revoked) + { + fprintf (stderr, "Key unexpectedly revoked\n"); + exit (1); + } + if (key->expired) + { + fprintf (stderr, "Key unexpectedly expired\n"); + exit (1); + } + if (key->disabled) + { + fprintf (stderr, "Key unexpectedly disabled\n"); + exit (1); + } + if (key->invalid) + { + fprintf (stderr, "Key unexpectedly invalid\n"); + exit (1); + } + if (!key->can_encrypt) + { + fprintf (stderr, "Key unexpectedly unusable for encryption\n"); + exit (1); + } + if (!key->can_sign) + { + fprintf (stderr, "Key unexpectedly unusable for signing\n"); + exit (1); + } + if (!key->can_certify) + { + fprintf (stderr, "Key unexpectedly unusable for certifications\n"); + exit (1); + } + if (key->secret) + { + fprintf (stderr, "Key unexpectedly secret\n"); + exit (1); + } + if (key->protocol != GPGME_PROTOCOL_OpenPGP) + { + fprintf (stderr, "Key has unexpected protocol: %s\n", + gpgme_get_protocol_name (key->protocol)); + exit (1); + } + if (key->issuer_serial) + { + fprintf (stderr, "Key unexpectedly carries issuer serial: %s\n", + key->issuer_serial); + exit (1); + } + if (key->issuer_name) + { + fprintf (stderr, "Key unexpectedly carries issuer name: %s\n", + key->issuer_name); + exit (1); + } + if (key->chain_id) + { + fprintf (stderr, "Key unexpectedly carries chain ID: %s\n", + key->chain_id); + exit (1); + } + if (key->owner_trust != GPGME_VALIDITY_UNKNOWN) + { + fprintf (stderr, "Key has unexpected owner trust: %i\n", + key->owner_trust); + exit (1); + } + + for (n=0, subkey = key->subkeys; subkey; subkey = subkey->next) + n++; + if (!n || n-1 != keys[i].n_subkeys) + { + fprintf (stderr, "Key `%s' has unexpected number of subkeys\n", + keys[i].uid[0].name); + exit (1); + } + + /* Primary key. */ + if (key->subkeys->revoked) + { + fprintf (stderr, "Primary key unexpectedly revoked\n"); + exit (1); + } + if (key->subkeys->expired) + { + fprintf (stderr, "Primary key unexpectedly expired\n"); + exit (1); + } + if (key->subkeys->disabled) + { + fprintf (stderr, "Primary key unexpectedly disabled\n"); + exit (1); + } + if (key->subkeys->invalid) + { + fprintf (stderr, "Primary key unexpectedly invalid\n"); + exit (1); + } + if (key->subkeys->can_encrypt) + { + fprintf (stderr, "Primary key unexpectedly usable for encryption\n"); + exit (1); + } + if (!key->subkeys->can_sign) + { + fprintf (stderr, "Primary key unexpectedly unusable for signing\n"); + exit (1); + } + if (!key->subkeys->can_certify) + { + fprintf (stderr, "Primary key unexpectedly unusable for certifications\n"); + exit (1); + } + if (key->subkeys->secret) + { + fprintf (stderr, "Primary key unexpectedly secret\n"); + exit (1); + } + if (key->subkeys->pubkey_algo != GPGME_PK_DSA) + { + fprintf (stderr, "Primary key has unexpected public key algo: %s\n", + gpgme_pubkey_algo_name (key->subkeys->pubkey_algo)); + exit (1); + } + if (key->subkeys->length != 1024) + { + fprintf (stderr, "Primary key has unexpected length: %i\n", + key->subkeys->length); + exit (1); + } + if (strcmp (key->subkeys->keyid, &keys[i].fpr[40 - 16])) + { + fprintf (stderr, "Primary key `%s' has unexpected key ID: %s\n", + keys[i].uid[0].name, key->subkeys->keyid); + exit (1); + } + if (strcmp (key->subkeys->fpr, keys[i].fpr)) + { + fprintf (stderr, "Primary key has unexpected fingerprint: %s\n", + key->subkeys->fpr); + exit (1); + } + if (key->subkeys->expires) + { + fprintf (stderr, "Primary key `%s' unexpectedly expires: %lu\n", + keys[i].uid[0].name, key->subkeys->expires); + exit (1); + } + + /* Secondary key. */ + if (key->subkeys->next->revoked) + { + fprintf (stderr, "Secondary key unexpectedly revoked\n"); + exit (1); + } + if (key->subkeys->next->expired) + { + fprintf (stderr, "Secondary key unexpectedly expired\n"); + exit (1); + } + if (key->subkeys->next->disabled) + { + fprintf (stderr, "Secondary key unexpectedly disabled\n"); + exit (1); + } + if (key->subkeys->next->invalid) + { + fprintf (stderr, "Secondary key unexpectedly invalid\n"); + exit (1); + } + if (!key->subkeys->next->can_encrypt) + { + fprintf (stderr, "Secondary key unexpectedly unusable for encryption\n"); + exit (1); + } + if (key->subkeys->next->can_sign) + { + fprintf (stderr, "Secondary key unexpectedly usable for signing\n"); + exit (1); + } + if (key->subkeys->next->can_certify) + { + fprintf (stderr, "Secondary key unexpectedly usable for certifications\n"); + exit (1); + } + if (key->subkeys->next->secret) + { + fprintf (stderr, "Secondary key unexpectedly secret\n"); + exit (1); + } + if (key->subkeys->next->pubkey_algo != GPGME_PK_ELG_E) + { + fprintf (stderr, "Secondary key has unexpected public key algo: %s\n", + gpgme_pubkey_algo_name (key->subkeys->next->pubkey_algo)); + exit (1); + } + if (key->subkeys->next->length != 1024) + { + fprintf (stderr, "Secondary key has unexpected length: %i\n", + key->subkeys->next->length); + exit (1); + } + if (strcmp (key->subkeys->next->keyid, keys[i].sec_keyid)) + { + fprintf (stderr, "Secondary key `%s' has unexpected key ID: %s/%s\n", + keys[i].uid[0].name, + key->subkeys->next->keyid, keys[i].sec_keyid ); + exit (1); + } + if (!key->subkeys->next->fpr) + { + fprintf (stderr, "Secondary key has unexpectedly no fingerprint\n"); + exit (1); + } + if (key->subkeys->next->expires) + { + fprintf (stderr, "Secondary key unexpectedly expires: %lu\n", + key->subkeys->next->expires); + exit (1); + } + + /* FIXME: The below test will crash if we want to check for a + name, comment or email that doesn't exist in the key's user + IDs. */ + if (!((!keys[i].uid[0].name && !key->uids) + || (keys[i].uid[0].name && !keys[i].uid[1].name + && key->uids && !key->uids->next) + || (keys[i].uid[0].name && keys[i].uid[1].name + && !keys[i].uid[2].name + && key->uids && key->uids->next && !key->uids->next->next) + || (keys[i].uid[0].name && keys[i].uid[1].name + && keys[i].uid[2].name + && key->uids && key->uids->next && key->uids->next->next + && !key->uids->next->next->next))) + { + fprintf (stderr, "Key has unexpected number of user IDs\n"); + exit (1); + } + if (key->uids && key->uids->revoked) + { + fprintf (stderr, "First user ID unexpectedly revoked\n"); + exit (1); + } + if (key->uids && key->uids->invalid) + { + fprintf (stderr, "First user ID unexpectedly invalid\n"); + exit (1); + } + if (key->uids && key->uids->validity != GPGME_VALIDITY_UNKNOWN) + { + fprintf (stderr, "First user ID has unexpectedly validity: %i\n", + key->uids->validity); + exit (1); + } + if (key->uids && key->uids->signatures) + { + fprintf (stderr, "First user ID unexpectedly signed\n"); + exit (1); + } + if (keys[i].uid[0].name + && strcmp (keys[i].uid[0].name, key->uids->name)) + { + fprintf (stderr, "Unexpected name in first user ID: %s\n", + key->uids->name); + exit (1); + } + if (keys[i].uid[0].comment + && strcmp (keys[i].uid[0].comment, key->uids->comment)) + { + fprintf (stderr, "Unexpected comment in first user ID: %s\n", + key->uids->comment); + exit (1); + } + if (keys[i].uid[0].email + && strcmp (keys[i].uid[0].email, key->uids->email)) + { + fprintf (stderr, "Unexpected email in first user ID: %s\n", + key->uids->email); + exit (1); + } + if (key->uids && key->uids->next && key->uids->next->revoked) + { + fprintf (stderr, "Second user ID unexpectedly revoked\n"); + exit (1); + } + if (key->uids && key->uids->next && key->uids->next->invalid) + { + fprintf (stderr, "Second user ID unexpectedly invalid\n"); + exit (1); + } + if (key->uids && key->uids->next + && key->uids->next->validity != GPGME_VALIDITY_UNKNOWN) + { + fprintf (stderr, "Second user ID has unexpectedly validity: %i\n", + key->uids->next->validity); + exit (1); + } + if (key->uids && key->uids->next && key->uids->next->signatures) + { + fprintf (stderr, "Second user ID unexpectedly signed\n"); + exit (1); + } + if (keys[i].uid[1].name + && strcmp (keys[i].uid[1].name, key->uids->next->name)) + { + fprintf (stderr, "Unexpected name in second user ID: %s\n", + key->uids->next->name); + exit (1); + } + if (keys[i].uid[1].comment + && strcmp (keys[i].uid[1].comment, key->uids->next->comment)) + { + fprintf (stderr, "Unexpected comment in second user ID: %s\n", + key->uids->next->comment); + exit (1); + } + if (keys[i].uid[1].email + && strcmp (keys[i].uid[1].email, key->uids->next->email)) + { + fprintf (stderr, "Unexpected email in second user ID: %s\n", + key->uids->next->email); + exit (1); + } + if (key->uids && key->uids->next && key->uids->next->next + && key->uids->next->next->revoked) + { + fprintf (stderr, "Third user ID unexpectedly revoked\n"); + exit (1); + } + if (key->uids && key->uids->next && key->uids->next->next + && key->uids->next->next->invalid) + { + fprintf (stderr, "Third user ID unexpectedly invalid\n"); + exit (1); + } + if (key->uids && key->uids->next && key->uids->next->next + && key->uids->next->next->validity != GPGME_VALIDITY_UNKNOWN) + { + fprintf (stderr, "Third user ID has unexpectedly validity: %i\n", + key->uids->next->next->validity); + exit (1); + } + if (key->uids && key->uids->next && key->uids->next->next + && key->uids->next->next->signatures) + { + fprintf (stderr, "Third user ID unexpectedly signed\n"); + exit (1); + } + if (keys[i].uid[2].name + && strcmp (keys[i].uid[2].name, key->uids->next->next->name)) + { + fprintf (stderr, "Unexpected name in third user ID: %s\n", + key->uids->next->next->name); + exit (1); + } + if (keys[i].uid[2].comment + && strcmp (keys[i].uid[2].comment, key->uids->next->next->comment)) + { + fprintf (stderr, "Unexpected comment in third user ID: %s\n", + key->uids->next->next->comment); + exit (1); + } + if (keys[i].uid[2].email + && strcmp (keys[i].uid[2].email, key->uids->next->next->email)) + { + fprintf (stderr, "Unexpected email in third user ID: %s\n", + key->uids->next->next->email); + exit (1); + } + + if (keys[i].misc_check) + keys[i].misc_check (keys+i, key); + + gpgme_key_unref (key); + i++; + } + if (gpg_err_code (err) != GPG_ERR_EOF) + fail_if_err (err); + err = gpgme_op_keylist_end (ctx); + fail_if_err (err); + + result = gpgme_op_keylist_result (ctx); + if (result->truncated) + { + fprintf (stderr, "Key listing unexpectedly truncated\n"); + exit (1); + } + + if (keys[i].fpr) + { + fprintf (stderr, "Less keys returned than expected\n"); + exit (1); + } + + gpgme_release (ctx); + return 0; +} + + + +/* Check expration of keys. This test assumes three subkeys of which + 2 are expired; it is used with the "Whisky" test key. It has + already been checked that these 3 subkeys are available. */ +static void +check_whisky (struct key_info_s *keyinfo, gpgme_key_t key) +{ + const char *name = keyinfo->uid[0].name; + gpgme_subkey_t sub1, sub2; + + sub1 = key->subkeys->next->next; + sub2 = sub1->next; + + if (!sub1->expired || !sub2->expired) + { + fprintf (stderr, "Subkey of `%s' not flagged as expired\n", name); + exit (1); + } + if (sub1->expires != 1129636886 || sub2->expires != 1129636939) + { + fprintf (stderr, "Subkey of `%s' has wrong expiration date\n", name); + exit (1); + } + +} + diff --git a/tags/gpgme-1.1.6/tests/gpg/t-sig-notation.c b/tags/gpgme-1.1.6/tests/gpg/t-sig-notation.c new file mode 100644 index 0000000..7345a52 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/t-sig-notation.c @@ -0,0 +1,166 @@ +/* t-sig-notation.c - Regression test. + Copyright (C) 2005 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +#include "t-support.h" + + +static struct { + const char *name; + const char *value; + gpgme_sig_notation_flags_t flags; + int seen; +} expected_notations[] = { + { "laughing@me", + "Just Squeeze Me", + GPGME_SIG_NOTATION_HUMAN_READABLE }, + { "preferred-email-encoding@pgp.com", + "pgpmime", + GPGME_SIG_NOTATION_HUMAN_READABLE | GPGME_SIG_NOTATION_CRITICAL }, + { NULL, + "http://www.gnu.org/policy/", + 0 } +}; + +static void +check_result (gpgme_verify_result_t result) +{ + int i; + gpgme_sig_notation_t r; + + gpgme_signature_t sig; + + sig = result->signatures; + if (!sig || sig->next) + { + fprintf (stderr, "%s:%i: Unexpected number of signatures\n", + __FILE__, __LINE__); + exit (1); + } + + for (i=0; i < DIM(expected_notations); i++ ) + expected_notations[i].seen = 0; + + for (r = result->signatures->notations; r; r = r->next) + { + int any = 0; + for (i=0; i < DIM(expected_notations); i++) + { + if ( ((r->name && expected_notations[i].name + && !strcmp (r->name, expected_notations[i].name) + && r->name_len + == strlen (expected_notations[i].name)) + || (!r->name && !expected_notations[i].name + && r->name_len == 0)) + && r->value + && !strcmp (r->value, expected_notations[i].value) + && r->value_len == strlen (expected_notations[i].value) + && r->flags + == (expected_notations[i].flags & ~GPGME_SIG_NOTATION_CRITICAL) + && r->human_readable + == !!(r->flags & GPGME_SIG_NOTATION_HUMAN_READABLE) + && r->critical == 0) + { + expected_notations[i].seen++; + any++; + } + } + if (!any) + { + fprintf (stderr, "%s:%i: Unexpected notation data\n", + __FILE__, __LINE__); + exit (1); + } + } + for (i=0; i < DIM(expected_notations); i++ ) + { + if (expected_notations[i].seen != 1) + { + fprintf (stderr, "%s:%i: Missing or duplicate notation data\n", + __FILE__, __LINE__); + exit (1); + } + } +} + + +int +main (int argc, char *argv[]) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_data_t in, out; + gpgme_verify_result_t result; + char *agent_info; + int i; + + init_gpgme (GPGME_PROTOCOL_OpenPGP); + + err = gpgme_new (&ctx); + fail_if_err (err); + + agent_info = getenv ("GPG_AGENT_INFO"); + if (!(agent_info && strchr (agent_info, ':'))) + gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL); + + 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); + + for (i = 0; i < sizeof (expected_notations) / sizeof (expected_notations[0]); + i++) + { + err = gpgme_sig_notation_add (ctx, expected_notations[i].name, + expected_notations[i].value, + expected_notations[i].flags); + fail_if_err (err); + } + + err = gpgme_op_sign (ctx, in, out, GPGME_SIG_MODE_NORMAL); + fail_if_err (err); + + gpgme_data_release (in); + err = gpgme_data_new (&in); + fail_if_err (err); + + gpgme_data_seek (out, 0, SEEK_SET); + + err = gpgme_op_verify (ctx, out, NULL, in); + fail_if_err (err); + result = gpgme_op_verify_result (ctx); + check_result (result); + + gpgme_data_release (in); + gpgme_data_release (out); + gpgme_release (ctx); + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpg/t-sign.c b/tags/gpgme-1.1.6/tests/gpg/t-sign.c new file mode 100644 index 0000000..3b71dc4 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/t-sign.c @@ -0,0 +1,144 @@ +/* t-sign.c - Regression test. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include + +#include "t-support.h" + + +static void +check_result (gpgme_sign_result_t result, gpgme_sig_mode_t type) +{ + if (result->invalid_signers) + { + fprintf (stderr, "Invalid signer found: %s\n", + result->invalid_signers->fpr); + exit (1); + } + if (!result->signatures || result->signatures->next) + { + fprintf (stderr, "Unexpected number of signatures created\n"); + exit (1); + } + if (result->signatures->type != type) + { + fprintf (stderr, "Wrong type of signature created\n"); + exit (1); + } + if (result->signatures->pubkey_algo != GPGME_PK_DSA) + { + fprintf (stderr, "Wrong pubkey algorithm reported: %i\n", + result->signatures->pubkey_algo); + exit (1); + } + if (result->signatures->hash_algo != GPGME_MD_SHA1) + { + fprintf (stderr, "Wrong hash algorithm reported: %i\n", + result->signatures->hash_algo); + exit (1); + } + if (result->signatures->sig_class != 1) + { + fprintf (stderr, "Wrong signature class reported: %u\n", + result->signatures->sig_class); + exit (1); + } + if (strcmp ("A0FF4590BB6122EDEF6E3C542D727CC768697734", + result->signatures->fpr)) + { + fprintf (stderr, "Wrong fingerprint reported: %s\n", + result->signatures->fpr); + exit (1); + } +} + + +int +main (int argc, char **argv) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_data_t in, out; + gpgme_sign_result_t result; + char *agent_info; + + init_gpgme (GPGME_PROTOCOL_OpenPGP); + + err = gpgme_new (&ctx); + fail_if_err (err); + + agent_info = getenv ("GPG_AGENT_INFO"); + if (!(agent_info && strchr (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); + result = gpgme_op_sign_result (ctx); + check_result (result, GPGME_SIG_MODE_NORMAL); + print_data (out); + gpgme_data_release (out); + + /* Now a detached signature. */ + gpgme_data_seek (in, 0, SEEK_SET); + err = gpgme_data_new (&out); + fail_if_err (err); + err = gpgme_op_sign (ctx, in, out, GPGME_SIG_MODE_DETACH); + fail_if_err (err); + result = gpgme_op_sign_result (ctx); + check_result (result, GPGME_SIG_MODE_DETACH); + print_data (out); + gpgme_data_release (out); + + /* And finally a cleartext signature. */ + gpgme_data_seek (in, 0, SEEK_SET); + err = gpgme_data_new (&out); + fail_if_err (err); + err = gpgme_op_sign (ctx, in, out, GPGME_SIG_MODE_CLEAR); + fail_if_err (err); + result = gpgme_op_sign_result (ctx); + check_result (result, GPGME_SIG_MODE_CLEAR); + print_data (out); + gpgme_data_release (out); + + gpgme_data_release (in); + gpgme_release (ctx); + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpg/t-signers.c b/tags/gpgme-1.1.6/tests/gpg/t-signers.c new file mode 100644 index 0000000..c75c1d4 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/t-signers.c @@ -0,0 +1,174 @@ +/* t-signers.c - Regression tests for the multiple signers interface. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include + +#include "t-support.h" + + +static void +check_result (gpgme_sign_result_t result, gpgme_sig_mode_t type) +{ + gpgme_new_signature_t signature; + + if (result->invalid_signers) + { + fprintf (stderr, "Invalid signer found: %s\n", + result->invalid_signers->fpr); + exit (1); + } + if (!result->signatures || !result->signatures->next + || result->signatures->next->next) + { + fprintf (stderr, "Unexpected number of signatures created\n"); + exit (1); + } + + signature = result->signatures; + while (signature) + { + if (signature->type != type) + { + fprintf (stderr, "Wrong type of signature created\n"); + exit (1); + } + if (signature->pubkey_algo != GPGME_PK_DSA) + { + fprintf (stderr, "Wrong pubkey algorithm reported: %i\n", + signature->pubkey_algo); + exit (1); + } + if (signature->hash_algo != GPGME_MD_SHA1) + { + fprintf (stderr, "Wrong hash algorithm reported: %i\n", + signature->hash_algo); + exit (1); + } + if (signature->sig_class != 1) + { + fprintf (stderr, "Wrong signature class reported: %u\n", + signature->sig_class); + exit (1); + } + if (strcmp ("A0FF4590BB6122EDEF6E3C542D727CC768697734", + signature->fpr) + && strcmp ("23FD347A419429BACCD5E72D6BC4778054ACD246", + signature->fpr)) + { + fprintf (stderr, "Wrong fingerprint reported: %s\n", + signature->fpr); + exit (1); + } + signature = signature->next; + } +} + + +int +main (int argc, char *argv[]) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_data_t in, out; + gpgme_key_t key[2]; + gpgme_sign_result_t result; + char *agent_info; + + init_gpgme (GPGME_PROTOCOL_OpenPGP); + + err = gpgme_new (&ctx); + fail_if_err (err); + + agent_info = getenv("GPG_AGENT_INFO"); + if (!(agent_info && strchr (agent_info, ':'))) + gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL); + + gpgme_set_textmode (ctx, 1); + gpgme_set_armor (ctx, 1); + + err = gpgme_op_keylist_start (ctx, NULL, 1); + fail_if_err (err); + err = gpgme_op_keylist_next (ctx, &key[0]); + fail_if_err (err); + err = gpgme_op_keylist_next (ctx, &key[1]); + fail_if_err (err); + err = gpgme_op_keylist_end (ctx); + fail_if_err (err); + + err = gpgme_signers_add (ctx, key[0]); + fail_if_err (err); + err = gpgme_signers_add (ctx, key[1]); + fail_if_err (err); + + 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); + result = gpgme_op_sign_result (ctx); + check_result (result, GPGME_SIG_MODE_NORMAL); + print_data (out); + gpgme_data_release (out); + + /* Now a detached signature. */ + gpgme_data_seek (in, 0, SEEK_SET); + err = gpgme_data_new (&out); + fail_if_err (err); + err = gpgme_op_sign (ctx, in, out, GPGME_SIG_MODE_DETACH); + fail_if_err (err); + result = gpgme_op_sign_result (ctx); + check_result (result, GPGME_SIG_MODE_DETACH); + print_data (out); + gpgme_data_release (out); + + /* And finally a cleartext signature. */ + gpgme_data_seek (in, 0, SEEK_SET); + err = gpgme_data_new (&out); + fail_if_err (err); + err = gpgme_op_sign (ctx, in, out, GPGME_SIG_MODE_CLEAR); + fail_if_err (err); + result = gpgme_op_sign_result (ctx); + check_result (result, GPGME_SIG_MODE_CLEAR); + print_data (out); + gpgme_data_release (out); + gpgme_data_seek (in, 0, SEEK_SET); + + gpgme_data_release (in); + gpgme_release (ctx); + + gpgme_key_unref (key[0]); + gpgme_key_unref (key[1]); + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpg/t-support.h b/tags/gpgme-1.1.6/tests/gpg/t-support.h new file mode 100644 index 0000000..362b857 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/t-support.h @@ -0,0 +1,115 @@ +/* t-support.h - Helper routines for regression tests. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +#include +#include +#include + +#ifdef HAVE_W32_SYSTEM +#include +#endif + +#include + +#ifndef DIM +#define DIM(v) (sizeof(v)/sizeof((v)[0])) +#endif + +#define fail_if_err(err) \ + do \ + { \ + if (err) \ + { \ + fprintf (stderr, "%s:%d: %s: %s\n", \ + __FILE__, __LINE__, gpgme_strsource (err), \ + gpgme_strerror (err)); \ + exit (1); \ + } \ + } \ + while (0) + + +void +print_data (gpgme_data_t dh) +{ +#define BUF_SIZE 512 + char buf[BUF_SIZE + 1]; + int ret; + + ret = gpgme_data_seek (dh, 0, SEEK_SET); + if (ret) + fail_if_err (gpgme_err_code_from_errno (errno)); + while ((ret = gpgme_data_read (dh, buf, BUF_SIZE)) > 0) + fwrite (buf, ret, 1, stdout); + if (ret < 0) + fail_if_err (gpgme_err_code_from_errno (errno)); +} + + +gpgme_error_t +passphrase_cb (void *opaque, const char *uid_hint, const char *passphrase_info, + int last_was_bad, int fd) +{ +#ifdef HAVE_W32_SYSTEM + DWORD written; + WriteFile ((HANDLE) fd, "abc\n", 4, &written, 0); +#else + write (fd, "abc\n", 4); +#endif + + return 0; +} + + +char * +make_filename (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; +} + + +void +init_gpgme (gpgme_protocol_t proto) +{ + gpgme_error_t err; + + gpgme_check_version (NULL); + setlocale (LC_ALL, ""); + gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL)); +#ifndef HAVE_W32_SYSTEM + gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL)); +#endif + + err = gpgme_engine_check_version (proto); + fail_if_err (err); +} diff --git a/tags/gpgme-1.1.6/tests/gpg/t-thread1.c b/tags/gpgme-1.1.6/tests/gpg/t-thread1.c new file mode 100644 index 0000000..86ea51a --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/t-thread1.c @@ -0,0 +1,156 @@ +/* t-thread1.c - Regression test. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include + +#include "t-support.h" + +#define ROUNDS 20 + + +void * +thread_one (void *name) +{ + int i; + + for (i = 0; i < ROUNDS; i++) + { + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_data_t in, out; + gpgme_key_t key[3] = { NULL, NULL, NULL }; + gpgme_encrypt_result_t result; + + err = gpgme_new (&ctx); + fail_if_err (err); + gpgme_set_armor (ctx, 1); + + 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_get_key (ctx, "A0FF4590BB6122EDEF6E3C542D727CC768697734", + &key[0], 0); + fail_if_err (err); + err = gpgme_get_key (ctx, "D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", + &key[1], 0); + fail_if_err (err); + + err = gpgme_op_encrypt (ctx, key, GPGME_ENCRYPT_ALWAYS_TRUST, in, out); + fail_if_err (err); + result = gpgme_op_encrypt_result (ctx); + if (result->invalid_recipients) + { + fprintf (stderr, "Invalid recipient encountered: %s\n", + result->invalid_recipients->fpr); + exit (1); + } + printf ("Encrypt %s %i\n", (char *) name, i); + + gpgme_key_unref (key[0]); + gpgme_key_unref (key[1]); + gpgme_data_release (in); + gpgme_data_release (out); + gpgme_release (ctx); + } + return NULL; +} + + +void * +thread_two (void *name) +{ + int i; + const char *cipher_1_asc = make_filename ("cipher-1.asc"); + char *agent_info; + + agent_info = getenv("GPG_AGENT_INFO"); + + for (i = 0; i < ROUNDS; i++) + { + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_data_t in, out; + gpgme_decrypt_result_t result; + + init_gpgme (GPGME_PROTOCOL_OpenPGP); + + err = gpgme_new (&ctx); + fail_if_err (err); + + if (!(agent_info && strchr (agent_info, ':'))) + gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL); + + 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); + result = gpgme_op_decrypt_result (ctx); + if (result->unsupported_algorithm) + { + fprintf (stderr, "%s:%i: unsupported algorithm: %s\n", + __FILE__, __LINE__, result->unsupported_algorithm); + exit (1); + } + printf ("Decrypt %s %i\n", (char *) name, i); + + gpgme_data_release (in); + gpgme_data_release (out); + gpgme_release (ctx); + } + return NULL; +} + +int +main (int argc, char *argv[]) +{ + pthread_t tone; + pthread_t ttwo; + + init_gpgme (GPGME_PROTOCOL_OpenPGP); + + pthread_create (&tone, NULL, thread_one, "A"); + pthread_create (&ttwo, NULL, thread_two, "B"); + + pthread_join (tone, NULL); + pthread_join (ttwo, NULL); + + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpg/t-trustlist.c b/tags/gpgme-1.1.6/tests/gpg/t-trustlist.c new file mode 100644 index 0000000..7707639 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/t-trustlist.c @@ -0,0 +1,64 @@ +/* t-trustlist.c - Regression test. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +#include "t-support.h" + + +int +main (int argc, char *argv[]) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_trust_item_t item; + + init_gpgme (GPGME_PROTOCOL_OpenPGP); + + err = gpgme_new (&ctx); + fail_if_err (err); + + err = gpgme_op_trustlist_start (ctx, "alice", 0); + fail_if_err (err); + + while (!(err = gpgme_op_trustlist_next (ctx, &item))) + { + printf ("l=%d k=%s t=%d o=%s v=%s u=%s\n", + item->level, item->keyid, item->type, item->owner_trust, + item->validity, item->name); + gpgme_trust_item_unref (item); + } + if (gpg_err_code (err) != GPG_ERR_EOF) + fail_if_err (err); + + gpgme_release (ctx); + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpg/t-verify.c b/tags/gpgme-1.1.6/tests/gpg/t-verify.c new file mode 100644 index 0000000..0efd06f --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/t-verify.c @@ -0,0 +1,273 @@ +/* t-verify.c - Regression test. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +#include "t-support.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 +; +static const char test_sig2[] = +"-----BEGIN PGP MESSAGE-----\n" +"\n" +"owGbwMvMwCSoW1RzPCOz3IRxjXQSR0lqcYleSUWJTZOvjVdpcYmCu1+oQmaJIleH\n" +"GwuDIBMDGysTSIqBi1MApi+nlGGuwDeHao53HBr+FoVGP3xX+kvuu9fCMJvl6IOf\n" +"y1kvP4y+8D5a11ang0udywsA\n" +"=Crq6\n" +"-----END PGP MESSAGE-----\n"; + +/* A message with a prepended but unsigned plaintext packet. */ +static const char double_plaintext_sig[] = +"-----BEGIN PGP MESSAGE-----\n" +"\n" +"rDRiCmZvb2Jhci50eHRF4pxNVGhpcyBpcyBteSBzbmVha3kgcGxhaW50ZXh0IG1l\n" +"c3NhZ2UKowGbwMvMwCSoW1RzPCOz3IRxTWISa6JebnG666MFD1wzSzJSixQ81XMV\n" +"UlITUxTyixRyKxXKE0uSMxQyEosVikvyCwpSU/S4FNCArq6Ce1F+aXJGvoJvYlGF\n" +"erFCTmJxiUJ5flFKMVeHGwuDIBMDGysTyA4GLk4BmO036xgWzMgzt9V85jCtfDFn\n" +"UqVooWlGXHwNw/xg/fVzt9VNbtjtJ/fhUqYo0/LyCGEA\n" +"=6+AK\n" +"-----END PGP MESSAGE-----\n"; + + + + +static void +check_result (gpgme_verify_result_t result, unsigned int summary, char *fpr, + gpgme_error_t status, int notation) +{ + gpgme_signature_t sig; + + sig = result->signatures; + if (!sig || sig->next) + { + fprintf (stderr, "%s:%i: Unexpected number of signatures\n", + __FILE__, __LINE__); + exit (1); + } + if (sig->summary != summary) + { + fprintf (stderr, "%s:%i: Unexpected signature summary: " + "want=0x%x have=0x%x\n", + __FILE__, __LINE__, summary, sig->summary); + exit (1); + } + if (strcmp (sig->fpr, fpr)) + { + fprintf (stderr, "%s:%i: Unexpected fingerprint: %s\n", + __FILE__, __LINE__, sig->fpr); + exit (1); + } + if (gpg_err_code (sig->status) != status) + { + fprintf (stderr, "%s:%i: Unexpected signature status: %s\n", + __FILE__, __LINE__, gpg_strerror (sig->status)); + exit (1); + } + if (notation) + { + static struct { + const char *name; + const char *value; + int seen; + } expected_notations[] = { + { "bar", + "\xc3\xb6\xc3\xa4\xc3\xbc\xc3\x9f" + " das waren Umlaute und jetzt ein prozent%-Zeichen" }, + { "foobar.1", + "this is a notation data with 2 lines" }, + { NULL, + "http://www.gu.org/policy/" } + }; + int i; + gpgme_sig_notation_t r; + + for (i=0; i < DIM(expected_notations); i++ ) + expected_notations[i].seen = 0; + + for (r = sig->notations; r; r = r->next) + { + int any = 0; + for (i=0; i < DIM(expected_notations); i++) + { + if ( ((r->name && expected_notations[i].name + && !strcmp (r->name, expected_notations[i].name) + && r->name_len + == strlen (expected_notations[i].name)) + || (!r->name && !expected_notations[i].name + && r->name_len == 0)) + && r->value + && !strcmp (r->value, expected_notations[i].value) + && r->value_len == strlen (expected_notations[i].value)) + { + expected_notations[i].seen++; + any++; + } + } + if (!any) + { + fprintf (stderr, "%s:%i: Unexpected notation data\n", + __FILE__, __LINE__); + exit (1); + } + } + for (i=0; i < DIM(expected_notations); i++ ) + { + if (expected_notations[i].seen != 1) + { + fprintf (stderr, "%s:%i: Missing or duplicate notation data\n", + __FILE__, __LINE__); + exit (1); + } + } + } + if (sig->wrong_key_usage) + { + fprintf (stderr, "%s:%i: Unexpectedly wrong key usage\n", + __FILE__, __LINE__); + exit (1); + } + if (sig->validity != GPGME_VALIDITY_UNKNOWN) + { + fprintf (stderr, "%s:%i: Unexpected validity: %i\n", + __FILE__, __LINE__, sig->validity); + exit (1); + } + if (gpg_err_code (sig->validity_reason) != GPG_ERR_NO_ERROR) + { + fprintf (stderr, "%s:%i: Unexpected validity reason: %s\n", + __FILE__, __LINE__, gpgme_strerror (sig->validity_reason)); + exit (1); + } +} + + +int +main (int argc, char *argv[]) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_data_t sig, text; + gpgme_verify_result_t result; + + init_gpgme (GPGME_PROTOCOL_OpenPGP); + + err = gpgme_new (&ctx); + fail_if_err (err); + + /* Checking a valid message. */ + err = gpgme_data_new_from_mem (&text, test_text1, strlen (test_text1), 0); + fail_if_err (err); + err = gpgme_data_new_from_mem (&sig, test_sig1, strlen (test_sig1), 0); + fail_if_err (err); + err = gpgme_op_verify (ctx, sig, text, NULL); + fail_if_err (err); + result = gpgme_op_verify_result (ctx); + check_result (result, 0, "A0FF4590BB6122EDEF6E3C542D727CC768697734", + GPG_ERR_NO_ERROR, 1); + + /* Checking a manipulated message. */ + gpgme_data_release (text); + err = gpgme_data_new_from_mem (&text, test_text1f, strlen (test_text1f), 0); + fail_if_err (err); + gpgme_data_seek (sig, 0, SEEK_SET); + err = gpgme_op_verify (ctx, sig, text, NULL); + fail_if_err (err); + result = gpgme_op_verify_result (ctx); + check_result (result, GPGME_SIGSUM_RED, "2D727CC768697734", + GPG_ERR_BAD_SIGNATURE, 0); + + /* Checking a normal signature. */ + gpgme_data_release (sig); + gpgme_data_release (text); + err = gpgme_data_new_from_mem (&sig, test_sig2, strlen (test_sig2), 0); + fail_if_err (err); + err = gpgme_data_new (&text); + fail_if_err (err); + err = gpgme_op_verify (ctx, sig, NULL, text); + fail_if_err (err); + result = gpgme_op_verify_result (ctx); + check_result (result, 0, "A0FF4590BB6122EDEF6E3C542D727CC768697734", + GPG_ERR_NO_ERROR, 0); + + + /* Checking an invalid message. */ + gpgme_data_release (sig); + gpgme_data_release (text); + err = gpgme_data_new_from_mem (&sig, double_plaintext_sig, + strlen (double_plaintext_sig), 0); + fail_if_err (err); + err = gpgme_data_new (&text); + fail_if_err (err); + err = gpgme_op_verify (ctx, sig, NULL, text); + if (gpg_err_code (err) != GPG_ERR_BAD_DATA) + { + fprintf (stderr, "%s:%i: Double plaintext message not detected\n", + __FILE__, __LINE__); + exit (1); + } + + gpgme_data_release (sig); + gpgme_data_release (text); + gpgme_release (ctx); + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpg/t-wait.c b/tags/gpgme-1.1.6/tests/gpg/t-wait.c new file mode 100644 index 0000000..eec4d96 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpg/t-wait.c @@ -0,0 +1,76 @@ +/* t-wait.c - Regression test. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#ifdef HAVE_W32_SYSTEM +#define sleep _sleep +#endif + +#include + +#include "t-support.h" + + +int +main (int argc, char *argv[]) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_data_t sig, text; + + init_gpgme (GPGME_PROTOCOL_OpenPGP); + + err = gpgme_new (&ctx); + fail_if_err (err); + + /* Checking a message without a signature. */ + err = gpgme_data_new_from_mem (&sig, "foo\n", 4, 0); + fail_if_err (err); + err = gpgme_data_new (&text); + fail_if_err (err); + err = gpgme_op_verify_start (ctx, sig, NULL, text); + fail_if_err (err); + + while (gpgme_wait (ctx, &err, 0) == NULL && err == 0) + sleep(1); + + if (gpg_err_code (err) != GPG_ERR_NO_DATA) + { + fprintf (stderr, "%s:%d: %s: %s\n", + __FILE__, __LINE__, gpgme_strsource (err), + gpgme_strerror (err)); + exit (1); + } + + gpgme_data_release (sig); + gpgme_data_release (text); + gpgme_release (ctx); + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpgsm/32100C27173EF6E9C4E9A25D3D69F86D37A4F939 b/tags/gpgme-1.1.6/tests/gpgsm/32100C27173EF6E9C4E9A25D3D69F86D37A4F939 new file mode 100644 index 0000000..cf0535f --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpgsm/32100C27173EF6E9C4E9A25D3D69F86D37A4F939 @@ -0,0 +1,18 @@ +(private-key + (oid.1.2.840.113549.1.1.1 + (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#) + (e #010001#) + (d #046129F2489D71579BE0A75FE029BD6CDB574EBF57EA8A5B0FDA942CAB943B117D7BB95E5D28875E0F9FC5FCC06A72F6D502464DABDED78EF6B716177B83D5BDC543DC5D3FED932E59F5897E92E6F58A0F33424106A3B6FA2CBF877510E4AC21C3EE47851E97D12996222AC3566D4CCB0B83D164074ABF7DE655FC2446DA1781#) + (p #00e861b700e17e8afe6837e7512e35b6ca11d0ae47d8b85161c67baf64377213fe52d772f2035b3ca830af41d8a4120e1c1c70d12cc22f00d28d31dd48a8d424f1#) + (q #00f7a7ca5367c661f8e62df34f0d05c10c88e5492348dd7bddc942c9a8f369f935a07785d2db805215ed786e4285df1658eed3ce84f469b81b50d358407b4ad361#) + (u #304559a9ead56d2309d203811a641bb1a09626bc8eb36fffa23c968ec5bd891eebbafc73ae666e01ba7c8990bae06cc2bbe10b75e69fcacb353a6473079d8e9b#) + ) +) + + + + + + + + diff --git a/tags/gpgme-1.1.6/tests/gpgsm/Makefile.am b/tags/gpgme-1.1.6/tests/gpgsm/Makefile.am new file mode 100644 index 0000000..4d34b91 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpgsm/Makefile.am @@ -0,0 +1,65 @@ +# Copyright (C) 2000 Werner Koch (dd9jn) +# Copyright (C) 2001 g10 Code GmbH +# +# This file is part of GPGME. +# +# GPGME is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser 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 + +## Process this file with automake to produce Makefile.in + +GPGSM = @GPGSM@ + +TESTS_ENVIRONMENT = GNUPGHOME=$(abs_builddir) GPG_AGENT_INFO= + +noinst_HEADERS = t-support.h +TESTS = t-import t-keylist t-encrypt t-verify t-decrypt t-sign t-export + +EXTRA_DIST = cert_dfn_pca01.der cert_dfn_pca15.der cert_g10code_test1.der \ + $(key_id) + +INCLUDES = -I$(top_srcdir)/gpgme + +AM_CPPFLAGS = @GPG_ERROR_CFLAGS@ +LDADD = ../../gpgme/libgpgme.la + +# We don't run t-genkey in the test suite, because it takes too long +# and needs a working pinentry. +noinst_PROGRAMS = $(TESTS) t-genkey + +key_id = 32100C27173EF6E9C4E9A25D3D69F86D37A4F939 + +DISTCLEANFILES = pubring.kbx pubring.kbx~ gpgsm.conf trustlist.txt \ + private-keys-v1.d/$(key_id).key random_seed + + +all-local: ./pubring.kbx ./gpgsm.conf ./private-keys-v1.d/$(key_id).key ./trustlist.txt + +./pubring.kbx: $(srcdir)/cert_g10code_test1.der + $(GPGSM) --homedir . --import $(srcdir)/cert_g10code_test1.der + +./gpgsm.conf: + echo disable-crl-checks > ./gpgsm.conf + echo faked-system-time 1008241200 >> ./gpgsm.conf + +./private-keys-v1.d/$(key_id).key: $(srcdir)/$(key_id) + test -d ./private-keys-v1.d || mkdir ./private-keys-v1.d + cp $(srcdir)/$(key_id) private-keys-v1.d/$(key_id).key + +./trustlist.txt: + echo $(key_id) > ./trustlist.txt + echo >> ./trustlist.txt + echo "# CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=Düsseldorf,C=DE" >> ./trustlist.txt + echo "3CF405464F66ED4A7DF45BBDD1E4282E33BDB76E S" >> ./trustlist.txt + diff --git a/tags/gpgme-1.1.6/tests/gpgsm/cert_dfn_pca01.der b/tags/gpgme-1.1.6/tests/gpgsm/cert_dfn_pca01.der new file mode 100644 index 0000000000000000000000000000000000000000..4c8593c383262faeb559788ebe93a12019562b16 GIT binary patch literal 1224 zcmXqLVmV^a#Jpw!GZP~d6Cdm#~COYH3Mvaz<*gf?IwOkWreKUYwU&Qe`M$zz0&oEzIuX=BFFr>}aTGpaT+N z7FGp{D1_t}DEOq7rRFF&rxulDre!84mSpDVDL9svWaJlRmQ;c*fw_W{QA{Wqtgh0b zAURPlB`r@cCDlMqoY&IA(7?#j(89pj&>%{j*TB%w$k-6d9klLlVpKv7Vn$X5<|amd z27@L>E~X|%MushUHzs|pzwzt(tPY90hhKdt&b~Zl_MQV}n}d%T6&+U2+_>CP*2F_r zxJK){KCjiYbHOQ_tv4PJe{)-?jO*Ork8eMgxV*3R5nrbLU#PCxQ~2tYpC?2fQ^#r}<{ZpE(;YZ*mapY>i>icscQq z)clTjCI1>P+hmu0ug^WvVtTw|!v3r|f23b(yiU;+dvo0K{zTu+Q{u09yU%|jHf7Gm zD}nF5I1Jue6~5dQa((NDHLeO`Tb?s9GcqtPZeo-MhKRUFeiK7MElu>mibezJVh`DF=&*m=Q=RP-S^}IkGZff&yyN zFUZfyOs)h;LRfkkCAm2U76>DFS+vD8Lo!koh)Tl-iU^&|EF!=(oSvx<%q_{;x<#pF zdO)7Nfh0l+3k#1J7sMrc$wfH^{J{JoE6m9FpM}+c8Aus$g9P}&VZer*fPi@vn1C1= z6cXa1tt?`iQ_ZJ~AJm$v`ZlmtYKybImHscUEk|Dqc7~-N@7`D*Fg9)&TC*`XlP($Xl7z=WD*7B8X6iI8yH#`06~;N<0LA$TiZYr;%+67 zyMt4U%2JCcadZ=-5_0%5vNA9?G4eAQG%<29H8CPGAGQ`aI&S84_> zJ$GZ*$?ey^M0(`@Ibz8Ds^qI=?83<=Yj0hXwXe~gJ6*5gpOZ%B!@t7iZ12o^4Lg@URjS}x2n9GBP3 zyeNB_v&^6#BrVTUVNhmZxxjpZX`69INlAf~zJ7UmxgH`N=>wA!kf#q#Vfw|zIZz?J zN|4VWEWM19+#Fz{VnGnSgep) zTwI!(qL5UnP?C|V0L`;HU=A>=a^cOY3i)YZh3=_ExruoSL8-;5iABj7Tz;t~<@rU~ z3L3ad2_29{ntEIzKr6FTD;4s~^HPh{fsRQ@%_{+x0brLU0!suC7v$6wh0Hvz#N_1s zqLjqEWT4A4OEO>%RtV28%1KcO2WnObPfbz?00)SULK(2+F;GN=0yB#UurNu_)CU$@ z$=SL^sbzXVo;`A&1eSTgJjuwgF~(W*cT%r98pr=DO7xZ>F+IM-&b(DhvUxUeLJof0{~EZDmefE literal 0 HcmV?d00001 diff --git a/tags/gpgme-1.1.6/tests/gpgsm/cert_g10code_test1.der b/tags/gpgme-1.1.6/tests/gpgsm/cert_g10code_test1.der new file mode 100644 index 0000000000000000000000000000000000000000..67c7db60241bf9aa0155c49fd6041417d9e6c7b9 GIT binary patch literal 793 zcmXqLViq-MVyauf%*4pV#K>U4%f_kI=F#?@mywZ$mBAp}klTQhjX9KsO_<5W)lk?# z5X4~@;d1#?T%4Mdl3$c&C}to6666x*O*b@9aL!LjRdCNu@-UP%5C@5K3kx`=rdJk} zq~<9E6y;~7CYKnB7zlx+n1#7ZQj1Fzl2eOH6budI#CZ)24UG(p4J?h#j4h&oTq7hd zeI3&{A2}=-Ss9ocdl?KGJDD0A86KRQ_LDnj9@FPZ+OKX+{ui*K^wqIF2fKH!Jg?U> zEoPOj{LiTR5S7$p2M*3v&vR8f$I_9pe5J@=6Pv>;YOgy@{C_kxAUArq>ghFEe7YBZ z>{+$p%Az^?<|hL_Cwq8*%KY9b;^5}JzOt!~d2wFB4w1=yukR$kOi`(R9(%N#(YtO@ zAQLkq1LNYx69$b(4P=1D-YYcmKuBS;MLb99{*~T8`%FF?G)@J{E3-8A z8Z>q_U{$j)e@QM~!?p>S&Uir15@umFU}j|ej~vp#RL2Yq;+%FCxh{(px1`0>#atAk zc&A=?SuQRe>7(=PwXgb)tfO4NAO8GSus>UVgHgfNwP`g?KAhG;Yh-e2Kfh4UP^p{p z&;P%orS;*%Z;e-ecrhb2X2U=3b&j1sR=!d%Q@avyC{9KFxBqha{g0FNCh2|(39e&t TY_*$Y)p{wdJ@E7ANE=B2yj}up literal 0 HcmV?d00001 diff --git a/tags/gpgme-1.1.6/tests/gpgsm/t-decrypt.c b/tags/gpgme-1.1.6/tests/gpgsm/t-decrypt.c new file mode 100644 index 0000000..654c7e1 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpgsm/t-decrypt.c @@ -0,0 +1,86 @@ +/* t-encrypt.c - Regression test. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include +#include "t-support.h" + + +static const char test_text1[] = "Hallo Leute!\n"; +static const char test_cip1[] = +"-----BEGIN CMS OBJECT-----\n" +"MIAGCSqGSIb3DQEHA6CAMIACAQAxggEJMIIBBQIBADBwMGsxCzAJBgNVBAYTAkRF\n" +"MRMwEQYDVQQHFApE/HNzZWxkb3JmMRYwFAYDVQQKEw1nMTAgQ29kZSBHbWJIMRkw\n" +"FwYDVQQLExBBZWd5cHRlbiBQcm9qZWN0MRQwEgYDVQQDEwt0ZXN0IGNlcnQgMQIB\n" +"ADALBgkqhkiG9w0BAQEEgYBOFcOfUtAav+XjKGM1RJtF+8JLkbnu46S3T3709Iok\n" +"u+Z9dwpOyfHwxXOmjzkSKQSBBxxi6ar+sKjU/KfPIvaMpARwT+NfIVSCZRWIJ27z\n" +"wbSrav/kcRRDDA0wXV7dHVmSLPUJNCpiFMNZbkYtI+ai15g0PVeDw+szYd9zdsjJ\n" +"2zCABgkqhkiG9w0BBwEwFAYIKoZIhvcNAwcECA8gPQY2NtJToIAECAeoY3MIcz9h\n" +"BAiiytWtOSmqnwAA\n" +"-----END CMS OBJECT-----\n"; + + +int +main (int argc, char *argv[]) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_data_t in, out; + gpgme_decrypt_result_t result; + + init_gpgme (GPGME_PROTOCOL_CMS); + + err = gpgme_new (&ctx); + fail_if_err (err); + gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS); + + err = gpgme_data_new_from_mem (&in, test_cip1, strlen (test_cip1), 0); + fail_if_err (err); + + err = gpgme_data_new (&out); + fail_if_err (err); + + err = gpgme_op_decrypt (ctx, in, out); + fail_if_err (err); + result = gpgme_op_decrypt_result (ctx); + if (result->unsupported_algorithm) + { + fprintf (stderr, "%s:%i: unsupported algorithm: %s\n", + __FILE__, __LINE__, result->unsupported_algorithm); + exit (1); + } + print_data (out); + + gpgme_data_release (in); + gpgme_data_release (out); + gpgme_release (ctx); + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpgsm/t-encrypt.c b/tags/gpgme-1.1.6/tests/gpgsm/t-encrypt.c new file mode 100644 index 0000000..45c772b --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpgsm/t-encrypt.c @@ -0,0 +1,78 @@ +/* t-encrypt.c - Regression test. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +#include "t-support.h" + +int +main (int argc, char **argv) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_data_t in, out; + gpgme_key_t key[] = { NULL, NULL }; + gpgme_encrypt_result_t result; + + init_gpgme (GPGME_PROTOCOL_CMS); + + err = gpgme_new (&ctx); + fail_if_err (err); + gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS); + gpgme_set_armor (ctx, 1); + + 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_get_key (ctx, "3CF405464F66ED4A7DF45BBDD1E4282E33BDB76E", + &key[0], 0); + fail_if_err (err); + + err = gpgme_op_encrypt (ctx, key, 0, in, out); + fail_if_err (err); + result = gpgme_op_encrypt_result (ctx); + if (result->invalid_recipients) + { + fprintf (stderr, "Invalid recipient encountered: %s\n", + result->invalid_recipients->fpr); + exit (1); + } + print_data (out); + + gpgme_key_unref (key[0]); + gpgme_data_release (in); + gpgme_data_release (out); + gpgme_release (ctx); + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpgsm/t-export.c b/tags/gpgme-1.1.6/tests/gpgsm/t-export.c new file mode 100644 index 0000000..d8856f2 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpgsm/t-export.c @@ -0,0 +1,86 @@ +/* t-export.c - Regression test. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include +#include "t-support.h" + + +int +main (int argc, char *argv[]) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_data_t out; + const char *pattern1[] = { "DFN Top Level Certification Authority", NULL }; + const char *pattern2[] = { "3CF405464F66ED4A7DF45BBDD1E4282E33BDB76E", + "DFN Server Certification Authority", + NULL }; + + init_gpgme (GPGME_PROTOCOL_CMS); + + err = gpgme_new (&ctx); + fail_if_err (err); + gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS); + + gpgme_set_armor (ctx, 1); + + /* Check exporting of one certificate. */ + err = gpgme_data_new (&out); + fail_if_err (err); + err = gpgme_op_export_ext (ctx, pattern1, 0, out); + fail_if_err (err); + + fflush (NULL); + fputs ("Begin Result:\n", stdout); + print_data (out); + fputs ("End Result.\n", stdout); + + gpgme_data_release (out); + + /* Check exporting of 2 certificates. */ + err = gpgme_data_new (&out); + fail_if_err (err); + err = gpgme_op_export_ext (ctx, pattern2, 0, out); + fail_if_err (err); + + fflush (NULL); + fputs ("Begin Result:\n", stdout); + print_data (out); + fputs ("End Result.\n", stdout); + + gpgme_data_release (out); + + + gpgme_release (ctx); + + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpgsm/t-genkey.c b/tags/gpgme-1.1.6/tests/gpgsm/t-genkey.c new file mode 100644 index 0000000..9de9d54 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpgsm/t-genkey.c @@ -0,0 +1,128 @@ +/* t-genkey.c - Regression test. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include +#include "t-support.h" + + +/* True if progress function printed something on the screen. */ +static int progress_called; + +static void +progress (void *self, const char *what, int type, int current, int total) +{ + if (!strcmp (what, "primegen") && !current && !total + && (type == '.' || type == '+' || type == '!' + || type == '^' || type == '<' || type == '>')) + { + printf ("%c", type); + fflush (stdout); + progress_called = 1; + } + else + { + fprintf (stderr, "unknown progress `%s' %d %d %d\n", what, type, + current, total); + exit (1); + } +} + + +int +main (int argc, char *argv[]) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + const char *parms = "\n" + "Key-Type: RSA\n" + "Key-Length: 1024\n" + "Name-DN: C=de,O=g10 code,OU=Testlab,CN=Joe 2 Tester\n" + "Name-Email: joe@foo.bar\n" + "\n"; + gpgme_genkey_result_t result; + gpgme_data_t certreq; + + init_gpgme (GPGME_PROTOCOL_CMS); + + err = gpgme_data_new (&certreq); + fail_if_err (err); + + err = gpgme_new (&ctx); + fail_if_err (err); + + gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS); + gpgme_set_armor (ctx, 1); + + gpgme_set_progress_cb (ctx, progress, NULL); + + err = gpgme_op_genkey (ctx, parms, certreq, NULL); + fail_if_err (err); + + result = gpgme_op_genkey_result (ctx); + if (!result) + { + fprintf (stderr, "%s:%d: gpgme_op_genkey_result returns NULL\n", + __FILE__, __LINE__); + exit (1); + } + if (progress_called) + printf ("\n"); + + printf ("Generated key: %s (%s)\n", result->fpr ? result->fpr : "none", + result->primary ? (result->sub ? "primary, sub" : "primary") + : (result->sub ? "sub" : "none")); + + if (result->fpr) + { + fprintf (stderr, "%s:%d: generated key has (unexpectdly) a fingerprint\n", + __FILE__, __LINE__); + exit (1); + } + if (!result->primary) + { + fprintf (stderr, "%s:%d: primary key was not generated\n", + __FILE__, __LINE__); + exit (1); + } + if (result->sub) + { + fprintf (stderr, "%s:%d: sub key was (unexpectedly) generated\n", + __FILE__, __LINE__); + exit (1); + } + gpgme_release (ctx); + + print_data (certreq); + gpgme_data_release (certreq); + + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpgsm/t-import.c b/tags/gpgme-1.1.6/tests/gpgsm/t-import.c new file mode 100644 index 0000000..2d23779 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpgsm/t-import.c @@ -0,0 +1,175 @@ +/* t-import.c - Regression test. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include + +#include "t-support.h" + + +void +check_result (gpgme_import_result_t result, char *fpr, int total, + int total_stat) +{ + if (result->considered != total) + { + fprintf (stderr, "Unexpected number of considered keys %i\n", + result->considered); + exit (1); + } + if (result->no_user_id != 0) + { + fprintf (stderr, "Unexpected number of user ids %i\n", + result->no_user_id); + exit (1); + } + if (result->imported != 0 && result->imported != 1) + { + fprintf (stderr, "Unexpected number of imported keys %i\n", + result->imported); + exit (1); + } + if (result->imported_rsa != 0) + { + fprintf (stderr, "Unexpected number of imported RSA keys %i\n", + result->imported_rsa); + exit (1); + } + if ((result->imported == 0 && result->unchanged != total) + || (result->imported == 1 && result->unchanged != total - 1)) + { + fprintf (stderr, "Unexpected number of unchanged keys %i\n", + result->unchanged); + exit (1); + } + if (result->new_user_ids != 0) + { + fprintf (stderr, "Unexpected number of new user IDs %i\n", + result->new_user_ids); + exit (1); + } + if (result->new_sub_keys != 0) + { + fprintf (stderr, "Unexpected number of new sub keys %i\n", + result->new_sub_keys); + exit (1); + } + if (result->new_signatures != 0) + { + fprintf (stderr, "Unexpected number of new signatures %i\n", + result->new_signatures); + exit (1); + } + if (result->new_revocations != 0) + { + fprintf (stderr, "Unexpected number of new revocations %i\n", + result->new_revocations); + exit (1); + } + if (result->secret_read != 0) + { + fprintf (stderr, "Unexpected number of secret keys read %i\n", + result->secret_read); + exit (1); + } + if (result->secret_imported != 0) + { + fprintf (stderr, "Unexpected number of secret keys imported %i\n", + result->secret_imported); + exit (1); + } + if (result->secret_unchanged != 0) + { + fprintf (stderr, "Unexpected number of secret keys unchanged %i\n", + result->secret_unchanged); + exit (1); + } + if (result->not_imported != 0) + { + fprintf (stderr, "Unexpected number of secret keys not imported %i\n", + result->not_imported); + exit (1); + } + + { + int n; + gpgme_import_status_t r; + + for (n=0, r=result->imports; r; r=r->next) + n++; + + if (n != total_stat) + { + fprintf (stderr, "Unexpected number of status reports\n"); + exit (1); + } + } +} + + +int +main (int argc, char **argv) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_data_t in; + gpgme_import_result_t result; + const char *cert_1 = make_filename ("cert_dfn_pca01.der"); + const char *cert_2 = make_filename ("cert_dfn_pca15.der"); + + init_gpgme (GPGME_PROTOCOL_CMS); + + err = gpgme_new (&ctx); + fail_if_err (err); + + gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS); + + err = gpgme_data_new_from_file (&in, cert_1, 1); + fail_if_err (err); + + err = gpgme_op_import (ctx, in); + fail_if_err (err); + result = gpgme_op_import_result (ctx); + check_result (result, "DFA56FB5FC41E3A8921F77AD1622EEFD9152A5AD", 1, 1); + gpgme_data_release (in); + + err = gpgme_data_new_from_file (&in, cert_2, 1); + fail_if_err (err); + + err = gpgme_op_import (ctx, in); + fail_if_err (err); + result = gpgme_op_import_result (ctx); + check_result (result, "2C8F3C356AB761CB3674835B792CDA52937F9285", 1, 2); + gpgme_data_release (in); + + gpgme_release (ctx); + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpgsm/t-keylist.c b/tags/gpgme-1.1.6/tests/gpgsm/t-keylist.c new file mode 100644 index 0000000..0f1cf33 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpgsm/t-keylist.c @@ -0,0 +1,389 @@ +/* t-keylist.c - regression test + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +#include "t-support.h" + + +struct +{ + char *fpr; + int secret; + long timestamp; + long expires; + char *issuer_serial; + char *issuer_name; + char *chain_id; + char *uid; + char *email; + gpgme_validity_t validity; + unsigned int key_length; +} +keys[] = + { + { "3CF405464F66ED4A7DF45BBDD1E4282E33BDB76E", 1, 1007372198, 1038908198, "00", + "CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=D\xc3\xbcsseldorf,C=DE", + "3CF405464F66ED4A7DF45BBDD1E4282E33BDB76E", + "CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=D\xc3\xbcsseldorf,C=DE", + NULL, GPGME_VALIDITY_ULTIMATE, 1024 + }, + { "DFA56FB5FC41E3A8921F77AD1622EEFD9152A5AD", 0, 909684190, 1009821790, "01", + "1.2.840.113549.1.9.1=#63657274696679407063612E64666E2E6465," + "CN=DFN Top Level Certification Authority,OU=DFN-PCA," + "O=Deutsches Forschungsnetz,C=DE", + "DFA56FB5FC41E3A8921F77AD1622EEFD9152A5AD", + "1.2.840.113549.1.9.1=#63657274696679407063612E64666E2E6465," + "CN=DFN Top Level Certification Authority,OU=DFN-PCA," + "O=Deutsches Forschungsnetz,C=DE", + "", GPGME_VALIDITY_NEVER, 2048 + }, + { "2C8F3C356AB761CB3674835B792CDA52937F9285", 0, 973183644, 1009735200, "15", + "1.2.840.113549.1.9.1=#63657274696679407063612E64666E2E6465," + "CN=DFN Top Level Certification Authority,OU=DFN-PCA," + "O=Deutsches Forschungsnetz,C=DE", + "DFA56FB5FC41E3A8921F77AD1622EEFD9152A5AD", + "1.2.840.113549.1.9.1=#63657274696679407063612E64666E2E6465," + "CN=DFN Server Certification Authority,OU=DFN-PCA," + "O=Deutsches Forschungsnetz,C=DE", + "", GPGME_VALIDITY_UNKNOWN, 2048 + }, + { NULL } + }; + + +int +main (int argc, char **argv) +{ + gpgme_error_t err; + gpgme_ctx_t ctx; + gpgme_key_t key; + gpgme_keylist_result_t result; + int i = 0; + + init_gpgme (GPGME_PROTOCOL_CMS); + + err = gpgme_new (&ctx); + fail_if_err (err); + gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS); + + err = gpgme_op_keylist_start (ctx, NULL, 0); + fail_if_err (err); + + while (!(err = gpgme_op_keylist_next (ctx, &key))) + { + if (!keys[i].fpr) + { + fprintf (stderr, "More keys returned than expected\n"); + exit (1); + } + + if (strcmp (key->subkeys->fpr, keys[i].fpr)) + { + fprintf (stderr, "Warning: Skipping unknown key %s\n", + key->subkeys->fpr); + continue; + } + else + printf ("Checking key %s\n", key->subkeys->fpr); + + /* Global key flags. */ + if (key->revoked) + { + fprintf (stderr, "Key unexpectedly revoked\n"); + exit (1); + } + if (key->expired) + { + fprintf (stderr, "Key unexpectedly expired\n"); + exit (1); + } + if (key->disabled) + { + fprintf (stderr, "Key unexpectedly disabled\n"); + exit (1); + } + if (key->invalid) + { + fprintf (stderr, "Key unexpectedly invalid\n"); + exit (1); + } + if (key->can_encrypt != keys[i].secret) + { + fprintf (stderr, "Key unexpectedly%s usable for encryption\n", + key->can_encrypt ? "" : " not"); + exit (1); + } + if (key->can_sign != keys[i].secret) + { + fprintf (stderr, "Key unexpectedly%s usable for signing\n", + key->can_sign ? "" : " not"); + exit (1); + } + if (!key->can_certify) + { + fprintf (stderr, "Key unexpectedly unusable for certifications\n"); + exit (1); + } + if (key->secret != keys[i].secret) + { + fprintf (stderr, "Key unexpectedly%s secret\n", + key->secret ? "" : " not"); + exit (1); + } + if (key->protocol != GPGME_PROTOCOL_CMS) + { + fprintf (stderr, "Key has unexpected protocol: %s\n", + gpgme_get_protocol_name (key->protocol)); + exit (1); + } + if (!key->issuer_serial) + { + fprintf (stderr, "Key unexpectedly misses issuer serial\n"); + exit (1); + } + if (strcmp (key->issuer_serial, keys[i].issuer_serial)) + { + fprintf (stderr, "Key has unexpected issuer serial: %s\n", + key->issuer_serial); + exit (1); + } + if (!key->issuer_name) + { + fprintf (stderr, "Key unexpectedly misses issuer name\n"); + exit (1); + } + if (strcmp (key->issuer_name, keys[i].issuer_name)) + { + fprintf (stderr, "Key has unexpected issuer name: %s\n", + key->issuer_name); + exit (1); + } + if (key->chain_id && !keys[i].chain_id) + { + fprintf (stderr, "Key unexpectedly carries chain ID: %s\n", + key->chain_id); + exit (1); + } + if (!key->chain_id && keys[i].chain_id) + { + fprintf (stderr, "Key unexpectedly carries no chain ID\n"); + exit (1); + } + if (key->chain_id && strcmp (key->chain_id, keys[i].chain_id)) + { + fprintf (stderr, "Key carries unexpected chain ID: %s\n", + key->chain_id); + exit (1); + } + if (key->owner_trust != GPGME_VALIDITY_UNKNOWN) + { + fprintf (stderr, "Key has unexpected owner trust: %i\n", + key->owner_trust); + exit (1); + } + if (!key->subkeys || key->subkeys->next) + { + fprintf (stderr, "Key has unexpected number of subkeys\n"); + exit (1); + } + + /* Primary key. */ + if (key->subkeys->revoked) + { + fprintf (stderr, "Primary key unexpectedly revoked\n"); + exit (1); + } + if (key->subkeys->expired) + { + fprintf (stderr, "Primary key unexpectedly expired\n"); + exit (1); + } + if (key->subkeys->disabled) + { + fprintf (stderr, "Primary key unexpectedly disabled\n"); + exit (1); + } + if (key->subkeys->invalid) + { + fprintf (stderr, "Primary key unexpectedly invalid\n"); + exit (1); + } + if (key->subkeys->can_encrypt != keys[i].secret) + { + fprintf (stderr, "Key unexpectedly%s usable for encryption\n", + key->subkeys->can_encrypt ? "" : " not"); + exit (1); + } + if (key->subkeys->can_sign != keys[i].secret) + { + fprintf (stderr, "Key unexpectedly%s usable for signing\n", + key->subkeys->can_sign ? "" : " not"); + exit (1); + } + if (!key->subkeys->can_certify) + { + fprintf (stderr, "Primary key unexpectedly unusable for certifications\n"); + exit (1); + } + if (key->subkeys->secret != keys[i].secret) + { + fprintf (stderr, "Primary Key unexpectedly%s secret\n", + key->secret ? "" : " not"); + exit (1); + } + if (key->subkeys->pubkey_algo != GPGME_PK_RSA) + { + fprintf (stderr, "Primary key has unexpected public key algo: %s\n", + gpgme_pubkey_algo_name (key->subkeys->pubkey_algo)); + exit (1); + } + if (key->subkeys->length != keys[i].key_length) + { + fprintf (stderr, "Primary key has unexpected length: %i\n", + key->subkeys->length); + exit (1); + } + if (strcmp (key->subkeys->keyid, &keys[i].fpr[40 - 16])) + { + fprintf (stderr, "Primary key has unexpected key ID: %s\n", + key->subkeys->keyid); + exit (1); + } + if (strcmp (key->subkeys->fpr, keys[i].fpr)) + { + fprintf (stderr, "Primary key has unexpected fingerprint: %s\n", + key->subkeys->fpr); + exit (1); + } + if (key->subkeys->timestamp != keys[i].timestamp) + { + fprintf (stderr, "Primary key unexpected timestamp: %lu\n", + key->subkeys->timestamp); + exit (1); + } + if (key->subkeys->expires != keys[i].expires) + { + fprintf (stderr, "Primary key unexpectedly expires: %lu\n", + key->subkeys->expires); + exit (1); + } + + /* Be tolerant against a missing email (ie, older gpgsm versions). */ + if (!key->uids || (key->uids->next && !keys[i].email)) + { + fprintf (stderr, "Key has unexpected number of user IDs\n"); + exit (1); + } + if (key->uids->revoked) + { + fprintf (stderr, "User ID unexpectedly revoked\n"); + exit (1); + } + if (key->uids->invalid) + { + fprintf (stderr, "User ID unexpectedly invalid\n"); + exit (1); + } + if (key->uids->validity != keys[i].validity) + { + fprintf (stderr, "User ID unexpectedly validity: %i\n", + key->uids->validity); + exit (1); + } + if (key->uids->signatures) + { + fprintf (stderr, "User ID unexpectedly signed\n"); + exit (1); + } + if (!key->uids->name || key->uids->name[0]) + { + fprintf (stderr, "Unexpected name in user ID: %s\n", + key->uids->name); + exit (1); + } + if (!key->uids->comment || key->uids->comment[0]) + { + fprintf (stderr, "Unexpected comment in user ID: %s\n", + key->uids->comment); + exit (1); + } + if (!key->uids->email || key->uids->email[0]) + { + fprintf (stderr, "Unexpected email in user ID: %s\n", + key->uids->email); + exit (1); + } + if (!key->uids->uid || strcmp (key->uids->uid, keys[i].uid)) + { + fprintf (stderr, "Unexpected uid in user ID: %s\n", + key->uids->uid); + exit (1); + } + if (key->uids->next && strcmp (key->uids->next->uid, keys[i].email)) + { + fprintf (stderr, "Unexpected email in user ID: %s\n", + key->uids->next->uid); + exit (1); + } + if (key->uids->next && strcmp (key->uids->next->uid, keys[i].email)) + { + fprintf (stderr, "Unexpected email in user ID: %s\n", + key->uids->next->uid); + exit (1); + } + + + + gpgme_key_unref (key); + i++; + } + if (gpg_err_code (err) != GPG_ERR_EOF) + fail_if_err (err); + err = gpgme_op_keylist_end (ctx); + fail_if_err (err); + + result = gpgme_op_keylist_result (ctx); + if (result->truncated) + { + fprintf (stderr, "Key listing unexpectedly truncated\n"); + exit (1); + } + + if (keys[i].fpr) + { + fprintf (stderr, "Less keys returned than expected\n"); + exit (1); + } + + gpgme_release (ctx); + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpgsm/t-sign.c b/tags/gpgme-1.1.6/tests/gpgsm/t-sign.c new file mode 100644 index 0000000..dc2d841 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpgsm/t-sign.c @@ -0,0 +1,127 @@ +/* t-sign.c - Regression test. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include "t-support.h" + + +static void +check_result (gpgme_sign_result_t result, gpgme_sig_mode_t type) +{ + if (result->invalid_signers) + { + fprintf (stderr, "Invalid signer found: %s\n", + result->invalid_signers->fpr); + exit (1); + } + if (!result->signatures || result->signatures->next) + { + fprintf (stderr, "Unexpected number of signatures created\n"); + exit (1); + } + if (result->signatures->type != type) + { + fprintf (stderr, "Wrong type of signature created\n"); + exit (1); + } + if (result->signatures->pubkey_algo != GPGME_PK_RSA) + { + fprintf (stderr, "Wrong pubkey algorithm reported: %i\n", + result->signatures->pubkey_algo); + exit (1); + } + if (result->signatures->hash_algo != GPGME_MD_SHA1) + { + fprintf (stderr, "Wrong hash algorithm reported: %i\n", + result->signatures->hash_algo); + exit (1); + } + if (result->signatures->sig_class != 0) + { + fprintf (stderr, "Wrong signature class reported: %u\n", + result->signatures->sig_class); + exit (1); + } + if (strcmp ("3CF405464F66ED4A7DF45BBDD1E4282E33BDB76E", + result->signatures->fpr)) + { + fprintf (stderr, "Wrong fingerprint reported: %s\n", + result->signatures->fpr); + exit (1); + } +} + + +int +main (int argc, char *argv[]) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_data_t in, out; + gpgme_sign_result_t result; + + init_gpgme (GPGME_PROTOCOL_CMS); + + err = gpgme_new (&ctx); + fail_if_err (err); + + gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS); + gpgme_set_textmode (ctx, 1); + gpgme_set_armor (ctx, 1); + + err = gpgme_data_new_from_mem (&in, "Hallo Leute!\n", 13, 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); + result = gpgme_op_sign_result (ctx); + check_result (result, GPGME_SIG_MODE_NORMAL); + print_data (out); + gpgme_data_release (out); + + /* Now a detached signature. */ + gpgme_data_seek (in, 0, SEEK_SET); + err = gpgme_data_new (&out); + fail_if_err (err); + err = gpgme_op_sign (ctx, in, out, GPGME_SIG_MODE_DETACH); + fail_if_err (err); + result = gpgme_op_sign_result (ctx); + check_result (result, GPGME_SIG_MODE_DETACH); + print_data (out); + gpgme_data_release (out); + + gpgme_data_release (in); + gpgme_release (ctx); + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/gpgsm/t-support.h b/tags/gpgme-1.1.6/tests/gpgsm/t-support.h new file mode 100644 index 0000000..07f00c3 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpgsm/t-support.h @@ -0,0 +1,102 @@ +/* t-support.h - Helper routines for regression tests. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +#include +#include +#include + +#include + +#define fail_if_err(err) \ + do \ + { \ + if (err) \ + { \ + fprintf (stderr, "%s:%d: %s: %s (%d.%d)\n", \ + __FILE__, __LINE__, gpg_strsource (err), \ + gpg_strerror (err), \ + gpg_err_source (err), gpg_err_code (err)); \ + exit (1); \ + } \ + } \ + while (0) + + +void +print_data (gpgme_data_t dh) +{ +#define BUF_SIZE 512 + char buf[BUF_SIZE + 1]; + int ret; + + ret = gpgme_data_seek (dh, 0, SEEK_SET); + if (ret) + fail_if_err (gpg_error_from_errno (errno)); + while ((ret = gpgme_data_read (dh, buf, BUF_SIZE)) > 0) + fwrite (buf, ret, 1, stdout); + if (ret < 0) + fail_if_err (gpg_error_from_errno (errno)); +} + + +gpgme_error_t +passphrase_cb (void *opaque, const char *uid_hint, const char *passphrase_info, + int last_was_bad, int fd) +{ + write (fd, "abc\n", 4); + return 0; +} + + +char * +make_filename (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; +} + + +void +init_gpgme (gpgme_protocol_t proto) +{ + gpgme_error_t err; + + gpgme_check_version (NULL); +#ifndef HAVE_W32_SYSTEM + setlocale (LC_ALL, ""); + gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL)); + gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL)); +#endif + + err = gpgme_engine_check_version (proto); + fail_if_err (err); +} diff --git a/tags/gpgme-1.1.6/tests/gpgsm/t-verify.c b/tags/gpgme-1.1.6/tests/gpgsm/t-verify.c new file mode 100644 index 0000000..d39487e --- /dev/null +++ b/tags/gpgme-1.1.6/tests/gpgsm/t-verify.c @@ -0,0 +1,182 @@ +/* t-verify.c - Regression test. + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +#include "t-support.h" + + +static int got_errors; + +static const char test_text1[] = "Hallo Leute!\n"; +static const char test_text1f[]= "Hallo Leute?\n"; +static const char test_sig1[] = +"-----BEGIN CMS OBJECT-----\n" +"MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAA\n" +"MYIBOTCCATUCAQEwcDBrMQswCQYDVQQGEwJERTETMBEGA1UEBxQKRPxzc2VsZG9y\n" +"ZjEWMBQGA1UEChMNZzEwIENvZGUgR21iSDEZMBcGA1UECxMQQWVneXB0ZW4gUHJv\n" +"amVjdDEUMBIGA1UEAxMLdGVzdCBjZXJ0IDECAQAwBwYFKw4DAhqgJTAjBgkqhkiG\n" +"9w0BCQQxFgQU7FC/ibH3lC9GE24RJJxa8zqP7wEwCwYJKoZIhvcNAQEBBIGAA3oC\n" +"DUmKERmD1eoJYFw38y/qnncS/6ZPjWINDIphZeK8mzAANpvpIaRPf3sNBznb89QF\n" +"mRgCXIWcjlHT0DTRLBf192Ve22IyKH00L52CqFsSN3a2sajqRUlXH8RY2D+Al71e\n" +"MYdRclgjObCcoilA8fZ13VR4DiMJVFCxJL4qVWI=\n" +"-----END CMS OBJECT-----\n"; + + +static void +check_result (gpgme_verify_result_t result, int summary, char *fpr, + gpgme_error_t status, gpgme_validity_t validity) +{ + gpgme_signature_t sig; + + sig = result->signatures; + if (!sig || sig->next) + { + fprintf (stderr, "%s:%i: Unexpected number of signatures\n", + __FILE__, __LINE__); + got_errors = 1; + } + if (sig->summary != summary) + { + fprintf (stderr, "%s:%i: Unexpected signature summary: " + "want=0x%x have=0x%x\n", + __FILE__, __LINE__, summary, sig->summary); + got_errors = 1; + } + if (strcmp (sig->fpr, fpr)) + { + fprintf (stderr, "%s:%i: Unexpected fingerprint: %s\n", + __FILE__, __LINE__, sig->fpr); + got_errors = 1; + } + if (gpg_err_code (sig->status) != status) + { + fprintf (stderr, "%s:%i: Unexpected signature status: %s\n", + __FILE__, __LINE__, gpgme_strerror (sig->status)); + got_errors = 1; + } + if (sig->notations) + { + fprintf (stderr, "%s:%i: Unexpected notation data\n", + __FILE__, __LINE__); + got_errors = 1; + } + if (sig->wrong_key_usage) + { + fprintf (stderr, "%s:%i: Unexpectedly wrong key usage\n", + __FILE__, __LINE__); + got_errors = 1; + } + if (sig->validity != validity) + { + fprintf (stderr, "%s:%i: Unexpected validity: %i\n", + __FILE__, __LINE__, sig->validity); + got_errors = 1; + } + if (gpg_err_code (sig->validity_reason) != GPG_ERR_NO_ERROR) + { + fprintf (stderr, "%s:%i: Unexpected validity reason: %s\n", + __FILE__, __LINE__, gpgme_strerror (sig->validity_reason)); + got_errors = 1; + } +} + + +static void +show_auditlog (gpgme_ctx_t ctx) +{ + gpgme_error_t err; + gpgme_data_t data; + + err = gpgme_data_new (&data); + fail_if_err (err); + err = gpgme_op_getauditlog (ctx, data, GPGME_AUDITLOG_HTML); + if (err) + { + fprintf (stderr, "%s:%i: Can't get audit log: %s\n", + __FILE__, __LINE__, gpgme_strerror (err)); + if (gpg_err_code (err) != GPG_ERR_ASS_UNKNOWN_CMD) + got_errors = 1; + } + print_data (data); + gpgme_data_release (data); +} + + + +int +main (int argc, char **argv) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_data_t sig, text; + gpgme_verify_result_t result; + + init_gpgme (GPGME_PROTOCOL_CMS); + + err = gpgme_new (&ctx); + fail_if_err (err); + gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS); + + /* Checking a valid message. */ + err = gpgme_data_new_from_mem (&text, test_text1, strlen (test_text1), 0); + fail_if_err (err); + err = gpgme_data_new_from_mem (&sig, test_sig1, strlen (test_sig1), 0); + fail_if_err (err); + + err = gpgme_op_verify (ctx, sig, text, NULL); + fail_if_err (err); + result = gpgme_op_verify_result (ctx); + check_result (result, GPGME_SIGSUM_VALID | GPGME_SIGSUM_GREEN, + "3CF405464F66ED4A7DF45BBDD1E4282E33BDB76E", + GPG_ERR_NO_ERROR, GPGME_VALIDITY_FULL); + + show_auditlog (ctx); + + /* Checking a manipulated message. */ + gpgme_data_release (text); + err = gpgme_data_new_from_mem (&text, test_text1f, strlen (test_text1f), 0); + fail_if_err (err); + gpgme_data_seek (sig, 0, SEEK_SET); + err = gpgme_op_verify (ctx, sig, text, NULL); + fail_if_err (err); + result = gpgme_op_verify_result (ctx); + check_result (result, GPGME_SIGSUM_RED, + "3CF405464F66ED4A7DF45BBDD1E4282E33BDB76E", + GPG_ERR_BAD_SIGNATURE, GPGME_VALIDITY_UNKNOWN); + + show_auditlog (ctx); + + gpgme_data_release (text); + gpgme_data_release (sig); + gpgme_release (ctx); + return got_errors? 1 : 0; +} diff --git a/tags/gpgme-1.1.6/tests/t-data-1.txt b/tags/gpgme-1.1.6/tests/t-data-1.txt new file mode 100644 index 0000000..16a15f2 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/t-data-1.txt @@ -0,0 +1 @@ +Just GNU it! diff --git a/tags/gpgme-1.1.6/tests/t-data-2.txt b/tags/gpgme-1.1.6/tests/t-data-2.txt new file mode 100644 index 0000000..9ae851c --- /dev/null +++ b/tags/gpgme-1.1.6/tests/t-data-2.txt @@ -0,0 +1,3 @@ +Just GNU it! +Just GNU it! +Just GNU it! diff --git a/tags/gpgme-1.1.6/tests/t-data.c b/tags/gpgme-1.1.6/tests/t-data.c new file mode 100644 index 0000000..713da0a --- /dev/null +++ b/tags/gpgme-1.1.6/tests/t-data.c @@ -0,0 +1,285 @@ +/* t-data - Regression tests for the gpgme_data_t abstraction. + Copyright (C) 2001, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +/* We need to include config.h so that we know whether we are building + with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include + +#define fail_if_err(a) do { if(a) { \ + fprintf (stderr, "%s:%d: (%i) gpgme_error_t " \ + "%s\n", __FILE__, __LINE__, round, \ + gpgme_strerror(a)); \ + exit (1); } \ + } while(0) + +static char * +make_filename (const char *fname) +{ + const char *srcdir = getenv ("srcdir"); + char *buf; + + if (!srcdir) + srcdir = "."; + buf = malloc (strlen(srcdir) + strlen(fname) + 2 ); + if (!buf) + { + fprintf (stderr, "%s:%d: could not allocate string: %s\n", + __FILE__, __LINE__, strerror (errno)); + exit (1); + } + strcpy (buf, srcdir); + strcat (buf, "/"); + strcat (buf, fname); + return buf; +} + +typedef enum + { + TEST_INITIALIZER, + TEST_INVALID_ARGUMENT, + TEST_INOUT_NONE, + TEST_INOUT_MEM_NO_COPY, + TEST_INOUT_MEM_COPY, + TEST_INOUT_MEM_FROM_FILE_COPY, + TEST_INOUT_MEM_FROM_INEXISTANT_FILE, + TEST_INOUT_MEM_FROM_FILE_NO_COPY, + TEST_INOUT_MEM_FROM_FILE_PART_BY_NAME, + TEST_INOUT_MEM_FROM_INEXISTANT_FILE_PART, + TEST_INOUT_MEM_FROM_FILE_PART_BY_FP, + TEST_END + } round_t; + +const char *text = "Just GNU it!\n"; +const char *text2 = "Just GNU it!\nJust GNU it!\n"; + +int +read_cb (void *cb_value, char *buffer, size_t count, size_t *nread) +{ + static int off = 0; + unsigned int amount = strlen (text) - off; + /* round_t round = *((round_t *) cb_value); */ + + if (!buffer && !count && !nread) + { + /* Rewind requested. */ + off = 0; + return 0; + } + if (! buffer || !nread) + return -1; + if (amount <= 0) + { + /* End of file. */ + *nread = 0; + return -1; + } + if (amount > count) + amount = count; + memcpy (buffer, text, amount); + off += amount; + *nread = amount; + return 0; +} + +void +read_once_test (round_t round, gpgme_data_t data) +{ + char buffer[1024]; + size_t read; + + read = gpgme_data_read (data, buffer, sizeof (buffer)); + + if (read != strlen (text) || strncmp (buffer, text, strlen (text))) + { + fprintf (stderr, "%s:%d: (%i) gpgme_data_read returned wrong data\n", + __FILE__, __LINE__, round); + exit (1); + } + + read = gpgme_data_read (data, buffer, sizeof (buffer)); + if (read) + { + fprintf (stderr, "%s:%d: (%i) gpgme_data_read did not signal EOF\n", + __FILE__, __LINE__, round); + exit (1); + } +} + +void +read_test (round_t round, gpgme_data_t data) +{ + char buffer[1024]; + size_t read; + + if (round == TEST_INOUT_NONE) + { + read = gpgme_data_read (data, buffer, sizeof (buffer)); + if (read > 0) + { + fprintf (stderr, "%s:%d: (%i) gpgme_data_read succeded unexpectedly\n", + __FILE__, __LINE__, round); + exit (1); + } + return; + } + + read_once_test (round, data); + gpgme_data_seek (data, 0, SEEK_SET); + read_once_test (round, data); +} + +void +write_test (round_t round, gpgme_data_t data) +{ + char buffer[1024]; + size_t amt; + + amt = gpgme_data_write (data, text, strlen (text)); + if (amt != strlen (text)) + fail_if_err (gpg_error_from_errno (errno)); + + gpgme_data_seek (data, 0, SEEK_SET); + + if (round == TEST_INOUT_NONE) + read_once_test (round, data); + else + { + amt = gpgme_data_read (data, buffer, sizeof (buffer)); + + if (amt != strlen (text2) || strncmp (buffer, text2, strlen (text2))) + { + fprintf (stderr, "%s:%d: (%i) gpgme_data_read returned wrong data\n", + __FILE__, __LINE__, round); + exit (1); + } + + amt = gpgme_data_read (data, buffer, sizeof (buffer)); + if (amt) + { + fprintf (stderr, "%s:%d: (%i) gpgme_data_read did not signal EOF\n", + __FILE__, __LINE__, round); + exit (1); + } + } +} + +int +main (int argc, char **argv) +{ + round_t round = TEST_INITIALIZER; + const char *text_filename = make_filename ("t-data-1.txt"); + const char *longer_text_filename = make_filename ("t-data-2.txt"); + const char *missing_filename = "this-file-surely-does-not-exist"; + gpgme_error_t err = 0; + gpgme_data_t data; + + while (++round) + { + switch (round) + { + case TEST_INVALID_ARGUMENT: + err = gpgme_data_new (NULL); + if (!err) + { + fprintf (stderr, "%s:%d: gpgme_data_new on NULL pointer succeeded " + "unexpectedly\n", __FILE__, __LINE__); + exit (1); + } + continue; + case TEST_INOUT_NONE: + err = gpgme_data_new (&data); + break; + case TEST_INOUT_MEM_NO_COPY: + err = gpgme_data_new_from_mem (&data, text, strlen (text), 0); + break; + case TEST_INOUT_MEM_COPY: + err = gpgme_data_new_from_mem (&data, text, strlen (text), 1); + break; + case TEST_INOUT_MEM_FROM_FILE_COPY: + err = gpgme_data_new_from_file (&data, text_filename, 1); + break; + case TEST_INOUT_MEM_FROM_INEXISTANT_FILE: + err = gpgme_data_new_from_file (&data, missing_filename, 1); + if (!err) + { + fprintf (stderr, "%s:%d: gpgme_data_new_from_file on inexistant " + "file succeeded unexpectedly\n", __FILE__, __LINE__); + exit (1); + } + continue; + case TEST_INOUT_MEM_FROM_FILE_NO_COPY: + err = gpgme_data_new_from_file (&data, text_filename, 0); + /* This is not implemented yet. */ + if (gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED + || gpg_err_code (err) == GPG_ERR_INV_VALUE) + continue; + break; + case TEST_INOUT_MEM_FROM_FILE_PART_BY_NAME: + err = gpgme_data_new_from_filepart (&data, longer_text_filename, 0, + strlen (text), strlen (text)); + break; + case TEST_INOUT_MEM_FROM_INEXISTANT_FILE_PART: + err = gpgme_data_new_from_filepart (&data, missing_filename, 0, + strlen (text), strlen (text)); + if (!err) + { + fprintf (stderr, "%s:%d: gpgme_data_new_from_file on inexistant " + "file succeeded unexpectedly\n", __FILE__, __LINE__); + exit (1); + } + continue; + case TEST_INOUT_MEM_FROM_FILE_PART_BY_FP: + { + FILE *fp = fopen (longer_text_filename, "rb"); + if (! fp) + { + fprintf (stderr, "%s:%d: fopen: %s\n", __FILE__, __LINE__, + strerror (errno)); + exit (1); + } + err = gpgme_data_new_from_filepart (&data, 0, fp, + strlen (text), strlen (text)); + } + break; + case TEST_END: + return 0; + case TEST_INITIALIZER: + /* Shouldn't happen. */ + fprintf (stderr, "%s:%d: impossible condition\n", __FILE__, __LINE__); + exit (1); + } + fail_if_err (err); + + read_test (round, data); + write_test (round, data); + gpgme_data_release (data); + } + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/t-engine-info.c b/tags/gpgme-1.1.6/tests/t-engine-info.c new file mode 100644 index 0000000..3864fe5 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/t-engine-info.c @@ -0,0 +1,93 @@ +/* t-engine-info.c - Regression test for gpgme_get_engine_info. + Copyright (C) 2003, 2004, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + + +#define fail_if_err(err) \ + do \ + { \ + if (err) \ + { \ + fprintf (stderr, "%s:%d: gpgme_error_t %s\n", \ + __FILE__, __LINE__, gpgme_strerror (err)); \ + exit (1); \ + } \ + } \ + while (0) + + +void +check_engine_info (gpgme_engine_info_t info, gpgme_protocol_t protocol, + const char *file_name, const char *req_version) +{ + if (info->protocol != protocol) + { + fprintf (stderr, "Unexpected protocol %i (expected %i instead)\n", + info->protocol, protocol); + exit (1); + } + if (strcmp (info->file_name, file_name)) + { + fprintf (stderr, "Unexpected file name to executable %s (expected %s instead)\n", + info->file_name, file_name); + exit (1); + } + if (strcmp (info->req_version, req_version)) + { + fprintf (stderr, "Unexpected required version %s (expected %s instead)\n", + info->req_version, req_version); + exit (1); + } +} + + +int +main (int argc, char **argv ) +{ + gpgme_engine_info_t info; + gpgme_error_t err; + + err = gpgme_get_engine_info (&info); + fail_if_err (err); + + check_engine_info (info, GPGME_PROTOCOL_OpenPGP, GPG_PATH, NEED_GPG_VERSION); + + info = info->next; +#ifdef GPGSM_PATH + check_engine_info (info, GPGME_PROTOCOL_CMS, GPGSM_PATH, NEED_GPGSM_VERSION); +#else + if (info) + { + fprintf (stderr, "Unexpected engine info.\n"); + exit (1); + } +#endif + + return 0; +} diff --git a/tags/gpgme-1.1.6/tests/t-version.c b/tags/gpgme-1.1.6/tests/t-version.c new file mode 100644 index 0000000..06bff60 --- /dev/null +++ b/tags/gpgme-1.1.6/tests/t-version.c @@ -0,0 +1,45 @@ +/* t-version.c - Regression test. + Copyright (C) 2001, 2004 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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. */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include + +int +main (int argc, char **argv) +{ + const char *null_result; + const char *current_result; + const char *future_result; + + null_result = gpgme_check_version (NULL); + current_result = gpgme_check_version (VERSION); + future_result = gpgme_check_version (VERSION ".1"); + + return !(null_result + && ! strcmp (null_result, VERSION) + && current_result + && ! strcmp (current_result, VERSION) + && ! future_result); +} -- 2.26.2