From cvs at cvs.gnupg.org Mon Jan 3 12:24:47 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Mon Jan 3 16:02:18 2005 Subject: GNUPG-1-9-BRANCH gnupg/common (ChangeLog asshelp.c) Message-ID: Date: Monday, January 3, 2005 @ 12:30:44 Author: wk Path: /cvs/gnupg/gnupg/common Tag: GNUPG-1-9-BRANCH Modified: ChangeLog asshelp.c (send_pinentry_environment): Fixed changed from 2004-12-18; cut+paste error for lc-messages. -----------+ ChangeLog | 5 +++++ asshelp.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) Index: gnupg/common/ChangeLog diff -u gnupg/common/ChangeLog:1.30.2.41 gnupg/common/ChangeLog:1.30.2.42 --- gnupg/common/ChangeLog:1.30.2.41 Tue Dec 21 20:05:15 2004 +++ gnupg/common/ChangeLog Mon Jan 3 12:30:43 2005 @@ -1,3 +1,8 @@ +2005-01-03 Werner Koch + + * asshelp.c (send_pinentry_environment): Fixed changed from + 2004-12-18; cut+paste error for lc-messages. + 2004-12-21 Werner Koch * simple-pwquery.c (agent_open) [W32]: Implement for W32. Index: gnupg/common/asshelp.c diff -u gnupg/common/asshelp.c:1.1.2.4 gnupg/common/asshelp.c:1.1.2.5 --- gnupg/common/asshelp.c:1.1.2.4 Sat Dec 18 11:22:10 2004 +++ gnupg/common/asshelp.c Mon Jan 3 12:30:43 2005 @@ -150,7 +150,7 @@ #endif if (opt_lc_messages || (dft_ttyname && dft_lc)) { - err = send_one_option (ctx, errsource, "display", + err = send_one_option (ctx, errsource, "lc-messages", opt_lc_messages ? opt_lc_messages : dft_lc); } #if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES) From cvs at cvs.gnupg.org Mon Jan 3 16:09:19 2005 From: cvs at cvs.gnupg.org (cvs user dshaw) Date: Mon Jan 3 16:19:05 2005 Subject: gnupg/g10 (ChangeLog Makefile.am import.c) Message-ID: Date: Monday, January 3, 2005 @ 16:15:35 Author: dshaw Path: /cvs/gnupg/gnupg/g10 Modified: ChangeLog Makefile.am import.c * Makefile.am: Use @LIBUSB@ instead of @LIBUSB_LIBS@ * import.c (delete_inv_parts): Comments on import-unusable-sigs. -------------+ ChangeLog | 6 ++++++ Makefile.am | 6 +++--- import.c | 6 ++++++ 3 files changed, 15 insertions(+), 3 deletions(-) Index: gnupg/g10/ChangeLog diff -u gnupg/g10/ChangeLog:1.675 gnupg/g10/ChangeLog:1.676 --- gnupg/g10/ChangeLog:1.675 Sat Jan 1 22:21:11 2005 +++ gnupg/g10/ChangeLog Mon Jan 3 16:15:34 2005 @@ -1,3 +1,9 @@ +2005-01-03 David Shaw + + * Makefile.am: Use @LIBUSB@ instead of @LIBUSB_LIBS@ + + * import.c (delete_inv_parts): Comments on import-unusable-sigs. + 2005-01-01 David Shaw * options.h, import.c (parse_import_options, delete_inv_parts): Index: gnupg/g10/Makefile.am diff -u gnupg/g10/Makefile.am:1.88 gnupg/g10/Makefile.am:1.89 --- gnupg/g10/Makefile.am:1.88 Sat Dec 18 23:23:48 2004 +++ gnupg/g10/Makefile.am Mon Jan 3 16:15:34 2005 @@ -1,5 +1,5 @@ -# Copyright (C) 1998, 1999, 2000, 2001, 2002, -# 2003 Free Software Foundation, Inc. +# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, +# 2004 Free Software Foundation, Inc. # # This file is part of GnuPG. # @@ -133,7 +133,7 @@ # $(common_source) LDADD = $(needed_libs) $(other_libs) @ZLIBS@ @W32LIBS@ @LIBREADLINE@ -gpg_LDADD = $(LDADD) @DLLIBS@ @NETLIBS@ @LIBUSB_LIBS@ +gpg_LDADD = $(LDADD) @DLLIBS@ @NETLIBS@ @LIBUSB@ $(PROGRAMS): $(needed_libs) Index: gnupg/g10/import.c diff -u gnupg/g10/import.c:1.118 gnupg/g10/import.c:1.119 --- gnupg/g10/import.c:1.118 Sat Jan 1 22:21:11 2005 +++ gnupg/g10/import.c Mon Jan 3 16:15:34 2005 @@ -1565,6 +1565,12 @@ || node->pkt->pkt.signature->keyid[1]!=keyid[1]) && !(options&IMPORT_UNUSABLE_SIGS)) { + /* Note that we haven't necessarily checked this sig for + validity. We strip it anyway since if it was valid, it + would be expired. If it wasn't valid, it either would + be expired if it was valid, or was altered to the point + that it looked expired (and so doesn't matter terribly + much if it is expired or not). */ if(opt.verbose) { char *kid=m_strdup(keystr(keyid)); From cvs at cvs.gnupg.org Mon Jan 3 16:12:07 2005 From: cvs at cvs.gnupg.org (cvs user dshaw) Date: Mon Jan 3 16:21:59 2005 Subject: gnupg (ChangeLog configure.ac) Message-ID: Date: Monday, January 3, 2005 @ 16:18:24 Author: dshaw Path: /cvs/gnupg/gnupg Modified: ChangeLog configure.ac * configure.ac: Use new GNUPG_CHECK_LIBUSB macro. --------------+ ChangeLog | 4 ++++ configure.ac | 22 +++++----------------- 2 files changed, 9 insertions(+), 17 deletions(-) Index: gnupg/ChangeLog diff -u gnupg/ChangeLog:1.231 gnupg/ChangeLog:1.232 --- gnupg/ChangeLog:1.231 Thu Dec 30 04:31:19 2004 +++ gnupg/ChangeLog Mon Jan 3 16:18:24 2005 @@ -1,3 +1,7 @@ +2005-01-03 David Shaw + + * configure.ac: Use new GNUPG_CHECK_LIBUSB macro. + 2004-12-28 David Shaw * configure.ac: Better implementation for the SRV check. We don't Index: gnupg/configure.ac diff -u gnupg/configure.ac:1.123 gnupg/configure.ac:1.124 --- gnupg/configure.ac:1.123 Thu Dec 30 04:31:19 2004 +++ gnupg/configure.ac Mon Jan 3 16:18:24 2005 @@ -1,6 +1,6 @@ -dnl Configure.ac script for GnuPG -dnl Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 -dnl 2004 Free Software Foundation, Inc. +dnl configure.ac script for GnuPG +dnl Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, +dnl 2005 Free Software Foundation, Inc. dnl dnl This file is part of GnuPG. dnl @@ -19,7 +19,7 @@ dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA dnl dnl (Process this file with autoconf to produce a configure script.) -dnlAC_REVISION($Revision: 1.123 $)dnl +dnlAC_REVISION($Revision: 1.124 $)dnl AC_PREREQ(2.59) min_automake_version="1.9.3" @@ -1179,20 +1179,8 @@ AM_CONDITIONAL(ENABLE_BZIP2_SUPPORT,test x"$have_bz2" = "xyes") AC_SUBST(ZLIBS) - -# # libusb allows us to use the integrated CCID smartcard reader driver. -# -LIBUSB_LIBS="" -if test "$card_support" = yes; then - AC_CHECK_LIB(usb, usb_bulk_write, - [ LIBUSB_LIBS="$LIBUSB_LIBS -lusb" - AC_DEFINE(HAVE_LIBUSB,1, - [defined if libusb is available]) - ]) -fi -AC_SUBST(LIBUSB_LIBS) -AC_CHECK_FUNCS(usb_get_busses) +GNUPG_CHECK_LIBUSB # Check for readline support GNUPG_CHECK_READLINE From cvs at cvs.gnupg.org Mon Jan 3 16:10:40 2005 From: cvs at cvs.gnupg.org (cvs user dshaw) Date: Mon Jan 3 16:22:08 2005 Subject: gnupg/m4 (ChangeLog Makefile.am libusb.m4) Message-ID: Date: Monday, January 3, 2005 @ 16:16:57 Author: dshaw Path: /cvs/gnupg/gnupg/m4 Added: libusb.m4 Modified: ChangeLog Makefile.am * Makefile.am, libusb.m4: New libusb check macro. -------------+ ChangeLog | 4 ++++ Makefile.am | 2 +- libusb.m4 | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) Index: gnupg/m4/ChangeLog diff -u gnupg/m4/ChangeLog:1.9 gnupg/m4/ChangeLog:1.10 --- gnupg/m4/ChangeLog:1.9 Fri Dec 24 20:41:06 2004 +++ gnupg/m4/ChangeLog Mon Jan 3 16:16:57 2005 @@ -1,3 +1,7 @@ +2005-01-03 David Shaw + + * Makefile.am, libusb.m4: New libusb check macro. + 2004-12-24 David Shaw * libcurl.m4: Rewrite this to use the new --protocols flag I gave Index: gnupg/m4/Makefile.am diff -u gnupg/m4/Makefile.am:1.4 gnupg/m4/Makefile.am:1.5 --- gnupg/m4/Makefile.am:1.4 Fri Dec 24 20:41:06 2004 +++ gnupg/m4/Makefile.am Mon Jan 3 16:16:57 2005 @@ -1 +1 @@ -EXTRA_DIST = intmax.m4 longdouble.m4 longlong.m4 printf-posix.m4 signed.m4 size_max.m4 wchar_t.m4 wint_t.m4 xsize.m4 codeset.m4 gettext.m4 glibc21.m4 iconv.m4 intdiv0.m4 inttypes.m4 inttypes_h.m4 inttypes-pri.m4 isc-posix.m4 lcmessage.m4 lib-ld.m4 lib-link.m4 lib-prefix.m4 nls.m4 po.m4 progtest.m4 stdint_h.m4 uintmax_t.m4 ulonglong.m4 readline.m4 libcurl.m4 +EXTRA_DIST = intmax.m4 longdouble.m4 longlong.m4 printf-posix.m4 signed.m4 size_max.m4 wchar_t.m4 wint_t.m4 xsize.m4 codeset.m4 gettext.m4 glibc21.m4 iconv.m4 intdiv0.m4 inttypes.m4 inttypes_h.m4 inttypes-pri.m4 isc-posix.m4 lcmessage.m4 lib-ld.m4 lib-link.m4 lib-prefix.m4 nls.m4 po.m4 progtest.m4 stdint_h.m4 uintmax_t.m4 ulonglong.m4 readline.m4 libcurl.m4 libusb.m4 Index: gnupg/m4/libusb.m4 diff -u /dev/null gnupg/m4/libusb.m4:1.1 --- /dev/null Mon Jan 3 16:16:57 2005 +++ gnupg/m4/libusb.m4 Mon Jan 3 16:16:57 2005 @@ -0,0 +1,50 @@ +dnl Check for libusb +dnl Copyright (C) 2004 Free Software Foundation, Inc. +dnl +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. +dnl +dnl Defines HAVE_LIBUSB to 1 if a working libusb setup is found, and sets +dnl @LIBUSB@ to the necessary libraries. HAVE_USB_GET_BUSSES is set if +dnl usb_get_busses() exists. + +AC_DEFUN([GNUPG_CHECK_LIBUSB], +[ + AC_ARG_WITH(libusb, + AC_HELP_STRING([--with-libusb=DIR], + [look for the libusb library in DIR]), + [_do_libusb=$withval],[_do_libusb=yes]) + + if test "$_do_libusb" != "no" ; then + if test -d "$withval" ; then + CPPFLAGS="${CPPFLAGS} -I$withval/include" + LDFLAGS="${LDFLAGS} -L$withval/lib" + fi + + _libusb_save_libs=$LIBS + LIBS="$LIBS -lusb" + + AC_MSG_CHECKING([whether libusb is present and sane]) + + AC_LINK_IFELSE(AC_LANG_PROGRAM([#include ],[ +usb_bulk_write(NULL,0,NULL,0,0); +]),_found_libusb=yes,_found_libusb=no) + + AC_MSG_RESULT([$_found_libusb]) + + if test $_found_libusb = yes ; then + AC_DEFINE(HAVE_LIBUSB,1, + [Define to 1 if you have a fully functional libusb library.]) + AC_SUBST(LIBUSB,"-lusb") + AC_CHECK_FUNCS(usb_get_busses) + fi + + LIBS=$_libusb_save_libs + + unset _libusb_save_libs + unset _found_libusb + fi +])dnl From cvs at cvs.gnupg.org Mon Jan 3 21:36:30 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Mon Jan 3 21:36:35 2005 Subject: dirmngr/src (ChangeLog dirmngr-client.c) Message-ID: Date: Monday, January 3, 2005 @ 21:42:46 Author: wk Path: /cvs/dirmngr/dirmngr/src Modified: ChangeLog dirmngr-client.c (read_pem_certificate): New. (read_certificate): Divert to it depending on pem option. (squid_loop_body): New. (main): New options --pem and --squid-mode. ------------------+ ChangeLog | 7 + dirmngr-client.c | 254 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 257 insertions(+), 4 deletions(-) Index: dirmngr/src/ChangeLog diff -u dirmngr/src/ChangeLog:1.39 dirmngr/src/ChangeLog:1.40 --- dirmngr/src/ChangeLog:1.39 Fri Dec 17 16:16:12 2004 +++ dirmngr/src/ChangeLog Mon Jan 3 21:42:46 2005 @@ -1,3 +1,10 @@ +2005-01-03 Werner Koch + + * dirmngr-client.c (read_pem_certificate): New. + (read_certificate): Divert to it depending on pem option. + (squid_loop_body): New. + (main): New options --pem and --squid-mode. + 2004-12-17 Werner Koch * dirmngr.c (launch_ripper_thread): Renamed to launch_reaper_thread. Index: dirmngr/src/dirmngr-client.c diff -u dirmngr/src/dirmngr-client.c:1.6 dirmngr/src/dirmngr-client.c:1.7 --- dirmngr/src/dirmngr-client.c:1.6 Fri Dec 3 15:42:36 2004 +++ dirmngr/src/dirmngr-client.c Mon Jan 3 21:42:46 2005 @@ -55,7 +55,10 @@ oCacheCert, oValidate, oLookup, - oLoadCRL + oLoadCRL, + oSquidMode, + oPEM, + oEscapedPEM, }; @@ -69,7 +72,9 @@ { oValidate, "validate", 0, N_("validate a certificate")}, { oLookup, "lookup", 0, N_("lookup a certificate")}, { oLoadCRL, "load-crl", 0, N_("load a CRL into the dirmngr")}, - {0} + { oSquidMode,"squid-mode",0, N_("special mode for use by Squid")}, + { oPEM, "pem", 0, N_("certificates are expected in PEM format")}, + { 0 } }; #define DEFAULT_SOCKET_NAME "/var/run/dirmngr/socket" @@ -81,6 +86,8 @@ int verbose; const char *dirmngr_program; int force_pipe_server; + int pem; + int escaped_pem; /* PEM is additional percent encoded. */ int use_ocsp; @@ -96,6 +103,13 @@ }; +/* Base64 conversion tables. */ +static unsigned char bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; +static unsigned char asctobin[256]; /* runtime initialized */ + + /* Prototypes. */ static assuan_context_t start_dirmngr (int only_daemon); static gpg_error_t read_certificate (const char *fname, @@ -108,6 +122,7 @@ const unsigned char *cert, size_t certlen); static gpg_error_t do_loadcrl (assuan_context_t ctx, const char *filename); static gpg_error_t do_lookup (assuan_context_t ctx, const char *pattern); +static gpg_error_t squid_loop_body (assuan_context_t ctx); @@ -173,6 +188,7 @@ int cmd_validate = 0; int cmd_lookup = 0; int cmd_loadcrl = 0; + int cmd_squid_mode = 0; set_strusage (my_strusage); log_set_prefix ("dirmngr-client", @@ -202,6 +218,12 @@ case oValidate: cmd_validate = 1; break; case oLookup: cmd_lookup = 1; break; case oLoadCRL: cmd_loadcrl = 1; break; + case oPEM: opt.pem = 1; break; + case oSquidMode: + opt.pem = 1; + opt.escaped_pem = 1; + cmd_squid_mode = 1; + break; default : pargs.err = 2; break; } @@ -209,6 +231,19 @@ if (log_get_errorcount (0)) exit (2); + /* Build the helptable for radix64 to bin conversion. */ + if (opt.pem) + { + int i; + unsigned char *s; + + for (i=0; i < 256; i++ ) + asctobin[i] = 255; /* Used to detect invalid characters. */ + for (s=bintoasc, i=0; *s; s++, i++) + asctobin[*s] = i; + } + + if (cmd_ping) err = 0; else if (cmd_lookup || cmd_loadcrl) @@ -217,6 +252,12 @@ usage (1); err = 0; } + else if (cmd_squid_mode) + { + err = 0; + if (argc) + usage (1); + } else if (!argc) { err = read_certificate (NULL, &certbuf, &certbuflen); @@ -252,6 +293,13 @@ if (cmd_ping) ; + else if (cmd_squid_mode) + { + while (!(err = squid_loop_body (ctx))) + ; + if (gpg_err_code (err) == GPG_ERR_EOF) + err = 0; + } else if (cmd_lookup) { int last_err = 0; @@ -307,7 +355,7 @@ log_info (_("a dirmngr daemon is up and running\n")); return 0; } - else if (cmd_lookup||cmd_loadcrl) + else if (cmd_lookup||cmd_loadcrl||cmd_squid_mode) return err? 1:0; else if (cmd_cache_cert) { @@ -488,9 +536,159 @@ } +/* Read the first PEM certificate from the file FNAME. If fname is + NULL the next certificate is read from stdin. The certificate is + returned in an alloced buffer whose address will be returned in + RBUF and its length in RBUFLEN. */ +static gpg_error_t +read_pem_certificate (const char *fname, unsigned char **rbuf, size_t *rbuflen) +{ + FILE *fp; + int c; + int pos; + int value; + unsigned char *buf; + size_t bufsize, buflen; + enum { + s_init, s_idle, s_lfseen, s_begin, + s_b64_0, s_b64_1, s_b64_2, s_b64_3, + s_waitend + } state = s_init; + + fp = fname? fopen (fname, "r") : stdin; + if (!fp) + return gpg_error_from_errno (errno); + + pos = 0; + value = 0; + bufsize = 8192; + buf = xmalloc (bufsize); + buflen = 0; + while ((c=getc (fp)) != EOF) + { + if (opt.escaped_pem) + { + if (c == '%') + { + char tmp[2]; + if ((c = getc(fp)) == EOF) + break; + tmp[0] = c; + if ((c = getc(fp)) == EOF) + break; + tmp[1] = c; + if (!hexdigitp (tmp) || !hexdigitp (tmp+1)) + { + log_error ("invalid percent escape sequence\n"); + state = s_idle; /* Force an error. */ + break; + } + c = xtoi_2 (tmp); + } + else if (c == '\n') + goto ready; /* Ready. */ + } + switch (state) + { + case s_idle: + if (c == '\n') + { + state = s_lfseen; + pos = 0; + } + break; + case s_init: + state = s_lfseen; + case s_lfseen: + if (c != "-----BEGIN "[pos]) + state = s_idle; + else if (pos == 10) + state = s_begin; + else + pos++; + break; + case s_begin: + if (c == '\n') + state = s_b64_0; + break; + case s_b64_0: + case s_b64_1: + case s_b64_2: + case s_b64_3: + { + if (buflen >= bufsize) + { + bufsize += 8192; + buf = xrealloc (buf, bufsize); + } + + if (c == '-') + state = s_waitend; + else if ((c = asctobin[c & 0xff]) == 255 ) + ; /* Just skip invalid base64 characters. */ + else if (state == s_b64_0) + { + value = c << 2; + state = s_b64_1; + } + else if (state == s_b64_1) + { + value |= (c>>4)&3; + buf[buflen++] = value; + value = (c<<4)&0xf0; + state = s_b64_2; + } + else if (state == s_b64_2) + { + value |= (c>>2)&15; + buf[buflen++] = value; + value = (c<<6)&0xc0; + state = s_b64_3; + } + else + { + value |= c&0x3f; + buf[buflen++] = value; + state = s_b64_0; + } + } + break; + case s_waitend: + /* Note that we do not check whether the END line really + follows, nor did we check that the base64 decoder was + left in the expected state. We assume that the PEM + header is just fine. */ + if (c== '\n') + goto ready; + break; + default: + BUG(); + } + } + ready: + if (fname) + fclose (fp); + + if (state == s_init && c == EOF) + { + xfree (buf); + return gpg_error (GPG_ERR_EOF); + } + else if (state != s_waitend) + { + log_error ("no certificate or invalid encoded\n"); + xfree (buf); + return gpg_error (GPG_ERR_INV_ARMOR); + } + + *rbuf = buf; + *rbuflen = buflen; + return 0; +} + /* Read a binary certificate from the file FNAME. If fname is NULL the file is read from stdin. The certificate is returned in an alloced - buffer whos address will be returned in RBUF and its length in + buffer whose address will be returned in RBUF and its length in RBUFLEN. */ static gpg_error_t read_certificate (const char *fname, unsigned char **rbuf, size_t *rbuflen) @@ -500,6 +698,9 @@ unsigned char *buf; size_t nread, bufsize, buflen; + if (opt.pem) + return read_pem_certificate (fname, rbuf, rbuflen); + fp = fname? fopen (fname, "rb") : stdin; if (!fp) return gpg_error_from_errno (errno); @@ -733,3 +934,48 @@ xfree (line); return ae? map_assuan_err (ae) : err; } + +/* The body of an endless loop: Read a line from stdin, retrieve the + certificate from it, validate it and print "ERR" or "OK" to stdout. + Continue. */ +static gpg_error_t +squid_loop_body (assuan_context_t ctx) +{ + gpg_error_t err; + unsigned char *certbuf; + size_t certbuflen = 0; + + err = read_pem_certificate (NULL, &certbuf, &certbuflen); + if (gpg_err_code (err) == GPG_ERR_EOF) + return err; + if (err) + { + log_error (_("error reading certificate from stdin: %s\n"), + gpg_strerror (err)); + puts ("ERROR"); + return 0; + } + + err = do_check (ctx, certbuf, certbuflen); + xfree (certbuf); + if (!err) + { + if (opt.verbose) + log_info (_("certificate is valid\n")); + puts ("OK"); + } + else + { + if (!opt.quiet) + { + if (gpg_err_code (err) == GPG_ERR_CERT_REVOKED ) + log_info (_("certificate has been revoked\n")); + else + log_error (_("certificate check failed: %s\n"), + gpg_strerror (err)); + } + puts ("ERROR"); + } + + return 0; +} From cvs at cvs.gnupg.org Tue Jan 4 09:27:08 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Tue Jan 4 09:28:24 2005 Subject: GNUPG-1-9-BRANCH gnupg/agent (ChangeLog cache.c) Message-ID: Date: Tuesday, January 4, 2005 @ 09:33:20 Author: wk Path: /cvs/gnupg/gnupg/agent Tag: GNUPG-1-9-BRANCH Modified: ChangeLog cache.c (agent_put_cache): Fix the test for using the default TTL. -----------+ ChangeLog | 5 +++++ cache.c | 9 +++++---- 2 files changed, 10 insertions(+), 4 deletions(-) Index: gnupg/agent/ChangeLog diff -u gnupg/agent/ChangeLog:1.59.2.54 gnupg/agent/ChangeLog:1.59.2.55 --- gnupg/agent/ChangeLog:1.59.2.54 Tue Dec 21 20:05:15 2004 +++ gnupg/agent/ChangeLog Tue Jan 4 09:33:20 2005 @@ -1,3 +1,8 @@ +2005-01-04 Werner Koch + + * cache.c (agent_put_cache): Fix the test for using the default + TTL. + 2004-12-21 Werner Koch * preset-passphrase.c (preset_passphrase): Handle --passphrase. Index: gnupg/agent/cache.c diff -u gnupg/agent/cache.c:1.10.2.2 gnupg/agent/cache.c:1.10.2.3 --- gnupg/agent/cache.c:1.10.2.2 Tue Dec 21 20:05:15 2004 +++ gnupg/agent/cache.c Tue Jan 4 09:33:20 2005 @@ -39,7 +39,7 @@ ITEM next; time_t created; time_t accessed; - int ttl; /* max. lifetime given in seonds, -1 one means infinite */ + int ttl; /* max. lifetime given in seconds, -1 one means infinite */ int lockcount; struct secret_data_s *pw; char key[1]; @@ -185,17 +185,18 @@ /* Store DATA of length DATALEN in the cache under KEY and mark it with a maximum lifetime of TTL seconds. If there is already data under this key, it will be replaced. Using a DATA of NULL deletes - the entry */ + the entry. A TTL of 0 is replaced by the default TTL and a TTL of + -1 set infinite timeout. */ int agent_put_cache (const char *key, const char *data, int ttl) { ITEM r; if (DBG_CACHE) - log_debug ("agent_put_cache `%s'\n", key); + log_debug ("agent_put_cache `%s' requested ttl=%d\n", key, ttl); housekeeping (); - if (ttl == 1) + if (!ttl) ttl = opt.def_cache_ttl; if (!ttl) return 0; From cvs at cvs.gnupg.org Tue Jan 4 16:50:49 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Tue Jan 4 16:50:53 2005 Subject: GNUPG-1-9-BRANCH gnupg/po (ChangeLog POTFILES.in de.po) Message-ID: Date: Tuesday, January 4, 2005 @ 16:57:11 Author: wk Path: /cvs/gnupg/gnupg/po Tag: GNUPG-1-9-BRANCH Modified: ChangeLog POTFILES.in de.po Updated. -------------+ ChangeLog | 4 ++++ POTFILES.in | 1 + de.po | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 53 insertions(+), 2 deletions(-) Index: gnupg/po/ChangeLog diff -u gnupg/po/ChangeLog:1.50.2.9 gnupg/po/ChangeLog:1.50.2.10 --- gnupg/po/ChangeLog:1.50.2.9 Fri Oct 22 18:03:03 2004 +++ gnupg/po/ChangeLog Tue Jan 4 16:57:10 2005 @@ -1,3 +1,7 @@ +2005-01-04 Werner Koch + + * de.po: Updated. + 2004-10-22 Werner Koch * POTFILES.in: Removed sc-investigate.c Index: gnupg/po/POTFILES.in diff -u gnupg/po/POTFILES.in:1.22.2.5 gnupg/po/POTFILES.in:1.22.2.6 --- gnupg/po/POTFILES.in:1.22.2.5 Fri Oct 22 18:03:03 2004 +++ gnupg/po/POTFILES.in Tue Jan 4 16:57:10 2005 @@ -5,6 +5,7 @@ agent/divert-scd.c agent/genkey.c agent/query.c +agent/trustlist.c common/sysutils.c common/simple-pwquery.c Index: gnupg/po/de.po diff -u gnupg/po/de.po:1.84.2.16 gnupg/po/de.po:1.84.2.17 --- gnupg/po/de.po:1.84.2.16 Wed Dec 22 19:05:14 2004 +++ gnupg/po/de.po Tue Jan 4 16:57:10 2005 @@ -10,8 +10,8 @@ msgstr "" "Project-Id-Version: gnupg2 1.9.14\n" "Report-Msgid-Bugs-To: translations@gnupg.org\n" -"POT-Creation-Date: 2004-12-22 18:57+0100\n" -"PO-Revision-Date: 2004-12-22 19:00+0100\n" +"POT-Creation-Date: 2005-01-04 16:45+0100\n" +"PO-Revision-Date: 2005-01-04 16:53+0100\n" "Last-Translator: Werner Koch \n" "Language-Team: de\n" "MIME-Version: 1.0\n" @@ -303,6 +303,52 @@ msgid "Passphrase" msgstr "Mantra" +#. TRANSLATORS: This prompt is shown by the Pinentry +#. and has one special property: A "%%0A" is used by +#. Pinentry to insert a line break. The double +#. percent sign is actually needed because it is also +#. a printf format string. If you need to insert a +#. plain % sign, you need to encode it as "%%25". The +#. second "%s" gets replaced by a hexdecimal +#. fingerprint string whereas the first one receives +#. the name as store in the certificate. +#: agent/trustlist.c:305 +#, c-format +msgid "" +"Please verify that the certificate identified as:%%0A \"%s\"%%0Ahas the " +"fingerprint:%%0A %s" +msgstr "Bitte prüfen Sie, daß das Zertifikat mit dem Namen:%%0A \"%s\"%%0Afolgenden Fingerabdruck hat:%%0A %s" + +#. TRANSLATORS: "Correct" is the label of a button and intended to +#. be hit if the fingerprint matches the one of the CA. The other +#. button is "the default "Cancel" of the Pinentry. +#: agent/trustlist.c:317 +msgid "Correct" +msgstr "Korrekt" + +#. TRANSLATORS: This prompt is shown by the Pinentry +#. and has one special property: A "%%0A" is used by +#. Pinentry to insert a line break. The double +#. percent sign is actually needed because it is also +#. a printf format string. If you need to insert a +#. plain % sign, you need to encode it as "%%25". The +#. "%s" gets replaced by the name as store in the +#. certificate. +#: agent/trustlist.c:334 +#, c-format +msgid "" +"Do you ultimately trust%%0A \"%s\"%%0Ato correctly certify user " +"certificates?" +msgstr "Wenn Sie vollständiges Vertrauen haben, daß%%0A \"%s\"%%0ABenutzerzertifikate verläßlich zertifiziert, so antworten Sie mit \"Ja\"" + +#: agent/trustlist.c:342 +msgid "Yes" +msgstr "Ja" + +#: agent/trustlist.c:342 +msgid "No" +msgstr "Nein" + #: common/sysutils.c:87 #, c-format msgid "can't disable core dumps: %s\n" From cvs at cvs.gnupg.org Tue Jan 4 20:13:26 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Tue Jan 4 20:15:16 2005 Subject: dirmngr (ChangeLog configure.ac po/dirmngr.pot) Message-ID: Date: Tuesday, January 4, 2005 @ 20:19:49 Author: wk Path: /cvs/dirmngr/dirmngr Modified: ChangeLog configure.ac po/dirmngr.pot (PTH_LIBS): Die if Pth is not available. There is not way to build it anymore without Pth support. ----------------+ ChangeLog | 3 configure.ac | 40 +++++++----- po/dirmngr.pot | 172 ++++++++++++++++++++++++++++--------------------------- 3 files changed, 115 insertions(+), 100 deletions(-) Index: dirmngr/ChangeLog diff -u dirmngr/ChangeLog:1.83 dirmngr/ChangeLog:1.84 --- dirmngr/ChangeLog:1.83 Tue Jan 4 15:16:39 2005 +++ dirmngr/ChangeLog Tue Jan 4 20:19:49 2005 @@ -1,5 +1,8 @@ 2005-01-04 Werner Koch + * configure.ac (PTH_LIBS): Die if Pth is not available. There is + not way to build it anymore without Pth support. + * doc/dirmngr.texi: Cleaned up. Use @copying. 2005-01-03 Werner Koch Index: dirmngr/configure.ac diff -u dirmngr/configure.ac:1.68 dirmngr/configure.ac:1.69 --- dirmngr/configure.ac:1.68 Sat Dec 18 09:50:39 2004 +++ dirmngr/configure.ac Tue Jan 4 20:19:49 2005 @@ -49,6 +49,7 @@ have_libassuan=no have_ksba=no have_ldap=no +have_pth=no AM_MAINTAINER_MODE @@ -183,24 +184,17 @@ PTH_CONFIG="$pth_config_prefix/bin/pth-config" fi AC_PATH_PROG(PTH_CONFIG, pth-config, no) -if test "$PTH_CONFIG" = "no"; then - AC_MSG_WARN([[ -*** -*** GNU Portable Threads Library not found. -*** The --daemon mode won't work. -*** Download GNU Pth from ftp://ftp.gnu.org/gnu/pth/ -*** On a Debian GNU/Linux system you might want to try -*** apt-get install libpth-dev -***]]) -else - GNUPG_PTH_VERSION_CHECK(1.3.7) - if test $have_pth = yes; then - PTH_CFLAGS=`$PTH_CONFIG --cflags` - PTH_LIBS=`$PTH_CONFIG --ldflags` - PTH_LIBS="$PTH_LIBS `$PTH_CONFIG --libs`" - AC_DEFINE(USE_GNU_PTH, 1, - [Defined if the GNU Portable Thread Library should be used]) - fi +if test "$PTH_CONFIG" != "no"; then + if test -x "$PTH_CONFIG"; then + GNUPG_PTH_VERSION_CHECK(1.3.7) + if test $have_pth = yes; then + PTH_CFLAGS=`$PTH_CONFIG --cflags` + PTH_LIBS=`$PTH_CONFIG --ldflags` + PTH_LIBS="$PTH_LIBS `$PTH_CONFIG --libs`" + AC_DEFINE(USE_GNU_PTH, 1, + [Defined if the GNU Portable Thread Library should be used]) + fi + fi fi AC_SUBST(PTH_CFLAGS) AC_SUBST(PTH_LIBS) @@ -384,6 +378,16 @@ *** for a suitable implementation. ***]]) fi +if test "$have_pth" = "no"; then + die=yes + AC_MSG_NOTICE([[ +*** +*** GNU Portable Threads Library not found. +*** Download GNU Pth from ftp://ftp.gnu.org/gnu/pth/ +*** On a Debian GNU/Linux system you might want to try +*** apt-get install libpth-dev +***]]) +fi if test "$die" = "yes"; then AC_MSG_ERROR([[ Index: dirmngr/po/dirmngr.pot diff -u dirmngr/po/dirmngr.pot:1.8 dirmngr/po/dirmngr.pot:1.9 --- dirmngr/po/dirmngr.pot:1.8 Fri Dec 17 11:55:41 2004 +++ dirmngr/po/dirmngr.pot Tue Jan 4 20:19:49 2005 @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: gpa-dev@gnupg.org\n" -"POT-Creation-Date: 2004-12-17 11:40+0100\n" +"POT-Creation-Date: 2005-01-04 15:12+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -16,7 +16,7 @@ "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: jnlib/logging.c:624 +#: jnlib/logging.c:625 #, c-format msgid "you found a bug ... (%s:%d)\n" msgstr "" @@ -46,7 +46,7 @@ msgid "can't access directory `%s': %s\n" msgstr "" -#: src/certcache.c:323 src/crlcache.c:2173 src/ldap.c:615 +#: src/certcache.c:323 src/crlcache.c:2173 src/ldap.c:625 #, c-format msgid "can't open `%s': %s\n" msgstr "" @@ -91,7 +91,7 @@ msgid " runtime cached certificates: %u\n" msgstr "" -#: src/certcache.c:457 src/dirmngr-client.c:317 +#: src/certcache.c:457 src/dirmngr-client.c:365 msgid "certificate already cached\n" msgstr "" @@ -99,7 +99,7 @@ msgid "certificate cached\n" msgstr "" -#: src/certcache.c:461 src/dirmngr-client.c:321 +#: src/certcache.c:461 src/dirmngr-client.c:369 #, c-format msgid "error caching certificate: %s\n" msgstr "" @@ -216,7 +216,7 @@ msgid "unsupported record type in `%s' line %u skipped\n" msgstr "" -#: src/crlcache.c:574 src/crlcache.c:803 src/dirmngr.c:1203 +#: src/crlcache.c:574 src/crlcache.c:803 src/dirmngr.c:1210 #, c-format msgid "error reading `%s': %s\n" msgstr "" @@ -573,7 +573,7 @@ msgid "End CRL dump\n" msgstr "" -#: src/crlcache.c:2182 src/crlfetch.c:97 src/ldap.c:683 +#: src/crlcache.c:2182 src/crlfetch.c:97 src/ldap.c:693 #, c-format msgid "error initializing reader object: %s\n" msgstr "" @@ -663,11 +663,11 @@ " " msgstr "" -#: src/dirmngr.c:119 src/dirmngr-client.c:64 src/dirmngr_ldap.c:76 +#: src/dirmngr.c:119 src/dirmngr-client.c:67 src/dirmngr_ldap.c:76 msgid "verbose" msgstr "" -#: src/dirmngr.c:120 src/dirmngr-client.c:65 src/dirmngr_ldap.c:77 +#: src/dirmngr.c:120 src/dirmngr-client.c:68 src/dirmngr_ldap.c:77 msgid "be somewhat more quiet" msgstr "" @@ -767,7 +767,7 @@ msgid "|FILE|listen on socket FILE" msgstr "" -#: src/dirmngr.c:218 src/dirmngr-client.c:128 src/dirmngr_ldap.c:140 +#: src/dirmngr.c:218 src/dirmngr-client.c:143 src/dirmngr_ldap.c:140 msgid "Please report bugs to .\n" msgstr "" @@ -797,162 +797,162 @@ #: src/dirmngr.c:360 #, c-format -msgid "error spawning ldap wrapper ripper thread: %s\n" +msgid "error spawning ldap wrapper reaper thread: %s\n" msgstr "" -#: src/dirmngr.c:490 src/dirmngr.c:500 +#: src/dirmngr.c:495 src/dirmngr.c:505 #, c-format msgid "%s is too old (need %s, have %s)\n" msgstr "" -#: src/dirmngr.c:597 +#: src/dirmngr.c:602 #, c-format msgid "NOTE: no default option file `%s'\n" msgstr "" -#: src/dirmngr.c:602 src/dirmngr.c:1260 +#: src/dirmngr.c:607 src/dirmngr.c:1267 #, c-format msgid "option file `%s': %s\n" msgstr "" -#: src/dirmngr.c:610 +#: src/dirmngr.c:615 #, c-format msgid "reading options from `%s'\n" msgstr "" -#: src/dirmngr.c:710 +#: src/dirmngr.c:715 #, c-format msgid "WARNING: running with faked system time %s\n" msgstr "" -#: src/dirmngr.c:786 +#: src/dirmngr.c:792 msgid "colons are not allowed in the socket name\n" msgstr "" -#: src/dirmngr.c:791 +#: src/dirmngr.c:797 msgid "name of socket too long\n" msgstr "" -#: src/dirmngr.c:798 +#: src/dirmngr.c:804 #, c-format msgid "can't create socket: %s\n" msgstr "" -#: src/dirmngr.c:817 +#: src/dirmngr.c:823 #, c-format msgid "error binding socket to `%s': %s\n" msgstr "" -#: src/dirmngr.c:826 +#: src/dirmngr.c:832 #, c-format msgid "listen() failed: %s\n" msgstr "" -#: src/dirmngr.c:832 +#: src/dirmngr.c:838 #, c-format msgid "listening on socket `%s'\n" msgstr "" -#: src/dirmngr.c:838 +#: src/dirmngr.c:844 #, c-format msgid "fork failed: %s\n" msgstr "" -#: src/dirmngr.c:856 +#: src/dirmngr.c:862 msgid "out of core\n" msgstr "" -#: src/dirmngr.c:895 +#: src/dirmngr.c:901 #, c-format msgid "setsid() failed: %s\n" msgstr "" -#: src/dirmngr.c:905 +#: src/dirmngr.c:911 #, c-format msgid "chdir to / failed: %s\n" msgstr "" -#: src/dirmngr.c:954 +#: src/dirmngr.c:961 #, c-format msgid "fetching CRL from `%s' failed: %s\n" msgstr "" -#: src/dirmngr.c:960 +#: src/dirmngr.c:967 #, c-format msgid "processing CRL from `%s' failed: %s\n" msgstr "" -#: src/dirmngr.c:1107 +#: src/dirmngr.c:1114 #, c-format msgid "error opening `%s': %s\n" msgstr "" -#: src/dirmngr.c:1124 +#: src/dirmngr.c:1131 #, c-format msgid "%s:%u: line too long - skipped\n" msgstr "" -#: src/dirmngr.c:1152 +#: src/dirmngr.c:1159 #, c-format msgid "%s:%u: no hostname given\n" msgstr "" -#: src/dirmngr.c:1171 +#: src/dirmngr.c:1178 #, c-format msgid "%s:%u: password given without user\n" msgstr "" -#: src/dirmngr.c:1192 +#: src/dirmngr.c:1199 #, c-format msgid "%s:%u: skipping this line\n" msgstr "" -#: src/dirmngr.c:1292 +#: src/dirmngr.c:1299 msgid "SIGHUP received - re-reading configuration and flushing caches\n" msgstr "" -#: src/dirmngr.c:1306 +#: src/dirmngr.c:1313 msgid "SIGUSR2 received - no action defined\n" msgstr "" -#: src/dirmngr.c:1311 +#: src/dirmngr.c:1318 msgid "SIGTERM received - shutting down ...\n" msgstr "" -#: src/dirmngr.c:1313 +#: src/dirmngr.c:1320 #, c-format msgid "SIGTERM received - still %d active connections\n" msgstr "" -#: src/dirmngr.c:1318 +#: src/dirmngr.c:1325 msgid "shutdown forced\n" msgstr "" -#: src/dirmngr.c:1326 +#: src/dirmngr.c:1333 msgid "SIGINT received - immediate shutdown\n" msgstr "" -#: src/dirmngr.c:1333 +#: src/dirmngr.c:1340 #, c-format msgid "signal %d received - no action defined\n" msgstr "" -#: src/dirmngr.c:1347 +#: src/dirmngr.c:1354 #, c-format msgid "handler for fd %d started\n" msgstr "" -#: src/dirmngr.c:1352 +#: src/dirmngr.c:1359 #, c-format msgid "handler for fd %d terminated\n" msgstr "" -#: src/dirmngr.c:1408 +#: src/dirmngr.c:1415 #, c-format msgid "accept failed: %s - waiting 1s\n" msgstr "" -#: src/dirmngr.c:1415 +#: src/dirmngr.c:1422 #, c-format msgid "error spawning connection handler: %s\n" msgstr "" @@ -1032,47 +1032,47 @@ msgid "ldap wrapper %d stalled - killing\n" msgstr "" -#: src/ldap.c:390 src/ldap.c:411 +#: src/ldap.c:401 src/ldap.c:422 #, c-format msgid "reading from ldap wrapper %d failed: %s\n" msgstr "" -#: src/ldap.c:556 src/ldap.c:562 +#: src/ldap.c:566 src/ldap.c:572 #, c-format msgid "error creating a pipe: %s\n" msgstr "" -#: src/ldap.c:572 +#: src/ldap.c:582 #, c-format msgid "error forking process: %s\n" msgstr "" -#: src/ldap.c:620 src/ldap.c:627 src/ldap.c:634 +#: src/ldap.c:630 src/ldap.c:637 src/ldap.c:644 #, c-format msgid "dup2 failed in child: %s\n" msgstr "" -#: src/ldap.c:652 +#: src/ldap.c:662 #, c-format msgid "error running `%s': %s\n" msgstr "" -#: src/ldap.c:664 +#: src/ldap.c:674 #, c-format msgid "error allocating memory: %s\n" msgstr "" -#: src/ldap.c:696 +#: src/ldap.c:706 #, c-format msgid "ldap wrapper %d started\n" msgstr "" -#: src/ldap.c:1160 +#: src/ldap.c:1170 #, c-format msgid "start_cert_fetch: invalid pattern `%s'\n" msgstr "" -#: src/ldap.c:1298 +#: src/ldap.c:1308 msgid "ldap_search hit the size limit of the server\n" msgstr "" @@ -1420,35 +1420,43 @@ msgid "certificate is not usable for signing\n" msgstr "" -#: src/dirmngr-client.c:66 +#: src/dirmngr-client.c:69 msgid "use OCSP instead of CRLs" msgstr "" -#: src/dirmngr-client.c:67 +#: src/dirmngr-client.c:70 msgid "check whether a dirmngr is running" msgstr "" -#: src/dirmngr-client.c:68 +#: src/dirmngr-client.c:71 msgid "add a certificate to the cache" msgstr "" -#: src/dirmngr-client.c:69 +#: src/dirmngr-client.c:72 msgid "validate a certificate" msgstr "" -#: src/dirmngr-client.c:70 +#: src/dirmngr-client.c:73 msgid "lookup a certificate" msgstr "" -#: src/dirmngr-client.c:71 +#: src/dirmngr-client.c:74 msgid "load a CRL into the dirmngr" msgstr "" -#: src/dirmngr-client.c:132 +#: src/dirmngr-client.c:75 +msgid "special mode for use by Squid" +msgstr "" + +#: src/dirmngr-client.c:76 +msgid "certificates are expected in PEM format" +msgstr "" + +#: src/dirmngr-client.c:147 msgid "Usage: dirmngr-client [options] [certfile|pattern] (-h for help)\n" msgstr "" -#: src/dirmngr-client.c:136 +#: src/dirmngr-client.c:151 msgid "" "Syntax: dirmngr-client [options] [certfile|pattern]\n" "Test an X.509 certificate against a CRL or do an OCSP check\n" @@ -1456,98 +1464,98 @@ "not valid and other error codes for general failures\n" msgstr "" -#: src/dirmngr-client.c:224 +#: src/dirmngr-client.c:265 src/dirmngr-client.c:953 #, c-format msgid "error reading certificate from stdin: %s\n" msgstr "" -#: src/dirmngr-client.c:231 +#: src/dirmngr-client.c:272 #, c-format msgid "error reading certificate from `%s': %s\n" msgstr "" -#: src/dirmngr-client.c:245 +#: src/dirmngr-client.c:286 msgid "certificate too large to make any sense\n" msgstr "" -#: src/dirmngr-client.c:264 +#: src/dirmngr-client.c:312 #, c-format msgid "lookup failed: %s\n" msgstr "" -#: src/dirmngr-client.c:279 +#: src/dirmngr-client.c:327 #, c-format msgid "loading CRL `%s' failed: %s\n" msgstr "" -#: src/dirmngr-client.c:307 +#: src/dirmngr-client.c:355 msgid "a dirmngr daemon is up and running\n" msgstr "" -#: src/dirmngr-client.c:329 +#: src/dirmngr-client.c:377 #, c-format msgid "validation of certificate failed: %s\n" msgstr "" -#: src/dirmngr-client.c:336 +#: src/dirmngr-client.c:384 src/dirmngr-client.c:964 msgid "certificate is valid\n" msgstr "" -#: src/dirmngr-client.c:342 +#: src/dirmngr-client.c:390 src/dirmngr-client.c:972 msgid "certificate has been revoked\n" msgstr "" -#: src/dirmngr-client.c:347 +#: src/dirmngr-client.c:395 src/dirmngr-client.c:974 #, c-format msgid "certificate check failed: %s\n" msgstr "" -#: src/dirmngr-client.c:358 +#: src/dirmngr-client.c:406 #, c-format msgid "got status: `%s'\n" msgstr "" -#: src/dirmngr-client.c:373 +#: src/dirmngr-client.c:421 #, c-format msgid "error writing base64 encoding: %s\n" msgstr "" -#: src/dirmngr-client.c:405 +#: src/dirmngr-client.c:453 msgid "apparently no running dirmngr\n" msgstr "" -#: src/dirmngr-client.c:410 +#: src/dirmngr-client.c:458 msgid "no running dirmngr - starting one\n" msgstr "" -#: src/dirmngr-client.c:443 +#: src/dirmngr-client.c:491 msgid "malformed DIRMNGR_INFO environment variable\n" msgstr "" -#: src/dirmngr-client.c:458 +#: src/dirmngr-client.c:506 #, c-format msgid "dirmngr protocol version %d is not supported\n" msgstr "" -#: src/dirmngr-client.c:474 +#: src/dirmngr-client.c:522 msgid "can't connect to the dirmngr - trying fall back\n" msgstr "" -#: src/dirmngr-client.c:482 +#: src/dirmngr-client.c:530 #, c-format msgid "can't connect to the dirmngr: %s\n" msgstr "" -#: src/dirmngr-client.c:565 +#: src/dirmngr-client.c:766 #, c-format msgid "unsupported inquiry `%s'\n" msgstr "" -#: src/dirmngr-client.c:657 +#: src/dirmngr-client.c:858 msgid "absolute file name expected\n" msgstr "" -#: src/dirmngr-client.c:700 +#: src/dirmngr-client.c:901 #, c-format msgid "looking up `%s'\n" msgstr "" From cvs at cvs.gnupg.org Tue Jan 4 21:07:24 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Tue Jan 4 21:07:29 2005 Subject: LIBGCRYPT-1-2-BRANCH libgcrypt/doc (ChangeLog gcrypt.texi) Message-ID: Date: Tuesday, January 4, 2005 @ 21:13:48 Author: wk Path: /cvs/libgcrypt/libgcrypt/doc Tag: LIBGCRYPT-1-2-BRANCH Modified: ChangeLog gcrypt.texi Updated to use @copying. Fixed list of copyright years; we had real changes in 2004. -------------+ ChangeLog | 5 ++ gcrypt.texi | 100 ++++++++++++++++++++-------------------------------------- 2 files changed, 41 insertions(+), 64 deletions(-) Index: libgcrypt/doc/ChangeLog diff -u libgcrypt/doc/ChangeLog:1.38.2.1 libgcrypt/doc/ChangeLog:1.38.2.2 --- libgcrypt/doc/ChangeLog:1.38.2.1 Mon Aug 9 12:38:02 2004 +++ libgcrypt/doc/ChangeLog Tue Jan 4 21:13:48 2005 @@ -1,3 +1,8 @@ +2005-01-04 Werner Koch + + * gcrypt.texi: Updated to use @copying. Fixed list of copyright + years; we had real changes in 2004. + 2004-05-07 Moritz Schulte * gcrypt.texi: Merged several fixes reported by Umberto Salsi. Index: libgcrypt/doc/gcrypt.texi diff -u libgcrypt/doc/gcrypt.texi:1.38.2.1 libgcrypt/doc/gcrypt.texi:1.38.2.2 --- libgcrypt/doc/gcrypt.texi:1.38.2.1 Mon Aug 9 12:38:02 2004 +++ libgcrypt/doc/gcrypt.texi Tue Jan 4 21:13:48 2005 @@ -1,88 +1,64 @@ \input texinfo @c -*- Texinfo -*- -@c Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc. -@c -@c This file is part of the Libgcrypt. -@c -@c Permission is granted to copy, distribute and/or modify this document -@c under the terms of the GNU General Public License as published by the -@c Free Software Foundation; either version 2 of the License, or (at your -@c option) any later version. A copy of the license is included in the -@c file 'gpl.texi'. -@c +@c %**start of header @setfilename gcrypt.info -@settitle The `Libgcrypt' Reference Manual - -@dircategory GNU Libraries -@direntry -* libgcrypt: (gcrypt) Cryptographic function library. -@end direntry - @include version.texi - +@settitle The Libgcrypt Reference Manual @c Unify some of the indices. @syncodeindex tp fn @syncodeindex pg fn +@c %**end of header +@copying +This manual is for Libgcrypt +(version @value{VERSION}, @value{UPDATED}), +which is GNU's library of cryptographic building blocks. -@ifinfo -This file documents the `Libgcrypt' library. - -This is Edition @value{EDITION}, last updated @value{UPDATED}, of -@cite{The `Libgcrypt' Reference Manual}, for Version -@value{VERSION}. - -Copyright @copyright{} 2000, 2002, 2003 Free Software Foundation, Inc. +Copyright @copyright{} 2000, 2002, 2003, 2004 Free Software Foundation, Inc. +@quotation Permission is granted to copy, distribute and/or modify this document 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. The text of the license can be found in the section entitled ``Copying''. -@end ifinfo +@end quotation +@end copying -@c @iftex -@c @shorttitlepage The `Libgcrypt' Reference Manual -@c @end iftex +@dircategory GNU Libraries +@direntry +* libgcrypt: (gcrypt) Cryptographic function library. +@end direntry + + + +@c +@c Titlepage +@c +@setchapternewpage odd @titlepage -@center @titlefont{The `Libgcrypt'} -@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} +@title The Libgcrypt Reference Manual +@subtitle Version @value{VERSION} +@subtitle @value{UPDATED} +@author Werner Koch (@email{wk@@gnupg.org}) +@author Moritz Schulte (@email{mo@g10code.com}) + @page @vskip 0pt plus 1filll -Copyright @copyright{} 2000, 2002, 2003 Free Software Foundation, Inc. - -Permission is granted to copy, distribute and/or modify this document -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. The text of the license can be found in the -section entitled ``Copying''. +@insertcopying @end titlepage + + @summarycontents @contents @page + @ifnottex @node Top -@top Main Menu -This is Edition @value{EDITION}, last updated @value{UPDATED}, of -@cite{The `Libgcrypt' Reference Manual}, for Version -@value{VERSION} of the @acronym{Libgcrypt} library. - -Copyright @copyright{} 2000, 2002, 2003 Free Software Foundation, Inc. - -Permission is granted to copy, distribute and/or modify this document -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. The text of the license can be found in the -section entitled ``Copying''. - +@top The Libgcrypt Library +@insertcopying @end ifnottex + @menu * Introduction:: What is @acronym{Libgcrypt}. * Preparation:: What you should do before using the library. @@ -208,6 +184,7 @@ interface (API). All functions and data types provided by the library are explained. +@noindent The reader is assumed to possess basic knowledge about applied cryptography. @@ -224,7 +201,6 @@ @node Features @section Features -@noindent `Libgcrypt' might have a couple of advantages over other libraries doing a similar job. @@ -247,7 +223,6 @@ @node Overview @section Overview -@noindent The `@acronym{Libgcrypt}' library is fully thread-safe, where it makes sense to be thread-safe. An exception for thread-safety are some cryptographic functions that modify a certain context stored in @@ -2206,13 +2181,10 @@ @node Cryptographic Functions @section Cryptographic Functions -@noindent Note, that we will in future allow to use keys without p,q and u specified and may also support other parameters for performance reasons. -@noindent - Some functions operating on S-expressions support `flags', that influence the operation. These flags have to be listed in a sub-S-expression named `flags'; the following flags are known: From cvs at cvs.gnupg.org Tue Jan 4 21:42:36 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Tue Jan 4 21:42:43 2005 Subject: libgcrypt/doc (ChangeLog gcrypt.texi) Message-ID: Date: Tuesday, January 4, 2005 @ 21:49:00 Author: wk Path: /cvs/libgcrypt/libgcrypt/doc Modified: ChangeLog gcrypt.texi Updated to use @copying. Fixed list of copyright years; we had real changes in 2004. Fixed some formatting issues. -------------+ ChangeLog | 5 ++ gcrypt.texi | 129 +++++++++++++++++++++------------------------------------- 2 files changed, 53 insertions(+), 81 deletions(-) Index: libgcrypt/doc/ChangeLog diff -u libgcrypt/doc/ChangeLog:1.41 libgcrypt/doc/ChangeLog:1.42 --- libgcrypt/doc/ChangeLog:1.41 Tue Aug 24 22:22:46 2004 +++ libgcrypt/doc/ChangeLog Tue Jan 4 21:49:00 2005 @@ -1,3 +1,8 @@ +2005-01-04 Werner Koch + + * gcrypt.texi: Updated to use @copying. Fixed list of copyright + years; we had real changes in 2004. Fixed some formatting issues. + 2004-08-24 Moritz Schulte * gcrypt.texi (Miscellaneous): Document gcry_mpi_randomize. Index: libgcrypt/doc/gcrypt.texi diff -u libgcrypt/doc/gcrypt.texi:1.43 libgcrypt/doc/gcrypt.texi:1.44 --- libgcrypt/doc/gcrypt.texi:1.43 Tue Oct 12 12:13:53 2004 +++ libgcrypt/doc/gcrypt.texi Tue Jan 4 21:49:00 2005 @@ -1,88 +1,64 @@ \input texinfo @c -*- Texinfo -*- -@c Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc. -@c -@c This file is part of the Libgcrypt. -@c -@c Permission is granted to copy, distribute and/or modify this document -@c under the terms of the GNU General Public License as published by the -@c Free Software Foundation; either version 2 of the License, or (at your -@c option) any later version. A copy of the license is included in the -@c file 'gpl.texi'. -@c +@c %**start of header @setfilename gcrypt.info -@settitle The `Libgcrypt' Reference Manual - -@dircategory GNU Libraries -@direntry -* libgcrypt: (gcrypt) Cryptographic function library. -@end direntry - @include version.texi - +@settitle The Libgcrypt Reference Manual @c Unify some of the indices. @syncodeindex tp fn @syncodeindex pg fn +@c %**end of header +@copying +This manual is for Libgcrypt +(version @value{VERSION}, @value{UPDATED}), +which is GNU's library of cryptographic building blocks. -@ifinfo -This file documents the `Libgcrypt' library. - -This is Edition @value{EDITION}, last updated @value{UPDATED}, of -@cite{The `Libgcrypt' Reference Manual}, for Version -@value{VERSION}. - -Copyright @copyright{} 2000, 2002, 2003 Free Software Foundation, Inc. +Copyright @copyright{} 2000, 2002, 2003, 2004 Free Software Foundation, Inc. +@quotation Permission is granted to copy, distribute and/or modify this document 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. The text of the license can be found in the section entitled ``Copying''. -@end ifinfo +@end quotation +@end copying -@c @iftex -@c @shorttitlepage The `Libgcrypt' Reference Manual -@c @end iftex +@dircategory GNU Libraries +@direntry +* libgcrypt: (gcrypt) Cryptographic function library. +@end direntry + + + +@c +@c Titlepage +@c +@setchapternewpage odd @titlepage -@center @titlefont{The `Libgcrypt'} -@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} +@title The Libgcrypt Reference Manual +@subtitle Version @value{VERSION} +@subtitle @value{UPDATED} +@author Werner Koch (@email{wk@@gnupg.org}) +@author Moritz Schulte (@email{mo@@g10code.com}) + @page @vskip 0pt plus 1filll -Copyright @copyright{} 2000, 2002, 2003 Free Software Foundation, Inc. - -Permission is granted to copy, distribute and/or modify this document -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. The text of the license can be found in the -section entitled ``Copying''. +@insertcopying @end titlepage + + @summarycontents @contents @page + @ifnottex @node Top -@top Main Menu -This is Edition @value{EDITION}, last updated @value{UPDATED}, of -@cite{The `Libgcrypt' Reference Manual}, for Version -@value{VERSION} of the @acronym{Libgcrypt} library. - -Copyright @copyright{} 2000, 2002, 2003 Free Software Foundation, Inc. - -Permission is granted to copy, distribute and/or modify this document -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. The text of the license can be found in the -section entitled ``Copying''. - +@top The Libgcrypt Library +@insertcopying @end ifnottex + @menu * Introduction:: What is @acronym{Libgcrypt}. * Preparation:: What you should do before using the library. @@ -208,6 +184,7 @@ interface (API). All functions and data types provided by the library are explained. +@noindent The reader is assumed to possess basic knowledge about applied cryptography. @@ -224,7 +201,6 @@ @node Features @section Features -@noindent `Libgcrypt' might have a couple of advantages over other libraries doing a similar job. @@ -243,7 +219,6 @@ @end table - @node Overview @section Overview @@ -1278,8 +1253,7 @@ To use a cipher algorithm, you must first allocate an according handle. This is to be done using the open function: -@deftypefun gcry_error_t gcry_cipher_open (gcry_cipher_hd_t *@var{hd}, -int @var{algo}, int @var{mode}, unsigned int @var{flags}) +@deftypefun gcry_error_t gcry_cipher_open (gcry_cipher_hd_t *@var{hd}, int @var{algo}, int @var{mode}, unsigned int @var{flags}) This function creates the context handle required for most of the other cipher functions and returns a handle to it in `hd'. In case of @@ -1754,8 +1728,7 @@ If the flag @code{GCRY_MD_FLAG_HMAC} was used, the key for the MAC must be set using the function: -@deftypefun gcry_error_t gcry_md_setkey (gcry_md_hd_t @var{h}, const void *@var{key}, -size_t @var{keylen}) +@deftypefun gcry_error_t gcry_md_setkey (gcry_md_hd_t @var{h}, const void *@var{key}, size_t @var{keylen}) For use with the HMAC feature, set the MAC key to the value of @var{key} of length @var{keylen}. @@ -2756,8 +2729,7 @@ Destroys the data set @var{data}. @end deftypefun -@deftypefun gcry_error_t gcry_ac_data_set (gcry_ac_data_t @var{data}, -unsigned int @var{flags}, char *@var{name}, gcry_mpi_t @var{mpi}) +@deftypefun gcry_error_t gcry_ac_data_set (gcry_ac_data_t @var{data}, unsigned int @var{flags}, char *@var{name}, gcry_mpi_t @var{mpi}) Add the value @var{mpi} to @var{data} with the label @var{name}. If @var{flags} contains GCRY_AC_FLAG_DATA_COPY, the data set will contain copies of @var{name} and @var{mpi}. If @var{flags} contains @@ -2775,16 +2747,13 @@ @var{data}. @end deftypefun -@deftypefun gcry_error_t gcry_ac_data_get_name (gcry_ac_data_t @var{data}, -unsigned int @var{flags}, char *@var{name}, gcry_mpi_t *@var{mpi}) +@deftypefun gcry_error_t gcry_ac_data_get_name (gcry_ac_data_t @var{data}, unsigned int @var{flags}, char *@var{name}, gcry_mpi_t *@var{mpi}) Store the value labelled with @var{name} found in @var{data} in @var{mpi}. If @var{flags} contains GCRY_AC_FLAG_COPY, store a copy of the @var{mpi} value contained in the data set. @var{mpi} may be NULL. @end deftypefun -@deftypefun gcry_error_t gcry_ac_data_get_index (gcry_ac_data_t @var{data}, -unsigned int flags, unsigned int @var{index}, -const char **@var{name}, gcry_mpi_t *@var{mpi}) +@deftypefun gcry_error_t gcry_ac_data_get_index (gcry_ac_data_t @var{data}, unsigned int flags, unsigned int @var{index}, const char **@var{name}, gcry_mpi_t *@var{mpi}) Stores in @var{name} and @var{mpi} the named @var{mpi} value contained in the data set @var{data} with the index @var{idx}. If @var{flags} contains GCRY_AC_FLAG_COPY, store copies of the values contained in @@ -2801,8 +2770,7 @@ In order to use an algorithm, an according handle must be created. This is done using the following function: -@deftypefun gcry_error_t gcry_ac_open (gcry_ac_handle_t *@var{handle}, -int @var{algorithm}, int @var{flags}) +@deftypefun gcry_error_t gcry_ac_open (gcry_ac_handle_t *@var{handle}, int @var{algorithm}, int @var{flags}) Creates a new handle for the algorithm @var{algorithm} and stores it in @var{handle}. @var{flags} is not used yet. @@ -2850,9 +2818,7 @@ contained in the data set @var{data} and stores it in @var{key}. @end deftypefun -@deftypefun gcry_error_t gcry_ac_key_pair_generate (gcry_ac_handle_t @var{handle}, -unsigned int @var{nbits}, void *@var{key_spec}, gcry_ac_key_pair_t *@var{key_pair}, -gcry_mpi_t **@var{misc_data}) +@deftypefun gcry_error_t gcry_ac_key_pair_generate (gcry_ac_handle_t @var{handle}, unsigned int @var{nbits}, void *@var{key_spec}, gcry_ac_key_pair_t *@var{key_pair}, gcry_mpi_t **@var{misc_data}) Generates a new key pair via the handle @var{handle} of @var{NBITS} bits and stores it in @var{key_pair}. @@ -2925,13 +2891,11 @@ Verifies that the private key @var{key} is sane via @var{handle}. @end deftypefun -@deftypefun gcry_error_t gcry_ac_key_get_nbits (gcry_ac_handle_t @var{handle}, -gcry_ac_key_t @var{key}, unsigned int *@var{nbits}) +@deftypefun gcry_error_t gcry_ac_key_get_nbits (gcry_ac_handle_t @var{handle}, gcry_ac_key_t @var{key}, unsigned int *@var{nbits}) Stores the number of bits of the key @var{key} in @var{nbits} via @var{handle}. @end deftypefun -@deftypefun gcry_error_t gcry_ac_key_get_grip (gcry_ac_handle_t @var{handle}, -gcry_ac_key_t @var{key}, unsigned char *@var{key_grip}) +@deftypefun gcry_error_t gcry_ac_key_get_grip (gcry_ac_handle_t @var{handle}, gcry_ac_key_t @var{key}, unsigned char *@var{key_grip}) Writes the 20 byte long key grip of the key @var{key} to @var{key_grip} via @var{handle}. @end deftypefun @@ -3787,3 +3751,6 @@ @c LocalWords: int HD + + + From cvs at cvs.gnupg.org Tue Jan 4 21:50:22 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Tue Jan 4 21:50:25 2005 Subject: LIBGCRYPT-1-2-BRANCH libgcrypt (ChangeLog Makefile.am configure.ac) Message-ID: Date: Tuesday, January 4, 2005 @ 21:56:46 Author: wk Path: /cvs/libgcrypt/libgcrypt Tag: LIBGCRYPT-1-2-BRANCH Modified: ChangeLog Makefile.am configure.ac Build a bzip archive; require new autotools --------------+ ChangeLog | 3 +++ Makefile.am | 2 ++ configure.ac | 6 +++--- 3 files changed, 8 insertions(+), 3 deletions(-) Index: libgcrypt/ChangeLog diff -u libgcrypt/ChangeLog:1.158.2.3 libgcrypt/ChangeLog:1.158.2.4 --- libgcrypt/ChangeLog:1.158.2.3 Tue Jan 4 21:50:23 2005 +++ libgcrypt/ChangeLog Tue Jan 4 21:56:46 2005 @@ -1,5 +1,8 @@ 2005-01-04 Werner Koch + * Makefile.am (ACLOCAL_AMFLAGS): New for -I m4. + (AUTOMAKE_OPTIONS): New to create a bzip archive. + Updated to automake 1.9. * acinclude.m4: Updated for automake 1.9. Index: libgcrypt/Makefile.am diff -u libgcrypt/Makefile.am:1.55 libgcrypt/Makefile.am:1.55.2.1 --- libgcrypt/Makefile.am:1.55 Mon Dec 8 22:43:02 2003 +++ libgcrypt/Makefile.am Tue Jan 4 21:56:46 2005 @@ -17,6 +17,8 @@ # License along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA +ACLOCAL_AMFLAGS = -I m4 +AUTOMAKE_OPTIONS = dist-bzip2 DIST_SUBDIRS = mpi cipher src doc tests w32-dll SUBDIRS = mpi cipher src doc tests Index: libgcrypt/configure.ac diff -u libgcrypt/configure.ac:1.70.2.2 libgcrypt/configure.ac:1.70.2.3 --- libgcrypt/configure.ac:1.70.2.2 Fri Sep 3 21:43:27 2004 +++ libgcrypt/configure.ac Tue Jan 4 21:56:46 2005 @@ -19,9 +19,9 @@ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA # # (Process this file with autoconf to produce a configure script.) -AC_REVISION($Revision: 1.70.2.2 $) -AC_PREREQ(2.57) -min_automake_version="1.7.6" +AC_REVISION($Revision: 1.70.2.3 $) +AC_PREREQ(2.59) +min_automake_version="1.9.3" # Version number: Remember to change it immediately *after* a release # but remove a "-cvs" prefix right *before* a release and append it From cvs at cvs.gnupg.org Tue Jan 4 15:10:17 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Wed Jan 5 07:57:32 2005 Subject: dirmngr (7 files) Message-ID: Date: Tuesday, January 4, 2005 @ 15:16:39 Author: wk Path: /cvs/dirmngr/dirmngr Added: tests/percent-escape.c Modified: ChangeLog NEWS doc/dirmngr.texi po/ChangeLog po/de.po tests/Makefile.am * de.po: Updated. * doc/dirmngr.texi: Cleaned up. Use @copying. ------------------------+ ChangeLog | 9 ++ NEWS | 5 + doc/dirmngr.texi | 133 +++++++++++++++++------------------ po/ChangeLog | 4 + po/de.po | 176 ++++++++++++++++++++++++----------------------- tests/Makefile.am | 6 + tests/percent-escape.c | 113 ++++++++++++++++++++++++++++++ 7 files changed, 292 insertions(+), 154 deletions(-) Index: dirmngr/ChangeLog diff -u dirmngr/ChangeLog:1.82 dirmngr/ChangeLog:1.83 --- dirmngr/ChangeLog:1.82 Sat Dec 18 09:50:39 2004 +++ dirmngr/ChangeLog Tue Jan 4 15:16:39 2005 @@ -1,3 +1,12 @@ +2005-01-04 Werner Koch + + * doc/dirmngr.texi: Cleaned up. Use @copying. + +2005-01-03 Werner Koch + + * tests/percent-escape.c: New. + * tests/Makefile.am (noinst_PROGRAMS): Add it. + 2004-12-18 Werner Koch * configure.ac: Include /usr/local for FreeBSD. Index: dirmngr/NEWS diff -u dirmngr/NEWS:1.33 dirmngr/NEWS:1.34 --- dirmngr/NEWS:1.33 Fri Dec 17 12:11:22 2004 +++ dirmngr/NEWS Tue Jan 4 15:16:39 2005 @@ -1,6 +1,11 @@ Noteworthy changes in version 0.9.1 ------------------------------------------------ + * New option --pem for dirmngr-client to allow requesing service + using a PEM encoded certificate. + + * New option --squid-mode to allow using dirmngr-client directly as a + Squid helper. Noteworthy changes in version 0.9.0 (2004-12-17) Index: dirmngr/doc/dirmngr.texi diff -u dirmngr/doc/dirmngr.texi:1.19 dirmngr/doc/dirmngr.texi:1.20 --- dirmngr/doc/dirmngr.texi:1.19 Mon Dec 13 16:16:35 2004 +++ dirmngr/doc/dirmngr.texi Tue Jan 4 15:16:39 2005 @@ -1,39 +1,44 @@ \input texinfo @c -*-texinfo-*- -@c Copyright (C) 2002 Klarälvdalens Datakonsult AB -@c Copyright (c) 2004 g10 Code GmbH -@c This is part of the Dirmngr manual. -@c For copying conditions, see the file gpl.texi. @c %**start of header @setfilename dirmngr.info - @include version.texi +@settitle Using Dirmngr +@c Create a separate index for command line options. +@defcodeindex op +@c Merge the standard indexes into a single one. +@syncodeindex fn cp +@syncodeindex vr cp +@syncodeindex ky cp +@syncodeindex pg cp +@syncodeindex tp cp +@c %**end of header +@copying +This manual is for Dirmngr +(version @value{VERSION}, @value{UPDATED}), +which is an X.509 CRL and OCSP manager. -@macro copyrightnotice Copyright @copyright{} 2002 Klarälvdalens Datakonsult AB Copyright @copyright{} 2004 g10 Code GmbH -@end macro -@macro permissionnotice + +@quotation Permission is granted to copy, distribute and/or modify this document 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. The text of the license can be found in the section entitled ``Copying''. -@end macro - +@end quotation +@end copying -@settitle Using Dirmngr - -@c Create a separate index for command line options. -@defcodeindex op -@c Merge the standard indexes into a single one. -@syncodeindex fn cp -@syncodeindex vr cp -@syncodeindex ky cp -@syncodeindex pg cp -@syncodeindex tp cp +@dircategory GNU Utilities +@direntry +* dirmngr: (gnupg). X.509 CRL and OCSP server. +* dirmngr-client: (gnupg). X.509 CRL and OCSP client. +@end direntry -@c printing stuff taken from gcc. +@c +@c Printing stuff taken from gcc. +@c @macro gnupgtabopt{body} @code{\body\} @end macro @@ -53,66 +58,31 @@ @end macro @end ifnottex - -@c Change the font used for @def... commands, since the default -@c proportional one used is bad for names starting __. -@tex -\global\setfont\defbf\ttbshape{10}{\magstep1} -@end tex - -@c %**end of header - -@ifnottex -@dircategory GNU Utilities -@direntry -* dirmngr: (gnupg). X.509 CRL and OCSP server. -* dirmngr-client: (gnupg). X.509 CRL and OCSP client. -@end direntry -This file documents the use of dirmngr. - -This is Edition @value{EDITION}, last updated @value{UPDATED}, of -@cite{The `Dirmngr' Manual}, for Version @value{VERSION}. -@sp 1 -@copyrightnotice{} -@sp 1 -@permissionnotice{} -@end ifnottex - +@c +@c Titlepage +@c @c @setchapternewpage odd - @titlepage @title Using Dirmngr -@subtitle Version @value{VERSION} -@subtitle @value{UPDATED} -@author Steffen Hansen @code{(steffen@@klaralvdalens-datakonsult.se)} -@author Werner Koch @code{(wk@@g10code.com)} - +@subtitle for version @value{VERSION}, @value{UPDATED} +@author Steffen Hansen (@email{steffen@@klaralvdalens-datakonsult.se}) +@author Werner Koch (@email{wk@@g10code.com}) @page @vskip 0pt plus 1filll -@copyrightnotice{} -@sp 2 -@permissionnotice{} +@insertcopying @end titlepage -@summarycontents -@contents -@page +@contents +@ifnottex @node Top -@top Introduction -@cindex introduction - -@c man begin DESCRIPTION - -Dirmngr is a server for managing and downloading certificate revocation -lists (CRLs) for X.509 certificates and for downloading the certificates -themselves. Dirmngr also handles OCSP requests as an alternative to -CRLs. Dirmngr is either invoked internally by gpgsm (from gnupg 1.9) or -when running as a system daemon through the @command{dirmngr-client} tool. +@top Dirmngr +@insertcopying +@end ifnottex -@c man end @menu +* Introduction:: About Dirmngr. * Installation:: How to install Dirmngr. * Dirmngr Commands:: List of all commands. * Dirmngr Options:: List of all options. @@ -130,6 +100,21 @@ @end menu +@node Introduction +@chapter About Dirmngr. + + +@c man begin DESCRIPTION + +Dirmngr is a server for managing and downloading certificate revocation +lists (CRLs) for X.509 certificates and for downloading the certificates +themselves. Dirmngr also handles OCSP requests as an alternative to +CRLs. Dirmngr is either invoked internally by gpgsm (from gnupg 1.9) or +when running as a system daemon through the @command{dirmngr-client} tool. + +@c man end + + @node Installation @chapter How to install Dirmngr. @@ -820,6 +805,10 @@ You can increase the verbosity by giving several verbose commands to @sc{dirmngr}, such as @samp{-vv}. +@item --pem +@opindex pem +Assume that the given certificate is in PEM (armored) format. + @item --ocsp @opindex ocsp Do the check using the COSP protocol and ignore any CRLs. @@ -850,6 +839,12 @@ may be used to retrieve certificates from a server. However the output format is not very well suited if more than one certificate is returned. +@item --squid-mode +@opindex squid-mode +Run @sc{dirmngr-client} in a mode suitable as a helper program for +Squid's @option{external_acl_type} option. + + @end table Index: dirmngr/po/ChangeLog diff -u dirmngr/po/ChangeLog:1.2 dirmngr/po/ChangeLog:1.3 --- dirmngr/po/ChangeLog:1.2 Tue Sep 28 15:10:35 2004 +++ dirmngr/po/ChangeLog Tue Jan 4 15:16:39 2005 @@ -1,3 +1,7 @@ +2005-01-04 Werner Koch + + * de.po: Updated. + 2004-09-28 Werner Koch * de.po: Converted to utf-8. Index: dirmngr/po/de.po diff -u dirmngr/po/de.po:1.10 dirmngr/po/de.po:1.11 --- dirmngr/po/de.po:1.10 Fri Dec 17 11:55:40 2004 +++ dirmngr/po/de.po Tue Jan 4 15:16:39 2005 @@ -7,15 +7,15 @@ msgstr "" "Project-Id-Version: dirmngr 0.9.0\n" "Report-Msgid-Bugs-To: gpa-dev@gnupg.org\n" -"POT-Creation-Date: 2004-12-17 11:40+0100\n" -"PO-Revision-Date: 2004-12-17 11:50+0100\n" +"POT-Creation-Date: 2005-01-04 15:12+0100\n" +"PO-Revision-Date: 2005-01-04 15:14+0100\n" "Last-Translator: Werner Koch \n" "Language-Team: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -#: jnlib/logging.c:624 +#: jnlib/logging.c:625 #, c-format msgid "you found a bug ... (%s:%d)\n" msgstr "Sie haben einen Bug (Softwarefehler) gefunden ... (%s:%d)\n" @@ -45,7 +45,7 @@ msgid "can't access directory `%s': %s\n" msgstr "Fehler beim Zugriff auf das Verzeichnis `%s': %s\n" -#: src/certcache.c:323 src/crlcache.c:2173 src/ldap.c:615 +#: src/certcache.c:323 src/crlcache.c:2173 src/ldap.c:625 #, c-format msgid "can't open `%s': %s\n" msgstr "`%s' kann nicht geöffnet werden: %s\n" @@ -90,7 +90,7 @@ msgid " runtime cached certificates: %u\n" msgstr "zur Laufzeit geladene Zertifikate: %u\n" -#: src/certcache.c:457 src/dirmngr-client.c:317 +#: src/certcache.c:457 src/dirmngr-client.c:365 msgid "certificate already cached\n" msgstr "Zertifikat ist bereits im Cache\n" @@ -98,7 +98,7 @@ msgid "certificate cached\n" msgstr "Zertifikat wurde gecachet\n" -#: src/certcache.c:461 src/dirmngr-client.c:321 +#: src/certcache.c:461 src/dirmngr-client.c:369 #, c-format msgid "error caching certificate: %s\n" msgstr "Fehler beim Cachen des Zertifikats: %s\n" @@ -215,7 +215,7 @@ msgid "unsupported record type in `%s' line %u skipped\n" msgstr "Nicht unterstützter Datensatztyp in `%s', Zeile %u übergangen\n" -#: src/crlcache.c:574 src/crlcache.c:803 src/dirmngr.c:1203 +#: src/crlcache.c:574 src/crlcache.c:803 src/dirmngr.c:1210 #, c-format msgid "error reading `%s': %s\n" msgstr "Fehler beim Lesen von `%s': %s\n" @@ -593,7 +593,7 @@ msgid "End CRL dump\n" msgstr "Ende CRL Ausgabe\n" -#: src/crlcache.c:2182 src/crlfetch.c:97 src/ldap.c:683 +#: src/crlcache.c:2182 src/crlfetch.c:97 src/ldap.c:693 #, c-format msgid "error initializing reader object: %s\n" msgstr "Fehler beim Initialisieren des \"reader\" Objekts: %s\n" @@ -688,11 +688,11 @@ "Optionen:\n" " " -#: src/dirmngr.c:119 src/dirmngr-client.c:64 src/dirmngr_ldap.c:76 +#: src/dirmngr.c:119 src/dirmngr-client.c:67 src/dirmngr_ldap.c:76 msgid "verbose" msgstr "ausführlich" -#: src/dirmngr.c:120 src/dirmngr-client.c:65 src/dirmngr_ldap.c:77 +#: src/dirmngr.c:120 src/dirmngr-client.c:68 src/dirmngr_ldap.c:77 msgid "be somewhat more quiet" msgstr "etwas weniger Ausgaben erzeugen" @@ -792,7 +792,7 @@ msgid "|FILE|listen on socket FILE" msgstr "|DATEI|Anfragen auf Socket DATEI annehmen" -#: src/dirmngr.c:218 src/dirmngr-client.c:128 src/dirmngr_ldap.c:140 +#: src/dirmngr.c:218 src/dirmngr-client.c:143 src/dirmngr_ldap.c:140 msgid "Please report bugs to .\n" msgstr "Berichte über Bugs (Programmfehler) bitte an .\n" @@ -824,163 +824,163 @@ #: src/dirmngr.c:360 #, c-format -msgid "error spawning ldap wrapper ripper thread: %s\n" -msgstr "Fehler beim Starten des LDAP Wrapper Thread: %s\n" +msgid "error spawning ldap wrapper reaper thread: %s\n" +msgstr "Fehler beim Starten des LDAP Wrapper Kontrollthreads: %s\n" -#: src/dirmngr.c:490 src/dirmngr.c:500 +#: src/dirmngr.c:495 src/dirmngr.c:505 #, c-format msgid "%s is too old (need %s, have %s)\n" msgstr "%s ist zu alt (benötige %s, habe %s)\n" -#: src/dirmngr.c:597 +#: src/dirmngr.c:602 #, c-format msgid "NOTE: no default option file `%s'\n" msgstr "Hinweis: Voreingestellte Optionendatei `%s' nicht vorhanden\n" -#: src/dirmngr.c:602 src/dirmngr.c:1260 +#: src/dirmngr.c:607 src/dirmngr.c:1267 #, c-format msgid "option file `%s': %s\n" msgstr "Optionendatei `%s': %s\n" -#: src/dirmngr.c:610 +#: src/dirmngr.c:615 #, c-format msgid "reading options from `%s'\n" msgstr "Optionen werden von `%s' gelesen\n" -#: src/dirmngr.c:710 +#: src/dirmngr.c:715 #, c-format msgid "WARNING: running with faked system time %s\n" msgstr "WARNUNG: Prozess läuft mit getürkter Systemzeit %s\n" -#: src/dirmngr.c:786 +#: src/dirmngr.c:792 msgid "colons are not allowed in the socket name\n" msgstr "Doppelpunkte sind im Namen des Sockets nicht erlaubt\n" -#: src/dirmngr.c:791 +#: src/dirmngr.c:797 msgid "name of socket too long\n" msgstr "Name des Sockets ist zu lang\n" -#: src/dirmngr.c:798 +#: src/dirmngr.c:804 #, c-format msgid "can't create socket: %s\n" msgstr "Fehler beim Erzeugen des Sockets: %s\n" -#: src/dirmngr.c:817 +#: src/dirmngr.c:823 #, c-format msgid "error binding socket to `%s': %s\n" msgstr "Fehler beim Binden des Sockets an `%s': %s\n" -#: src/dirmngr.c:826 +#: src/dirmngr.c:832 #, c-format msgid "listen() failed: %s\n" msgstr "listen() fehlgeschlagen: %s\n" -#: src/dirmngr.c:832 +#: src/dirmngr.c:838 #, c-format msgid "listening on socket `%s'\n" msgstr "Anfragen werden auf Socket `%s' engegengenommen\n" -#: src/dirmngr.c:838 +#: src/dirmngr.c:844 #, c-format msgid "fork failed: %s\n" msgstr "fork() fehlgeschlagen: %s\n" -#: src/dirmngr.c:856 +#: src/dirmngr.c:862 msgid "out of core\n" msgstr "Nicht genügend Hauptspeicher vorhanden\n" -#: src/dirmngr.c:895 +#: src/dirmngr.c:901 #, c-format msgid "setsid() failed: %s\n" msgstr "setsid() fehlgeschlagen: %s\n" -#: src/dirmngr.c:905 +#: src/dirmngr.c:911 #, c-format msgid "chdir to / failed: %s\n" msgstr "chdir nach / fehlgeschlagen: %s\n" -#: src/dirmngr.c:954 +#: src/dirmngr.c:961 #, c-format msgid "fetching CRL from `%s' failed: %s\n" msgstr "Holen der CRL von `%s' fehlgeschlagen: %s\n" -#: src/dirmngr.c:960 +#: src/dirmngr.c:967 #, c-format msgid "processing CRL from `%s' failed: %s\n" msgstr "Verarbeitung der CRL von `%s' fehlgeschlagen: %s\n" -#: src/dirmngr.c:1107 +#: src/dirmngr.c:1114 #, c-format msgid "error opening `%s': %s\n" msgstr "Fehler beim Öffnen von `%s': %s\n" -#: src/dirmngr.c:1124 +#: src/dirmngr.c:1131 #, c-format msgid "%s:%u: line too long - skipped\n" msgstr "%s:%u: Zeile ist zu lang - übergangen\n" -#: src/dirmngr.c:1152 +#: src/dirmngr.c:1159 #, c-format msgid "%s:%u: no hostname given\n" msgstr "%s:%u: Kein Hostname angegeben\n" -#: src/dirmngr.c:1171 +#: src/dirmngr.c:1178 #, c-format msgid "%s:%u: password given without user\n" msgstr "%s:%u: Passwort angegeben ohne Username\n" -#: src/dirmngr.c:1192 +#: src/dirmngr.c:1199 #, c-format msgid "%s:%u: skipping this line\n" msgstr "%s:%u: Diese Zeile wird übersprungen\n" -#: src/dirmngr.c:1292 +#: src/dirmngr.c:1299 msgid "SIGHUP received - re-reading configuration and flushing caches\n" msgstr "" "SIGHUP empfangen - lese die Konfiguration erneut und lösche die Caches\n" -#: src/dirmngr.c:1306 +#: src/dirmngr.c:1313 msgid "SIGUSR2 received - no action defined\n" msgstr "SIGUSR2 empfangen - keine Aktion definiert\n" -#: src/dirmngr.c:1311 +#: src/dirmngr.c:1318 msgid "SIGTERM received - shutting down ...\n" msgstr "SIGTERM empfangen - wird heruntergefahren ...\n" -#: src/dirmngr.c:1313 +#: src/dirmngr.c:1320 #, c-format msgid "SIGTERM received - still %d active connections\n" msgstr "SIGTERM empfangen - immer noch %d Verbindungen aktiv\n" -#: src/dirmngr.c:1318 +#: src/dirmngr.c:1325 msgid "shutdown forced\n" msgstr "Herunterfahren wurde erzwungen\n" -#: src/dirmngr.c:1326 +#: src/dirmngr.c:1333 msgid "SIGINT received - immediate shutdown\n" msgstr "SIGINT empfangen - wird sofort heruntergefahren\n" -#: src/dirmngr.c:1333 +#: src/dirmngr.c:1340 #, c-format msgid "signal %d received - no action defined\n" msgstr "Signal %d empfangen - keine Aktion definiert\n" -#: src/dirmngr.c:1347 +#: src/dirmngr.c:1354 #, c-format msgid "handler for fd %d started\n" msgstr "Routine für fd %d gestartet\n" -#: src/dirmngr.c:1352 +#: src/dirmngr.c:1359 #, c-format msgid "handler for fd %d terminated\n" msgstr "Routine für fd %d beendet\n" -#: src/dirmngr.c:1408 +#: src/dirmngr.c:1415 #, c-format msgid "accept failed: %s - waiting 1s\n" msgstr "accept() fehlgeschlagen: %s - warte 1s\n" -#: src/dirmngr.c:1415 +#: src/dirmngr.c:1422 #, c-format msgid "error spawning connection handler: %s\n" msgstr "Fehler beim Starten des Verbindungshandler: %s\n" @@ -1060,47 +1060,47 @@ msgid "ldap wrapper %d stalled - killing\n" msgstr "LDAP Wrapper %d versackt - abgeschossen\n" -#: src/ldap.c:390 src/ldap.c:411 +#: src/ldap.c:401 src/ldap.c:422 #, c-format msgid "reading from ldap wrapper %d failed: %s\n" msgstr "Lesen vom LDAP Wrapper %d fehlgeschlagen: %s\n" -#: src/ldap.c:556 src/ldap.c:562 +#: src/ldap.c:566 src/ldap.c:572 #, c-format msgid "error creating a pipe: %s\n" msgstr "Fehler beim Erzeugen einer Pipe: %s\n" -#: src/ldap.c:572 +#: src/ldap.c:582 #, c-format msgid "error forking process: %s\n" msgstr "Fehler beim Forken eines Prozesses: %s\n" -#: src/ldap.c:620 src/ldap.c:627 src/ldap.c:634 +#: src/ldap.c:630 src/ldap.c:637 src/ldap.c:644 #, c-format msgid "dup2 failed in child: %s\n" msgstr "dup2() im Kindprozess fehlgeschlagen: %s\n" -#: src/ldap.c:652 +#: src/ldap.c:662 #, c-format msgid "error running `%s': %s\n" msgstr "Fehler beim Ausführen von `%s': %s\n" -#: src/ldap.c:664 +#: src/ldap.c:674 #, c-format msgid "error allocating memory: %s\n" msgstr "Fehler beim Allozieren von Speicher: %s\n" -#: src/ldap.c:696 +#: src/ldap.c:706 #, c-format msgid "ldap wrapper %d started\n" msgstr "LDAP Wrapper %d gestartet\n" -#: src/ldap.c:1160 +#: src/ldap.c:1170 #, c-format msgid "start_cert_fetch: invalid pattern `%s'\n" msgstr "start_cert_fetch: Ungültiges Muster `%s'\n" -#: src/ldap.c:1298 +#: src/ldap.c:1308 msgid "ldap_search hit the size limit of the server\n" msgstr "ldap_search erreichte die Größengrenze des Servers\n" @@ -1455,36 +1455,44 @@ msgid "certificate is not usable for signing\n" msgstr "Das Zertifikat kann nicht zum Signieren benutzt werden\n" -#: src/dirmngr-client.c:66 +#: src/dirmngr-client.c:69 msgid "use OCSP instead of CRLs" msgstr "OCSP anstatt CRL benutzen" -#: src/dirmngr-client.c:67 +#: src/dirmngr-client.c:70 msgid "check whether a dirmngr is running" msgstr "Teste ob der dirmngr noch läuft" -#: src/dirmngr-client.c:68 +#: src/dirmngr-client.c:71 msgid "add a certificate to the cache" msgstr "Ein Zertifikat dem Cache zufügen" -#: src/dirmngr-client.c:69 +#: src/dirmngr-client.c:72 msgid "validate a certificate" msgstr "Zertifikat prüfen" -#: src/dirmngr-client.c:70 +#: src/dirmngr-client.c:73 msgid "lookup a certificate" msgstr "Zertifikat auffinden" -#: src/dirmngr-client.c:71 +#: src/dirmngr-client.c:74 msgid "load a CRL into the dirmngr" msgstr "CRL in den Dirmngr laden" -#: src/dirmngr-client.c:132 +#: src/dirmngr-client.c:75 +msgid "special mode for use by Squid" +msgstr "Sondermodus für Squid" + +#: src/dirmngr-client.c:76 +msgid "certificates are expected in PEM format" +msgstr "Zertifikate werden im PEM Format erwartet" + +#: src/dirmngr-client.c:147 msgid "Usage: dirmngr-client [options] [certfile|pattern] (-h for help)\n" msgstr "" "Gebrauch: dirmngr-client [Optionen] [Zertdatei|Muster] (-h für Hilfe)\n" -#: src/dirmngr-client.c:136 +#: src/dirmngr-client.c:151 msgid "" "Syntax: dirmngr-client [options] [certfile|pattern]\n" "Test an X.509 certificate against a CRL or do an OCSP check\n" @@ -1497,98 +1505,98 @@ "The Prozess gibt 0 zurück wenn das Zertifikat gültig ist, 1 wenn es nicht\n" "gültig ist und weitere Werte bei anderen Fehlern.\n" -#: src/dirmngr-client.c:224 +#: src/dirmngr-client.c:265 src/dirmngr-client.c:953 #, c-format msgid "error reading certificate from stdin: %s\n" msgstr "Fehler beim Lesen des Zertifikats von der Standardeingabe: %s\n" -#: src/dirmngr-client.c:231 +#: src/dirmngr-client.c:272 #, c-format msgid "error reading certificate from `%s': %s\n" msgstr "Fehler beim Lesen des Zertifikats von `%s': %s\n" -#: src/dirmngr-client.c:245 +#: src/dirmngr-client.c:286 msgid "certificate too large to make any sense\n" msgstr "Zertifikat ist zu groß um Sinnvoll zu sein\n" -#: src/dirmngr-client.c:264 +#: src/dirmngr-client.c:312 #, c-format msgid "lookup failed: %s\n" msgstr "Aufsuchen fehlgeschlagen: %s\n" -#: src/dirmngr-client.c:279 +#: src/dirmngr-client.c:327 #, c-format msgid "loading CRL `%s' failed: %s\n" msgstr "Laden der CRL von `%s' fehlgeschlagen: %s\n" -#: src/dirmngr-client.c:307 +#: src/dirmngr-client.c:355 msgid "a dirmngr daemon is up and running\n" msgstr "Ein dirmngr ist vorhanden und aktiv\n" -#: src/dirmngr-client.c:329 +#: src/dirmngr-client.c:377 #, c-format msgid "validation of certificate failed: %s\n" msgstr "Prüfung des Zertifikats fehlgeschlagen: %s\n" -#: src/dirmngr-client.c:336 +#: src/dirmngr-client.c:384 src/dirmngr-client.c:964 msgid "certificate is valid\n" msgstr "Zertifikat ist gültig\n" -#: src/dirmngr-client.c:342 +#: src/dirmngr-client.c:390 src/dirmngr-client.c:972 msgid "certificate has been revoked\n" msgstr "Zertifikat wurde widerrufen\n" -#: src/dirmngr-client.c:347 +#: src/dirmngr-client.c:395 src/dirmngr-client.c:974 #, c-format msgid "certificate check failed: %s\n" msgstr "Zertifikatprüfung fehlgeschlagen: %s\n" -#: src/dirmngr-client.c:358 +#: src/dirmngr-client.c:406 #, c-format msgid "got status: `%s'\n" msgstr "Erhielt Status: `%s'\n" -#: src/dirmngr-client.c:373 +#: src/dirmngr-client.c:421 #, c-format msgid "error writing base64 encoding: %s\n" msgstr "Fehler beim Schreiben der Base-64 Darstellung: %s\n" -#: src/dirmngr-client.c:405 +#: src/dirmngr-client.c:453 msgid "apparently no running dirmngr\n" msgstr "Offensichtlich ist kein Dirmngr vorhanden\n" -#: src/dirmngr-client.c:410 +#: src/dirmngr-client.c:458 msgid "no running dirmngr - starting one\n" msgstr "Dirmngr läuft nicht - ein neuer wird gestartet\n" -#: src/dirmngr-client.c:443 +#: src/dirmngr-client.c:491 msgid "malformed DIRMNGR_INFO environment variable\n" msgstr "Fehlerhafte DIRMNGR_INFO Variable\n" -#: src/dirmngr-client.c:458 +#: src/dirmngr-client.c:506 #, c-format msgid "dirmngr protocol version %d is not supported\n" msgstr "Dirmngr Protocol Version %d wird nicht unterstützt\n" -#: src/dirmngr-client.c:474 +#: src/dirmngr-client.c:522 msgid "can't connect to the dirmngr - trying fall back\n" msgstr "Verbindung zum Dirmngr nicht möglich - Rückfallmethode wird versucht\n" -#: src/dirmngr-client.c:482 +#: src/dirmngr-client.c:530 #, c-format msgid "can't connect to the dirmngr: %s\n" msgstr "Verbindung zum Dirmngr nicht möglich: %s\n" -#: src/dirmngr-client.c:565 +#: src/dirmngr-client.c:766 #, c-format msgid "unsupported inquiry `%s'\n" msgstr "Nicht unterstützte INQUIRY `%s'\n" -#: src/dirmngr-client.c:657 +#: src/dirmngr-client.c:858 msgid "absolute file name expected\n" msgstr "Absoluter Dateiname erwartet\n" -#: src/dirmngr-client.c:700 +#: src/dirmngr-client.c:901 #, c-format msgid "looking up `%s'\n" msgstr "Auffinden von `%s'\n" Index: dirmngr/tests/Makefile.am diff -u dirmngr/tests/Makefile.am:1.9 dirmngr/tests/Makefile.am:1.10 --- dirmngr/tests/Makefile.am:1.9 Tue Nov 16 19:24:35 2004 +++ dirmngr/tests/Makefile.am Tue Jan 4 15:16:38 2005 @@ -10,7 +10,7 @@ TESTS = -noinst_PROGRAMS = test-dirmngr asschk show-multi +noinst_PROGRAMS = test-dirmngr asschk show-multi percent-escape LDADD = ../jnlib/libjnlib.a @LIBASSUAN_LIBS@ @LIBGCRYPT_LIBS@ @KSBA_LIBS@ asschk_SOURCES = asschk.c @@ -18,6 +18,10 @@ show_multi_SOURCERS = show-multi.c show_multi_LDADD = +percent_escape_SOURCERS = percent-escape.c +percent_escape_LDADD = + + Index: dirmngr/tests/percent-escape.c diff -u /dev/null dirmngr/tests/percent-escape.c:1.1 --- /dev/null Tue Jan 4 15:16:39 2005 +++ dirmngr/tests/percent-escape.c Tue Jan 4 15:16:38 2005 @@ -0,0 +1,113 @@ +/*percent-escape.c - Test tool to create percent escaped data + * Copyright (C) 2004 g10 Code GmbH + * + * This file is part of DirMngr. + * + * DirMngr 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. + * + * DirMngr 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 + +#define PGM "percent-escape" + +/* Print diagnostic message and exit with failure. */ +static void +die (const char *format, ...) +{ + va_list arg_ptr; + + fflush (stdout); + fprintf (stderr, "%s: ", PGM); + + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + putc ('\n', stderr); + + exit (1); +} + + +static void +proc (FILE *fp) +{ + int c; + + while ((c=getc (fp))!= EOF) + if ( c <= ' ' || c >= 127 || c == '%' ) + printf ("%%%02X", (unsigned int)c); + else + putchar (c); +} + + + +int +main (int argc, char **argv) +{ + int last_argc = -1; + + if (argc) + { + argc--; argv++; + } + while (argc && last_argc != argc ) + { + last_argc = argc; + if (!strcmp (*argv, "--")) + { + argc--; argv++; + break; + } + else if (!strcmp (*argv, "--help")) + { + puts ( + "Usage: " PGM " [OPTION] [FILE]\n" + "Percent escape the input\n\n" + " --help display this help and exit\n\n" + "With no FILE, or when FILE is -, read standard input.\n"); + exit (0); + } + } + + if (argc > 1) + die ("usage: " PGM " [OPTION] [FILE] (try --help for more information)\n"); + + if (argc && strcmp (*argv, "-")) + { + FILE *fp = fopen (*argv, "rb"); + if (!fp) + die ("can't open `%s': %s", *argv, strerror (errno)); + proc (fp); + fclose (fp); + } + else + proc (stdin); + + return 0; +} + + +/* +Local Variables: +compile-command: "gcc -Wall -g -o percent-escape percent-escape.c" +End: +*/ From cvs at cvs.gnupg.org Wed Jan 5 17:23:10 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Wed Jan 5 17:23:30 2005 Subject: LIBGCRYPT-1-2-BRANCH libgcrypt/cipher (ChangeLog serpent.c) Message-ID: Date: Wednesday, January 5, 2005 @ 17:29:38 Author: wk Path: /cvs/libgcrypt/libgcrypt/cipher Tag: LIBGCRYPT-1-2-BRANCH Modified: ChangeLog serpent.c s/u32_t/u32/ -----------+ ChangeLog | 5 ++ serpent.c | 108 ++++++++++++++++++++++++++++-------------------------------- 2 files changed, 57 insertions(+), 56 deletions(-) Index: libgcrypt/cipher/ChangeLog diff -u libgcrypt/cipher/ChangeLog:1.211.2.7 libgcrypt/cipher/ChangeLog:1.211.2.8 --- libgcrypt/cipher/ChangeLog:1.211.2.7 Thu Dec 9 18:04:16 2004 +++ libgcrypt/cipher/ChangeLog Wed Jan 5 17:29:38 2005 @@ -1,3 +1,8 @@ +2005-01-05 Werner Koch + + * serpent.c: s/u32_t/u32/ and s/byte_t/byte/. Too match what we + have always used and are using in all other files too. + 2004-12-09 Werner Koch * serpent.c (serpent_test): Moved prototype out of a fucntion. Index: libgcrypt/cipher/serpent.c diff -u libgcrypt/cipher/serpent.c:1.4.2.2 libgcrypt/cipher/serpent.c:1.4.2.3 --- libgcrypt/cipher/serpent.c:1.4.2.2 Thu Dec 9 18:04:16 2004 +++ libgcrypt/cipher/serpent.c Wed Jan 5 17:29:38 2005 @@ -35,19 +35,15 @@ /* Magic number, used during generating of the subkeys. */ #define PHI 0x9E3779B9 -/* Internal types. */ -typedef byte byte_t; -typedef u32 u32_t; - /* Serpent works on 128 bit blocks. */ -typedef u32_t serpent_block_t[4]; +typedef u32 serpent_block_t[4]; /* Serpent key, provided by the user. If the original key is shorter than 256 bits, it is padded. */ -typedef u32_t serpent_key_t[8]; +typedef u32 serpent_key_t[8]; /* The key schedule consists of 33 128 bit subkeys. */ -typedef u32_t serpent_subkeys_t[ROUNDS + 1][4]; +typedef u32 serpent_subkeys_t[ROUNDS + 1][4]; /* A Serpent context. */ typedef struct serpent_context @@ -83,8 +79,8 @@ #define SBOX0(a, b, c, d, w, x, y, z) \ { \ - u32_t t02, t03, t05, t06, t07, t08, t09; \ - u32_t t11, t12, t13, t14, t15, t17, t01; \ + u32 t02, t03, t05, t06, t07, t08, t09; \ + u32 t11, t12, t13, t14, t15, t17, t01; \ t01 = b ^ c ; \ t02 = a | d ; \ t03 = a ^ b ; \ @@ -107,8 +103,8 @@ #define SBOX0_INVERSE(a, b, c, d, w, x, y, z) \ { \ - u32_t t02, t03, t04, t05, t06, t08, t09, t10; \ - u32_t t12, t13, t14, t15, t17, t18, t01; \ + u32 t02, t03, t04, t05, t06, t08, t09, t10; \ + u32 t12, t13, t14, t15, t17, t18, t01; \ t01 = c ^ d ; \ t02 = a | b ; \ t03 = b | c ; \ @@ -132,8 +128,8 @@ #define SBOX1(a, b, c, d, w, x, y, z) \ { \ - u32_t t02, t03, t04, t05, t06, t07, t08; \ - u32_t t10, t11, t12, t13, t16, t17, t01; \ + u32 t02, t03, t04, t05, t06, t07, t08; \ + u32 t10, t11, t12, t13, t16, t17, t01; \ t01 = a | d ; \ t02 = c ^ d ; \ t03 = ~ b ; \ @@ -156,8 +152,8 @@ #define SBOX1_INVERSE(a, b, c, d, w, x, y, z) \ { \ - u32_t t02, t03, t04, t05, t06, t07, t08; \ - u32_t t09, t10, t11, t14, t15, t17, t01; \ + u32 t02, t03, t04, t05, t06, t07, t08; \ + u32 t09, t10, t11, t14, t15, t17, t01; \ t01 = a ^ b ; \ t02 = b | d ; \ t03 = a & c ; \ @@ -180,8 +176,8 @@ #define SBOX2(a, b, c, d, w, x, y, z) \ { \ - u32_t t02, t03, t05, t06, t07, t08; \ - u32_t t09, t10, t12, t13, t14, t01; \ + u32 t02, t03, t05, t06, t07, t08; \ + u32 t09, t10, t12, t13, t14, t01; \ t01 = a | c ; \ t02 = a ^ b ; \ t03 = d ^ t01; \ @@ -202,8 +198,8 @@ #define SBOX2_INVERSE(a, b, c, d, w, x, y, z) \ { \ - u32_t t02, t03, t04, t06, t07, t08, t09; \ - u32_t t10, t11, t12, t15, t16, t17, t01; \ + u32 t02, t03, t04, t06, t07, t08, t09; \ + u32 t10, t11, t12, t15, t16, t17, t01; \ t01 = a ^ d ; \ t02 = c ^ d ; \ t03 = a & c ; \ @@ -226,8 +222,8 @@ #define SBOX3(a, b, c, d, w, x, y, z) \ { \ - u32_t t02, t03, t04, t05, t06, t07, t08; \ - u32_t t09, t10, t11, t13, t14, t15, t01; \ + u32 t02, t03, t04, t05, t06, t07, t08; \ + u32 t09, t10, t11, t13, t14, t15, t01; \ t01 = a ^ c ; \ t02 = a | d ; \ t03 = a & d ; \ @@ -250,8 +246,8 @@ #define SBOX3_INVERSE(a, b, c, d, w, x, y, z) \ { \ - u32_t t02, t03, t04, t05, t06, t07, t09; \ - u32_t t11, t12, t13, t14, t16, t01; \ + u32 t02, t03, t04, t05, t06, t07, t09; \ + u32 t11, t12, t13, t14, t16, t01; \ t01 = c | d ; \ t02 = a | d ; \ t03 = c ^ t02; \ @@ -273,8 +269,8 @@ #define SBOX4(a, b, c, d, w, x, y, z) \ { \ - u32_t t02, t03, t04, t05, t06, t08, t09; \ - u32_t t10, t11, t12, t13, t14, t15, t16, t01; \ + u32 t02, t03, t04, t05, t06, t08, t09; \ + u32 t10, t11, t12, t13, t14, t15, t16, t01; \ t01 = a | b ; \ t02 = b | c ; \ t03 = a ^ t02; \ @@ -298,8 +294,8 @@ #define SBOX4_INVERSE(a, b, c, d, w, x, y, z) \ { \ - u32_t t02, t03, t04, t05, t06, t07, t09; \ - u32_t t10, t11, t12, t13, t15, t01; \ + u32 t02, t03, t04, t05, t06, t07, t09; \ + u32 t10, t11, t12, t13, t15, t01; \ t01 = b | d ; \ t02 = c | d ; \ t03 = a & t01; \ @@ -321,8 +317,8 @@ #define SBOX5(a, b, c, d, w, x, y, z) \ { \ - u32_t t02, t03, t04, t05, t07, t08, t09; \ - u32_t t10, t11, t12, t13, t14, t01; \ + u32 t02, t03, t04, t05, t07, t08, t09; \ + u32 t10, t11, t12, t13, t14, t01; \ t01 = b ^ d ; \ t02 = b | d ; \ t03 = a & t01; \ @@ -344,8 +340,8 @@ #define SBOX5_INVERSE(a, b, c, d, w, x, y, z) \ { \ - u32_t t02, t03, t04, t05, t07, t08, t09; \ - u32_t t10, t12, t13, t15, t16, t01; \ + u32 t02, t03, t04, t05, t07, t08, t09; \ + u32 t10, t12, t13, t15, t16, t01; \ t01 = a & d ; \ t02 = c ^ t01; \ t03 = a ^ d ; \ @@ -367,8 +363,8 @@ #define SBOX6(a, b, c, d, w, x, y, z) \ { \ - u32_t t02, t03, t04, t05, t07, t08, t09, t10; \ - u32_t t11, t12, t13, t15, t17, t18, t01; \ + u32 t02, t03, t04, t05, t07, t08, t09, t10; \ + u32 t11, t12, t13, t15, t17, t18, t01; \ t01 = a & d ; \ t02 = b ^ c ; \ t03 = a ^ d ; \ @@ -392,8 +388,8 @@ #define SBOX6_INVERSE(a, b, c, d, w, x, y, z) \ { \ - u32_t t02, t03, t04, t05, t06, t07, t08, t09; \ - u32_t t12, t13, t14, t15, t16, t17, t01; \ + u32 t02, t03, t04, t05, t06, t07, t08, t09; \ + u32 t12, t13, t14, t15, t16, t17, t01; \ t01 = a ^ c ; \ t02 = ~ c ; \ t03 = b & t01; \ @@ -417,8 +413,8 @@ #define SBOX7(a, b, c, d, w, x, y, z) \ { \ - u32_t t02, t03, t04, t05, t06, t08, t09, t10; \ - u32_t t11, t13, t14, t15, t16, t17, t01; \ + u32 t02, t03, t04, t05, t06, t08, t09, t10; \ + u32 t11, t13, t14, t15, t16, t17, t01; \ t01 = a & c ; \ t02 = ~ d ; \ t03 = a & t02; \ @@ -442,8 +438,8 @@ #define SBOX7_INVERSE(a, b, c, d, w, x, y, z) \ { \ - u32_t t02, t03, t04, t06, t07, t08, t09; \ - u32_t t10, t11, t13, t14, t15, t16, t01; \ + u32 t02, t03, t04, t06, t07, t08, t09; \ + u32 t10, t11, t13, t14, t15, t16, t01; \ t01 = a & b ; \ t02 = a | b ; \ t03 = c | t01; \ @@ -583,7 +579,7 @@ /* Convert the user provided key KEY of KEY_LENGTH bytes into the internally used format. */ static void -serpent_key_prepare (const byte_t *key, unsigned int key_length, +serpent_key_prepare (const byte *key, unsigned int key_length, serpent_key_t key_prepared) { int i; @@ -592,9 +588,9 @@ for (i = 0; i < key_length / 4; i++) { #ifdef WORDS_BIGENDIAN - key_prepared[i] = byte_swap_32 (((u32_t *) key)[i]); + key_prepared[i] = byte_swap_32 (((u32 *) key)[i]); #else - key_prepared[i] = ((u32_t *) key)[i]; + key_prepared[i] = ((u32 *) key)[i]; #endif } @@ -613,9 +609,9 @@ static void serpent_subkeys_generate (serpent_key_t key, serpent_subkeys_t subkeys) { - u32_t w_real[140]; /* The `prekey'. */ - u32_t k[132]; - u32_t *w = &w_real[8]; + u32 w_real[140]; /* The `prekey'. */ + u32 k[132]; + u32 *w = &w_real[8]; int i, j; /* Initialize with key values. */ @@ -670,19 +666,19 @@ /* Initialize CONTEXT with the key KEY of KEY_LENGTH bits. */ static void serpent_setkey_internal (serpent_context_t *context, - const byte_t *key, unsigned int key_length) + const byte *key, unsigned int key_length) { serpent_key_t key_prepared; serpent_key_prepare (key, key_length, key_prepared); serpent_subkeys_generate (key_prepared, context->keys); - _gcry_burn_stack (272 * sizeof (u32_t)); + _gcry_burn_stack (272 * sizeof (u32)); } /* Initialize CTX with the key KEY of KEY_LENGTH bytes. */ static gcry_err_code_t serpent_setkey (void *ctx, - const byte_t *key, unsigned int key_length) + const byte *key, unsigned int key_length) { serpent_context_t *context = ctx; static const char *serpent_test_ret; @@ -843,12 +839,12 @@ } static void -serpent_encrypt (void *ctx, byte_t *buffer_out, const byte_t *buffer_in) +serpent_encrypt (void *ctx, byte *buffer_out, const byte *buffer_in) { serpent_context_t *context = ctx; serpent_encrypt_internal (context, - (const u32_t *) buffer_in, (u32_t *) buffer_out); + (const u32 *) buffer_in, (u32 *) buffer_out); _gcry_burn_stack (2 * sizeof (serpent_block_t)); } @@ -858,8 +854,8 @@ serpent_context_t *context = ctx; serpent_decrypt_internal (context, - (const u32_t *) buffer_in, - (u32_t *) buffer_out); + (const u32 *) buffer_in, + (u32 *) buffer_out); _gcry_burn_stack (2 * sizeof (serpent_block_t)); } @@ -919,8 +915,8 @@ serpent_setkey_internal (&context, test_data[i].key, test_data[i].key_length); serpent_encrypt_internal (&context, - (const u32_t *) test_data[i].text_plain, - (u32_t *) scratch); + (const u32 *) test_data[i].text_plain, + (u32 *) scratch); if (memcmp (scratch, test_data[i].text_cipher, sizeof (serpent_block_t))) switch (test_data[i].key_length) @@ -934,8 +930,8 @@ } serpent_decrypt_internal (&context, - (const u32_t *) test_data[i].text_cipher, - (u32_t *) scratch); + (const u32 *) test_data[i].text_cipher, + (u32 *) scratch); if (memcmp (scratch, test_data[i].text_plain, sizeof (serpent_block_t))) switch (test_data[i].key_length) { From cvs at cvs.gnupg.org Wed Jan 5 21:00:38 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Wed Jan 5 21:00:44 2005 Subject: dirmngr/src (ChangeLog dirmngr-client.c) Message-ID: Date: Wednesday, January 5, 2005 @ 21:07:08 Author: wk Path: /cvs/dirmngr/dirmngr/src Modified: ChangeLog dirmngr-client.c (read_pem_certificate): Skip trailing percent escaped linefeeds. ------------------+ ChangeLog | 5 +++++ dirmngr-client.c | 18 ++++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) Index: dirmngr/src/ChangeLog diff -u dirmngr/src/ChangeLog:1.40 dirmngr/src/ChangeLog:1.41 --- dirmngr/src/ChangeLog:1.40 Mon Jan 3 21:42:46 2005 +++ dirmngr/src/ChangeLog Wed Jan 5 21:07:08 2005 @@ -1,3 +1,8 @@ +2005-01-05 Werner Koch + + * dirmngr-client.c (read_pem_certificate): Skip trailing percent + escaped linefeeds. + 2005-01-03 Werner Koch * dirmngr-client.c (read_pem_certificate): New. Index: dirmngr/src/dirmngr-client.c diff -u dirmngr/src/dirmngr-client.c:1.7 dirmngr/src/dirmngr-client.c:1.8 --- dirmngr/src/dirmngr-client.c:1.7 Mon Jan 3 21:42:46 2005 +++ dirmngr/src/dirmngr-client.c Wed Jan 5 21:07:08 2005 @@ -566,6 +566,8 @@ buflen = 0; while ((c=getc (fp)) != EOF) { + int escaped_c = 0; + if (opt.escaped_pem) { if (c == '%') @@ -581,9 +583,13 @@ { log_error ("invalid percent escape sequence\n"); state = s_idle; /* Force an error. */ - break; + /* Skip to end of line. */ + while ( (c=getc (fp)) != EOF && c != '\n') + ; + goto ready; } c = xtoi_2 (tmp); + escaped_c = 1; } else if (c == '\n') goto ready; /* Ready. */ @@ -654,11 +660,11 @@ } break; case s_waitend: - /* Note that we do not check whether the END line really - follows, nor did we check that the base64 decoder was - left in the expected state. We assume that the PEM - header is just fine. */ - if (c== '\n') + /* Note that we do not check that the base64 decoder has + been left in the expected state. We assume that the PEM + header is just fine. However we need to wait for the + real LF and not a trailing percent escaped one. */ + if (c== '\n' && !escaped_c) goto ready; break; default: From cvs at cvs.gnupg.org Wed Jan 5 17:38:07 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Wed Jan 5 22:57:20 2005 Subject: LIBGCRYPT-1-2-BRANCH libgcrypt (NEWS configure.ac) Message-ID: Date: Wednesday, January 5, 2005 @ 17:44:35 Author: wk Path: /cvs/libgcrypt/libgcrypt Tag: LIBGCRYPT-1-2-BRANCH Modified: NEWS configure.ac post release preps --------------+ NEWS | 3 +++ configure.ac | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) Index: libgcrypt/NEWS diff -u libgcrypt/NEWS:1.69.2.2 libgcrypt/NEWS:1.69.2.3 --- libgcrypt/NEWS:1.69.2.2 Wed Jan 5 14:52:33 2005 +++ libgcrypt/NEWS Wed Jan 5 17:44:35 2005 @@ -1,3 +1,6 @@ +Noteworthy changes in version 1.2.2 +------------------------------------------------ + Noteworthy changes in version 1.2.1 (2005-01-05) ------------------------------------------------ Index: libgcrypt/configure.ac diff -u libgcrypt/configure.ac:1.70.2.4 libgcrypt/configure.ac:1.70.2.5 --- libgcrypt/configure.ac:1.70.2.4 Wed Jan 5 14:52:33 2005 +++ libgcrypt/configure.ac Wed Jan 5 17:44:35 2005 @@ -19,7 +19,7 @@ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA # # (Process this file with autoconf to produce a configure script.) -AC_REVISION($Revision: 1.70.2.4 $) +AC_REVISION($Revision: 1.70.2.5 $) AC_PREREQ(2.59) min_automake_version="1.9.3" @@ -27,7 +27,7 @@ # but remove a "-cvs" prefix right *before* a release and append it # soon later. -AC_INIT(libgcrypt, 1.2.1, bug-libgcrypt@gnupg.org) +AC_INIT(libgcrypt, 1.2.2-cvs, bug-libgcrypt@gnupg.org) # LT Version numbers, remember to change them just *before* a release. # (Interfaces removed: CURRENT++, AGE=0, REVISION=0) From cvs at cvs.gnupg.org Wed Jan 5 17:38:36 2005 From: cvs at cvs.gnupg.org (cvs user marcus) Date: Wed Jan 5 22:59:13 2005 Subject: libgpg-error (ChangeLog configure.ac) Message-ID: Date: Wednesday, January 5, 2005 @ 17:38:36 Author: marcus Path: /cvs/gnupg/libgpg-error Modified: ChangeLog configure.ac 2005-01-05 Marcus Brinkmann * configure.ac: Check for locale.h. --------------+ ChangeLog | 4 ++++ configure.ac | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) From cvs at cvs.gnupg.org Wed Jan 5 14:46:13 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Wed Jan 5 23:45:59 2005 Subject: LIBGCRYPT-1-2-BRANCH libgcrypt (8 files) Message-ID: Date: Wednesday, January 5, 2005 @ 14:52:34 Author: wk Path: /cvs/libgcrypt/libgcrypt Tag: LIBGCRYPT-1-2-BRANCH Modified: ChangeLog NEWS configure.ac mpi/ChangeLog mpi/hppa1.1/udiv-qrnnd.S src/ChangeLog src/gcrypt.h src/global.c Preapred 1.2.1 --------------------------+ ChangeLog | 6 ++++++ NEWS | 16 +++++++++++++++- configure.ac | 10 +++++----- mpi/ChangeLog | 5 +++++ mpi/hppa1.1/udiv-qrnnd.S | 15 ++++++++------- src/ChangeLog | 6 ++++++ src/gcrypt.h | 9 ++++++++- src/global.c | 7 +++++++ 8 files changed, 60 insertions(+), 14 deletions(-) Index: libgcrypt/ChangeLog diff -u libgcrypt/ChangeLog:1.158.2.4 libgcrypt/ChangeLog:1.158.2.5 --- libgcrypt/ChangeLog:1.158.2.4 Tue Jan 4 21:56:46 2005 +++ libgcrypt/ChangeLog Wed Jan 5 14:52:33 2005 @@ -1,3 +1,9 @@ +2005-01-05 Werner Koch + + Released 1.2.1. + + * configure.ac: Set LT to C13/A2/R0. + 2005-01-04 Werner Koch * Makefile.am (ACLOCAL_AMFLAGS): New for -I m4. Index: libgcrypt/NEWS diff -u libgcrypt/NEWS:1.69.2.1 libgcrypt/NEWS:1.69.2.2 --- libgcrypt/NEWS:1.69.2.1 Fri Sep 3 21:43:27 2004 +++ libgcrypt/NEWS Wed Jan 5 14:52:33 2005 @@ -1,6 +1,20 @@ -Noteworthy changes in version 1.2.1 +Noteworthy changes in version 1.2.1 (2005-01-05) ------------------------------------------------ + * Portability fixes, memory allocation fixes and other minor things. + + * Support to build as a W32 static library. + + * Changed the way the RNG gets initialized. This allows to keep it + uninitialized as long as no random numbers are used. To override + this, the new macro gcry_fast_random_poll may be used. It is in + general a good idea to spread this macro into the application code + to make sure that these polls happen often enough. + + * Interface changes relative to the 1.2.0 release: + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + gcry_fast_random_poll NEW + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Noteworthy changes in version 1.2.0 (2004-04-15) Index: libgcrypt/configure.ac diff -u libgcrypt/configure.ac:1.70.2.3 libgcrypt/configure.ac:1.70.2.4 --- libgcrypt/configure.ac:1.70.2.3 Tue Jan 4 21:56:46 2005 +++ libgcrypt/configure.ac Wed Jan 5 14:52:33 2005 @@ -19,7 +19,7 @@ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA # # (Process this file with autoconf to produce a configure script.) -AC_REVISION($Revision: 1.70.2.3 $) +AC_REVISION($Revision: 1.70.2.4 $) AC_PREREQ(2.59) min_automake_version="1.9.3" @@ -27,15 +27,15 @@ # but remove a "-cvs" prefix right *before* a release and append it # soon later. -AC_INIT(libgcrypt, 1.2.1-cvs, bug-libgcrypt@gnupg.org) +AC_INIT(libgcrypt, 1.2.1, bug-libgcrypt@gnupg.org) # LT Version numbers, remember to change them just *before* a release. # (Interfaces removed: CURRENT++, AGE=0, REVISION=0) # (Interfaces added: CURRENT++, AGE++, REVISION=0) # (No interfaces changed: REVISION++) -LIBGCRYPT_LT_CURRENT=12 -LIBGCRYPT_LT_AGE=1 -LIBGCRYPT_LT_REVISION=1 +LIBGCRYPT_LT_CURRENT=13 +LIBGCRYPT_LT_AGE=2 +LIBGCRYPT_LT_REVISION=0 # If the API is changed in an incompatible way: increment the next counter. LIBGCRYPT_CONFIG_API_VERSION=1 Index: libgcrypt/mpi/ChangeLog diff -u libgcrypt/mpi/ChangeLog:1.89.2.1 libgcrypt/mpi/ChangeLog:1.89.2.2 --- libgcrypt/mpi/ChangeLog:1.89.2.1 Thu Dec 16 17:32:51 2004 +++ libgcrypt/mpi/ChangeLog Wed Jan 5 14:52:33 2005 @@ -1,3 +1,8 @@ +2005-01-05 Werner Koch + + * hppa1.1/udiv-qrnnd.S: Reverted change of 2004-03-02 but kept the + .align directive. + 2004-12-16 Werner Koch * config.links (mpi_optional_modules): Move entry for powerpc64 Index: libgcrypt/mpi/hppa1.1/udiv-qrnnd.S diff -u libgcrypt/mpi/hppa1.1/udiv-qrnnd.S:1.7 libgcrypt/mpi/hppa1.1/udiv-qrnnd.S:1.7.2.1 --- libgcrypt/mpi/hppa1.1/udiv-qrnnd.S:1.7 Wed Mar 3 09:08:41 2004 +++ libgcrypt/mpi/hppa1.1/udiv-qrnnd.S Wed Jan 5 14:52:33 2005 @@ -36,11 +36,12 @@ * d gr23 */ - .code + .data .align 8 .label L$0000 .word 0x43f00000 .word 0x0 + .code .export __udiv_qrnnd .label __udiv_qrnnd .proc @@ -50,13 +51,14 @@ stws %r25,-16(0,%r30) ; n_hi stws %r24,-12(0,%r30) ; n_lo - ldil L'L$0000,%r19 ; ' - ldo R'L$0000(%r19),%r19 ; ' + stw %r19,-32(%r30) + addil LT%L$0000,%r19 + ldw RT%L$0000(%r1),%r1 fldds -16(0,%r30),%fr5 stws %r23,-12(0,%r30) comib,<= 0,%r25,L$1 fcnvxf,dbl,dbl %fr5,%fr5 - fldds 0(0,%r19),%fr4 + fldds 0(0,%r1),%fr4 fadd,dbl %fr4,%fr5,%fr5 .label L$1 fcpy,sgl %fr0,%fr6L @@ -73,8 +75,8 @@ ldws -12(0,%r30),%r21 ldws -16(0,%r30),%r20 sub %r24,%r21,%r22 - subb %r25,%r20,%r19 - comib,= 0,%r19,L$2 + subb %r25,%r20,%r1 + comib,= 0,%r1,L$2 ldo -64(%r30),%r30 add %r22,%r23,%r22 @@ -86,4 +88,3 @@ .exit .procend - \ No newline at end of file Index: libgcrypt/src/ChangeLog diff -u libgcrypt/src/ChangeLog:1.151.2.10 libgcrypt/src/ChangeLog:1.151.2.11 --- libgcrypt/src/ChangeLog:1.151.2.10 Tue Jan 4 21:50:23 2005 +++ libgcrypt/src/ChangeLog Wed Jan 5 14:52:33 2005 @@ -1,3 +1,9 @@ +2005-01-05 Werner Koch + + * gcrypt.h: Added GCRYCTL_FAST_POLL. + (gcry_fast_random_poll): New. + * global.c (gcry_control) : New. + 2004-12-20 Werner Koch * gcrypt.h (GCRY_THREAD_OPTION_PTH_IMPL): Tweaks for W32. Index: libgcrypt/src/gcrypt.h diff -u libgcrypt/src/gcrypt.h:1.125.2.4 libgcrypt/src/gcrypt.h:1.125.2.5 --- libgcrypt/src/gcrypt.h:1.125.2.4 Tue Jan 4 21:50:22 2005 +++ libgcrypt/src/gcrypt.h Wed Jan 5 14:52:33 2005 @@ -346,7 +346,8 @@ GCRYCTL_ENABLE_QUICK_RANDOM = 44, GCRYCTL_SET_RANDOM_SEED_FILE = 45, GCRYCTL_UPDATE_RANDOM_SEED_FILE = 46, - GCRYCTL_SET_THREAD_CBS = 47 + GCRYCTL_SET_THREAD_CBS = 47, + GCRYCTL_FAST_POLL = 48 }; /* Perform various operations defined by CMD. */ @@ -1340,6 +1341,12 @@ gcry_error_t gcry_random_add_bytes (const void *buffer, size_t length, int quality); +/* If random numbers are used in an application, this macro should be + called from time to time so that new stuff gets added to the + internal pool of the RNG. */ +#define gcry_fast_random_poll() gcry_control (GCRYCTL_FAST_POLL, NULL) + + /* Return NBYTES of allocated random using a random numbers of quality LEVEL. */ void *gcry_random_bytes (size_t nbytes, enum gcry_random_level level) Index: libgcrypt/src/global.c diff -u libgcrypt/src/global.c:1.45.2.1 libgcrypt/src/global.c:1.45.2.2 --- libgcrypt/src/global.c:1.45.2.1 Wed Sep 15 12:23:04 2004 +++ libgcrypt/src/global.c Wed Jan 5 14:52:33 2005 @@ -274,6 +274,13 @@ err = ath_install (va_arg (arg_ptr, void *), any_init_done); break; + case GCRYCTL_FAST_POLL: + /* We need to do make sure that the random pool is really + initialized so that the poll fucntion is not a NOP. */ + _gcry_random_initialize (1); + _gcry_fast_random_poll (); + break; + default: err = GPG_ERR_INV_OP; } From cvs at cvs.gnupg.org Wed Jan 5 17:01:02 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Wed Jan 5 23:57:39 2005 Subject: LIBGCRYPT-1-2-BRANCH libgcrypt/src (gcrypt.h) Message-ID: Date: Wednesday, January 5, 2005 @ 17:07:31 Author: wk Path: /cvs/libgcrypt/libgcrypt/src Tag: LIBGCRYPT-1-2-BRANCH Modified: gcrypt.h Preparing a release ----------+ gcrypt.h | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: libgcrypt/src/gcrypt.h diff -u libgcrypt/src/gcrypt.h:1.125.2.5 libgcrypt/src/gcrypt.h:1.125.2.6 --- libgcrypt/src/gcrypt.h:1.125.2.5 Wed Jan 5 14:52:33 2005 +++ libgcrypt/src/gcrypt.h Wed Jan 5 17:07:31 2005 @@ -49,7 +49,7 @@ autoconf (using the AM_PATH_GCRYPT macro) check that this header matches the installed library. Note: Do not edit the next line as configure may fix the string here. */ -#define GCRYPT_VERSION "1.2.1-cvs" +#define GCRYPT_VERSION "1.2.1" /* Internal: We can't use the convenience macros for the multi precision integer functions when building this library. */ From cvs at cvs.gnupg.org Thu Jan 6 05:38:07 2005 From: cvs at cvs.gnupg.org (cvs user dshaw) Date: Thu Jan 6 05:38:12 2005 Subject: gnupg/g10 (ChangeLog armor.c g10.c) Message-ID: Date: Thursday, January 6, 2005 @ 05:44:38 Author: dshaw Path: /cvs/gnupg/gnupg/g10 Modified: ChangeLog armor.c g10.c * g10.c (main): Typo. * armor.c (is_armor_header): Allow CR and LF (not just actual spaces) in an armor header line (-----BEGIN etc). This is needed due to CRLF issues on win32. As before, --openpgp makes it strict. -----------+ ChangeLog | 9 +++++++++ armor.c | 25 ++++++++++++++++--------- g10.c | 4 ++-- 3 files changed, 27 insertions(+), 11 deletions(-) Index: gnupg/g10/ChangeLog diff -u gnupg/g10/ChangeLog:1.676 gnupg/g10/ChangeLog:1.677 --- gnupg/g10/ChangeLog:1.676 Mon Jan 3 16:15:34 2005 +++ gnupg/g10/ChangeLog Thu Jan 6 05:44:38 2005 @@ -1,3 +1,12 @@ +2005-01-05 David Shaw + + * g10.c (main): Typo. + + * armor.c (is_armor_header): Allow CR and LF (not just actual + spaces) in an armor header line (-----BEGIN etc). This is needed + due to CRLF issues on win32. As before, --openpgp makes it + strict. + 2005-01-03 David Shaw * Makefile.am: Use @LIBUSB@ instead of @LIBUSB_LIBS@ Index: gnupg/g10/armor.c diff -u gnupg/g10/armor.c:1.77 gnupg/g10/armor.c:1.78 --- gnupg/g10/armor.c:1.77 Thu Oct 14 22:13:16 2004 +++ gnupg/g10/armor.c Thu Jan 6 05:44:38 2005 @@ -291,17 +291,24 @@ save_p = p; p += 5; - /* Some mail programs on Windows seem to add spaces to the end of - the line. This becomes strict if --openpgp is set. */ - - if(!RFC2440) - while(*p==' ') + /* Some Windows environments seem to add whitespace to the end of + the line, so we strip it here. This becomes strict if + --rfc2440 is set since 2440 reads "The header lines, therefore, + MUST start at the beginning of a line, and MUST NOT have text + following them on the same line." It is unclear whether "text" + refers to all text or just non-whitespace text. */ + + if(RFC2440) + { + if( *p == '\r' ) + p++; + if( *p == '\n' ) + p++; + } + else + while(*p==' ' || *p=='\r' || *p=='\n') p++; - if( *p == '\r' ) - p++; - if( *p == '\n' ) - p++; if( *p ) return -1; /* garbage after dashes */ save_c = *save_p; *save_p = 0; Index: gnupg/g10/g10.c diff -u gnupg/g10/g10.c:1.295 gnupg/g10/g10.c:1.296 --- gnupg/g10/g10.c:1.295 Mon Dec 20 06:19:09 2004 +++ gnupg/g10/g10.c Thu Jan 6 05:44:38 2005 @@ -2607,8 +2607,8 @@ if(require_secmem && !got_secmem) { - log_info(_("will not run with insecure memory due to %s"), - "--require-secmem\n"); + log_info(_("will not run with insecure memory due to %s\n"), + "--require-secmem"); g10_exit(2); } From cvs at cvs.gnupg.org Thu Jan 6 12:45:15 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Thu Jan 6 12:45:19 2005 Subject: gnupg/util (ChangeLog strgutil.c) Message-ID: Date: Thursday, January 6, 2005 @ 12:51:49 Author: wk Path: /cvs/gnupg/gnupg/util Modified: ChangeLog strgutil.c (set_native_charset): Assume that ASCII, ANSI_X3.4-1968 and 646 are actually meant as Latin-1. If nl_langinfo is not available get the charset from environment variables. For W32 use GetACP as error fallback. Removed Latin-15 to Latin-1 aliasing. ------------+ ChangeLog | 8 ++++++++ strgutil.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 55 insertions(+), 8 deletions(-) Index: gnupg/util/ChangeLog diff -u gnupg/util/ChangeLog:1.174 gnupg/util/ChangeLog:1.175 --- gnupg/util/ChangeLog:1.174 Wed Dec 29 01:58:05 2004 +++ gnupg/util/ChangeLog Thu Jan 6 12:51:49 2005 @@ -1,3 +1,11 @@ +2005-01-06 Werner Koch + + * strgutil.c (set_native_charset): Assume that ASCII, + ANSI_X3.4-1968 and 646 are actually meant as Latin-1. If + nl_langinfo is not available get the charset from environment + variables. For W32 use GetACP as error fallback. Removed Latin-15 + to Latin-1 aliasing. + 2004-12-28 David Shaw * srv.h: Better implementation for the SRV check. We don't need Index: gnupg/util/strgutil.c diff -u gnupg/util/strgutil.c:1.46 gnupg/util/strgutil.c:1.47 --- gnupg/util/strgutil.c:1.46 Mon Dec 20 09:55:03 2004 +++ gnupg/util/strgutil.c Thu Jan 6 12:51:49 2005 @@ -144,6 +144,8 @@ { log_info (_("error loading `%s': %s\n"), "iconv.dll", dlerror ()); + log_info(_("please see http://www.gnupg.org/download/iconv.html " + "for more information\n")); iconv_open = NULL; iconv = NULL; iconv_close = NULL; @@ -479,14 +481,19 @@ if (!newset) { #ifdef _WIN32 static char codepage[30]; + unsigned int cpno; /* We are a console program thus we need to use the - GetConsoleOutputCP fucntion and not the the GetACP which + GetConsoleOutputCP function and not the the GetACP which would give the codepage for a GUI program. Note this is not a bulletproof detection because GetConsoleCP might - retrun a different one for console input. Not sure how to - cope with that. */ - sprintf (codepage, "CP%u", (unsigned int)GetConsoleOutputCP ()); + return a different one for console input. Not sure how to + cope with that. If the console Code page is not known we + fall back to the system code page. */ + cpno = GetConsoleOutputCP (); + if (!cpno) + cpno = GetACP (); + sprintf (codepage, "CP%u", cpno ); /* If it is the Windows name for Latin-1 we use the standard name instead to avoid loading of iconv.dll. Unfortunately it is often CP850 and we don't have a custom translation @@ -498,9 +505,32 @@ #else #ifdef HAVE_LANGINFO_CODESET newset = nl_langinfo (CODESET); -#else - newset = "iso-8859-1"; -#endif +#else /* !HAVE_LANGINFO_CODESET */ + /* Try to get the used charset from environment variables. */ + static char codepage[30]; + const char *lc, *dot, *mod; + + strcpy (codepage, "iso-8859-1"); + lc = getenv ("LC_ALL"); + if (!lc || !*lc) { + lc = getenv ("LC_CTYPE"); + if (!lc || !*lc) + lc = getenv ("LANG"); + } + if (lc && *lc) { + dot = strchr (lc, '.'); + if (dot) { + mod = strchr (++dot, '@'); + if (!mod) + mod = dot + strlen (dot); + if (mod - dot < sizeof codepage && dot != mod) { + memcpy (codepage, dot, mod - dot); + codepage [mod - dot] = 0; + } + } + } + newset = codepage; +#endif /* !HAVE_LANGINFO_CODESET */ #endif } @@ -511,9 +541,18 @@ newset++; } + /* Note that we silently assume that plain ASCII is actually meant + as Latin-1. This makes sense because many Unix system don't + have their locale set up properly and thus would get annoying + error messages and we have to handle all the "bug" + reports. Latin-1 has always been the character set used for 8 + bit characters on Unix systems. */ if( !*newset || !ascii_strcasecmp (newset, "8859-1" ) - || !ascii_strcasecmp (newset, "8859-15" ) ) { + || !ascii_strcasecmp (newset, "646" ) + || !ascii_strcasecmp (newset, "ASCII" ) + || !ascii_strcasecmp (newset, "ANSI_X3.4-1968" ) + ) { active_charset_name = "iso-8859-1"; no_translation = 0; active_charset = NULL; From cvs at cvs.gnupg.org Thu Jan 6 17:17:13 2005 From: cvs at cvs.gnupg.org (cvs user dshaw) Date: Thu Jan 6 17:28:32 2005 Subject: gnupg/g10 (ChangeLog armor.c filter.h keyserver.c) Message-ID: Date: Thursday, January 6, 2005 @ 17:23:47 Author: dshaw Path: /cvs/gnupg/gnupg/g10 Modified: ChangeLog armor.c filter.h keyserver.c * filter.h, armor.c (armor_filter): Use the eol string from the armor filter context instead of hardcoding '\n' or '\r\n'. If no eol string is provided, default to '\n' or '\r\n' as appropriate. (is_armor_header): Trim tabs in armor header lines as well. * keyserver.c (keyserver_spawn): Use it here to force '\n' line endings since the keyserver output file gets a LF->CRLF expansion on win32. -------------+ ChangeLog | 11 +++++++++ armor.c | 67 +++++++++++++++++++++++++++++++++++----------------------- filter.h | 7 +++++- keyserver.c | 9 ++++++- 4 files changed, 66 insertions(+), 28 deletions(-) Index: gnupg/g10/ChangeLog diff -u gnupg/g10/ChangeLog:1.677 gnupg/g10/ChangeLog:1.678 --- gnupg/g10/ChangeLog:1.677 Thu Jan 6 05:44:38 2005 +++ gnupg/g10/ChangeLog Thu Jan 6 17:23:47 2005 @@ -1,3 +1,14 @@ +2005-01-06 David Shaw + + * filter.h, armor.c (armor_filter): Use the eol string from the + armor filter context instead of hardcoding '\n' or '\r\n'. If no + eol string is provided, default to '\n' or '\r\n' as appropriate. + (is_armor_header): Trim tabs in armor header lines as well. + + * keyserver.c (keyserver_spawn): Use it here to force '\n' line + endings since the keyserver output file gets a LF->CRLF expansion + on win32. + 2005-01-05 David Shaw * g10.c (main): Typo. Index: gnupg/g10/armor.c diff -u gnupg/g10/armor.c:1.78 gnupg/g10/armor.c:1.79 --- gnupg/g10/armor.c:1.78 Thu Jan 6 05:44:38 2005 +++ gnupg/g10/armor.c Thu Jan 6 17:23:47 2005 @@ -1,6 +1,6 @@ /* armor.c - Armor flter - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, - * 2004 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, + * 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -38,12 +38,6 @@ #include "status.h" #include "i18n.h" -#ifdef HAVE_DOSISH_SYSTEM -#define LF "\r\n" -#else -#define LF "\n" -#endif - #define MAX_LINELEN 20000 #define CRCINIT 0xB704CE @@ -119,7 +113,6 @@ }; - static void initialize(void) { @@ -306,7 +299,7 @@ p++; } else - while(*p==' ' || *p=='\r' || *p=='\n') + while(*p==' ' || *p=='\r' || *p=='\n' || *p=='\t') p++; if( *p ) @@ -984,10 +977,14 @@ log_bug("afx->what=%d", afx->what); iobuf_writestr(a, "-----"); iobuf_writestr(a, head_strings[afx->what] ); - iobuf_writestr(a, "-----" LF ); + iobuf_writestr(a, "-----" ); + iobuf_writestr(a,afx->eol); if( !opt.no_version ) + { iobuf_writestr(a, "Version: GnuPG v" VERSION " (" - PRINTABLE_OS_NAME ")" LF ); + PRINTABLE_OS_NAME ")" ); + iobuf_writestr(a,afx->eol); + } /* write the comment strings */ for(s=comment->d;comment;comment=comment->next,s=comment->d) @@ -1004,7 +1001,8 @@ else iobuf_put(a, *s ); } - iobuf_writestr(a, LF ); + + iobuf_writestr(a,afx->eol); } if ( afx->hdrlines ) { @@ -1016,7 +1014,8 @@ iobuf_put(a, *s ); } } - iobuf_writestr(a, LF ); + + iobuf_writestr(a,afx->eol); afx->status++; afx->idx = 0; afx->idx2 = 0; @@ -1045,10 +1044,11 @@ iobuf_put(a, c); c = bintoasc[radbuf[2]&077]; iobuf_put(a, c); - if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */ - iobuf_writestr(a, LF ); + if( ++idx2 >= (64/4) ) + { /* pgp doesn't like 72 here */ + iobuf_writestr(a,afx->eol); idx2=0; - } + } } } for(i=0; i < idx; i++ ) @@ -1057,10 +1057,23 @@ afx->idx2 = idx2; afx->crc = crc; } - else if( control == IOBUFCTRL_INIT ) { + else if( control == IOBUFCTRL_INIT ) + { if( !is_initialized ) - initialize(); - } + initialize(); + + /* Figure out what we're using for line endings if the caller + didn't specify. */ + if(afx->eol[0]==0) + { +#ifdef HAVE_DOSISH_SYSTEM + afx->eol[0]='\r'; + afx->eol[1]='\n'; +#else + afx->eol[0]='\n'; +#endif + } + } else if( control == IOBUFCTRL_CANCEL ) { afx->cancel = 1; } @@ -1089,14 +1102,15 @@ iobuf_put(a, c); iobuf_put(a, '='); } - if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */ - iobuf_writestr(a, LF ); + if( ++idx2 >= (64/4) ) + { /* pgp doesn't like 72 here */ + iobuf_writestr(a,afx->eol); idx2=0; - } + } } /* may need a linefeed */ if( idx2 ) - iobuf_writestr(a, LF ); + iobuf_writestr(a,afx->eol); /* write the CRC */ iobuf_put(a, '='); radbuf[0] = crc >>16; @@ -1110,13 +1124,14 @@ iobuf_put(a, c); c = bintoasc[radbuf[2]&077]; iobuf_put(a, c); - iobuf_writestr(a, LF ); + iobuf_writestr(a,afx->eol); /* and the the trailer */ if( afx->what >= DIM(tail_strings) ) log_bug("afx->what=%d", afx->what); iobuf_writestr(a, "-----"); iobuf_writestr(a, tail_strings[afx->what] ); - iobuf_writestr(a, "-----" LF ); + iobuf_writestr(a, "-----" ); + iobuf_writestr(a,afx->eol); } else if( !afx->any_data && !afx->inp_bypass ) { log_error(_("no valid OpenPGP data found.\n")); Index: gnupg/g10/filter.h diff -u gnupg/g10/filter.h:1.46 gnupg/g10/filter.h:1.47 --- gnupg/g10/filter.h:1.46 Fri Oct 31 06:39:01 2003 +++ gnupg/g10/filter.h Thu Jan 6 17:23:47 2005 @@ -1,5 +1,6 @@ /* filter.h - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2003, + * 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -48,6 +49,10 @@ int truncated; /* number of truncated lines */ int qp_detected; int pgp2mode; + byte eol[3]; /* The end of line characters as a + zero-terminated string. Defaults + (eol[0]=='\0') to whatever the local + platform uses. */ byte *buffer; /* malloced buffer */ unsigned buffer_size; /* and size of this buffer */ Index: gnupg/g10/keyserver.c diff -u gnupg/g10/keyserver.c:1.76 gnupg/g10/keyserver.c:1.77 --- gnupg/g10/keyserver.c:1.76 Fri Dec 24 20:51:02 2004 +++ gnupg/g10/keyserver.c Thu Jan 6 17:23:47 2005 @@ -1,5 +1,5 @@ /* keyserver.c - generic keyserver code - * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -966,6 +966,13 @@ memset(&afx,0,sizeof(afx)); afx.what=1; + /* Tell the armor filter to use Unix-style \n line + endings, since we're going to fprintf this to a file + that (on Win32) is open in text mode. The win32 stdio + will transform the \n to \r\n and we'll end up with the + proper line endings on win32. This is a no-op on + Unix. */ + afx.eol[0]='\n'; iobuf_push_filter(buffer,armor_filter,&afx); /* TODO: Remove Comment: lines from keys exported this From cvs at cvs.gnupg.org Mon Jan 10 04:39:20 2005 From: cvs at cvs.gnupg.org (cvs user dshaw) Date: Mon Jan 10 04:39:27 2005 Subject: gnupg/keyserver (ChangeLog gpgkeys_curl.c) Message-ID: Date: Monday, January 10, 2005 @ 04:46:12 Author: dshaw Path: /cvs/gnupg/gnupg/keyserver Modified: ChangeLog gpgkeys_curl.c * gpgkeys_curl.c (get_key): Newer versions of libcurl don't define TRUE. ----------------+ ChangeLog | 5 +++++ gpgkeys_curl.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) Index: gnupg/keyserver/ChangeLog diff -u gnupg/keyserver/ChangeLog:1.99 gnupg/keyserver/ChangeLog:1.100 --- gnupg/keyserver/ChangeLog:1.99 Fri Dec 24 20:48:36 2004 +++ gnupg/keyserver/ChangeLog Mon Jan 10 04:46:12 2005 @@ -1,3 +1,8 @@ +2005-01-09 David Shaw + + * gpgkeys_curl.c (get_key): Newer versions of libcurl don't define + TRUE. + 2004-12-24 David Shaw * gpgkeys_curl.c (main): Use new defines for opting out of certain Index: gnupg/keyserver/gpgkeys_curl.c diff -u gnupg/keyserver/gpgkeys_curl.c:1.4 gnupg/keyserver/gpgkeys_curl.c:1.5 --- gnupg/keyserver/gpgkeys_curl.c:1.4 Fri Dec 24 20:48:36 2004 +++ gnupg/keyserver/gpgkeys_curl.c Mon Jan 10 04:46:12 2005 @@ -94,7 +94,7 @@ if(verbose>1) { curl_easy_setopt(curl,CURLOPT_STDERR,console); - curl_easy_setopt(curl,CURLOPT_VERBOSE,TRUE); + curl_easy_setopt(curl,CURLOPT_VERBOSE,1); } res=curl_easy_perform(curl); From cvs at cvs.gnupg.org Mon Jan 10 23:49:50 2005 From: cvs at cvs.gnupg.org (cvs user dshaw) Date: Tue Jan 11 05:05:36 2005 Subject: gnupg/g10 (ChangeLog passphrase.c) Message-ID: Date: Monday, January 10, 2005 @ 23:56:47 Author: dshaw Path: /cvs/gnupg/gnupg/g10 Modified: ChangeLog passphrase.c * passphrase.c (readline, agent_send_option, agent_open, agent_get_passphrase, passphrase_clear_cache): Rename readline() to readaline() to keep readline library namespace clear. --------------+ ChangeLog | 6 ++++++ passphrase.c | 12 +++++------- 2 files changed, 11 insertions(+), 7 deletions(-) Index: gnupg/g10/ChangeLog diff -u gnupg/g10/ChangeLog:1.678 gnupg/g10/ChangeLog:1.679 --- gnupg/g10/ChangeLog:1.678 Thu Jan 6 17:23:47 2005 +++ gnupg/g10/ChangeLog Mon Jan 10 23:56:46 2005 @@ -1,3 +1,9 @@ +2005-01-10 David Shaw + + * passphrase.c (readline, agent_send_option, agent_open, + agent_get_passphrase, passphrase_clear_cache): Rename readline() + to readaline() to keep readline library namespace clear. + 2005-01-06 David Shaw * filter.h, armor.c (armor_filter): Use the eol string from the Index: gnupg/g10/passphrase.c diff -u gnupg/g10/passphrase.c:1.74 gnupg/g10/passphrase.c:1.75 --- gnupg/g10/passphrase.c:1.74 Mon Dec 20 06:19:09 2004 +++ gnupg/g10/passphrase.c Mon Jan 10 23:56:46 2005 @@ -299,7 +299,7 @@ /* read an entire line */ static int -readline (int fd, char *buf, size_t buflen) +readaline (int fd, char *buf, size_t buflen) { size_t nleft = buflen; char *p; @@ -360,7 +360,7 @@ return -1; /* get response */ - nread = readline (fd, buf, DIM(buf)-1); + nread = readaline (fd, buf, DIM(buf)-1); if (nread < 3) return -1; @@ -584,7 +584,7 @@ char line[200]; int nread; - nread = readline (fd, line, DIM(line)); + nread = readaline (fd, line, DIM(line)); if (nread < 3 || !(line[0] == 'O' && line[1] == 'K' && (line[2] == '\n' || line[2] == ' ')) ) { log_error ( _("communication problem with gpg-agent\n")); @@ -900,7 +900,7 @@ /* get response */ pw = m_alloc_secure (500); - nread = readline (fd, pw, 499); + nread = readaline (fd, pw, 499); if (nread < 3) goto failure; @@ -1035,7 +1035,7 @@ goto failure; /* get response */ - nread = readline (fd, buf, DIM(buf)-1); + nread = readaline (fd, buf, DIM(buf)-1); if (nread < 3) goto failure; @@ -1056,8 +1056,6 @@ } - - /**************** * Ask for a passphrase and return that string. */ From cvs at cvs.gnupg.org Tue Jan 11 05:08:54 2005 From: cvs at cvs.gnupg.org (cvs user dshaw) Date: Tue Jan 11 07:02:26 2005 Subject: gnupg/g10 (ChangeLog keyedit.c) Message-ID: Date: Tuesday, January 11, 2005 @ 05:15:55 Author: dshaw Path: /cvs/gnupg/gnupg/g10 Modified: ChangeLog keyedit.c * keyedit.c (keyedit_menu): Move command strings outside the function to get ready for the readline completion code. -----------+ ChangeLog | 3 + keyedit.c | 166 +++++++++++++++++++++++++++++++----------------------------- 2 files changed, 89 insertions(+), 80 deletions(-) Index: gnupg/g10/ChangeLog diff -u gnupg/g10/ChangeLog:1.679 gnupg/g10/ChangeLog:1.680 --- gnupg/g10/ChangeLog:1.679 Mon Jan 10 23:56:46 2005 +++ gnupg/g10/ChangeLog Tue Jan 11 05:15:55 2005 @@ -1,5 +1,8 @@ 2005-01-10 David Shaw + * keyedit.c (keyedit_menu): Move command strings outside the + function to get ready for the readline completion code. + * passphrase.c (readline, agent_send_option, agent_open, agent_get_passphrase, passphrase_clear_cache): Rename readline() to readaline() to keep readline library namespace clear. Index: gnupg/g10/keyedit.c diff -u gnupg/g10/keyedit.c:1.167 gnupg/g10/keyedit.c:1.168 --- gnupg/g10/keyedit.c:1.167 Thu Dec 30 04:26:57 2004 +++ gnupg/g10/keyedit.c Tue Jan 11 05:15:55 2005 @@ -1,6 +1,6 @@ /* keyedit.c - keyedit stuff - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, - * 2004 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, + * 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -1261,84 +1261,89 @@ /* Match the tail of the string */ #define KEYEDIT_TAIL_MATCH 8 +enum cmdids + { + cmdNONE = 0, + cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN, + cmdREVSIG, cmdREVKEY, cmdREVUID, cmdDELSIG, cmdPRIMARY, cmdDEBUG, + cmdSAVE, cmdADDUID, cmdADDPHOTO, cmdDELUID, cmdADDKEY, cmdDELKEY, + cmdADDREVOKER, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF, + cmdEXPIRE, cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF, cmdSETPREF, + cmdPREFKS, cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST, cmdCHKTRUST, + cmdADDCARDKEY, cmdKEYTOCARD, cmdNOP + }; + +static struct +{ + const char *name; + enum cmdids id; + int flags; + const char *desc; +} cmds[] = + { + { "quit" , cmdQUIT , 0, N_("quit this menu") }, + { "q" , cmdQUIT , 0, NULL }, + { "save" , cmdSAVE , 0, N_("save and quit") }, + { "help" , cmdHELP , 0, N_("show this help") }, + { "?" , cmdHELP , 0, NULL }, + { "fpr" , cmdFPR , 0, N_("show key fingerprint") }, + { "list" , cmdLIST , 0, N_("list key and user IDs") }, + { "l" , cmdLIST , 0, NULL }, + { "uid" , cmdSELUID , 0, N_("select user ID N") }, + { "key" , cmdSELKEY , 0, N_("select subkey N") }, + { "check" , cmdCHECK , 0, N_("check signatures") }, + { "c" , cmdCHECK , 0, NULL }, + { "sign" , cmdSIGN , KEYEDIT_NOT_SK|KEYEDIT_TAIL_MATCH, N_("sign selected user IDs [* see below for related commands]") }, + { "s" , cmdSIGN , KEYEDIT_NOT_SK, NULL }, + /* "lsign" and friends will never match since "sign" comes first + and it is a tail match. They are just here so they show up in + the help menu. */ + { "lsign" , cmdNOP , 0, N_("sign selected user IDs locally") }, + { "tsign" , cmdNOP , 0, N_("sign selected user IDs with a trust signature") }, + { "nrsign" , cmdNOP , 0, N_("sign selected user IDs with a non-revocable signature") }, + { "debug" , cmdDEBUG , 0, NULL }, + { "adduid" , cmdADDUID , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("add a user ID") }, + { "addphoto", cmdADDPHOTO , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("add a photo ID") }, + { "deluid" , cmdDELUID , KEYEDIT_NOT_SK, N_("delete selected user IDs") }, + /* delphoto is really deluid in disguise */ + { "delphoto", cmdDELUID , KEYEDIT_NOT_SK, NULL }, + { "addkey" , cmdADDKEY , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("add a subkey") }, +#ifdef ENABLE_CARD_SUPPORT + { "addcardkey", cmdADDCARDKEY , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("add a key to a smartcard") }, + { "keytocard", cmdKEYTOCARD , KEYEDIT_NEED_SK|KEYEDIT_ONLY_SK, N_("move a key to a smartcard")}, +#endif /*ENABLE_CARD_SUPPORT*/ + { "delkey" , cmdDELKEY , KEYEDIT_NOT_SK, N_("delete selected subkeys") }, + { "addrevoker",cmdADDREVOKER,KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("add a revocation key") }, + { "delsig" , cmdDELSIG , KEYEDIT_NOT_SK, N_("delete signatures from the selected user IDs") }, + { "expire" , cmdEXPIRE , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("change the expiration date for the key or selected subkeys") }, + { "primary" , cmdPRIMARY , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("flag the selected user ID as primary")}, + { "toggle" , cmdTOGGLE , KEYEDIT_NEED_SK, N_("toggle between the secret and public key listings") }, + { "t" , cmdTOGGLE , KEYEDIT_NEED_SK, NULL }, + { "pref" , cmdPREF , KEYEDIT_NOT_SK, N_("list preferences (expert)")}, + { "showpref", cmdSHOWPREF , KEYEDIT_NOT_SK, N_("list preferences (verbose)") }, + { "setpref" , cmdSETPREF , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("set preference list for the selected user IDs") }, + /* Alias */ + { "updpref" , cmdSETPREF , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, NULL }, + { "keyserver",cmdPREFKS , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("set preferred keyserver URL for the selected user IDs")}, + { "passwd" , cmdPASSWD , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("change the passphrase") }, + /* Alias */ + { "password", cmdPASSWD , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, NULL }, + { "trust" , cmdTRUST , KEYEDIT_NOT_SK, N_("change the ownertrust") }, + { "revsig" , cmdREVSIG , KEYEDIT_NOT_SK, N_("revoke signatures on the selected user IDs") }, + { "revuid" , cmdREVUID , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("revoke selected user IDs") }, + /* Alias */ + { "revphoto", cmdREVUID , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, NULL }, + { "revkey" , cmdREVKEY , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("revoke key or selected subkeys") }, + { "enable" , cmdENABLEKEY , KEYEDIT_NOT_SK, N_("enable key") }, + { "disable" , cmdDISABLEKEY, KEYEDIT_NOT_SK, N_("disable key") }, + { "showphoto",cmdSHOWPHOTO , 0, N_("show selected photo IDs") }, + { NULL, cmdNONE, 0, NULL } + }; + void keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, int quiet, int seckey_check ) { - enum cmdids - { cmdNONE = 0, - cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN, - cmdREVSIG, cmdREVKEY, cmdREVUID, cmdDELSIG, cmdPRIMARY, cmdDEBUG, - cmdSAVE, cmdADDUID, cmdADDPHOTO, cmdDELUID, cmdADDKEY, cmdDELKEY, - cmdADDREVOKER, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF, - cmdEXPIRE, cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF, cmdSETPREF, - cmdPREFKS, cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST, cmdCHKTRUST, - cmdADDCARDKEY, cmdKEYTOCARD, - cmdNOP }; - static struct - { - const char *name; - enum cmdids id; - int flags; - const char *desc; - } cmds[] = - { - { "quit" , cmdQUIT , 0, N_("quit this menu") }, - { "q" , cmdQUIT , 0, NULL }, - { "save" , cmdSAVE , 0, N_("save and quit") }, - { "help" , cmdHELP , 0, N_("show this help") }, - { "?" , cmdHELP , 0, NULL }, - { "fpr" , cmdFPR , 0, N_("show key fingerprint") }, - { "list" , cmdLIST , 0, N_("list key and user IDs") }, - { "l" , cmdLIST , 0, NULL }, - { "uid" , cmdSELUID , 0, N_("select user ID N") }, - { "key" , cmdSELKEY , 0, N_("select subkey N") }, - { "check" , cmdCHECK , 0, N_("check signatures") }, - { "c" , cmdCHECK , 0, NULL }, - { "sign" , cmdSIGN , KEYEDIT_NOT_SK|KEYEDIT_TAIL_MATCH, N_("sign selected user IDs [* see below for related commands]") }, - { "s" , cmdSIGN , KEYEDIT_NOT_SK, NULL }, - /* "lsign" will never match since "sign" comes first and it is a - tail match. It is just here so it shows up in the help - menu. */ - { "lsign" , cmdNOP , 0, N_("sign selected user IDs locally") }, - { "debug" , cmdDEBUG , 0, NULL }, - { "adduid" , cmdADDUID , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("add a user ID") }, - { "addphoto", cmdADDPHOTO , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("add a photo ID") }, - { "deluid" , cmdDELUID , KEYEDIT_NOT_SK, N_("delete selected user IDs") }, - /* delphoto is really deluid in disguise */ - { "delphoto", cmdDELUID , KEYEDIT_NOT_SK, NULL }, - { "addkey" , cmdADDKEY , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("add a subkey") }, -#ifdef ENABLE_CARD_SUPPORT - { "addcardkey", cmdADDCARDKEY , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("add a key to a smartcard") }, - { "keytocard", cmdKEYTOCARD , KEYEDIT_NEED_SK|KEYEDIT_ONLY_SK, N_("move a key to a smartcard")}, -#endif /*ENABLE_CARD_SUPPORT*/ - { "delkey" , cmdDELKEY , KEYEDIT_NOT_SK, N_("delete selected subkeys") }, - { "addrevoker",cmdADDREVOKER,KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("add a revocation key") }, - { "delsig" , cmdDELSIG , KEYEDIT_NOT_SK, N_("delete signatures from the selected user IDs") }, - { "expire" , cmdEXPIRE , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("change the expiration date for the key or selected subkeys") }, - { "primary" , cmdPRIMARY , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("flag the selected user ID as primary")}, - { "toggle" , cmdTOGGLE , KEYEDIT_NEED_SK, N_("toggle between the secret and public key listings") }, - { "t" , cmdTOGGLE , KEYEDIT_NEED_SK, NULL }, - { "pref" , cmdPREF , KEYEDIT_NOT_SK, N_("list preferences (expert)")}, - { "showpref", cmdSHOWPREF , KEYEDIT_NOT_SK, N_("list preferences (verbose)") }, - { "setpref" , cmdSETPREF , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("set preference list for the selected user IDs") }, - /* Alias */ - { "updpref" , cmdSETPREF , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, NULL }, - { "keyserver",cmdPREFKS , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("set preferred keyserver URL for the selected user IDs")}, - { "passwd" , cmdPASSWD , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("change the passphrase") }, - /* Alias */ - { "password", cmdPASSWD , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, NULL }, - { "trust" , cmdTRUST , KEYEDIT_NOT_SK, N_("change the ownertrust") }, - { "revsig" , cmdREVSIG , KEYEDIT_NOT_SK, N_("revoke signatures on the selected user IDs") }, - { "revuid" , cmdREVUID , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("revoke selected user IDs") }, - /* Alias */ - { "revphoto", cmdREVUID , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, NULL }, - { "revkey" , cmdREVKEY , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("revoke key or selected subkeys") }, - { "enable" , cmdENABLEKEY , KEYEDIT_NOT_SK, N_("enable key") }, - { "disable" , cmdDISABLEKEY, KEYEDIT_NOT_SK, N_("disable key") }, - { "showphoto",cmdSHOWPHOTO , 0, N_("show selected photo IDs") }, - { NULL, cmdNONE, 0, NULL } - }; enum cmdids cmd = 0; int rc = 0; KBNODE keyblock = NULL; @@ -1499,7 +1504,8 @@ else cmd = cmds[i].id; } - switch( cmd ) { + switch( cmd ) + { case cmdHELP: for(i=0; cmds[i].name; i++ ) { @@ -1511,9 +1517,9 @@ tty_printf("\n"); tty_printf(_( -"* The `sign' command may be prefixed with `l' for local signatures (lsign),\n" -" a `t' for trust signatures (tsign), a `nr' for non-revocable signatures\n" -" (nrsign), or any combination thereof (ltsign, tnrsign, etc).\n")); +"* The `sign' command may be prefixed with an `l' for local signatures (lsign),\n" +" a `t' for trust signatures (tsign), an `nr' for non-revocable signatures\n" +" (nrsign), or any combination thereof (ltsign, tnrsign, etc.).\n")); break; From cvs at cvs.gnupg.org Tue Jan 11 12:56:19 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Tue Jan 11 18:01:18 2005 Subject: gnupg/scripts (ChangeLog mk-w32-dist w32installer.nsi) Message-ID: Date: Tuesday, January 11, 2005 @ 13:03:22 Author: wk Path: /cvs/gnupg/gnupg/scripts Added: w32installer.nsi Modified: ChangeLog mk-w32-dist * w32installer.nsi: New. * mk-w32-dist: Append ".txt" to some files. Call makensis if available. ------------------+ ChangeLog | 6 + mk-w32-dist | 17 ++- w32installer.nsi | 253 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 269 insertions(+), 7 deletions(-) Index: gnupg/scripts/ChangeLog diff -u gnupg/scripts/ChangeLog:1.59 gnupg/scripts/ChangeLog:1.60 --- gnupg/scripts/ChangeLog:1.59 Wed Dec 22 00:44:06 2004 +++ gnupg/scripts/ChangeLog Tue Jan 11 13:03:22 2005 @@ -1,3 +1,9 @@ +2005-01-11 Werner Koch + + * w32installer.nsi: New. + * mk-w32-dist: Append ".txt" to some files. Call makensis if + available. + 2004-12-21 David Shaw * autogen.sh: automake needs --add-missing for conditional Index: gnupg/scripts/mk-w32-dist diff -u gnupg/scripts/mk-w32-dist:1.12 gnupg/scripts/mk-w32-dist:1.13 --- gnupg/scripts/mk-w32-dist:1.12 Thu Oct 28 11:06:49 2004 +++ gnupg/scripts/mk-w32-dist Tue Jan 11 13:03:22 2005 @@ -41,7 +41,7 @@ version=$(sed -n 's/^#[ ]*define[ ][ ]*VERSION[ ][ ]*\"\([0-9.a-z-]*\)\"/\1/p' $bindir/config.h) echo "building version $version" -rm * 2>/dev/null || true +rm * >/dev/null 2>/dev/null || true cp ${bindir}/g10/gpg.exe gpg.exe $STRIP gpg.exe @@ -55,8 +55,8 @@ $STRIP gpgsplit.exe for i in FAQ; do - cp ${bindir}/doc/$i . - todos $i + cp ${bindir}/doc/$i $i.txt + todos $i.txt done man -Tlatin1 -l ${srcdir}/doc/gpg.1 | sed `printf "s/\b.//g"` >gpg.man todos gpg.man @@ -64,16 +64,16 @@ todos gpgv.man man -Tlatin1 -l ${srcdir}/doc/gnupg.7 | sed `printf "s/\b.//g"` >gnupg.man todos gnupg.man -for i in README COPYING; do - cp ${srcdir}/$i . - todos $i +for i in README COPYING NEWS; do + cp ${srcdir}/$i $i.txt + todos $i.txt done for i in README.W32 gnupg-w32.reg; do cp ${srcdir}/doc/$i . todos $i done -# We must distribute the MO files in UTF-8, the conmversion is done by +# We must distribute the MO files in UTF-8, the conversion is done by # gpg at runtime. for i in ${srcdir}/po/*.po; do lang=$(basename $i .po) @@ -94,3 +94,6 @@ esac done zip -9 "gnupg-w32cli-${version}.zip" * +if makensis -version >/dev/null 2>&1 ; then + makensis -v2 -nocd -DVERSION="${version}" ${srcdir}/scripts/w32installer.nsi +fi Index: gnupg/scripts/w32installer.nsi diff -u /dev/null gnupg/scripts/w32installer.nsi:1.1 --- /dev/null Tue Jan 11 13:03:22 2005 +++ gnupg/scripts/w32installer.nsi Tue Jan 11 13:03:22 2005 @@ -0,0 +1,253 @@ +; w32installer.nsi - W32 Installer definition -*- lisp -*- +; Copyright (C) 2005 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 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 is an installer script used to create a W32 installer "exe" file +; using NSIS. It is usually used by the mk-w32-dist script. +;---------------------------------------------------------------------- + +; TODO: +; - Display credit for the installer +; - Provide the location of the corresponding source +; - Check for iconv.dll and optionalkly install or download it. +; - Allow inclusion of the source into the installer. +; - Translate all strings +; - Setup the home directory and check for old (c:/gnupg located) +; versions of the program + +; We use the modern UI. +!include "MUI.nsh" + +; ------------- +; General stuff +; ------------- +Name "GNU Privacy Guard" + +OutFile "gnupg-w32cli-${VERSION}.exe" + +InstallDir "$PROGRAMFILES\GNU\GnuPG" + +InstallDirRegKey HKCU "Software\GNU\GnuPG" "" + +SetCompressor lzma + +ReserveFile "COPYING.txt" + +; ------------------ +; Interface Settings +; ------------------ + +!define MUI_ABORTWARNING +!define MUI_FINISHPAGE_NOAUTOCLOSE +!define MUI_UNFINISHPAGE_NOAUTOCLOSE + +; Remember the installer language +!define MUI_LANGDLL_REGISTRY_ROOT "HKCU" +!define MUI_LANGDLL_REGISTRY_KEY "Software\GNU\GnuPG" +!define MUI_LANGDLL_REGISTRY_VALUENAME "Installer Language" + + +; ----- +; Pages +; ----- + +!define MUI_WELCOMEPAGE_TEXT "$(T_About)" + +!insertmacro MUI_PAGE_WELCOME + + +!define MUI_PAGE_HEADER_SUBTEXT \ + "This software is licensed under the terms of the GNU General Public \ + License (GPL) which guarantees your freedom to share and change Free \ + Software." + +!define MUI_LICENSEPAGE_TEXT_BOTTOM \ + "In short: You are allowed to run this software for any purpose. \ + You may distribute it as long as you give the recipients the same \ + rights you have received." + +!define MUI_LICENSEPAGE_BUTTON "$(^NextBtn)" + +!insertmacro MUI_PAGE_LICENSE "COPYING.txt" + + +!insertmacro MUI_PAGE_COMPONENTS +!insertmacro MUI_PAGE_DIRECTORY +!insertmacro MUI_PAGE_INSTFILES + +!define MUI_FINISHPAGE_SHOWREADME "README.txt" +!define MUI_FINISHPAGE_SHOWREADME_TEXT "$(T_ShowReadme)" +!define MUI_FINISHPAGE_LINK "Goto the GnuPG website" +!define MUI_FINISHPAGE_LINK_LOCATION "http://www.gnupg.org" +!insertmacro MUI_PAGE_FINISH + + +!insertmacro MUI_UNPAGE_CONFIRM +!insertmacro MUI_UNPAGE_INSTFILES + + +; ----------------- +; i18n Declarations +; ----------------- + +!insertmacro MUI_LANGUAGE "English" +!insertmacro MUI_LANGUAGE "German" + +; ------------------ +; Installer Sections +; ------------------ + +;InstType "full" +;InstType "minimal" + +;---------------------- +Section "Base" SecBase +; SectionIn 1 2 RO + SectionIn RO + + SetOutPath "$INSTDIR" + + File "README.txt" + File "README.W32" + File "COPYING.txt" + File "gpg.exe" + File "gpgkeys_finger.exe" + File "gpgkeys_hkp.exe" + File "gpgkeys_http.exe" + File "gpgkeys_ldap.exe" + File "*.mo" + + WriteRegStr HKCU "Software\GNU\GnuPG" "" $INSTDIR + + WriteUninstaller "$INSTDIR\Uninstall.exe" + +SectionEnd ; Section Base + +;------------------------ +Section "Tools" SecTools +; SectionIn 1 + + File "gpgsplit.exe" + File "gpgv.exe" + +SectionEnd ; Section Tools + +;---------------------- +Section "Documentation" SecDoc +; SectionIn 1 + + File "gnupg.man" + File "gpg.man" + File "gpgv.man" + File "NEWS.txt" + File "FAQ.txt" + +SectionEnd ; Section Documentation + + +;------------------ +!ifdef WITH_SOURCE +Section "Source" SecSource + + ; Note that we include the uncompressed tarball because this allows + ; far better compression results for the distribution. We might + ; want to compress it again after installation. + File "gnupg-1.4.0.tar" + +SectionEnd ; Section Source +!endif + + +;------------------ +Section "Uninstall" + + Delete "$INSTDIR\README.txt" + Delete "$INSTDIR\README.W32" + Delete "$INSTDIR\COPYING.txt" + Delete "$INSTDIR\gpg.exe" + Delete "$INSTDIR\gpgkeys_finger.exe" + Delete "$INSTDIR\gpgkeys_hkp.exe" + Delete "$INSTDIR\gpgkeys_http.exe" + Delete "$INSTDIR\gpgkeys_ldap.exe" + Delete "$INSTDIR\*.mo" + Delete "$INSTDIR\gpgsplit.exe" + Delete "$INSTDIR\gpgv.exe" + Delete "$INSTDIR\gnupg.man" + Delete "$INSTDIR\gpg.man" + Delete "$INSTDIR\gpgv.man" + Delete "$INSTDIR\NEWS.txt" + Delete "$INSTDIR\FAQ.txt" + + Delete "$INSTDIR\Uninstall.exe" + + RMDir "$INSTDIR" + + DeleteRegKey /ifempty HKCU "Software\GNU\GnuPG" + +SectionEnd ; Uninstall + + +; --------- +; Functions +; --------- + +Function .onInit + + !insertmacro MUI_LANGDLL_DISPLAY + +FunctionEnd + + +Function un.onInit + + !insertmacro MUI_UNGETLANGUAGE + +FunctionEnd + + +; ------------ +; Descriptions +; ------------ + + +LangString T_About ${LANG_ENGLISH} \ + "GnuPG is GNU's tool for secure communication and data storage. \ + It can be used to encrypt data and to create digital signatures. \ + It includes an advanced key management facility and is compliant \ + with the proposed OpenPGP Internet standard as described in RFC2440." +LangString T_About ${LANG_GERMAN} \ + "GnuPG is das Werzeug aus dem GNU Projekt zur sicheren Kommunikation \ + sowie zum sicheren Speichern von Daten." +LangString T_ShowReadme ${LANG_ENGLISH} "Show the README file" +LangString T_ShowReadme ${LANG_GERMAN} "Die README Datei anzeigen" + + +LangString DESC_SecBase ${LANG_ENGLISH} \ + "The basic files used for the standard OpenPGP protocol" +LangString DESC_SecBase ${LANG_GERMAN} \ + "Die Basis Dateien zur Benutzung des OpenPGP Protokolls" + +LangString DESC_SecTools ${LANG_ENGLISH} \ + "Extra tools like gpgv and gpgsplit" +LangString DESC_SecTools ${LANG_GERMAN} \ + "Weitere Tools wie gpgv und gpgsplit" + +LangString DESC_SecDoc ${LANG_ENGLISH} \ + "Manual pages and a FAQ" +LangString DESC_SecDoc ${LANG_GERMAN} \ + "Handbuchseiten und eine FAQ" + +!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN + !insertmacro MUI_DESCRIPTION_TEXT ${SecBase} $(DESC_SecBase) + !insertmacro MUI_DESCRIPTION_TEXT ${SecTools} $(DESC_SecTools) + !insertmacro MUI_DESCRIPTION_TEXT ${SecDoc} $(DESC_SecDoc) +!insertmacro MUI_FUNCTION_DESCRIPTION_END + From cvs at cvs.gnupg.org Wed Jan 12 12:06:07 2005 From: cvs at cvs.gnupg.org (cvs user marcus) Date: Wed Jan 12 15:15:13 2005 Subject: gpgme/doc (ChangeLog gpgme.texi) Message-ID: Date: Wednesday, January 12, 2005 @ 12:13:17 Author: marcus Path: /cvs/gpgme/gpgme/doc Modified: ChangeLog gpgme.texi 2005-01-12 Marcus Brinkmann * gpgme.texi (Engine Configuration): New section. (Crypto Engine): New subsection. ------------+ ChangeLog | 5 +++ gpgme.texi | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 91 insertions(+), 2 deletions(-) Index: gpgme/doc/ChangeLog diff -u gpgme/doc/ChangeLog:1.134 gpgme/doc/ChangeLog:1.135 --- gpgme/doc/ChangeLog:1.134 Tue Dec 7 22:21:41 2004 +++ gpgme/doc/ChangeLog Wed Jan 12 12:13:17 2005 @@ -1,3 +1,8 @@ +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 Index: gpgme/doc/gpgme.texi diff -u gpgme/doc/gpgme.texi:1.136 gpgme/doc/gpgme.texi:1.137 --- gpgme/doc/gpgme.texi:1.136 Tue Dec 7 22:21:41 2004 +++ gpgme/doc/gpgme.texi Wed Jan 12 12:13:17 2005 @@ -125,6 +125,7 @@ * 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. @@ -165,6 +166,7 @@ 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. @@ -745,6 +747,7 @@ @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 @@ -789,6 +792,11 @@ 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, @@ -803,10 +811,10 @@ @end table @end deftp -@deftypefun gpgme_error_t gpgme_get_engine_info (gpgme_engine_info_t *info) +@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 -one configured backend. +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. @@ -850,6 +858,37 @@ @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 @@ -1847,6 +1886,7 @@ @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. @@ -1882,6 +1922,50 @@ 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 From cvs at cvs.gnupg.org Wed Jan 12 11:21:33 2005 From: cvs at cvs.gnupg.org (cvs user marcus) Date: Thu Jan 13 02:00:34 2005 Subject: gpgme (ChangeLog Makefile.am NEWS README acinclude.m4 configure.ac) Message-ID: Date: Wednesday, January 12, 2005 @ 11:28:42 Author: marcus Path: /cvs/gpgme/gpgme Modified: ChangeLog Makefile.am NEWS README acinclude.m4 configure.ac 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. --------------+ ChangeLog | 10 ++++++++++ Makefile.am | 5 ++++- NEWS | 7 +++++++ README | 10 +++++----- acinclude.m4 | 4 ++-- configure.ac | 10 +++++----- 6 files changed, 33 insertions(+), 13 deletions(-) Index: gpgme/ChangeLog diff -u gpgme/ChangeLog:1.110 gpgme/ChangeLog:1.111 --- gpgme/ChangeLog:1.110 Sat Dec 11 16:48:00 2004 +++ gpgme/ChangeLog Wed Jan 12 11:28:42 2005 @@ -1,3 +1,13 @@ +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 Index: gpgme/Makefile.am diff -u gpgme/Makefile.am:1.18 gpgme/Makefile.am:1.19 --- gpgme/Makefile.am:1.18 Tue Dec 7 22:13:36 2004 +++ gpgme/Makefile.am Wed Jan 12 11:28:42 2005 @@ -1,6 +1,6 @@ # Makefile.am - Top level Makefile for GPGME. # Copyright (C) 2000 Werner Koch (dd9jn) -# Copyright (C) 2001, 2002, 2004 g10 Code GmbH +# Copyright (C) 2001, 2002, 2004, 2005 g10 Code GmbH # # This file is part of GPGME. # @@ -20,6 +20,9 @@ ## Process this file with automake to produce Makefile.in +ACLOCAL_AMFLAGS = -I m4 +AUTOMAKE_OPTIONS = dist-bzip2 + EXTRA_DIST = gpgme.spec.in if BUILD_ASSUAN Index: gpgme/NEWS diff -u gpgme/NEWS:1.138 gpgme/NEWS:1.139 --- gpgme/NEWS:1.138 Tue Dec 7 22:24:03 2004 +++ gpgme/NEWS Wed Jan 12 11:28:42 2005 @@ -11,6 +11,13 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +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) ------------------------------------------------ Index: gpgme/README diff -u gpgme/README:1.30 gpgme/README:1.31 --- gpgme/README:1.30 Tue Dec 7 22:13:36 2004 +++ gpgme/README Wed Jan 12 11:28:42 2005 @@ -44,7 +44,7 @@ libgpg-error 0.5. For support of the OpenPGP protocol (default), you should use the -latest version of GnuPG 1.2, available at: +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. @@ -55,7 +55,7 @@ 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/(en)/download/cvs_access.html +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/ @@ -99,13 +99,13 @@ with the fingerprint published elsewhere. b) If you don't have any of the above programs, you have to verify - the MD5 checksum: + the SHA1 checksum: - $ md5sum gpgme-x.y.z.tar.gz + $ sha1sum gpgme-x.y.z.tar.gz This should yield an output _similar_ to this: - fd9351b26b3189c1d577f0970f9dcadc gpgme-x.y.z.tar.gz + 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. Index: gpgme/acinclude.m4 diff -u gpgme/acinclude.m4:1.13 gpgme/acinclude.m4:1.14 --- gpgme/acinclude.m4:1.13 Tue Dec 7 22:13:36 2004 +++ gpgme/acinclude.m4 Wed Jan 12 11:28:42 2005 @@ -24,7 +24,7 @@ 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, +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 @@ -47,7 +47,7 @@ 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_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,[ gnupg_cv_must_copy_va_byval=no Index: gpgme/configure.ac diff -u gpgme/configure.ac:1.95 gpgme/configure.ac:1.96 --- gpgme/configure.ac:1.95 Sat Dec 11 16:48:00 2004 +++ gpgme/configure.ac Wed Jan 12 11:28:42 2005 @@ -20,11 +20,11 @@ # (Process this file with autoconf to produce a configure script.) -AC_PREREQ(2.57) -min_automake_version="1.7.6" +AC_PREREQ(2.59) +min_automake_version="1.9.3" # Version number: Remember to change it immediately *after* a release. -AC_INIT(gpgme, 1.0.1, [bug-gpgme@gnupg.org]) +AC_INIT(gpgme, 1.1.0-cvs, [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) @@ -35,7 +35,7 @@ # 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=3 -LIBGPGME_LT_REVISION=2 +LIBGPGME_LT_REVISION=3 # If the API is changed in an incompatible way: increment the next counter. GPGME_CONFIG_API_VERSION=1 @@ -44,7 +44,7 @@ NEED_GPGSM_VERSION=1.9.6 ############################################## AC_PREREQ(2.52) -AC_REVISION($Revision: 1.95 $) +AC_REVISION($Revision: 1.96 $) PACKAGE=$PACKAGE_NAME VERSION=$PACKAGE_VERSION From cvs at cvs.gnupg.org Wed Jan 12 12:11:10 2005 From: cvs at cvs.gnupg.org (cvs user marcus) Date: Thu Jan 13 02:05:53 2005 Subject: gpgme (TODO) Message-ID: Date: Wednesday, January 12, 2005 @ 12:18:19 Author: marcus Path: /cvs/gpgme/gpgme Modified: TODO Remove some obsolete entries. ------+ TODO | 12 ++++-------- 1 files changed, 4 insertions(+), 8 deletions(-) Index: gpgme/TODO diff -u gpgme/TODO:1.97 gpgme/TODO:1.98 --- gpgme/TODO:1.97 Tue Dec 7 22:13:36 2004 +++ gpgme/TODO Wed Jan 12 12:18:19 2005 @@ -1,18 +1,15 @@ Hey Emacs, this is -*- outline -*- mode! * Before release: -** Switch to LGPL? ** 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. ** Add notation data to key signatures. -** Document gpgme_set_engine_info, gpgme_ctx_get_engine_info, - gpgme_ctx_set_engine_info. - * ABI's to break: ** 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. +* 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: *** ath compatibility modules. *** gpgme_data_new_from_filepart @@ -144,14 +141,13 @@ * Build suite ** Make sure everything is cleaned correctly (esp. test area). -** Configure test for gpg and gpgsm version (as a warning). ** Enable AC_CONFIG_MACRO_DIR and bump up autoconf version requirement. (To fix "./autogen.sh; ./configure --enable-maintainer-mode; touch - configure.ac; make"). + 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. + Add error checking some time after releasing a new gpgsm. Copyright 2004 g10 Code GmbH From cvs at cvs.gnupg.org Wed Jan 12 11:09:36 2005 From: cvs at cvs.gnupg.org (cvs user marcus) Date: Thu Jan 13 02:50:09 2005 Subject: gpgme/m4 (ChangeLog pth.m4) Message-ID: Date: Wednesday, January 12, 2005 @ 11:16:32 Author: marcus Path: /cvs/gpgme/gpgme/m4 Modified: ChangeLog pth.m4 2004-12-28 Werner Koch * pth.m4: Changed quoting for use with automake 1.9. -----------+ ChangeLog | 4 ++++ pth.m4 | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) Index: gpgme/m4/ChangeLog diff -u gpgme/m4/ChangeLog:1.2 gpgme/m4/ChangeLog:1.3 --- gpgme/m4/ChangeLog:1.2 Tue Sep 14 20:31:45 2004 +++ gpgme/m4/ChangeLog Wed Jan 12 11:16:32 2005 @@ -1,3 +1,7 @@ +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 Index: gpgme/m4/pth.m4 diff -u gpgme/m4/pth.m4:1.2 gpgme/m4/pth.m4:1.3 --- gpgme/m4/pth.m4:1.2 Tue Sep 14 20:31:44 2004 +++ gpgme/m4/pth.m4 Wed Jan 12 11:16:32 2005 @@ -40,7 +40,7 @@ dnl ## dnl dnl # auxilliary macros -AC_DEFUN(_AC_PTH_ERROR, [dnl +AC_DEFUN([_AC_PTH_ERROR], [dnl AC_MSG_RESULT([*FAILED*]) dnl define(_ac_pth_line,dnl dnl "+------------------------------------------------------------------------+") @@ -52,13 +52,13 @@ dnl undefine(_ac_pth_line) exit 1 ]) -AC_DEFUN(_AC_PTH_VERBOSE, [dnl +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 +AC_DEFUN([AC_CHECK_PTH], [dnl dnl dnl # prerequisites AC_REQUIRE([AC_PROG_CC])dnl From cvs at cvs.gnupg.org Tue Jan 18 10:44:23 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Tue Jan 18 11:54:19 2005 Subject: gnupg/g10 (ChangeLog keylist.c) Message-ID: Date: Tuesday, January 18, 2005 @ 10:51:58 Author: wk Path: /cvs/gnupg/gnupg/g10 Modified: ChangeLog keylist.c (public_key_list): Do a trustdb staleness check before opening the keyring. (secret_key_list): Ditto. -----------+ ChangeLog | 6 ++++++ keylist.c | 9 +++++++++ 2 files changed, 15 insertions(+) Index: gnupg/g10/ChangeLog diff -u gnupg/g10/ChangeLog:1.680 gnupg/g10/ChangeLog:1.681 --- gnupg/g10/ChangeLog:1.680 Tue Jan 11 05:15:55 2005 +++ gnupg/g10/ChangeLog Tue Jan 18 10:51:58 2005 @@ -1,3 +1,9 @@ +2005-01-18 Werner Koch + + * keylist.c (public_key_list): Do a trustdb staleness check before + opening the keyring. + (secret_key_list): Ditto. + 2005-01-10 David Shaw * keyedit.c (keyedit_menu): Move command strings outside the Index: gnupg/g10/keylist.c diff -u gnupg/g10/keylist.c:1.93 gnupg/g10/keylist.c:1.94 --- gnupg/g10/keylist.c:1.93 Tue Dec 21 05:19:03 2004 +++ gnupg/g10/keylist.c Tue Jan 18 10:51:58 2005 @@ -95,6 +95,13 @@ printf("\n"); } + /* We need to do the stale check right here because it might need to + update the keyring while we already have the keyring open. This + is very bad for W32 because of a sharing violation. For real OSes + it might lead to false results if we are later listing a keyring + which is associated with the inode of a deleted file. */ + check_trustdb_stale (); + if( !list ) list_all(0); else @@ -104,6 +111,8 @@ void secret_key_list( STRLIST list ) { + check_trustdb_stale (); + if( !list ) list_all(1); else /* List by user id */ From cvs at cvs.gnupg.org Tue Jan 18 12:08:25 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Tue Jan 18 12:08:28 2005 Subject: gnupg/keyserver (ChangeLog gpgkeys_curl.c gpgkeys_http.c ksutil.h) Message-ID: Date: Tuesday, January 18, 2005 @ 12:16:10 Author: wk Path: /cvs/gnupg/gnupg/keyserver Modified: ChangeLog gpgkeys_curl.c gpgkeys_http.c ksutil.h * gpgkeys_curl.c: s/MAX_PATH/URLMAX_PATH/g to avoid a clash with the W32 defined macro. Removed unneeded initialization of static variables. * gpgkeys_http.c: Ditto. * ksutil.h: s/MAX_PATH/URLMAX_PATH/. ----------------+ ChangeLog | 8 ++++++++ gpgkeys_curl.c | 15 ++++++++++----- gpgkeys_http.c | 12 ++++++++---- ksutil.h | 5 +++-- 4 files changed, 29 insertions(+), 11 deletions(-) Index: gnupg/keyserver/ChangeLog diff -u gnupg/keyserver/ChangeLog:1.104 gnupg/keyserver/ChangeLog:1.105 --- gnupg/keyserver/ChangeLog:1.104 Tue Jan 18 05:24:52 2005 +++ gnupg/keyserver/ChangeLog Tue Jan 18 12:16:10 2005 @@ -1,3 +1,11 @@ +2005-01-18 Werner Koch + + * gpgkeys_curl.c: s/MAX_PATH/URLMAX_PATH/g to avoid a clash with + the W32 defined macro. Removed unneeded initialization of static + variables. + * gpgkeys_http.c: Ditto. + * ksutil.h: s/MAX_PATH/URLMAX_PATH/. + 2005-01-17 David Shaw * gpgkeys_curl.c (main): Only allow specified protocols to use the Index: gnupg/keyserver/gpgkeys_curl.c diff -u gnupg/keyserver/gpgkeys_curl.c:1.7 gnupg/keyserver/gpgkeys_curl.c:1.8 --- gnupg/keyserver/gpgkeys_curl.c:1.7 Tue Jan 18 05:24:52 2005 +++ gnupg/keyserver/gpgkeys_curl.c Tue Jan 18 12:16:10 2005 @@ -35,10 +35,15 @@ extern int optind; static int verbose=0; -static char scheme[MAX_SCHEME+1],auth[MAX_AUTH+1],host[MAX_HOST+1]={'\0'},port[MAX_PORT+1]={'\0'},path[MAX_PATH+1]={'\0'},proxy[MAX_PROXY+1]={'\0'}; -static FILE *input=NULL,*output=NULL,*console=NULL; +static char scheme[MAX_SCHEME+1]; +static char auth[MAX_AUTH+1]; +static char host[MAX_HOST+1]; +static char port[MAX_PORT+1]; +static char path[URLMAX_PATH+1]; +static char proxy[MAX_PROXY+1; +static FILE *input, *output, *console; static CURL *curl; -static char request[MAX_URL]={'\0'}; +static char request[MAX_URL]; static int curl_err_to_gpg_err(CURLcode error) @@ -217,9 +222,9 @@ continue; } - if(sscanf(line,"PATH %" MKSTRING(MAX_PATH) "s\n",path)==1) + if(sscanf(line,"PATH %" MKSTRING(URLMAX_PATH) "s\n",path)==1) { - path[MAX_PATH]='\0'; + path[URLMAX_PATH]='\0'; continue; } Index: gnupg/keyserver/gpgkeys_http.c diff -u gnupg/keyserver/gpgkeys_http.c:1.11 gnupg/keyserver/gpgkeys_http.c:1.12 --- gnupg/keyserver/gpgkeys_http.c:1.11 Fri Jan 14 00:37:26 2005 +++ gnupg/keyserver/gpgkeys_http.c Tue Jan 18 12:16:10 2005 @@ -38,8 +38,12 @@ static int verbose=0; static unsigned int http_flags=0; -static char auth[MAX_AUTH+1]={'\0'},host[MAX_HOST+1]={'\0'},proxy[MAX_PROXY+1]={'\0'},port[MAX_PORT+1]={'\0'},path[MAX_PATH+1]={'\0'}; -static FILE *input=NULL,*output=NULL,*console=NULL; +static char auth[MAX_AUTH+1]; +static char host[MAX_HOST+1]; +static char proxy[MAX_PROXY+1]; +static char port[MAX_PORT+1]; +static char path[URLMAX_PATH+1]; +static FILE *input,*output,*console; #ifdef __riscos__ #define HTTP_PROXY_ENV "GnuPG$HttpProxy" @@ -231,9 +235,9 @@ continue; } - if(sscanf(line,"PATH %" MKSTRING(MAX_PATH) "s\n",path)==1) + if(sscanf(line,"PATH %" MKSTRING(URLMAX_PATH) "s\n",path)==1) { - path[MAX_PATH]='\0'; + path[URLMAX_PATH]='\0'; continue; } Index: gnupg/keyserver/ksutil.h diff -u gnupg/keyserver/ksutil.h:1.2 gnupg/keyserver/ksutil.h:1.3 --- gnupg/keyserver/ksutil.h:1.2 Fri Jan 14 00:37:26 2005 +++ gnupg/keyserver/ksutil.h Tue Jan 18 12:16:10 2005 @@ -36,9 +36,10 @@ #define MAX_AUTH 128 #define MAX_HOST 80 #define MAX_PORT 10 -#define MAX_PATH 1024 +#define URLMAX_PATH 1024 #define MAX_PROXY 128 -#define MAX_URL (MAX_SCHEME+1+3+MAX_AUTH+1+1+MAX_HOST+1+1+MAX_PORT+1+1+MAX_PATH+1+50) +#define MAX_URL (MAX_SCHEME+1+3+MAX_AUTH+1+1+MAX_HOST+1+1 \ + +MAX_PORT+1+1+URLMAX_PATH+1+50) #define STRINGIFY(x) #x #define MKSTRING(x) STRINGIFY(x) From cvs at cvs.gnupg.org Tue Jan 18 15:35:28 2005 From: cvs at cvs.gnupg.org (cvs user dshaw) Date: Tue Jan 18 15:35:31 2005 Subject: gnupg/keyserver (ChangeLog gpgkeys_curl.c) Message-ID: Date: Tuesday, January 18, 2005 @ 15:43:14 Author: dshaw Path: /cvs/gnupg/gnupg/keyserver Modified: ChangeLog gpgkeys_curl.c * gpgkeys_curl.c: Fix typo. ----------------+ ChangeLog | 4 ++++ gpgkeys_curl.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) Index: gnupg/keyserver/ChangeLog diff -u gnupg/keyserver/ChangeLog:1.105 gnupg/keyserver/ChangeLog:1.106 --- gnupg/keyserver/ChangeLog:1.105 Tue Jan 18 12:16:10 2005 +++ gnupg/keyserver/ChangeLog Tue Jan 18 15:43:14 2005 @@ -1,3 +1,7 @@ +2005-01-18 David Shaw + + * gpgkeys_curl.c: Fix typo. + 2005-01-18 Werner Koch * gpgkeys_curl.c: s/MAX_PATH/URLMAX_PATH/g to avoid a clash with Index: gnupg/keyserver/gpgkeys_curl.c diff -u gnupg/keyserver/gpgkeys_curl.c:1.8 gnupg/keyserver/gpgkeys_curl.c:1.9 --- gnupg/keyserver/gpgkeys_curl.c:1.8 Tue Jan 18 12:16:10 2005 +++ gnupg/keyserver/gpgkeys_curl.c Tue Jan 18 15:43:14 2005 @@ -40,7 +40,7 @@ static char host[MAX_HOST+1]; static char port[MAX_PORT+1]; static char path[URLMAX_PATH+1]; -static char proxy[MAX_PROXY+1; +static char proxy[MAX_PROXY+1]; static FILE *input, *output, *console; static CURL *curl; static char request[MAX_URL]; From cvs at cvs.gnupg.org Wed Jan 19 04:48:38 2005 From: cvs at cvs.gnupg.org (cvs user dshaw) Date: Wed Jan 19 04:48:41 2005 Subject: gnupg (ChangeLog NEWS configure.ac) Message-ID: Date: Wednesday, January 19, 2005 @ 04:56:25 Author: dshaw Path: /cvs/gnupg/gnupg Modified: ChangeLog NEWS configure.ac * NEWS: Note --rfc2440-text import/export-unusable-sigs and gpgkeys_curl. * configure.ac: gpgkeys_mailto is disabled by default. Define HTTPS flag if we're using curl, and HTTPS is available. --------------+ ChangeLog | 8 ++++++++ NEWS | 17 +++++++++++++++++ configure.ac | 11 +++++++---- 3 files changed, 32 insertions(+), 4 deletions(-) Index: gnupg/ChangeLog diff -u gnupg/ChangeLog:1.234 gnupg/ChangeLog:1.235 --- gnupg/ChangeLog:1.234 Mon Jan 17 11:19:57 2005 +++ gnupg/ChangeLog Wed Jan 19 04:56:25 2005 @@ -1,3 +1,11 @@ +2005-01-18 David Shaw + + * NEWS: Note --rfc2440-text import/export-unusable-sigs and + gpgkeys_curl. + + * configure.ac: gpgkeys_mailto is disabled by default. Define + HTTPS flag if we're using curl, and HTTPS is available. + 2005-01-17 Werner Koch * configure.ac: Make --without-included-zlib work as Index: gnupg/NEWS diff -u gnupg/NEWS:1.226 gnupg/NEWS:1.227 --- gnupg/NEWS:1.226 Thu Dec 16 11:53:25 2004 +++ gnupg/NEWS Wed Jan 19 04:56:25 2005 @@ -1,6 +1,23 @@ Noteworthy changes in version 1.4.1 ------------------------------------------------- + * New --rfc2440-text option which controls how text is handled in + signatures. This is in response to some problems seen with + certain PGP/MIME mail clients and GnuPG version 1.4.0. More + details about this are available at + + + * New "import-unusable-sigs" and "export-unusable-sigs" tags for + --import-options and --export-options. These are on by + default, and cause GnuPG to not import or export key signatures + that are not usable (e.g. expired signatures). + + * New experimental HTTP, HTTPS, and FTP keyserver helper that uses + the cURL library (http://curl.haxx.se) to retrieve keys. This + is disabled by default, but may be enabled with the configure + option --with-libcurl. Without this option, the existing HTTP + code is used for HTTP, and HTTPS and FTP are not supported. + Noteworthy changes in version 1.4.0 (2004-12-16) ------------------------------------------------- Index: gnupg/configure.ac diff -u gnupg/configure.ac:1.126 gnupg/configure.ac:1.127 --- gnupg/configure.ac:1.126 Mon Jan 17 11:19:57 2005 +++ gnupg/configure.ac Wed Jan 19 04:56:25 2005 @@ -19,7 +19,7 @@ dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA dnl dnl (Process this file with autoconf to produce a configure script.) -dnlAC_REVISION($Revision: 1.126 $)dnl +dnlAC_REVISION($Revision: 1.127 $)dnl AC_PREREQ(2.59) min_automake_version="1.9.3" @@ -332,9 +332,9 @@ AC_MSG_CHECKING([whether email keyserver support is requested]) AC_ARG_ENABLE(mailto, - AC_HELP_STRING([--disable-mailto], - [disable email keyserver interface only]), - try_mailto=$enableval, try_mailto=yes) + AC_HELP_STRING([--enable-mailto], + [enable email keyserver interface only]), + try_mailto=$enableval, try_mailto=no) AC_MSG_RESULT($try_mailto) fi @@ -656,6 +656,9 @@ if test x$libcurl_protocol_HTTP = xyes ; then AC_SUBST(GPGKEYS_CURL,"gpgkeys_curl$EXEEXT") AC_DEFINE(HTTP_VIA_LIBCURL,1,[Define if HTTP is handled via libcurl]) + if test x$libcurl_protocol_HTTPS = xyes ; then + AC_DEFINE(HTTPS_VIA_LIBCURL,1,[Define if HTTPS is handled via libcurl]) + fi else AC_SUBST(GPGKEYS_HTTP,"gpgkeys_http$EXEEXT") fi From cvs at cvs.gnupg.org Thu Jan 20 12:34:10 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Thu Jan 20 12:34:14 2005 Subject: gnupg (19 files) Message-ID: Date: Thursday, January 20, 2005 @ 12:42:05 Author: wk Path: /cvs/gnupg/gnupg Modified: ChangeLog NEWS README configure.ac doc/ChangeLog doc/README.W32 doc/gnupg-w32.reg g10/ChangeLog g10/g10.c g10/gpgv.c g10/main.h g10/misc.c include/i18n.h scripts/mk-w32-dist scripts/w32installer.nsi util/ChangeLog util/argparse.c util/simple-gettext.c util/strgutil.c * g10.c (i18n_init) [W32]: Pass registry key to gettext initialization. * gpgv.c (i18n_init) [W32]: Ditto. * simple-gettext.c (set_gettext_file): Use MO files depending on the installation directory. Add new arg REGKEY. --------------------------+ ChangeLog | 6 + NEWS | 9 ++ README | 9 +- configure.ac | 4 doc/ChangeLog | 4 doc/README.W32 | 8 - doc/gnupg-w32.reg | 8 - g10/ChangeLog | 10 ++ g10/g10.c | 13 --- g10/gpgv.c | 15 +-- g10/main.h | 3 g10/misc.c | 59 +++++++++++++ include/i18n.h | 2 scripts/mk-w32-dist | 7 + scripts/w32installer.nsi | 193 +++++++++++++++++++++++++++++---------------- util/ChangeLog | 13 +++ util/argparse.c | 2 util/simple-gettext.c | 83 +++++++++++++------ util/strgutil.c | 47 +++++++++- 19 files changed, 351 insertions(+), 144 deletions(-) Index: gnupg/ChangeLog diff -u gnupg/ChangeLog:1.235 gnupg/ChangeLog:1.236 --- gnupg/ChangeLog:1.235 Wed Jan 19 04:56:25 2005 +++ gnupg/ChangeLog Thu Jan 20 12:42:03 2005 @@ -1,3 +1,7 @@ +2005-01-18 Werner Koch + + * configure.ac (HAVE_W32_SYSTEM): Define it. + 2005-01-18 David Shaw * NEWS: Note --rfc2440-text import/export-unusable-sigs and @@ -8,6 +12,8 @@ 2005-01-17 Werner Koch + * README: Updated for SHA1 checksums. + * configure.ac: Make --without-included-zlib work as expected. Reported by Norihiko Murase. Same for --without-included-regex. Index: gnupg/NEWS diff -u gnupg/NEWS:1.227 gnupg/NEWS:1.228 --- gnupg/NEWS:1.227 Wed Jan 19 04:56:25 2005 +++ gnupg/NEWS Thu Jan 20 12:42:03 2005 @@ -1,6 +1,15 @@ Noteworthy changes in version 1.4.1 ------------------------------------------------- + * [W32] The algorithm for the default home directory changed: + First we look at the environment variable GNUPGHOME, if this one + is not set, we check whether the registry entry + HKCU\Software\GNU\GnuPG:HomeDir has been set and if this fails + we use a GnuPG directory below the standard application data + directory (APPDATA) of the current user. Only in the case that + this directory cannot be determined, the old default of c:\gnupg + will be used. The option --homedir still overrides all of them. + * New --rfc2440-text option which controls how text is handled in signatures. This is in response to some problems seen with certain PGP/MIME mail clients and GnuPG version 1.4.0. More Index: gnupg/README diff -u gnupg/README:1.91 gnupg/README:1.92 --- gnupg/README:1.91 Tue Dec 14 08:49:26 2004 +++ gnupg/README Thu Jan 20 12:42:03 2005 @@ -54,7 +54,8 @@ this. Don't skip it - this is an important step! 2) Unpack the tarball. With GNU tar you can do it this way: - "tar xzvf gnupg-x.y.z.tar.gz" + "tar xzvf gnupg-x.y.z.tar.gz". If got a bzip2 compressed + tarball you need to use: "tar xjvf gnupg-x.y.z.tar.bz2". 3) "cd gnupg-x.y.z" @@ -104,13 +105,13 @@ b) If you don't have any of the above programs, you have to verify - the MD5 checksum: + the SHA1 checksum: - $ md5sum gnupg-x.y.z.tar.gz + $ sha1sum gnupg-x.y.z.tar.gz This should yield an output _similar_ to this: - fd9351b26b3189c1d577f0970f9dcadc gnupg-x.y.z.tar.gz + fd9351b26b3189c1d577f0970f9dcadc1234abcd gnupg-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. Index: gnupg/configure.ac diff -u gnupg/configure.ac:1.127 gnupg/configure.ac:1.128 --- gnupg/configure.ac:1.127 Wed Jan 19 04:56:25 2005 +++ gnupg/configure.ac Thu Jan 20 12:42:03 2005 @@ -19,7 +19,7 @@ dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA dnl dnl (Process this file with autoconf to produce a configure script.) -dnlAC_REVISION($Revision: 1.127 $)dnl +dnlAC_REVISION($Revision: 1.128 $)dnl AC_PREREQ(2.59) min_automake_version="1.9.3" @@ -455,6 +455,8 @@ [because the Unix gettext has too much overhead on MingW32 systems and these systems lack Posix functions, we use a simplified version of gettext]) + AC_DEFINE(HAVE_W32_SYSTEM,1, + [Defined if we run on a W32 API based system]) have_dosish_system=yes need_dlopen=no try_gettext="no" Index: gnupg/doc/ChangeLog diff -u gnupg/doc/ChangeLog:1.90 gnupg/doc/ChangeLog:1.91 --- gnupg/doc/ChangeLog:1.90 Thu Dec 16 11:13:02 2004 +++ gnupg/doc/ChangeLog Thu Jan 20 12:42:03 2005 @@ -1,3 +1,7 @@ +2005-01-18 Werner Koch + + * gnupg-w32.reg: Remove the entry for the home directory. + 2004-12-16 Werner Koch * TRANSLATE: Add a note on how to send translations. Index: gnupg/doc/README.W32 diff -u gnupg/doc/README.W32:1.4 gnupg/doc/README.W32:1.5 --- gnupg/doc/README.W32:1.4 Fri Nov 15 05:15:39 2002 +++ gnupg/doc/README.W32 Thu Jan 20 12:42:03 2005 @@ -7,6 +7,9 @@ particular the list gnupg-users@gnupg.org might be useful to answer questions - but please read the FAQ first. +Note: Due to the use of the NSIS installer, the information below are +mostly out of date. + Installation instructions: -------------------------- 1. Unpack the ZIP archive (alright, you already did this). @@ -40,11 +43,6 @@ (Example: "copy fr.mo c:\gnu\locale\fr\gnupg.mo") 4. Done. -Currently we only support the Codepages 437, 850 und Latin1. If you have -problems, either delete the gnupg.mo file or don't set the environment -variable - - How to build it from the source: -------------------------------- Index: gnupg/doc/gnupg-w32.reg diff -u gnupg/doc/gnupg-w32.reg:1.3 gnupg/doc/gnupg-w32.reg:1.4 --- gnupg/doc/gnupg-w32.reg:1.3 Mon May 26 15:34:42 2003 +++ gnupg/doc/gnupg-w32.reg Thu Jan 20 12:42:03 2005 @@ -1,13 +1,5 @@ REGEDIT4 -[HKEY_LOCAL_MACHINE\Software\GNU] - -[HKEY_LOCAL_MACHINE\Software\GNU\GNUPG] - -[HKEY_LOCAL_MACHINE\Software\GNU\GNUPG] -"HomeDir"="C:\\GnuPG" -"gpgProgram"="C:\\GnuPG\\gpg.exe" - [HKEY_CURRENT_USER\Control Panel\Mingw32] Index: gnupg/g10/ChangeLog diff -u gnupg/g10/ChangeLog:1.681 gnupg/g10/ChangeLog:1.682 --- gnupg/g10/ChangeLog:1.681 Tue Jan 18 10:51:58 2005 +++ gnupg/g10/ChangeLog Thu Jan 20 12:42:03 2005 @@ -1,5 +1,15 @@ +2005-01-20 Werner Koch + + * g10.c (i18n_init) [W32]: Pass registry key to gettext + initialization. + * gpgv.c (i18n_init) [W32]: Ditto. + 2005-01-18 Werner Koch + * misc.c (default_homedir): New. Taken from gnupg 1.9.15. + * g10.c (main): Use it. + * gpgv.c (main): Ditto. + * keylist.c (public_key_list): Do a trustdb staleness check before opening the keyring. (secret_key_list): Ditto. Index: gnupg/g10/g10.c diff -u gnupg/g10/g10.c:1.296 gnupg/g10/g10.c:1.297 --- gnupg/g10/g10.c:1.296 Thu Jan 6 05:44:38 2005 +++ gnupg/g10/g10.c Thu Jan 20 12:42:03 2005 @@ -1,6 +1,6 @@ /* g10.c - The GnuPG utility (main for gpg) * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 - * 2004 Free Software Foundation, Inc. + * 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -839,7 +839,7 @@ i18n_init(void) { #ifdef USE_SIMPLE_GETTEXT - set_gettext_file( PACKAGE ); + set_gettext_file (PACKAGE, "Software\\GNU\\GnuPG"); #else #ifdef ENABLE_NLS setlocale( LC_ALL, "" ); @@ -1673,14 +1673,7 @@ set_screen_dimensions(); opt.keyid_format=KF_SHORT; opt.rfc2440_text=1; -#if defined (_WIN32) - set_homedir ( read_w32_registry_string( NULL, - "Software\\GNU\\GnuPG", "HomeDir" )); -#else - set_homedir ( getenv("GNUPGHOME") ); -#endif - if( !*opt.homedir ) - set_homedir ( GNUPG_HOMEDIR ); + set_homedir ( default_homedir () ); #ifdef ENABLE_CARD_SUPPORT # ifdef _WIN32 Index: gnupg/g10/gpgv.c diff -u gnupg/g10/gpgv.c:1.25 gnupg/g10/gpgv.c:1.26 --- gnupg/g10/gpgv.c:1.25 Wed Nov 24 06:25:03 2004 +++ gnupg/g10/gpgv.c Thu Jan 20 12:42:03 2005 @@ -1,5 +1,6 @@ /* gpgv.c - The GnuPG signature verify utility - * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, + * 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -112,7 +113,7 @@ i18n_init(void) { #ifdef USE_SIMPLE_GETTEXT - set_gettext_file( PACKAGE ); + set_gettext_file (PACKAGE, "Software\\GNU\\GnuPG"); #else #ifdef ENABLE_NLS setlocale( LC_ALL, "" ); @@ -141,14 +142,8 @@ opt.trust_model = TM_ALWAYS; opt.batch = 1; -#if defined (_WIN32) - opt.homedir = read_w32_registry_string( NULL, "Software\\GNU\\GnuPG", "HomeDir" ); -#else - opt.homedir = getenv("GNUPGHOME"); -#endif - if( !opt.homedir || !*opt.homedir ) { - opt.homedir = GNUPG_HOMEDIR; - } + opt.homedir = default_homedir (); + tty_no_terminal(1); tty_batchmode(1); disable_dotlock(); Index: gnupg/g10/main.h diff -u gnupg/g10/main.h:1.123 gnupg/g10/main.h:1.124 --- gnupg/g10/main.h:1.123 Thu Oct 14 09:11:56 2004 +++ gnupg/g10/main.h Thu Jan 20 12:42:03 2005 @@ -122,6 +122,9 @@ int parse_options(char *str,unsigned int *options, struct parse_options *opts,int noisy); +char *default_homedir (void); + + /*-- helptext.c --*/ void display_online_help( const char *keyword ); Index: gnupg/g10/misc.c diff -u gnupg/g10/misc.c:1.63 gnupg/g10/misc.c:1.64 --- gnupg/g10/misc.c:1.63 Wed Nov 3 21:35:28 2004 +++ gnupg/g10/misc.c Thu Jan 20 12:42:03 2005 @@ -1,6 +1,6 @@ /* misc.c - miscellaneous functions * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, - * 2004 Free Software Foundation, Inc. + * 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -40,7 +40,19 @@ #ifdef _WIN32 #include #include +#include +#include +#ifndef CSIDL_APPDATA +#define CSIDL_APPDATA 0x001a #endif +#ifndef CSIDL_LOCAL_APPDATA +#define CSIDL_LOCAL_APPDATA 0x001c +#endif +#ifndef CSIDL_FLAG_CREATE +#define CSIDL_FLAG_CREATE 0x8000 +#endif +#endif /*_WIN32*/ + #include "util.h" #include "main.h" #include "photoid.h" @@ -49,6 +61,8 @@ #include "cardglue.h" + + #ifdef ENABLE_SELINUX_HACKS /* A object and a global variable to keep track of files marked as secured. */ @@ -1002,3 +1016,46 @@ return 1; } + + +/* Set up the default home directory. The usual --homedir option + should be parsed later. */ +char * +default_homedir (void) +{ + char *dir; + + dir = getenv("GNUPGHOME"); +#ifdef HAVE_W32_SYSTEM + if (!dir || !*dir) + dir = read_w32_registry_string (NULL, "Software\\GNU\\GnuPG", "HomeDir"); + if (!dir || !*dir) + { + char path[MAX_PATH]; + + /* It might be better to use LOCAL_APPDATA because this is + defined as "non roaming" and thus more likely to be kept + locally. For private keys this is desired. However, given + that many users copy private keys anyway forth and back, + using a system roaming serives might be better than to let + them do it manually. A security conscious user will anyway + use the registry entry to have better control. */ + if (SHGetFolderPath(NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE, + NULL, 0, path) >= 0) + { + char *tmp = xmalloc (strlen (path) + 6 +1); + strcpy (stpcpy (tmp, path), "\\gnupg"); + dir = tmp; + + /* Try to create the directory if it does not yet + exists. */ + if (access (dir, F_OK)) + CreateDirectory (dir, NULL); + } + } +#endif /*HAVE_W32_SYSTEM*/ + if (!dir || !*dir) + dir = GNUPG_HOMEDIR; + + return dir; +} Index: gnupg/include/i18n.h diff -u gnupg/include/i18n.h:1.10 gnupg/include/i18n.h:1.11 --- gnupg/include/i18n.h:1.10 Sat May 24 18:40:46 2003 +++ gnupg/include/i18n.h Thu Jan 20 12:42:03 2005 @@ -22,7 +22,7 @@ #define G10_I18N_H #ifdef USE_SIMPLE_GETTEXT -int set_gettext_file( const char *filename ); +int set_gettext_file( const char *filename, const char *regkey ); const char *gettext( const char *msgid ); #define _(a) gettext (a) Index: gnupg/scripts/mk-w32-dist diff -u gnupg/scripts/mk-w32-dist:1.14 gnupg/scripts/mk-w32-dist:1.15 --- gnupg/scripts/mk-w32-dist:1.14 Mon Jan 17 11:19:57 2005 +++ gnupg/scripts/mk-w32-dist Thu Jan 20 12:42:02 2005 @@ -96,8 +96,13 @@ done if makensis -version >/dev/null 2>&1 ; then + echo "invokin installer as:" + echo makensis -v3 -nocd -DVERSION="${version}" \ + -DPROD_VERSION="${prod_version}" \ + -DGNUPG_SRCDIR="${srcdir}" ${srcdir}/scripts/w32installer.nsi makensis -v3 -nocd -DVERSION="${version}" \ - -DPROD_VERSION="${prod_version}" ${srcdir}/scripts/w32installer.nsi + -DPROD_VERSION="${prod_version}" \ + -DGNUPG_SRCDIR="${srcdir}" ${srcdir}/scripts/w32installer.nsi echo "Installer created" >&2 else zip -9 "gnupg-w32cli-${version}.zip" * Index: gnupg/scripts/w32installer.nsi diff -u gnupg/scripts/w32installer.nsi:1.2 gnupg/scripts/w32installer.nsi:1.3 --- gnupg/scripts/w32installer.nsi:1.2 Mon Jan 17 11:19:57 2005 +++ gnupg/scripts/w32installer.nsi Thu Jan 20 12:42:02 2005 @@ -1,4 +1,5 @@ -; w32installer.nsi - W32 Installer definition -*- lisp -*- +; w32installer.nsi -*- mode: lisp; coding: latin-1; -*- +; W32 Installer script ; Copyright (C) 2005 Free Software Foundation, Inc. ; ; This file is free software; as a special exception the author gives @@ -17,11 +18,8 @@ ; TODO: ; - Display credit for the installer ; - Provide the location of the corresponding source -; - Check for iconv.dll and optionalkly install or download it. -; - Allow inclusion of the source into the installer. ; - Translate all strings -; - Setup the home directory and check for old (c:/gnupg located) -; versions of the program + ; We use the modern UI. !include "MUI.nsh" @@ -35,11 +33,10 @@ InstallDir "$PROGRAMFILES\GNU\GnuPG" -InstallDirRegKey HKCU "Software\GNU\GnuPG" "" +InstallDirRegKey HKLM "Software\GNU\GnuPG" "Install Directory" SetCompressor lzma -ReserveFile "COPYING.txt" VIProductVersion "${PROD_VERSION}" VIAddVersionKey "ProductName" "GNU Privacy Guard (${VERSION})" @@ -62,7 +59,7 @@ ; Interface Settings ; ------------------ -!define MUI_ABORTWARNING +;;;!define MUI_ABORTWARNING !define MUI_FINISHPAGE_NOAUTOCLOSE !define MUI_UNFINISHPAGE_NOAUTOCLOSE @@ -95,15 +92,18 @@ !insertmacro MUI_PAGE_LICENSE "COPYING.txt" +;;Page custom PageSelectOptions !insertmacro MUI_PAGE_COMPONENTS + !insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_INSTFILES !define MUI_FINISHPAGE_SHOWREADME "README.txt" !define MUI_FINISHPAGE_SHOWREADME_TEXT "$(T_ShowReadme)" -!define MUI_FINISHPAGE_LINK "Goto the GnuPG website" -!define MUI_FINISHPAGE_LINK_LOCATION "http://www.gnupg.org" +!define MUI_FINISHPAGE_LINK \ + "Visit the GnuPG website for latest news and support" +!define MUI_FINISHPAGE_LINK_LOCATION "http://www.gnupg.org/" !insertmacro MUI_PAGE_FINISH @@ -122,9 +122,17 @@ ; Installer Sections ; ------------------ + + ;InstType "full" ;InstType "minimal" +!insertmacro MUI_RESERVEFILE_LANGDLL +;;!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS +;;ReserveFile "w32inst-opt.ini" +ReserveFile "COPYING.txt" + + ;---------------------- Section "Base" SecBase ; SectionIn 1 2 RO @@ -132,26 +140,41 @@ SetOutPath "$INSTDIR" - File "README.txt" - File "README.W32" - File "COPYING.txt" File "gpg.exe" File "gpgkeys_finger.exe" File "gpgkeys_hkp.exe" File "gpgkeys_http.exe" File "gpgkeys_ldap.exe" - File "*.mo" - WriteRegStr HKCU "Software\GNU\GnuPG" "" $INSTDIR + SetOutPath "$INSTDIR\Doc" + + File "README.txt" + File "README.W32" + File "COPYING.txt" + + Call InstallIconv + + WriteRegStr HKLM "Software\GNU\GnuPG" "Install Directory" $INSTDIR WriteUninstaller "$INSTDIR\Uninstall.exe" SectionEnd ; Section Base +;---------------------- +Section "NLS" SecNLS +; SectionIn 1 + + SetOutPath "$INSTDIR\gnupg.nls" + + File "*.mo" + +SectionEnd ; Section NLS + ;------------------------ Section "Tools" SecTools ; SectionIn 1 + SetOutPath "$INSTDIR" File "gpgsplit.exe" File "gpgv.exe" @@ -161,6 +184,8 @@ Section "Documentation" SecDoc ; SectionIn 1 + SetOutPath "$INSTDIR\Doc" + File "gnupg.man" File "gpg.man" File "gpgv.man" @@ -174,76 +199,52 @@ !ifdef WITH_SOURCE Section "Source" SecSource - ; Note that we include the uncompressed tarball because this allows - ; far better compression results for the distribution. We might - ; want to compress it again after installation. - File "gnupg-1.4.0.tar" + SetOutPath "$INSTDIR\Src" + + ; Note that we include the uncompressed tarball because this allows + ; far better compression results for the distribution. We might + ; want to compress it again after installation. + File "gnupg-1.4.0.tar" SectionEnd ; Section Source !endif -;---------------------- -Section "-Finish" - - ClearErrors - GetDllVersion "iconv.dll" $R0 $R1 - IfErrors 0 +3 - MessageBox MB_OK \ - "iconv.dll is not installed.$\r$\n \ - It is highy suggested to install \ - this DLL to help with character set conversion.$\r$\n$\r$\n \ - See http://www.gnupg.org/download/iconv.html for instructions." - Return - - IntOp $R2 $R0 / 0x00010000 - IntOp $R3 $R0 & 0x0000FFFF - IntOp $R4 $R1 / 0x00010000 - IntOp $R5 $R1 & 0x0000FFFF - StrCpy $0 "$R2.$R3.$R4.$R5" - - DetailPrint "iconv.dll version is $0" - - IntCmp $R2 1 0 IconvTooOld - IntCmp $R3 9 0 IconvTooOld - goto +3 - IconvTooOld: - MessageBox MB_OK \ - "The installed iconv.dll is too old.$\r$\n \ - We require at least version 1.9.0.0 (installed: $0).$\r$\n \ - It is highly suggested to install an updated DLL to help \ - with character set conversion.$\r$\n$\r$\n \ - See http://www.gnupg.org/download/iconv.html for instructions." - - -SectionEnd - - ;------------------ Section "Uninstall" - Delete "$INSTDIR\README.txt" - Delete "$INSTDIR\README.W32" - Delete "$INSTDIR\COPYING.txt" Delete "$INSTDIR\gpg.exe" Delete "$INSTDIR\gpgkeys_finger.exe" Delete "$INSTDIR\gpgkeys_hkp.exe" Delete "$INSTDIR\gpgkeys_http.exe" Delete "$INSTDIR\gpgkeys_ldap.exe" - Delete "$INSTDIR\*.mo" + + Delete "$INSTDIR\Doc\README.txt" + Delete "$INSTDIR\Doc\README.W32" + Delete "$INSTDIR\Doc\COPYING.txt" + + Delete "$INSTDIR\iconv.dll" + + Delete "$INSTDIR\gnupg.nls\*.mo" + Delete "$INSTDIR\gpgsplit.exe" Delete "$INSTDIR\gpgv.exe" - Delete "$INSTDIR\gnupg.man" - Delete "$INSTDIR\gpg.man" - Delete "$INSTDIR\gpgv.man" - Delete "$INSTDIR\NEWS.txt" - Delete "$INSTDIR\FAQ.txt" + + Delete "$INSTDIR\Doc\gnupg.man" + Delete "$INSTDIR\Doc\gpg.man" + Delete "$INSTDIR\Doc\gpgv.man" + Delete "$INSTDIR\Doc\NEWS.txt" + Delete "$INSTDIR\Doc\FAQ.txt" Delete "$INSTDIR\Uninstall.exe" + RMDir "$INSTDIR\Doc" + RMDir "$INSTDIR\Src" + RMDir "$INSTDIR\gnupg.nls" RMDir "$INSTDIR" - DeleteRegKey /ifempty HKCU "Software\GNU\GnuPG" + DeleteRegValue HKLM "Software\GNU\GnuPG" "Install Directory" + DeleteRegKey /ifempty HKLM "Software\GNU\GnuPG" SectionEnd ; Uninstall @@ -256,6 +257,9 @@ !insertmacro MUI_LANGDLL_DISPLAY +; !insertmacro MUI_INSTALLOPTIONS_EXTRACT_AS \ +; "${GNUPG_SRCDIR}/scripts/w32inst-opt.ini" "w32inst-opt.ini" + FunctionEnd @@ -266,6 +270,53 @@ FunctionEnd +;;Function PageSelectOptions +;; +;; ; Setup a default for the langage to install. Take it form the registry +;; +;; !insertmacro MUI_HEADER_TEXT "Install Options" "Languages" +;; !insertmacro MUI_INSTALLOPTIONS_DISPLAY "w32inst-opt.ini" +;; +;; ; Save away the language to install +;; +;;FunctionEnd +;; + + +; Install iconv.dll if it has not been installed on the system. +Function InstallIconv + + ; First delete a iconv DLL already installed in the target directory. + ; This is required to detect a meanwhile globally installed dll. + Delete "$INSTDIR\iconv.dll" + ClearErrors + GetDllVersion "iconv.dll" $R0 $R1 + IfErrors 0 +3 + DetailPrint "iconv.dll is not installed." + goto InstallIconv + + IntOp $R2 $R0 / 0x00010000 + IntOp $R3 $R0 & 0x0000FFFF + IntOp $R4 $R1 / 0x00010000 + IntOp $R5 $R1 & 0x0000FFFF + StrCpy $0 "$R2.$R3.$R4.$R5" + + DetailPrint "iconv.dll version is $0" + + IntCmp $R2 1 0 IconvTooOld + IntCmp $R3 9 0 IconvTooOld + return + + IconvTooOld: + DetailPrint "The installed iconv.dll is too old." + + InstallIconv: + SetOutPath "$INSTDIR" + File "iconv.dll" + +FunctionEnd + + ; ------------ ; Descriptions ; ------------ @@ -275,10 +326,12 @@ "GnuPG is GNU's tool for secure communication and data storage. \ It can be used to encrypt data and to create digital signatures. \ It includes an advanced key management facility and is compliant \ - with the proposed OpenPGP Internet standard as described in RFC2440." + with the proposed OpenPGP Internet standard as described in RFC2440. \ + \r\n\r\nThis is GnuPG version ${VERSION}" LangString T_About ${LANG_GERMAN} \ "GnuPG is das Werzeug aus dem GNU Projekt zur sicheren Kommunikation \ - sowie zum sicheren Speichern von Daten." + sowie zum sicheren Speichern von Daten. \ + \r\n\r\nThis is GnuPG version ${VERSION}" LangString T_ShowReadme ${LANG_ENGLISH} "Show the README file" LangString T_ShowReadme ${LANG_GERMAN} "Die README Datei anzeigen" @@ -288,6 +341,11 @@ LangString DESC_SecBase ${LANG_GERMAN} \ "Die Basis Dateien zur Benutzung des OpenPGP Protokolls" +Langstring DESC_SecNLS ${LANG_ENGLISH} \ + "Support for languages other than English" +LangString DESC_SecNLS ${LANG_GERMAN} \ + "Unterstützung für weitere Sprachen neben Englisch" + LangString DESC_SecTools ${LANG_ENGLISH} \ "Extra tools like gpgv and gpgsplit" LangString DESC_SecTools ${LANG_GERMAN} \ @@ -300,6 +358,7 @@ !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN !insertmacro MUI_DESCRIPTION_TEXT ${SecBase} $(DESC_SecBase) + !insertmacro MUI_DESCRIPTION_TEXT ${SecNLS} $(DESC_SecNLS) !insertmacro MUI_DESCRIPTION_TEXT ${SecTools} $(DESC_SecTools) !insertmacro MUI_DESCRIPTION_TEXT ${SecDoc} $(DESC_SecDoc) !insertmacro MUI_FUNCTION_DESCRIPTION_END Index: gnupg/util/ChangeLog diff -u gnupg/util/ChangeLog:1.177 gnupg/util/ChangeLog:1.178 --- gnupg/util/ChangeLog:1.177 Mon Jan 17 11:19:57 2005 +++ gnupg/util/ChangeLog Thu Jan 20 12:42:02 2005 @@ -1,3 +1,16 @@ +2005-01-20 Werner Koch + + * simple-gettext.c (set_gettext_file): Use MO files depending on + the installation directory. Add new arg REGKEY. + +2005-01-18 Werner Koch + + * argparse.c (default_strusage): Changed default copyright year to + 2005. + + * strgutil.c (handle_iconv_error): Print error messages only once. + (native_to_utf8, utf8_to_native): Ditto. + 2005-01-11 Werner Koch * strgutil.c (set_native_charset) [W32]: Use the alias table from Index: gnupg/util/argparse.c diff -u gnupg/util/argparse.c:1.38 gnupg/util/argparse.c:1.39 --- gnupg/util/argparse.c:1.38 Fri Jan 16 06:16:42 2004 +++ gnupg/util/argparse.c Thu Jan 20 12:42:02 2005 @@ -914,7 +914,7 @@ switch( level ) { case 11: p = "foo"; break; case 13: p = "0.0"; break; - case 14: p = "Copyright (C) 2004 Free Software Foundation, Inc."; break; + case 14: p = "Copyright (C) 2005 Free Software Foundation, Inc."; break; case 15: p = "This program comes with ABSOLUTELY NO WARRANTY.\n" "This is free software, and you are welcome to redistribute it\n" Index: gnupg/util/simple-gettext.c diff -u gnupg/util/simple-gettext.c:1.12 gnupg/util/simple-gettext.c:1.13 --- gnupg/util/simple-gettext.c:1.12 Wed Nov 3 21:03:46 2004 +++ gnupg/util/simple-gettext.c Thu Jan 20 12:42:02 2005 @@ -1,5 +1,6 @@ /* simple-gettext.c - a simplified version of gettext. - * Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc. + * Copyright (C) 1995, 1996, 1997, 1999, + * 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -231,13 +232,14 @@ /**************** - * Set the file used for translations. Pass a NULL to disable - * translation. A new filename may be set at anytime. - * WARNING: After changing the filename you should not access any data - * retrieved by gettext(). + * Set the file used for translations. Pass a NULL to disable + * translation. A new filename may be set at anytime. If REGKEY is + * not NULL, the function tries to selected the language the registry + * key "Lang" below that key. WARNING: After changing the filename you + * should not access any data retrieved by gettext(). */ int -set_gettext_file( const char *filename ) +set_gettext_file ( const char *filename, const char *regkey ) { struct loaded_domain *domain = NULL; @@ -252,30 +254,57 @@ /* absolute path - use it as is */ domain = load_domain( filename ); } - else { /* relative path - append ".mo" and get dir from the environment */ - char *buf = NULL; - char *dir; + else if (regkey) { /* Standard. */ + char *instdir, *langid, *fname; char *p; - dir = read_w32_registry_string( NULL, - "Control Panel\\Mingw32\\NLS", - "MODir" ); - if( dir && (buf=malloc(strlen(dir)+strlen(filename)+1+3+1)) ) { - strcpy(stpcpy(stpcpy(stpcpy( buf, dir),"\\"), filename),".mo"); - /* Better make sure that we don't mix forward and - backward slashes. It seems that some Windoze - versions don't accept this. */ - for (p=buf; *p; p++) - { - if (*p == '/') - *p = '\\'; - } - domain = load_domain( buf ); - free(buf); - } - free(dir); + instdir = read_w32_registry_string ("HKEY_LOCAL_MACHINE", + regkey, + "Install Directory"); + if (!instdir) + return -1; + langid = read_w32_registry_string (NULL, /* HKCU then HKLM */ + regkey, + "Lang"); + if (!langid) { + free (instdir); + return -1; + } + /* Strip stuff after a dot in case the user tried to enter + * the entire locale synatcs as usual for POSIX. */ + p = strchr (langid, '.'); + if (p) + *p = 0; + + /* Build the key: "/.nls/.mo" We + use a directory below the installation directory with + the domain included in case the software has been + insalled with other software altogether at the same + place. */ + fname = malloc (strlen (instdir) + 1 + strlen (filename) + 5 + + strlen (langid) + 3 + 1); + if (!fname) { + free (instdir); + free (langid); + return -1; + } + strcpy (stpcpy (stpcpy (stpcpy (stpcpy ( stpcpy (fname, + instdir),"\\"), filename), ".nls\\"), langid), ".mo"); + free (instdir); + free (langid); + + /* Better make sure that we don't mix forward and + backward slashes. It seems that some Windoze + versions don't accept this. */ + for (p=fname; *p; p++) { + if (*p == '/') + *p = '\\'; + } + domain = load_domain (fname); + free(fname); } - if( !domain ) + + if (!domain) return -1; } Index: gnupg/util/strgutil.c diff -u gnupg/util/strgutil.c:1.48 gnupg/util/strgutil.c:1.49 --- gnupg/util/strgutil.c:1.48 Mon Jan 17 11:19:57 2005 +++ gnupg/util/strgutil.c Thu Jan 20 12:42:02 2005 @@ -1,6 +1,6 @@ /* strgutil.c - string utilities * Copyright (C) 1994, 1998, 1999, 2000, 2001, - * 2003 Free Software Foundation, Inc. + * 2003, 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -453,10 +453,33 @@ handle_iconv_error (const char *to, const char *from, int use_fallback) { if (errno == EINVAL) - log_info (_("conversion from `%s' to `%s' not available\n"), - from, to); + { + static int shown1, shown2; + int x; + + if (to && !strcmp (to, "utf-8")) + { + x = shown1; + shown1 = 1; + } + else + { + x = shown2; + shown2 = 1; + } + + if (!x) + log_info (_("conversion from `%s' to `%s' not available\n"), + from, to); + } else - log_info (_("iconv_open failed: %s\n"), strerror (errno)); + { + static int shown; + + if (!shown) + log_info (_("iconv_open failed: %s\n"), strerror (errno)); + shown = 1; + } if (use_fallback) { @@ -706,8 +729,12 @@ if ( iconv (cd, (ICONV_CONST char **)&inptr, &inbytes, &outptr, &outbytes) == (size_t)-1) { - log_info (_("conversion from `%s' to `%s' failed: %s\n"), - active_charset_name, "utf-8", strerror (errno)); + static int shown; + + if (!shown) + log_info (_("conversion from `%s' to `%s' failed: %s\n"), + active_charset_name, "utf-8", strerror (errno)); + shown = 1; /* We don't do any conversion at all but use the strings as is. */ strcpy (buffer, string); } @@ -980,8 +1007,12 @@ outbuf = outptr = m_alloc (outbytes); if ( iconv (cd, (ICONV_CONST char **)&inptr, &inbytes, &outptr, &outbytes) == (size_t)-1) { - log_info (_("conversion from `%s' to `%s' failed: %s\n"), - "utf-8", active_charset_name, strerror (errno)); + static int shown; + + if (!shown) + log_info (_("conversion from `%s' to `%s' failed: %s\n"), + "utf-8", active_charset_name, strerror (errno)); + shown = 1; /* Didn't worked out. Temporary disable the use of * iconv and fall back to our old code. */ m_free (buffer); From cvs at cvs.gnupg.org Thu Jan 20 12:34:51 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Thu Jan 20 12:34:55 2005 Subject: gnupg (cipher/idea-stub.c scripts/compile) Message-ID: Date: Thursday, January 20, 2005 @ 12:42:48 Author: wk Path: /cvs/gnupg/gnupg Modified: cipher/idea-stub.c scripts/compile Minor changes --------------------+ cipher/idea-stub.c | 4 - scripts/compile | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+), 2 deletions(-) Index: gnupg/cipher/idea-stub.c diff -u gnupg/cipher/idea-stub.c:1.8 gnupg/cipher/idea-stub.c:1.9 --- gnupg/cipher/idea-stub.c:1.8 Wed Nov 3 21:03:46 2004 +++ gnupg/cipher/idea-stub.c Thu Jan 20 12:42:48 2005 @@ -52,8 +52,8 @@ #endif #ifdef _WIN32 -#define HAVE_DL_DLOPEN -#define USE_DYNAMIC_LINKING +#define HAVE_DL_DLOPEN 1 +#define USE_DYNAMIC_LINKING 1 static int last_error = 0; Index: gnupg/scripts/compile diff -u /dev/null gnupg/scripts/compile:1.2 --- /dev/null Thu Jan 20 12:42:48 2005 +++ gnupg/scripts/compile Thu Jan 20 12:42:48 2005 @@ -0,0 +1,142 @@ +#! /bin/sh +# Wrapper for compilers which do not understand `-c -o'. + +scriptversion=2004-10-12.08 + +# Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc. +# Written by Tom Tromey . +# +# 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. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand `-c -o'. +Remove `-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file `INSTALL'. + +Report bugs to . +EOF + exit 0 + ;; + -v | --v*) + echo "compile $scriptversion" + exit 0 + ;; +esac + +ofile= +cfile= +eat= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as `compile cc -o foo foo.c'. + # So we strip `-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + 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 "$@" +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. +"$@" +ret=$? + +if test -f "$cofile"; then + mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: From cvs at cvs.gnupg.org Thu Jan 20 18:13:43 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Thu Jan 20 18:13:48 2005 Subject: gnupg (10 files) Message-ID: Date: Thursday, January 20, 2005 @ 18:21:40 Author: wk Path: /cvs/gnupg/gnupg Modified: NEWS doc/README.W32 g10/ChangeLog g10/card-util.c g10/getkey.c g10/gpgv.c g10/import.c g10/keydb.h g10/keylist.c g10/main.h * gpgv.c (tty_fprintf): New stub. * card-util.c (card_status): Create asecret key stub on the fly and print more information about a card key. * import.c (pub_to_sec_keyblock, auto_create_card_key_stub): New. * getkey.c (get_seckeyblock_byfprint): New. * keylist.c (print_card_key_info): New. -----------------+ NEWS | 31 +++++-- doc/README.W32 | 14 --- g10/ChangeLog | 8 + g10/card-util.c | 35 +++++++- g10/getkey.c | 32 ++++++- g10/gpgv.c | 1 g10/import.c | 233 +++++++++++++++++++++++++++++++++++++++++++++++++++++- g10/keydb.h | 9 +- g10/keylist.c | 60 +++++++++++++ g10/main.h | 6 + 10 files changed, 396 insertions(+), 33 deletions(-) Index: gnupg/NEWS diff -u gnupg/NEWS:1.228 gnupg/NEWS:1.229 --- gnupg/NEWS:1.228 Thu Jan 20 12:42:03 2005 +++ gnupg/NEWS Thu Jan 20 18:21:40 2005 @@ -1,15 +1,6 @@ Noteworthy changes in version 1.4.1 ------------------------------------------------- - * [W32] The algorithm for the default home directory changed: - First we look at the environment variable GNUPGHOME, if this one - is not set, we check whether the registry entry - HKCU\Software\GNU\GnuPG:HomeDir has been set and if this fails - we use a GnuPG directory below the standard application data - directory (APPDATA) of the current user. Only in the case that - this directory cannot be determined, the old default of c:\gnupg - will be used. The option --homedir still overrides all of them. - * New --rfc2440-text option which controls how text is handled in signatures. This is in response to some problems seen with certain PGP/MIME mail clients and GnuPG version 1.4.0. More @@ -27,6 +18,28 @@ option --with-libcurl. Without this option, the existing HTTP code is used for HTTP, and HTTPS and FTP are not supported. + * When running a --card-status or --card-edit and a public key is + available, missing secret key stubs will be created on the fly. + Details of the key are listed too. + + * [W32] The algorithm for the default home directory changed: + First we look at the environment variable GNUPGHOME, if this one + is not set, we check whether the registry entry + {HKCU,HKLM}\Software\GNU\GnuPG:HomeDir has been set. If this + fails we use a GnuPG directory below the standard application + data directory (APPDATA) of the current user. Only in the case + that this directory cannot be determined, the old default of + c:\gnupg will be used. The option --homedir still overrides all + of them. + + * [W32] The locale selection under Windows changed. You need to + enter the locale in the registry at HKCU\Software\GNU\GnuPG:Lang. + For German you would use "de". If it is not set, GnupG falls + back to HKLM. The languages files "*.mo" are expected in a + directory named "gnupg.nls" below the installation directory; + that directory must be stored in the registry at the same key as + above with the name "Install Directory". + Noteworthy changes in version 1.4.0 (2004-12-16) ------------------------------------------------- Index: gnupg/doc/README.W32 diff -u gnupg/doc/README.W32:1.5 gnupg/doc/README.W32:1.6 --- gnupg/doc/README.W32:1.5 Thu Jan 20 12:42:03 2005 +++ gnupg/doc/README.W32 Thu Jan 20 18:21:40 2005 @@ -30,18 +30,10 @@ Internationalization support: ----------------------------- - 1. Decide where to store the translation files for your language. - Here we assume the directory "c:/gnu/locale/fr" + 1 - 2. Set the directory with the translations into the Registry under - the key: - HKEY_CURRENT_USER -> Control Panel -> Mingw32 -> NLS - (you probably need to create the keys Mingw32 and NLS) using a string - entry with the name "MoDir". - 3. Select which language to use and copy the currect translation file - under the name "gnupg.mo" into the directory set in step 2 - (Example: "copy fr.mo c:\gnu\locale\fr\gnupg.mo") - 4. Done. +Store the locale id (like "de") into the registry under the key +HKEY_CURRENT_USER\Software\GNU\GnuPG with the name "Lang". How to build it from the source: Index: gnupg/g10/ChangeLog diff -u gnupg/g10/ChangeLog:1.682 gnupg/g10/ChangeLog:1.683 --- gnupg/g10/ChangeLog:1.682 Thu Jan 20 12:42:03 2005 +++ gnupg/g10/ChangeLog Thu Jan 20 18:21:40 2005 @@ -1,5 +1,13 @@ 2005-01-20 Werner Koch + * gpgv.c (tty_fprintf): New stub. + + * card-util.c (card_status): Create asecret key stub on the fly + and print more information about a card key. + * import.c (pub_to_sec_keyblock, auto_create_card_key_stub): New. + * getkey.c (get_seckeyblock_byfprint): New. + * keylist.c (print_card_key_info): New. + * g10.c (i18n_init) [W32]: Pass registry key to gettext initialization. * gpgv.c (i18n_init) [W32]: Ditto. Index: gnupg/g10/card-util.c diff -u gnupg/g10/card-util.c:1.24 gnupg/g10/card-util.c:1.25 --- gnupg/g10/card-util.c:1.24 Tue Dec 14 08:49:26 2004 +++ gnupg/g10/card-util.c Thu Jan 20 18:21:40 2005 @@ -1,5 +1,5 @@ /* card-util.c - Utility functions for the OpenPGP card. - * Copyright (C) 2003 Free Software Foundation, Inc. + * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -270,6 +270,7 @@ PKT_public_key *pk = xcalloc (1, sizeof *pk); int rc; unsigned int uval; + const unsigned char *thefpr; if (serialno && serialnobuflen) *serialno = 0; @@ -425,8 +426,34 @@ tty_fprintf (fp, " created ....: %s\n", asctimestamp (info.fpr3time)); tty_fprintf (fp, "General key info..: "); - if (info.fpr1valid && !get_pubkey_byfprint (pk, info.fpr1, 20)) - print_pubkey_info (fp, pk); + + thefpr = (info.fpr1valid? info.fpr1 : info.fpr2valid? info.fpr2 : + info.fpr3valid? info.fpr3 : NULL); + if ( thefpr && !get_pubkey_byfprint (pk, thefpr, 20)) + { + KBNODE keyblock = NULL; + + print_pubkey_info (fp, pk); + + if ( !get_seckeyblock_byfprint (&keyblock, thefpr, 20) ) + print_card_key_info (fp, keyblock); + else if ( !get_keyblock_byfprint (&keyblock, thefpr, 20) ) + { + release_kbnode (keyblock); + keyblock = NULL; + + if (!auto_create_card_key_stub (info.serialno, + info.fpr1valid? info.fpr1:NULL, + info.fpr2valid? info.fpr2:NULL, + info.fpr3valid? info.fpr3:NULL)) + { + if ( !get_seckeyblock_byfprint (&keyblock, thefpr, 20) ) + print_card_key_info (fp, keyblock); + } + } + + release_kbnode (keyblock); + } else tty_fprintf (fp, "[none]\n"); } @@ -1037,7 +1064,7 @@ } -/* This fucntion is used by the key edit menu to generate an arbitrary +/* This function is used by the key edit menu to generate an arbitrary subkey. */ int card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock) Index: gnupg/g10/getkey.c diff -u gnupg/g10/getkey.c:1.123 gnupg/g10/getkey.c:1.124 --- gnupg/g10/getkey.c:1.123 Thu Dec 30 04:26:57 2004 +++ gnupg/g10/getkey.c Thu Jan 20 18:21:40 2005 @@ -1,6 +1,6 @@ /* getkey.c - Get a key from the database * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, - * 2004 Free Software Foundation, Inc. + * 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -1139,13 +1139,41 @@ if (!rc && sk ) sk_from_block ( &ctx, sk, kb ); release_kbnode ( kb ); - get_pubkey_end( &ctx ); + get_seckey_end( &ctx ); } else rc = G10ERR_GENERAL; /* Oops */ return rc; } + +/* Search for a secret key with the given fingerprint and return the + complete keyblock which may have more than only this key. */ +int +get_seckeyblock_byfprint (KBNODE *ret_keyblock, const byte *fprint, + size_t fprint_len ) +{ + int rc; + struct getkey_ctx_s ctx; + + if (fprint_len != 20 && fprint_len == 16) + return G10ERR_GENERAL; /* Oops */ + + memset (&ctx, 0, sizeof ctx); + ctx.not_allocated = 1; + ctx.kr_handle = keydb_new (1); + ctx.nitems = 1; + ctx.items[0].mode = (fprint_len==16 + ? KEYDB_SEARCH_MODE_FPR16 + : KEYDB_SEARCH_MODE_FPR20); + memcpy (ctx.items[0].u.fpr, fprint, fprint_len); + rc = lookup (&ctx, ret_keyblock, 1); + get_seckey_end (&ctx); + + return rc; +} + + /************************************************ ************* Merging stuff ******************** Index: gnupg/g10/gpgv.c diff -u gnupg/g10/gpgv.c:1.26 gnupg/g10/gpgv.c:1.27 --- gnupg/g10/gpgv.c:1.26 Thu Jan 20 12:42:03 2005 +++ gnupg/g10/gpgv.c Thu Jan 20 18:21:40 2005 @@ -380,6 +380,7 @@ /* Stubs to avoid linking to ../util/ttyio.c */ int tty_batchmode( int onoff ) { return 0; } void tty_printf( const char *fmt, ... ) { } +void tty_fprintf (FILE *fp, const char *fmt, ... ) { } void tty_print_string( const byte *p, size_t n ) { } void tty_print_utf8_string( const byte *p, size_t n ) {} void tty_print_utf8_string2( const byte *p, size_t n, size_t max_n ) {} Index: gnupg/g10/import.c diff -u gnupg/g10/import.c:1.119 gnupg/g10/import.c:1.120 --- gnupg/g10/import.c:1.119 Mon Jan 3 16:15:34 2005 +++ gnupg/g10/import.c Thu Jan 20 18:21:40 2005 @@ -1,6 +1,6 @@ -/* import.c +/* import.c - import a key into our key storage. * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, - * 2004 Free Software Foundation, Inc. + * 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -2118,3 +2118,232 @@ return 0; } + + + +/* Walk a public keyblock and produce a secret keyblock out of it. + Instead of inserting the secret key parameters (which we don't + have), we insert a stub. */ +static KBNODE +pub_to_sec_keyblock (KBNODE pub_keyblock) +{ + KBNODE pubnode, secnode; + KBNODE sec_keyblock = NULL; + KBNODE walkctx = NULL; + + while((pubnode = walk_kbnode (pub_keyblock,&walkctx,0))) + { + if (pubnode->pkt->pkttype == PKT_PUBLIC_KEY + || pubnode->pkt->pkttype == PKT_PUBLIC_SUBKEY) + { + /* Make a secret key. We only need to convert enough to + write the keyblock out. */ + PKT_public_key *pk = pubnode->pkt->pkt.public_key; + PACKET *pkt = m_alloc_clear (sizeof *pkt); + PKT_secret_key *sk = m_alloc_clear (sizeof *sk); + int i, n; + + if (pubnode->pkt->pkttype == PKT_PUBLIC_KEY) + pkt->pkttype = PKT_SECRET_KEY; + else + pkt->pkttype = PKT_SECRET_SUBKEY; + + pkt->pkt.secret_key = sk; + + copy_public_parts_to_secret_key ( pk, sk ); + sk->version = pk->version; + sk->timestamp = pk->timestamp; + + n = pubkey_get_npkey (pk->pubkey_algo); + if (!n) + n = 1; /* Unknown number of parameters, however the data + is stored in the first mpi. */ + for (i=0; i < n; i++ ) + sk->skey[i] = mpi_copy (pk->pkey[i]); + + sk->is_protected = 1; + sk->protect.s2k.mode = 1001; + + secnode = new_kbnode (pkt); + } + else + { + secnode = clone_kbnode (pubnode); + } + + if(!sec_keyblock) + sec_keyblock = secnode; + else + add_kbnode (sec_keyblock, secnode); + } + + return sec_keyblock; +} + + +/* Walk over the secret keyring SEC_KEYBLOCK and update any simple + stub keys with the serial number SNNUM of the card if one of the + fingerprints FPR1, FPR2 or FPR3 match. Print a note if the key is + a duplicate (may happen in case of backed uped keys). + + Returns: True if anything changed. +*/ +static int +update_sec_keyblock_with_cardinfo (KBNODE sec_keyblock, + const unsigned char *fpr1, + const unsigned char *fpr2, + const unsigned char *fpr3, + const char *serialnostr) +{ + KBNODE node; + KBNODE walkctx = NULL; + PKT_secret_key *sk; + byte array[MAX_FINGERPRINT_LEN]; + size_t n; + int result = 0; + const char *s; + + while((node = walk_kbnode (sec_keyblock, &walkctx, 0))) + { + if (node->pkt->pkttype != PKT_SECRET_KEY + && node->pkt->pkttype != PKT_SECRET_SUBKEY) + continue; + sk = node->pkt->pkt.secret_key; + + fingerprint_from_sk (sk, array, &n); + if (n != 20) + continue; /* Can't be a card key. */ + if ( !((fpr1 && !memcmp (array, fpr1, 20)) + || (fpr2 && !memcmp (array, fpr2, 20)) + || (fpr3 && !memcmp (array, fpr3, 20))) ) + continue; /* No match. */ + + if (sk->is_protected == 1 && sk->protect.s2k.mode == 1001) + { + /* Standard case: migrate that stub to a key stub. */ + sk->protect.s2k.mode = 1002; + s = serialnostr; + for (sk->protect.ivlen=0; sk->protect.ivlen < 16 && *s && s[1]; + sk->protect.ivlen++, s += 2) + sk->protect.iv[sk->protect.ivlen] = xtoi_2 (s); + result = 1; + } + else if (sk->is_protected == 1 && sk->protect.s2k.mode == 1002) + { + s = serialnostr; + for (sk->protect.ivlen=0; sk->protect.ivlen < 16 && *s && s[1]; + sk->protect.ivlen++, s += 2) + if (sk->protect.iv[sk->protect.ivlen] != xtoi_2 (s)) + { + log_info (_("NOTE: a key's S/N does not " + "match the card's one\n")); + break; + } + } + else + { + if (node->pkt->pkttype != PKT_SECRET_KEY) + log_info (_("NOTE: primary key is online and stored on card\n")); + else + log_info (_("NOTE: secondary key is online and stored on card\n")); + } + } + + return result; +} + + + +/* Check whether a secret key stub exists for the public key PK. If + not create such a stub key and store it into the secring. If it + exists, add appropriate subkey stubs and update the secring. + Return 0 if the key could be created. */ +int +auto_create_card_key_stub ( const char *serialnostr, + const unsigned char *fpr1, + const unsigned char *fpr2, + const unsigned char *fpr3) +{ + KBNODE pub_keyblock; + KBNODE sec_keyblock; + KEYDB_HANDLE hd; + int rc; + + /* We only want to do this for an OpenPGP card. */ + if (!serialnostr || strncmp (serialnostr, "D27600012401", 12) + || strlen (serialnostr) != 32 ) + return G10ERR_GENERAL; + + /* First get the public keyring from any of the provided fingerprints. */ + if ( (fpr1 && !get_keyblock_byfprint (&pub_keyblock, fpr1, 20)) + || (fpr2 && !get_keyblock_byfprint (&pub_keyblock, fpr2, 20)) + || (fpr3 && !get_keyblock_byfprint (&pub_keyblock, fpr3, 20))) + ; + else + return G10ERR_GENERAL; + + hd = keydb_new (1); + + /* Now check whether there is a secret keyring. */ + { + PKT_public_key *pk = pub_keyblock->pkt->pkt.public_key; + byte afp[MAX_FINGERPRINT_LEN]; + size_t an; + + fingerprint_from_pk (pk, afp, &an); + memset (afp, 0, MAX_FINGERPRINT_LEN); + rc = keydb_search_fpr (hd, afp); + } + + if (!rc) + { + rc = keydb_get_keyblock (hd, &sec_keyblock); + if (rc) + { + log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) ); + rc = G10ERR_GENERAL; + } + else + { + merge_keys_and_selfsig (sec_keyblock); + + /* FIXME: We need to add new subkeys first. */ + if (update_sec_keyblock_with_cardinfo (sec_keyblock, + fpr1, fpr2, fpr3, + serialnostr)) + { + rc = keydb_update_keyblock (hd, sec_keyblock ); + if (rc) + log_error (_("error writing keyring `%s': %s\n"), + keydb_get_resource_name (hd), g10_errstr(rc) ); + } + } + } + else /* A secret key does not exists - create it. */ + { + sec_keyblock = pub_to_sec_keyblock (pub_keyblock); + update_sec_keyblock_with_cardinfo (sec_keyblock, + fpr1, fpr2, fpr3, + serialnostr); + + rc = keydb_locate_writable (hd, NULL); + if (rc) + { + log_error (_("no default secret keyring: %s\n"), g10_errstr (rc)); + rc = G10ERR_GENERAL; + } + else + { + rc = keydb_insert_keyblock (hd, sec_keyblock ); + if (rc) + log_error (_("error writing keyring `%s': %s\n"), + keydb_get_resource_name (hd), g10_errstr(rc) ); + } + } + + release_kbnode (sec_keyblock); + release_kbnode (pub_keyblock); + keydb_release (hd); + return rc; +} + Index: gnupg/g10/keydb.h diff -u gnupg/g10/keydb.h:1.87 gnupg/g10/keydb.h:1.88 --- gnupg/g10/keydb.h:1.87 Wed Nov 17 17:04:21 2004 +++ gnupg/g10/keydb.h Thu Jan 20 18:21:40 2005 @@ -224,10 +224,15 @@ int get_seckey_byname( PKT_secret_key *sk, const char *name, int unlock ); int get_seckey_bynames( GETKEY_CTX *rx, PKT_secret_key *sk, STRLIST names, KBNODE *ret_keyblock ); +int get_seckey_next (GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_keyblock); +void get_seckey_end( GETKEY_CTX ctx ); + int get_seckey_byfprint( PKT_secret_key *sk, const byte *fprint, size_t fprint_len); -int get_seckey_next( GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_keyblock ); -void get_seckey_end( GETKEY_CTX ctx ); +int get_seckeyblock_byfprint (KBNODE *ret_keyblock, const byte *fprint, + size_t fprint_len ); + + int enum_secret_keys( void **context, PKT_secret_key *sk, int with_subkeys, int with_spm ); void merge_keys_and_selfsig( KBNODE keyblock ); Index: gnupg/g10/keylist.c diff -u gnupg/g10/keylist.c:1.94 gnupg/g10/keylist.c:1.95 --- gnupg/g10/keylist.c:1.94 Tue Jan 18 10:51:58 2005 +++ gnupg/g10/keylist.c Thu Jan 20 18:21:40 2005 @@ -1,6 +1,6 @@ /* keylist.c * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, - * 2004 Free Software Foundation, Inc. + * 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -167,6 +167,60 @@ m_free (p); } + +/* Print basic information of a secret key including the card serial + number information. */ +void +print_card_key_info (FILE *fp, KBNODE keyblock) +{ + KBNODE node; + int i; + + for (node = keyblock; node; node = node->next ) + { + if (node->pkt->pkttype == PKT_SECRET_KEY + || (node->pkt->pkttype == PKT_SECRET_SUBKEY) ) + { + PKT_secret_key *sk = node->pkt->pkt.secret_key; + + tty_fprintf (fp, "%s%c %4u%c/%s ", + node->pkt->pkttype == PKT_SECRET_KEY? "sec":"ssb", + (sk->protect.s2k.mode==1001)?'#': + (sk->protect.s2k.mode==1002)?'>':' ', + nbits_from_sk (sk), + pubkey_letter (sk->pubkey_algo), + keystr_from_sk(sk)); + tty_fprintf (fp, _("created: %s"), datestr_from_sk (sk)); + tty_fprintf (fp, " "); + tty_fprintf (fp, _("expires: %s"), expirestr_from_sk (sk)); + if (sk->is_protected && sk->protect.s2k.mode == 1002) + { + tty_fprintf (fp, "\n "); + tty_fprintf (fp, _("card-no: ")); + if (sk->protect.ivlen == 16 + && !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6)) + { + /* This is an OpenPGP card. */ + for (i=8; i < 14; i++) + { + if (i == 10) + tty_fprintf (fp, " "); + tty_fprintf (fp, "%02X", sk->protect.iv[i]); + } + } + else + { /* Something is wrong: Print all. */ + for (i=0; i < sk->protect.ivlen; i++) + tty_fprintf (fp, "%02X", sk->protect.iv[i]); + } + } + tty_fprintf (fp, "\n"); + } + } +} + + + /* Flags = 0x01 hashed 0x02 critical */ static void status_one_subpacket(sigsubpkttype_t type,size_t len,int flags,const byte *buf) @@ -1437,9 +1491,9 @@ } else if (mode == 2) { fp = NULL; /* use tty */ - /* Translators: this should fit into 24 bytes to that the fingerprint - * data is properly aligned with the user ID */ if(primary) + /* TRANSLATORS: this should fit into 24 bytes to that the + * fingerprint data is properly aligned with the user ID */ text = _(" Primary key fingerprint:"); else text = _(" Subkey fingerprint:"); Index: gnupg/g10/main.h diff -u gnupg/g10/main.h:1.124 gnupg/g10/main.h:1.125 --- gnupg/g10/main.h:1.124 Thu Jan 20 12:42:03 2005 +++ gnupg/g10/main.h Thu Jan 20 18:21:40 2005 @@ -211,6 +211,11 @@ int collapse_uids( KBNODE *keyblock ); +int auto_create_card_key_stub ( const char *serialnostr, + const unsigned char *fpr1, + const unsigned char *fpr2, + const unsigned char *fpr3); + /*-- export.c --*/ int parse_export_options(char *str,unsigned int *options,int noisy); int export_pubkeys( STRLIST users, unsigned int options ); @@ -247,6 +252,7 @@ void set_attrib_fd(int fd); void print_seckey_info (PKT_secret_key *sk); void print_pubkey_info (FILE *fp, PKT_public_key *pk); +void print_card_key_info (FILE *fp, KBNODE keyblock); /*-- verify.c --*/ void print_file_status( int status, const char *name, int what ); From cvs at cvs.gnupg.org Thu Jan 20 19:17:27 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Thu Jan 20 19:17:30 2005 Subject: gnupg/g10 (ChangeLog cardglue.c) Message-ID: Date: Thursday, January 20, 2005 @ 19:25:25 Author: wk Path: /cvs/gnupg/gnupg/g10 Modified: ChangeLog cardglue.c (open_card): Issue new CARDCTRL(4) status. ------------+ ChangeLog | 4 +++- cardglue.c | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) Index: gnupg/g10/ChangeLog diff -u gnupg/g10/ChangeLog:1.683 gnupg/g10/ChangeLog:1.684 --- gnupg/g10/ChangeLog:1.683 Thu Jan 20 18:21:40 2005 +++ gnupg/g10/ChangeLog Thu Jan 20 19:25:25 2005 @@ -1,8 +1,10 @@ 2005-01-20 Werner Koch + * cardglue.c (open_card): Issue new CARDCTRL(4) status. + * gpgv.c (tty_fprintf): New stub. - * card-util.c (card_status): Create asecret key stub on the fly + * card-util.c (card_status): Create a secret key stub on the fly and print more information about a card key. * import.c (pub_to_sec_keyblock, auto_create_card_key_stub): New. * getkey.c (get_seckeyblock_byfprint): New. Index: gnupg/g10/cardglue.c diff -u gnupg/g10/cardglue.c:1.21 gnupg/g10/cardglue.c:1.22 --- gnupg/g10/cardglue.c:1.21 Fri Dec 10 11:49:14 2004 +++ gnupg/g10/cardglue.c Thu Jan 20 19:25:25 2005 @@ -295,6 +295,7 @@ } if (rc) { + write_status_text (STATUS_CARDCTRL, "4"); log_info ("selecting openpgp failed: %s\n", gpg_strerror (rc)); apdu_close_reader (slot); xfree (app); From cvs at cvs.gnupg.org Sat Jan 22 04:19:16 2005 From: cvs at cvs.gnupg.org (cvs user dshaw) Date: Sat Jan 22 04:19:23 2005 Subject: gnupg/keyserver (ChangeLog gpgkeys_curl.c gpgkeys_ldap.c) Message-ID: Date: Saturday, January 22, 2005 @ 04:27:19 Author: dshaw Path: /cvs/gnupg/gnupg/keyserver Modified: ChangeLog gpgkeys_curl.c gpgkeys_ldap.c * gpgkeys_ldap.c (main): Add "check-cert" option to disable SSL certificate checking (which is on by default). * gpgkeys_curl.c (main): Add "debug" option to match the LDAP helper. Add "check-cert" option to disable SSL certificate checking (which is on by default). ----------------+ ChangeLog | 9 +++++++++ gpgkeys_curl.c | 32 +++++++++++++++++++++++++------- gpgkeys_ldap.c | 42 +++++++++++++++++++++++++++++++++++------- 3 files changed, 69 insertions(+), 14 deletions(-) Index: gnupg/keyserver/ChangeLog diff -u gnupg/keyserver/ChangeLog:1.106 gnupg/keyserver/ChangeLog:1.107 --- gnupg/keyserver/ChangeLog:1.106 Tue Jan 18 15:43:14 2005 +++ gnupg/keyserver/ChangeLog Sat Jan 22 04:27:19 2005 @@ -1,3 +1,12 @@ +2005-01-21 David Shaw + + * gpgkeys_ldap.c (main): Add "check-cert" option to disable SSL + certificate checking (which is on by default). + + * gpgkeys_curl.c (main): Add "debug" option to match the LDAP + helper. Add "check-cert" option to disable SSL certificate + checking (which is on by default). + 2005-01-18 David Shaw * gpgkeys_curl.c: Fix typo. Index: gnupg/keyserver/gpgkeys_curl.c diff -u gnupg/keyserver/gpgkeys_curl.c:1.9 gnupg/keyserver/gpgkeys_curl.c:1.10 --- gnupg/keyserver/gpgkeys_curl.c:1.9 Tue Jan 18 15:43:14 2005 +++ gnupg/keyserver/gpgkeys_curl.c Sat Jan 22 04:27:19 2005 @@ -82,12 +82,6 @@ curl_easy_setopt(curl,CURLOPT_FILE,output); curl_easy_setopt(curl,CURLOPT_ERRORBUFFER,errorbuffer); - if(verbose>1) - { - curl_easy_setopt(curl,CURLOPT_STDERR,console); - curl_easy_setopt(curl,CURLOPT_VERBOSE,1); - } - res=curl_easy_perform(curl); if(res!=0) { @@ -116,7 +110,7 @@ char line[MAX_LINE]; char *thekey=NULL; unsigned int timeout=DEFAULT_KEYSERVER_TIMEOUT; - long follow_redirects=5; + long follow_redirects=5,debug=0,check_cert=1; console=stderr; @@ -287,6 +281,22 @@ else if(start[16]=='\0') follow_redirects=-1; } + else if(strncasecmp(start,"debug",5)==0) + { + if(no) + debug=0; + else if(start[5]=='=') + debug=atoi(&start[6]); + else if(start[5]=='\0') + debug=1; + } + else if(strcasecmp(start,"check-cert")==0) + { + if(no) + check_cert=0; + else + check_cert=1; + } continue; } @@ -337,6 +347,14 @@ curl_easy_setopt(curl,CURLOPT_MAXREDIRS,follow_redirects); } + if(debug) + { + curl_easy_setopt(curl,CURLOPT_STDERR,console); + curl_easy_setopt(curl,CURLOPT_VERBOSE,1); + } + + curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,check_cert); + if(proxy[0]) curl_easy_setopt(curl,CURLOPT_PROXY,proxy); Index: gnupg/keyserver/gpgkeys_ldap.c diff -u gnupg/keyserver/gpgkeys_ldap.c:1.47 gnupg/keyserver/gpgkeys_ldap.c:1.48 --- gnupg/keyserver/gpgkeys_ldap.c:1.47 Fri Jan 14 00:37:26 2005 +++ gnupg/keyserver/gpgkeys_ldap.c Sat Jan 22 04:27:19 2005 @@ -1534,7 +1534,7 @@ { int debug=0,port=0,arg,err,action=-1,ret=KEYSERVER_INTERNAL_ERROR; char line[MAX_LINE]; - int version,failed=0,use_ssl=0,use_tls=0,bound=0; + int version,failed=0,use_ssl=0,use_tls=0,bound=0,check_cert=1; struct keylist *keylist=NULL,*keyptr=NULL; unsigned int timeout=DEFAULT_KEYSERVER_TIMEOUT; @@ -1719,6 +1719,13 @@ else if(start[3]=='\0') use_tls=1; } + else if(strcasecmp(start,"check-cert")==0) + { + if(no) + check_cert=0; + else + check_cert=1; + } else if(strncasecmp(start,"debug",5)==0) { if(no) @@ -1868,8 +1875,9 @@ if(use_ssl) { -#if defined(LDAP_OPT_X_TLS_HARD) && defined(HAVE_LDAP_SET_OPTION) +#if defined(LDAP_OPT_X_TLS) && defined(HAVE_LDAP_SET_OPTION) int ssl=LDAP_OPT_X_TLS_HARD; + err=ldap_set_option(ldap,LDAP_OPT_X_TLS,&ssl); if(err!=LDAP_SUCCESS) { @@ -1878,6 +1886,19 @@ fail_all(keylist,action,ldap_err_to_gpg_err(err)); goto fail; } + + if(!check_cert) + ssl=LDAP_OPT_X_TLS_NEVER; + + err=ldap_set_option(NULL,LDAP_OPT_X_TLS_REQUIRE_CERT,&ssl); + if(err!=LDAP_SUCCESS) + { + fprintf(console, + "gpgkeys: unable to set certificate validation: %s\n", + ldap_err2string(err)); + fail_all(keylist,action,ldap_err_to_gpg_err(err)); + goto fail; + } #else fprintf(console,"gpgkeys: unable to make SSL connection: %s\n", "not built with LDAPS support"); @@ -1915,15 +1936,22 @@ #if defined(HAVE_LDAP_START_TLS_S) && defined(HAVE_LDAP_SET_OPTION) int ver=LDAP_VERSION3; - err=LDAP_SUCCESS; - err=ldap_set_option(ldap,LDAP_OPT_PROTOCOL_VERSION,&ver); if(err==LDAP_SUCCESS) - err=ldap_start_tls_s(ldap,NULL,NULL); + { + if(check_cert) + ver=LDAP_OPT_X_TLS_HARD; + else + ver=LDAP_OPT_X_TLS_NEVER; + + err=ldap_set_option(ldap,LDAP_OPT_X_TLS_REQUIRE_CERT,&ver); + if(err==LDAP_SUCCESS) + err=ldap_start_tls_s(ldap,NULL,NULL); + } if(err!=LDAP_SUCCESS) { - if(use_tls==2 || verbose>2) + if(use_tls>=2 || verbose>2) fprintf(console,"gpgkeys: unable to start TLS: %s\n", ldap_err2string(err)); /* Are we forcing it? */ @@ -1952,7 +1980,7 @@ /* The LDAP keyserver doesn't require this, but it might be useful if someone stores keys on a V2 LDAP server somewhere. (V3 doesn't require a bind). Leave this out for now since it is not - clear if anyone server we're likely to use really cares, plus + clear if anyone's server we're likely to use really cares, plus there are some servers that don't allow it. */ err=ldap_simple_bind_s(ldap,NULL,NULL); From cvs at cvs.gnupg.org Sat Jan 22 04:25:05 2005 From: cvs at cvs.gnupg.org (cvs user dshaw) Date: Sat Jan 22 04:25:12 2005 Subject: gnupg/g10 (ChangeLog keyserver.c) Message-ID: Date: Saturday, January 22, 2005 @ 04:33:12 Author: dshaw Path: /cvs/gnupg/gnupg/g10 Modified: ChangeLog keyserver.c * keyserver.c (free_keyserver_spec): Fix small leak. (keyserver_typemap): Map https if we are supporting it. -------------+ ChangeLog | 5 +++++ keyserver.c | 6 ++++++ 2 files changed, 11 insertions(+) Index: gnupg/g10/ChangeLog diff -u gnupg/g10/ChangeLog:1.684 gnupg/g10/ChangeLog:1.685 --- gnupg/g10/ChangeLog:1.684 Thu Jan 20 19:25:25 2005 +++ gnupg/g10/ChangeLog Sat Jan 22 04:33:12 2005 @@ -1,3 +1,8 @@ +2005-01-21 David Shaw + + * keyserver.c (free_keyserver_spec): Fix small leak. + (keyserver_typemap): Map https if we are supporting it. + 2005-01-20 Werner Koch * cardglue.c (open_card): Issue new CARDCTRL(4) status. Index: gnupg/g10/keyserver.c diff -u gnupg/g10/keyserver.c:1.77 gnupg/g10/keyserver.c:1.78 --- gnupg/g10/keyserver.c:1.77 Thu Jan 6 17:23:47 2005 +++ gnupg/g10/keyserver.c Sat Jan 22 04:33:12 2005 @@ -139,6 +139,8 @@ free_keyserver_spec(struct keyserver_spec *keyserver) { m_free(keyserver->uri); + m_free(keyserver->scheme); + m_free(keyserver->auth); m_free(keyserver->host); m_free(keyserver->port); m_free(keyserver->path); @@ -792,6 +794,10 @@ else if(strcmp(type,"http")==0) return "curl"; #endif +#ifdef HTTPS_VIA_LIBCURL + else if(strcmp(type,"https")==0) + return "curl"; +#endif else return type; } From cvs at cvs.gnupg.org Sun Jan 23 00:02:14 2005 From: cvs at cvs.gnupg.org (cvs user dshaw) Date: Sun Jan 23 01:40:38 2005 Subject: gnupg/m4 (ChangeLog libcurl.m4) Message-ID: Date: Sunday, January 23, 2005 @ 00:10:23 Author: dshaw Path: /cvs/gnupg/gnupg/m4 Modified: ChangeLog libcurl.m4 * libcurl.m4: Note that FTPS existed, but wasn't fully standards-compliant until version 7.11.0. ------------+ ChangeLog | 5 +++++ libcurl.m4 | 47 +++++++++++++++++++++++++++++++++-------------- 2 files changed, 38 insertions(+), 14 deletions(-) Index: gnupg/m4/ChangeLog diff -u gnupg/m4/ChangeLog:1.11 gnupg/m4/ChangeLog:1.12 --- gnupg/m4/ChangeLog:1.11 Tue Jan 18 04:54:46 2005 +++ gnupg/m4/ChangeLog Sun Jan 23 00:10:23 2005 @@ -1,3 +1,8 @@ +2005-01-22 David Shaw + + * libcurl.m4: Note that FTPS existed, but wasn't fully + standards-compliant until version 7.11.0. + 2005-01-17 David Shaw * libcurl.m4: Use LIBCURL_CPPFLAGS and not LIBCURL_INCLUDES to Index: gnupg/m4/libcurl.m4 diff -u gnupg/m4/libcurl.m4:1.6 gnupg/m4/libcurl.m4:1.7 --- gnupg/m4/libcurl.m4:1.6 Tue Jan 18 04:54:46 2005 +++ gnupg/m4/libcurl.m4 Sun Jan 23 00:10:23 2005 @@ -1,16 +1,17 @@ # LIBCURL_CHECK_CONFIG ([DEFAULT-ACTION], [MINIMUM-VERSION], # [ACTION-IF-YES], [ACTION-IF-NO]) # ---------------------------------------------------------- -# David Shaw Dec-24-2004 +# David Shaw Jan-23-2005 # -# Checks for libcurl. DEFAULT-ACTION is yes or no whether to default -# to --with-libcurl or --without-libcurl. If not supplied, -# DEFAULT-ACTION is yes. MINIMUM-VERSION is the minimum version of -# libcurl to accept. If not supplied, any version is accepted. -# ACTION-IF-YES is a list of shell commands to run if libcurl was -# successfully found and passed the various tests. ACTION-IF-NO is a -# list of shell commands that are run otherwise. Note that using -# --without-libcurl does run ACTION-IF-NO. +# Checks for libcurl. DEFAULT-ACTION is the string yes or no to +# specify whether to default to --with-libcurl or --without-libcurl. +# If not supplied, DEFAULT-ACTION is yes. MINIMUM-VERSION is the +# minimum version of libcurl to accept. Pass the version as a regular +# version number like 7.10.1. If not supplied, any version is +# accepted. ACTION-IF-YES is a list of shell commands to run if +# libcurl was successfully found and passed the various tests. +# ACTION-IF-NO is a list of shell commands that are run otherwise. +# Note that using --without-libcurl does run ACTION-IF-NO. # # This macro defines HAVE_LIBCURL if a working libcurl setup is found, # and sets @LIBCURL@ and @LIBCURL_CPPFLAGS@ to the necessary values. @@ -22,7 +23,19 @@ # variables $libcurl_feature_xxx and $libcurl_protocol_yyy are also # defined to 'yes' for those features and protocols that were found. # Note that xxx and yyy keep the same capitalization as in the -# curl-config list (i.e. it's "HTTP" and not "http"). +# curl-config list (e.g. it's "HTTP" and not "http"). +# +# For the sake of sanity, this macro assumes that any libcurl that is +# found is after version 7.7.2, the first version that included the +# curl-config script. Note that it is very important for people +# packaging binary versions of libcurl to include this script! +# Without curl-config, we can only make educated guesses as to what +# protocols are available. Specifically, we assume that all of HTTP, +# FTP, GOPHER, FILE, TELNET, LDAP, and DICT exist, and (if SSL exists) +# HTTPS is present. All of these protocols existed when libcurl was +# first created in version 7, so this is a safe assumption. If the +# version is 7.11.0 or later, FTPS is assumed to be present as well. +# FTPS existed before then, but was not yet fully standards compliant. AC_DEFUN([LIBCURL_CHECK_CONFIG], [ @@ -111,7 +124,6 @@ fi unset _libcurl_wanted - unset _libcurl_version fi if test $_libcurl_try_link = yes ; then @@ -159,13 +171,19 @@ done if test "x$_libcurl_protocols" = "x" ; then - # We don't have --protocols, so just assume that all protocols - # are available + # We don't have --protocols, so just assume that all + # protocols are available _libcurl_protocols="HTTP FTP GOPHER FILE TELNET LDAP DICT" if test x$libcurl_feature_SSL = xyes ; then - _libcurl_protocols="$_libcurl_protocols HTTPS FTPS" + _libcurl_protocols="$_libcurl_protocols HTTPS" + + # FTPS wasn't standards-compliant until version + # 7.11.0 + if test $_libcurl_version -ge 461568; then + _libcurl_protocols="$_libcurl_protocols FTPS" + fi fi fi @@ -183,6 +201,7 @@ unset _libcurl_features unset _libcurl_protocol unset _libcurl_protocols + unset _libcurl_version fi if test x$_libcurl_with = xno || test x$libcurl_cv_lib_curl_usable != xyes ; then From cvs at cvs.gnupg.org Sun Jan 23 02:11:20 2005 From: cvs at cvs.gnupg.org (cvs user dshaw) Date: Sun Jan 23 06:57:49 2005 Subject: gnupg (ChangeLog NEWS README configure.ac) Message-ID: Date: Sunday, January 23, 2005 @ 02:19:32 Author: dshaw Path: /cvs/gnupg/gnupg Modified: ChangeLog NEWS README configure.ac * configure.ac: Define FTPS flag if we're using curl, and FTPS is available. * README: Fix some typos (noted by Norihiko Murase), update to 1.4.1, and tweak some descriptions. * NEWS: Note FTPS. --------------+ ChangeLog | 10 ++++++++++ NEWS | 19 ++++++++++--------- README | 41 +++++++++++++++++++++-------------------- configure.ac | 7 +++++-- 4 files changed, 46 insertions(+), 31 deletions(-) Index: gnupg/ChangeLog diff -u gnupg/ChangeLog:1.236 gnupg/ChangeLog:1.237 --- gnupg/ChangeLog:1.236 Thu Jan 20 12:42:03 2005 +++ gnupg/ChangeLog Sun Jan 23 02:19:32 2005 @@ -1,3 +1,13 @@ +2005-01-22 David Shaw + + * configure.ac: Define FTPS flag if we're using curl, and FTPS is + available. + + * README: Fix some typos (noted by Norihiko Murase), update to + 1.4.1, and tweak some descriptions. + + * NEWS: Note FTPS. + 2005-01-18 Werner Koch * configure.ac (HAVE_W32_SYSTEM): Define it. Index: gnupg/NEWS diff -u gnupg/NEWS:1.229 gnupg/NEWS:1.230 --- gnupg/NEWS:1.229 Thu Jan 20 18:21:40 2005 +++ gnupg/NEWS Sun Jan 23 02:19:32 2005 @@ -1,5 +1,5 @@ Noteworthy changes in version 1.4.1 -------------------------------------------------- +------------------------------------------------ * New --rfc2440-text option which controls how text is handled in signatures. This is in response to some problems seen with @@ -12,11 +12,12 @@ default, and cause GnuPG to not import or export key signatures that are not usable (e.g. expired signatures). - * New experimental HTTP, HTTPS, and FTP keyserver helper that uses - the cURL library (http://curl.haxx.se) to retrieve keys. This - is disabled by default, but may be enabled with the configure - option --with-libcurl. Without this option, the existing HTTP - code is used for HTTP, and HTTPS and FTP are not supported. + * New experimental HTTP, HTTPS, FTP, and FTPS keyserver helper + that uses the cURL library to retrieve + keys. This is disabled by default, but may be enabled with the + configure option --with-libcurl. Without this option, the + existing HTTP code is used for HTTP, and HTTPS, FTP, and FTPS + are not supported. * When running a --card-status or --card-edit and a public key is available, missing secret key stubs will be created on the fly. @@ -42,7 +43,7 @@ Noteworthy changes in version 1.4.0 (2004-12-16) -------------------------------------------------- +------------------------------------------------ * See the file doc/highlights-1.4.txt for an overview of all changes in respect to the 1.2 series. @@ -1729,8 +1730,8 @@ is generated on a system without a good random number generator. -Copyright 1998, 1999, 2000, 2001, 2002, 2003, - 2004 Free Software Foundation, Inc. +Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, + 2005 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 Index: gnupg/README diff -u gnupg/README:1.92 gnupg/README:1.93 --- gnupg/README:1.92 Thu Jan 20 12:42:03 2005 +++ gnupg/README Sun Jan 23 02:19:32 2005 @@ -1,10 +1,10 @@ GnuPG - The GNU Privacy Guard ------------------------------- - Version 1.4.0 + Version 1.4.1 - Copyright 1998, 1999, 2000, 2001, 2002, 2003, - 2004 Free Software Foundation, Inc. + Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, + 2005 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 @@ -488,9 +488,9 @@ GnuPG home directory which is "~/.gnupg" by default. --without-readline - Do not include support for the readline libary + Do not include support for the readline library even if it is available. The default is to check - whether the readline libarry is a availbale and + whether the readline library is a available and use it to allow fancy command line editing. --with-included-zlib @@ -561,7 +561,7 @@ --disable-twofish --disable-sha256 --disable-sha512 - Removes support for the selected symmetric + Removes support for the selected symmetric or hash algorithm. This can give a smaller gpg binary for places where space is tight. @@ -574,21 +574,22 @@ The public key preference list can be updated to match the list of available algorithms by using "gpg --edit-key (thekey)", and running the - "updpref" command. + "setpref" command. --enable-minimal - Build the smallest gpg possible (disables all - optional algorithms, disables keyserver access, - and disables photo IDs). Specifically, this means - --disable-rsa --disable-idea, --disable-cast5, - --disable-blowfish, --disable-aes, - --disable-twofish, --disable-sha256, - --disable-sha512, --without-bzip2, and - --disable-exec. Configure command lines are read - from left to right, so if you want to have an - "almost minimal" configuration, you can do (for - example) "--enable-minimal --enable-rsa" to have - RSA added to the minimal build. + Build the smallest gpg binary possible (disables + all optional algorithms, disables keyserver + access, and disables photo IDs). Specifically, + this means --disable-rsa --disable-idea, + --disable-cast5, --disable-blowfish, + --disable-aes, --disable-twofish, + --disable-sha256, --disable-sha512, + --without-bzip2, and --disable-exec. Configure + command lines are read from left to right, so if + you want to have an "almost minimal" + configuration, you can do (for example) + "--enable-minimal --enable-rsa" to have RSA added + to the minimal build. --enable-key-cache=SIZE Set the internal key and UID cache size. This has @@ -614,7 +615,7 @@ give different output than with the limited old support. This option allows to explicity disable the use of iconv. Note, that iconv is also - disabled if getext has been disabled. + disabled if gettext has been disabled. --enable-backsigs Enables "backsigs" support. This is a currently Index: gnupg/configure.ac diff -u gnupg/configure.ac:1.128 gnupg/configure.ac:1.129 --- gnupg/configure.ac:1.128 Thu Jan 20 12:42:03 2005 +++ gnupg/configure.ac Sun Jan 23 02:19:32 2005 @@ -19,7 +19,7 @@ dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA dnl dnl (Process this file with autoconf to produce a configure script.) -dnlAC_REVISION($Revision: 1.128 $)dnl +dnlAC_REVISION($Revision: 1.129 $)dnl AC_PREREQ(2.59) min_automake_version="1.9.3" @@ -669,8 +669,11 @@ # Are we doing FTP? We only do FTP if we have libcurl. if test x"$try_ftp" = xyes && test x$libcurl_protocol_FTP = xyes ; then - AC_DEFINE(FTP_VIA_LIBCURL,1,[Define if FTP is handled via libcurl]) AC_SUBST(GPGKEYS_CURL,"gpgkeys_curl$EXEEXT") + AC_DEFINE(FTP_VIA_LIBCURL,1,[Define if FTP is handled via libcurl]) + if test x$libcurl_protocol_FTPS = xyes ; then + AC_DEFINE(FTPS_VIA_LIBCURL,1,[Define if FTPS is handled via libcurl]) + fi fi dnl This isn't necessarily sendmail itself, but anything that gives a From cvs at cvs.gnupg.org Mon Jan 24 14:54:27 2005 From: cvs at cvs.gnupg.org (cvs user stefan) Date: Mon Jan 24 21:40:42 2005 Subject: gnupgjava/src/junit/com/freiheit (- New directory) Message-ID: Date: Monday, January 24, 2005 @ 14:54:27 Author: stefan Path: /cvs/gnupg/gnupgjava/src/junit/com/freiheit Directory /cvs/gnupg/gnupgjava/src/junit/com/freiheit added to the repository + 0 files changed From cvs at cvs.gnupg.org Mon Jan 24 14:54:38 2005 From: cvs at cvs.gnupg.org (cvs user stefan) Date: Mon Jan 24 21:42:43 2005 Subject: gnupgjava/src/junit/com/freiheit/gnupg (- New directory) Message-ID: Date: Monday, January 24, 2005 @ 14:54:37 Author: stefan Path: /cvs/gnupg/gnupgjava/src/junit/com/freiheit/gnupg Directory /cvs/gnupg/gnupgjava/src/junit/com/freiheit/gnupg added to the repository + 0 files changed From cvs at cvs.gnupg.org Mon Jan 24 14:37:32 2005 From: cvs at cvs.gnupg.org (cvs user stefan) Date: Mon Jan 24 21:48:57 2005 Subject: gnupgjava/etc (- New directory) Message-ID: Date: Monday, January 24, 2005 @ 14:37:32 Author: stefan Path: /cvs/gnupg/gnupgjava/etc Directory /cvs/gnupg/gnupgjava/etc added to the repository + 0 files changed From cvs at cvs.gnupg.org Mon Jan 24 14:51:30 2005 From: cvs at cvs.gnupg.org (cvs user stefan) Date: Mon Jan 24 22:04:07 2005 Subject: gnupgjava/src/java/com (- New directory) Message-ID: Date: Monday, January 24, 2005 @ 14:51:30 Author: stefan Path: /cvs/gnupg/gnupgjava/src/java/com Directory /cvs/gnupg/gnupgjava/src/java/com added to the repository + 0 files changed From cvs at cvs.gnupg.org Mon Jan 24 14:56:48 2005 From: cvs at cvs.gnupg.org (cvs user stefan) Date: Mon Jan 24 22:04:15 2005 Subject: gnupgjava (COPYING INSTALL build.properties build.xml) Message-ID: Date: Monday, January 24, 2005 @ 14:56:48 Author: stefan Path: /cvs/gnupg/gnupgjava Added: COPYING INSTALL build.properties build.xml First alpha release. Happy Birthday, GnuPG for Java ------------------+ COPYING | 504 +++++++++++++++++++++++++++++++++++++++++++++++++++++ INSTALL | 19 + build.properties | 27 ++ build.xml | 105 +++++++++++ 4 files changed, 655 insertions(+) From cvs at cvs.gnupg.org Mon Jan 24 14:51:41 2005 From: cvs at cvs.gnupg.org (cvs user stefan) Date: Mon Jan 24 22:12:06 2005 Subject: gnupgjava/src/java/com/freiheit (- New directory) Message-ID: Date: Monday, January 24, 2005 @ 14:51:41 Author: stefan Path: /cvs/gnupg/gnupgjava/src/java/com/freiheit Directory /cvs/gnupg/gnupgjava/src/java/com/freiheit added to the repository + 0 files changed From cvs at cvs.gnupg.org Mon Jan 24 14:57:01 2005 From: cvs at cvs.gnupg.org (cvs user stefan) Date: Mon Jan 24 22:13:50 2005 Subject: gnupgjava/src/junit/com/freiheit/gnupg (1 file) Message-ID: Date: Monday, January 24, 2005 @ 14:57:01 Author: stefan Path: /cvs/gnupg/gnupgjava/src/junit/com/freiheit/gnupg Added: GnuPGTestSuite.java First alpha release. Happy Birthday, GnuPG for Java ---------------------+ GnuPGTestSuite.java | 199 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 199 insertions(+) From cvs at cvs.gnupg.org Mon Jan 24 14:51:51 2005 From: cvs at cvs.gnupg.org (cvs user stefan) Date: Mon Jan 24 22:13:58 2005 Subject: gnupgjava/src/java/com/freiheit/gnupg (- New directory) Message-ID: Date: Monday, January 24, 2005 @ 14:51:51 Author: stefan Path: /cvs/gnupg/gnupgjava/src/java/com/freiheit/gnupg Directory /cvs/gnupg/gnupgjava/src/java/com/freiheit/gnupg added to the repository + 0 files changed From cvs at cvs.gnupg.org Mon Jan 24 14:40:56 2005 From: cvs at cvs.gnupg.org (cvs user stefan) Date: Mon Jan 24 22:14:12 2005 Subject: gnupgjava/lib (- New directory) Message-ID: Date: Monday, January 24, 2005 @ 14:40:56 Author: stefan Path: /cvs/gnupg/gnupgjava/lib Directory /cvs/gnupg/gnupgjava/lib added to the repository + 0 files changed From cvs at cvs.gnupg.org Mon Jan 24 14:56:53 2005 From: cvs at cvs.gnupg.org (cvs user stefan) Date: Mon Jan 24 22:18:50 2005 Subject: gnupgjava/examples (KeySearch.java) Message-ID: Date: Monday, January 24, 2005 @ 14:56:53 Author: stefan Path: /cvs/gnupg/gnupgjava/examples Added: KeySearch.java First alpha release. Happy Birthday, GnuPG for Java ----------------+ KeySearch.java | 39 +++++++++++++++++++++++++++++++++++++++ 1 files changed, 39 insertions(+) From cvs at cvs.gnupg.org Mon Jan 24 19:15:37 2005 From: cvs at cvs.gnupg.org (cvs user dshaw) Date: Mon Jan 24 22:18:58 2005 Subject: gnupg/keyserver (ChangeLog gpgkeys_curl.c gpgkeys_ldap.c) Message-ID: Date: Monday, January 24, 2005 @ 19:23:56 Author: dshaw Path: /cvs/gnupg/gnupg/keyserver Modified: ChangeLog gpgkeys_curl.c gpgkeys_ldap.c * gpgkeys_ldap.c (print_nocr): New. (get_key): Call it here to canonicalize line endings. * gpgkeys_curl.c (writer): Discard everything outside the BEGIN and END lines when retrieving keys. Canonicalize line endings. (main): Accept FTPS. ----------------+ ChangeLog | 15 +++++++++++--- gpgkeys_curl.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++----- gpgkeys_ldap.c | 14 ++++++++++++- 3 files changed, 77 insertions(+), 9 deletions(-) Index: gnupg/keyserver/ChangeLog diff -u gnupg/keyserver/ChangeLog:1.107 gnupg/keyserver/ChangeLog:1.108 --- gnupg/keyserver/ChangeLog:1.107 Sat Jan 22 04:27:19 2005 +++ gnupg/keyserver/ChangeLog Mon Jan 24 19:23:56 2005 @@ -1,4 +1,13 @@ -2005-01-21 David Shaw +2005-01-24 David Shaw + + * gpgkeys_ldap.c (print_nocr): New. + (get_key): Call it here to canonicalize line endings. + + * gpgkeys_curl.c (writer): Discard everything outside the BEGIN + and END lines when retrieving keys. Canonicalize line endings. + (main): Accept FTPS. + +2005-01-21 David Shaw * gpgkeys_ldap.c (main): Add "check-cert" option to disable SSL certificate checking (which is on by default). @@ -7,7 +16,7 @@ helper. Add "check-cert" option to disable SSL certificate checking (which is on by default). -2005-01-18 David Shaw +2005-01-18 David Shaw * gpgkeys_curl.c: Fix typo. @@ -19,7 +28,7 @@ * gpgkeys_http.c: Ditto. * ksutil.h: s/MAX_PATH/URLMAX_PATH/. -2005-01-17 David Shaw +2005-01-17 David Shaw * gpgkeys_curl.c (main): Only allow specified protocols to use the curl handler. Index: gnupg/keyserver/gpgkeys_curl.c diff -u gnupg/keyserver/gpgkeys_curl.c:1.10 gnupg/keyserver/gpgkeys_curl.c:1.11 --- gnupg/keyserver/gpgkeys_curl.c:1.10 Sat Jan 22 04:27:19 2005 +++ gnupg/keyserver/gpgkeys_curl.c Mon Jan 24 19:23:56 2005 @@ -55,12 +55,55 @@ } } -/* We wrap fwrite so to avoid DLL problems on Win32 (see curl faq for - more). */ static size_t writer(const void *ptr,size_t size,size_t nmemb,void *stream) { - return fwrite(ptr,size,nmemb,stream); + const char *buf=ptr; + size_t i; + static int markeridx=0,begun=0,done=0; + static const char *marker=BEGIN; + + /* scan the incoming data for our marker */ + for(i=0;!done && i<(size*nmemb);i++) + { + if(buf[i]==marker[markeridx]) + { + markeridx++; + if(marker[markeridx]=='\0') + { + if(begun) + done=1; + else + { + /* We've found the BEGIN marker, so now we're looking + for the END marker. */ + begun=1; + marker=END; + markeridx=0; + fprintf(output,BEGIN); + continue; + } + } + } + else + markeridx=0; + + if(begun) + { + /* Canonicalize CRLF to just LF by stripping CRs. This + actually makes sense, since on Unix-like machines LF is + correct, and on win32-like machines, our output buffer is + opened in textmode and will re-canonicalize line endings + back to CRLF. Since we only need to handle armored keys, + we don't have to worry about odd cases like CRCRCR and + the like. */ + + if(buf[i]!='\r') + fputc(buf[i],output); + } + } + + return size*nmemb; } static int @@ -87,10 +130,10 @@ { fprintf(console,"gpgkeys: %s fetch error %d: %s\n",scheme, res,errorbuffer); - fprintf(output,"KEY 0x%s FAILED %d\n",getkey,curl_err_to_gpg_err(res)); + fprintf(output,"\nKEY 0x%s FAILED %d\n",getkey,curl_err_to_gpg_err(res)); } else - fprintf(output,"KEY 0x%s END\n",getkey); + fprintf(output,"\nKEY 0x%s END\n",getkey); return KEYSERVER_OK; } @@ -319,6 +362,10 @@ else if(strcasecmp(scheme,"ftp")==0) ; #endif /* FTP_VIA_LIBCURL */ +#ifdef FTPS_VIA_LIBCURL + else if(strcasecmp(scheme,"ftps")==0) + ; +#endif /* FTPS_VIA_LIBCURL */ else { fprintf(console,"gpgkeys: scheme `%s' not supported\n",scheme); Index: gnupg/keyserver/gpgkeys_ldap.c diff -u gnupg/keyserver/gpgkeys_ldap.c:1.48 gnupg/keyserver/gpgkeys_ldap.c:1.49 --- gnupg/keyserver/gpgkeys_ldap.c:1.48 Sat Jan 22 04:27:19 2005 +++ gnupg/keyserver/gpgkeys_ldap.c Mon Jan 24 19:23:56 2005 @@ -952,6 +952,17 @@ fprintf(output,"INFO %s END\n",certid); } +static void +print_nocr(FILE *stream,const char *str) +{ + while(*str) + { + if(*str!='\r') + fputc(*str,stream); + str++; + } +} + /* Note that key-not-found is not a fatal error */ static int get_key(char *getkey) @@ -1091,7 +1102,8 @@ } else { - fprintf(output,"%sKEY 0x%s END\n",vals[0],getkey); + print_nocr(output,vals[0]); + fprintf(output,"\nKEY 0x%s END\n",getkey); ldap_value_free(vals); } From cvs at cvs.gnupg.org Mon Jan 24 14:50:32 2005 From: cvs at cvs.gnupg.org (cvs user stefan) Date: Mon Jan 24 22:19:24 2005 Subject: gnupgjava/src/c (- New directory) Message-ID: Date: Monday, January 24, 2005 @ 14:50:32 Author: stefan Path: /cvs/gnupg/gnupgjava/src/c Directory /cvs/gnupg/gnupgjava/src/c added to the repository + 0 files changed From cvs at cvs.gnupg.org Mon Jan 24 14:56:50 2005 From: cvs at cvs.gnupg.org (cvs user stefan) Date: Mon Jan 24 22:27:49 2005 Subject: gnupgjava/etc (6 files) Message-ID: Date: Monday, January 24, 2005 @ 14:56:50 Author: stefan Path: /cvs/gnupg/gnupgjava/etc Added: SOURCEFOOTER SOURCEHEADER fdc.javadoc.png overview.html stylesheet.css whitepaper.gif First alpha release. Happy Birthday, GnuPG for Java ----------------+ SOURCEFOOTER | 7 +++++++ SOURCEHEADER | 13 +++++++++++++ overview.html | 43 +++++++++++++++++++++++++++++++++++++++++++ stylesheet.css | 41 +++++++++++++++++++++++++++++++++++++++++ whitepaper.gif | 0 5 files changed, 104 insertions(+) From cvs at cvs.gnupg.org Mon Jan 24 14:39:58 2005 From: cvs at cvs.gnupg.org (cvs user stefan) Date: Mon Jan 24 22:28:09 2005 Subject: gnupgjava/examples (- New directory) Message-ID: Date: Monday, January 24, 2005 @ 14:39:57 Author: stefan Path: /cvs/gnupg/gnupgjava/examples Directory /cvs/gnupg/gnupgjava/examples added to the repository + 0 files changed From cvs at cvs.gnupg.org Mon Jan 24 14:56:54 2005 From: cvs at cvs.gnupg.org (cvs user stefan) Date: Mon Jan 24 22:29:32 2005 Subject: gnupgjava/lib (junit-3.8.1.jar) Message-ID: Date: Monday, January 24, 2005 @ 14:56:54 Author: stefan Path: /cvs/gnupg/gnupgjava/lib Added: junit-3.8.1.jar First alpha release. Happy Birthday, GnuPG for Java -----------------+ junit-3.8.1.jar | 0 1 files changed From cvs at cvs.gnupg.org Mon Jan 24 14:54:05 2005 From: cvs at cvs.gnupg.org (cvs user stefan) Date: Mon Jan 24 22:41:21 2005 Subject: gnupgjava/src/junit (- New directory) Message-ID: Date: Monday, January 24, 2005 @ 14:54:05 Author: stefan Path: /cvs/gnupg/gnupgjava/src/junit Directory /cvs/gnupg/gnupgjava/src/junit added to the repository + 0 files changed From cvs at cvs.gnupg.org Mon Jan 24 14:56:56 2005 From: cvs at cvs.gnupg.org (cvs user stefan) Date: Mon Jan 24 22:42:00 2005 Subject: gnupgjava/src/c (10 files) Message-ID: Date: Monday, January 24, 2005 @ 14:56:56 Author: stefan Path: /cvs/gnupg/gnupgjava/src/c Added: GNUmakefile GnuPGContext.c GnuPGData.c GnuPGKey.c GnuPGSignature.c com_freiheit_gnupg_GnuPGContext.h com_freiheit_gnupg_GnuPGData.h com_freiheit_gnupg_GnuPGKey.h com_freiheit_gnupg_GnuPGSignature.h gpgmeutils.h First alpha release. Happy Birthday, GnuPG for Java -------------------------------------+ GNUmakefile | 39 +++ GnuPGContext.c | 385 ++++++++++++++++++++++++++++++++++ GnuPGData.c | 124 ++++++++++ GnuPGKey.c | 101 ++++++++ GnuPGSignature.c | 62 +++++ com_freiheit_gnupg_GnuPGContext.h | 149 +++++++++++++ com_freiheit_gnupg_GnuPGData.h | 53 ++++ com_freiheit_gnupg_GnuPGKey.h | 85 +++++++ com_freiheit_gnupg_GnuPGSignature.h | 93 ++++++++ gpgmeutils.h | 62 +++++ 10 files changed, 1153 insertions(+) From cvs at cvs.gnupg.org Mon Jan 24 14:54:16 2005 From: cvs at cvs.gnupg.org (cvs user stefan) Date: Mon Jan 24 22:48:50 2005 Subject: gnupgjava/src/junit/com (- New directory) Message-ID: Date: Monday, January 24, 2005 @ 14:54:16 Author: stefan Path: /cvs/gnupg/gnupgjava/src/junit/com Directory /cvs/gnupg/gnupgjava/src/junit/com added to the repository + 0 files changed From cvs at cvs.gnupg.org Mon Jan 24 14:56:59 2005 From: cvs at cvs.gnupg.org (cvs user stefan) Date: Mon Jan 24 22:54:24 2005 Subject: gnupgjava/src/java/com/freiheit/gnupg (10 files) Message-ID: Date: Monday, January 24, 2005 @ 14:56:59 Author: stefan Path: /cvs/gnupg/gnupgjava/src/java/com/freiheit/gnupg Added: GnuPGContext.java GnuPGData.java GnuPGException.java GnuPGKey.java GnuPGPassphraseConsole.java GnuPGPassphraseListener.java GnuPGPassphraseWindow.java GnuPGPeer.java GnuPGSignature.java package.html First alpha release. Happy Birthday, GnuPG for Java ------------------------------+ GnuPGContext.java | 484 +++++++++++++++++++++++++++++++++++++++++ GnuPGData.java | 150 ++++++++++++ GnuPGException.java | 40 +++ GnuPGKey.java | 204 +++++++++++++++++ GnuPGPassphraseConsole.java | 64 +++++ GnuPGPassphraseListener.java | 52 ++++ GnuPGPassphraseWindow.java | 88 +++++++ GnuPGPeer.java | 46 +++ GnuPGSignature.java | 195 ++++++++++++++++ package.html | 10 10 files changed, 1333 insertions(+) From cvs at cvs.gnupg.org Mon Jan 24 14:51:22 2005 From: cvs at cvs.gnupg.org (cvs user stefan) Date: Mon Jan 24 23:00:58 2005 Subject: gnupgjava/src/java (- New directory) Message-ID: Date: Monday, January 24, 2005 @ 14:51:21 Author: stefan Path: /cvs/gnupg/gnupgjava/src/java Directory /cvs/gnupg/gnupgjava/src/java added to the repository + 0 files changed From cvs at cvs.gnupg.org Mon Jan 24 14:50:16 2005 From: cvs at cvs.gnupg.org (cvs user stefan) Date: Mon Jan 24 23:11:37 2005 Subject: gnupgjava/src (- New directory) Message-ID: Date: Monday, January 24, 2005 @ 14:50:16 Author: stefan Path: /cvs/gnupg/gnupgjava/src Directory /cvs/gnupg/gnupgjava/src added to the repository + 0 files changed From cvs at cvs.gnupg.org Tue Jan 25 03:39:33 2005 From: cvs at cvs.gnupg.org (cvs user dshaw) Date: Tue Jan 25 06:26:21 2005 Subject: gnupg/m4 (ChangeLog libcurl.m4) Message-ID: Date: Tuesday, January 25, 2005 @ 03:47:57 Author: dshaw Path: /cvs/gnupg/gnupg/m4 Modified: ChangeLog libcurl.m4 * libcurl.m4: All versions of curl-config support --feature. ------------+ ChangeLog | 8 ++++++-- libcurl.m4 | 9 +++++---- 2 files changed, 11 insertions(+), 6 deletions(-) Index: gnupg/m4/ChangeLog diff -u gnupg/m4/ChangeLog:1.12 gnupg/m4/ChangeLog:1.13 --- gnupg/m4/ChangeLog:1.12 Sun Jan 23 00:10:23 2005 +++ gnupg/m4/ChangeLog Tue Jan 25 03:47:57 2005 @@ -1,9 +1,13 @@ -2005-01-22 David Shaw +2005-01-24 David Shaw + + * libcurl.m4: All versions of curl-config support --feature. + +2005-01-22 David Shaw * libcurl.m4: Note that FTPS existed, but wasn't fully standards-compliant until version 7.11.0. -2005-01-17 David Shaw +2005-01-17 David Shaw * libcurl.m4: Use LIBCURL_CPPFLAGS and not LIBCURL_INCLUDES to match automake syntax. Index: gnupg/m4/libcurl.m4 diff -u gnupg/m4/libcurl.m4:1.7 gnupg/m4/libcurl.m4:1.8 --- gnupg/m4/libcurl.m4:1.7 Sun Jan 23 00:10:23 2005 +++ gnupg/m4/libcurl.m4 Tue Jan 25 03:47:57 2005 @@ -25,6 +25,9 @@ # Note that xxx and yyy keep the same capitalization as in the # curl-config list (e.g. it's "HTTP" and not "http"). # +# Users may override the detected values by doing something like: +# LIBCURL="-lcurl" LIBCURL_CPPFLAGS="-I/usr/myinclude" ./configure +# # For the sake of sanity, this macro assumes that any libcurl that is # found is after version 7.7.2, the first version that included the # curl-config script. Note that it is very important for people @@ -110,10 +113,8 @@ esac fi - # Is it modern enough to have --feature? - if test $_libcurl_version -ge 0 ; then - _libcurl_features=`$_libcurl_config --feature` - fi + # All curl-config scripts support --feature + _libcurl_features=`$_libcurl_config --feature` # Is it modern enough to have --protocols? (7.12.4) if test $_libcurl_version -ge 461828 ; then From cvs at cvs.gnupg.org Tue Jan 25 15:10:32 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Tue Jan 25 17:10:38 2005 Subject: gnupg (doc/DETAILS g10/ChangeLog g10/apdu.c g10/app-openpgp.c) Message-ID: Date: Tuesday, January 25, 2005 @ 15:18:56 Author: wk Path: /cvs/gnupg/gnupg Modified: doc/DETAILS g10/ChangeLog g10/apdu.c g10/app-openpgp.c (get_cached_data): New arg GET_IMMEDIATE to bypass the cache. Changed all callers. (get_one_do): Bypass the cache if the value would have been read directly for v1.1 cards.It makes things a bit slower but obnly for 1.0 cards and there are not that many cards out in the wild. This is required to fix a caching bug when generating new keys; as a side effect of the retrieval of the the C4 DO from the 6E DO the chaced fingerprint will get updated to the old value and later when signing the generated key the checking of the fingerprint fails becuase it won't match the new one. Thanks to Moritz for analyzing this problem. (verify_chv3): Removed the CHV status reread logic because we won't cache the C4 DO anymore. -------------------+ doc/DETAILS | 2 + g10/ChangeLog | 16 +++++++++++ g10/apdu.c | 30 ++++++++++++--------- g10/app-openpgp.c | 71 ++++++++++++++++++++++++---------------------------- 4 files changed, 69 insertions(+), 50 deletions(-) Index: gnupg/doc/DETAILS diff -u gnupg/doc/DETAILS:1.87 gnupg/doc/DETAILS:1.88 --- gnupg/doc/DETAILS:1.87 Fri Oct 29 00:08:15 2004 +++ gnupg/doc/DETAILS Tue Jan 25 15:18:56 2005 @@ -549,6 +549,8 @@ to request a specific card. 2 = Request removal of a card. 3 = Card with serialnumber detected + 4 = No card available. + PLAINTEXT This indicates the format of the plaintext that is about to be Index: gnupg/g10/ChangeLog diff -u gnupg/g10/ChangeLog:1.685 gnupg/g10/ChangeLog:1.686 --- gnupg/g10/ChangeLog:1.685 Sat Jan 22 04:33:12 2005 +++ gnupg/g10/ChangeLog Tue Jan 25 15:18:56 2005 @@ -1,3 +1,19 @@ +2005-01-25 Werner Koch + + * app-openpgp.c (get_cached_data): New arg GET_IMMEDIATE to bypass + the cache. Changed all callers. + (get_one_do): Bypass the cache if the value would have been read + directly for v1.1 cards.It makes things a bit slower but obnly for + 1.0 cards and there are not that many cards out in the wild. This + is required to fix a caching bug when generating new keys; as a + side effect of the retrieval of the the C4 DO from the 6E DO the + chaced fingerprint will get updated to the old value and later + when signing the generated key the checking of the fingerprint + fails becuase it won't match the new one. Thanks to Moritz for + analyzing this problem. + (verify_chv3): Removed the CHV status reread logic because we + won't cache the C4 DO anymore. + 2005-01-21 David Shaw * keyserver.c (free_keyserver_spec): Fix small leak. Index: gnupg/g10/apdu.c diff -u gnupg/g10/apdu.c:1.18 gnupg/g10/apdu.c:1.19 --- gnupg/g10/apdu.c:1.18 Wed Dec 15 06:16:53 2004 +++ gnupg/g10/apdu.c Tue Jan 25 15:18:56 2005 @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: apdu.c,v 1.18 2004/12/15 05:16:53 dshaw Exp $ + * $Id: apdu.c,v 1.19 2005/01/25 14:18:56 wk Exp $ */ #include @@ -65,11 +65,16 @@ #include "dynload.h" #include "ccid-driver.h" + +/* To to conflicting use of threading libraries we usually can't link + against libpcsclite. Instead we use a wrapper program. */ #ifdef USE_GNU_PTH +#ifndef HAVE_W32_SYSTEM #define NEED_PCSC_WRAPPER 1 #endif +#endif - + #define MAX_READER 4 /* Number of readers we support concurrently. */ @@ -1482,7 +1487,6 @@ } strcpy (reader_table[slot].rdrname, portstr? portstr : list); xfree (list); - list = NULL; err = pcsc_connect (reader_table[slot].pcsc.context, reader_table[slot].rdrname, @@ -1496,11 +1500,11 @@ { log_error ("pcsc_connect failed: %s (0x%lx)\n", pcsc_error_string (err), err); - - pcsc_release_context (reader_table[slot].pcsc.context); + pcsc_release_context (reader_table[slot].pcsc.context); xfree (reader_table[slot].rdrname); reader_table[slot].rdrname = NULL; reader_table[slot].used = 0; + xfree (list); return -1; } @@ -2717,8 +2721,8 @@ resultlen -= 2; if (DBG_CARD_IO) { - log_debug (" response: sw=%04X datalen=%u\n", - sw, (unsigned int)resultlen); + log_debug (" response: sw=%04X datalen=%d\n", + sw, (unsigned int)resultlen); if ( !retbuf && (sw == SW_SUCCESS || (sw & 0xff00) == SW_MORE_DATA)) log_printhex (" dump: ", result, resultlen); } @@ -2784,8 +2788,8 @@ resultlen -= 2; if (DBG_CARD_IO) { - log_debug (" more: sw=%04X datalen=%u\n", - sw, (unsigned int)resultlen); + log_debug (" more: sw=%04X datalen=%d\n", + sw, (unsigned int)resultlen); if (!retbuf && (sw==SW_SUCCESS || (sw&0xff00)==SW_MORE_DATA)) log_printhex (" dump: ", result, resultlen); } @@ -2918,8 +2922,8 @@ resultlen -= 2; if (DBG_CARD_IO) { - log_debug (" response: sw=%04X datalen=%u\n", - sw, (unsigned int)resultlen); + log_debug (" response: sw=%04X datalen=%d\n", + sw, (unsigned int)resultlen); if ( !retbuf && (sw == SW_SUCCESS || (sw & 0xff00) == SW_MORE_DATA)) log_printhex (" dump: ", result, resultlen); } @@ -2971,8 +2975,8 @@ resultlen -= 2; if (DBG_CARD_IO) { - log_debug (" more: sw=%04X datalen=%u\n", - sw, (unsigned int)resultlen); + log_debug (" more: sw=%04X datalen=%d\n", + sw, (unsigned int)resultlen); if (!retbuf && (sw==SW_SUCCESS || (sw&0xff00)==SW_MORE_DATA)) log_printhex (" dump: ", result, resultlen); } Index: gnupg/g10/app-openpgp.c diff -u gnupg/g10/app-openpgp.c:1.22 gnupg/g10/app-openpgp.c:1.23 --- gnupg/g10/app-openpgp.c:1.22 Fri Dec 10 11:49:14 2004 +++ gnupg/g10/app-openpgp.c Tue Jan 25 15:18:55 2005 @@ -1,5 +1,5 @@ /* app-openpgp.c - The OpenPGP card application. - * Copyright (C) 2003, 2004 Free Software Foundation, Inc. + * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: app-openpgp.c,v 1.22 2004/12/10 10:49:14 wk Exp $ + * $Id: app-openpgp.c,v 1.23 2005/01/25 14:18:55 wk Exp $ */ #include @@ -138,10 +138,12 @@ /* Wrapper around iso7816_get_data which first tries to get the data - from the cache. */ + from the cache. With GET_IMMEDIATE passed as true, the cache is + bypassed. */ static gpg_error_t get_cached_data (app_t app, int tag, - unsigned char **result, size_t *resultlen) + unsigned char **result, size_t *resultlen, + int get_immediate) { gpg_error_t err; int i; @@ -152,23 +154,25 @@ *result = NULL; *resultlen = 0; - for (c=app->app_local->cache; c; c = c->next) - if (c->tag == tag) - { - if(c->length) + if (!get_immediate) + { + for (c=app->app_local->cache; c; c = c->next) + if (c->tag == tag) { - p = xtrymalloc (c->length); - if (!p) - return gpg_error (gpg_err_code_from_errno (errno)); - memcpy (p, c->data, c->length); - *result = p; + if(c->length) + { + p = xtrymalloc (c->length); + if (!p) + return gpg_error (gpg_err_code_from_errno (errno)); + memcpy (p, c->data, c->length); + *result = p; + } + + *resultlen = c->length; + + return 0; } - - *resultlen = c->length; - - return 0; - } - + } err = iso7816_get_data (app->slot, tag, &p, &len); if (err) @@ -177,6 +181,9 @@ *resultlen = len; /* Check whether we should cache this object. */ + if (get_immediate) + return 0; + for (i=0; data_objects[i].tag; i++) if (data_objects[i].tag == tag) { @@ -185,8 +192,7 @@ break; } - /* No, cache it. */ - + /* Okay, cache it. */ for (c=app->app_local->cache; c; c = c->next) assert (c->tag != tag); @@ -299,7 +305,8 @@ if (data_objects[i].tag && data_objects[i].get_from) { rc = get_cached_data (app, data_objects[i].get_from, - &buffer, &buflen); + &buffer, &buflen, + data_objects[i].get_immediate_in_v11); if (!rc) { const unsigned char *s; @@ -320,7 +327,8 @@ if (!value) /* Not in a constructed DO, try simple. */ { - rc = get_cached_data (app, tag, &buffer, &buflen); + rc = get_cached_data (app, tag, &buffer, &buflen, + data_objects[i].get_immediate_in_v11); if (!rc) { value = buffer; @@ -426,7 +434,7 @@ at any time and should be called after changing the login-data DO. Everything up to a LF is considered a mailbox or account name. If - the first LF is follewed by DC4 (0x14) control sequence are + the first LF is followed by DC4 (0x14) control sequence are expected up to the next LF. Control sequences are separated by FS (0x28) and consist of key=value pairs. There is one key defined: @@ -836,8 +844,6 @@ void *relptr; unsigned char *value; size_t valuelen; - int reread_chv_status; - relptr = get_one_do (app, 0x00C4, &value, &valuelen); if (!relptr || valuelen < 7) @@ -853,13 +859,11 @@ return gpg_error (GPG_ERR_BAD_PIN); } - reread_chv_status = (value[6] < 3); - log_info(_("%d Admin PIN attempts remaining before card" " is permanently locked\n"), value[6]); xfree (relptr); - /* Note to translators: Do not translate the "|A|" prefix but + /* TRANSLATORS: Do not translate the "|A|" prefix but keep it at the start of the string. We need this elsewhere to get some infos on the string. */ rc = pincb (pincb_arg, _("|A|Admin PIN"), &pinvalue); @@ -886,13 +890,6 @@ return rc; } app->did_chv3 = 1; - /* If the PIN has been entered wrongly before, we need to flush - the cached value so that the next read correctly reflects the - resetted retry counter. Note that version 1.1 of the specs - allow direct reading of that DO, so that we could actually - flush it in all cases. */ - if (reread_chv_status) - flush_cache_item (app, 0x00C4); } return rc; } @@ -1227,7 +1224,7 @@ assert (keyno >= 1 && keyno <= 3); - rc = get_cached_data (app, 0x006E, &buffer, &buflen); + rc = get_cached_data (app, 0x006E, &buffer, &buflen, 0); if (rc) { log_error (_("error reading application data\n")); From cvs at cvs.gnupg.org Tue Jan 25 15:26:25 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Tue Jan 25 19:08:35 2005 Subject: gnupg/g10 (ChangeLog keygen.c) Message-ID: Date: Tuesday, January 25, 2005 @ 15:34:51 Author: wk Path: /cvs/gnupg/gnupg/g10 Modified: ChangeLog keygen.c (do_generate_keypair): Don't continue after an error; fixed at two places. Why at all didn't I used a goto to cleanup, tsss? -----------+ ChangeLog | 6 +++++- keygen.c | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) Index: gnupg/g10/ChangeLog diff -u gnupg/g10/ChangeLog:1.686 gnupg/g10/ChangeLog:1.687 --- gnupg/g10/ChangeLog:1.686 Tue Jan 25 15:18:56 2005 +++ gnupg/g10/ChangeLog Tue Jan 25 15:34:51 2005 @@ -1,9 +1,13 @@ 2005-01-25 Werner Koch + * keygen.c (do_generate_keypair): Don't continue after an error; + fixed at two places. Why at all didn't I used a goto to cleanup, + tsss? + * app-openpgp.c (get_cached_data): New arg GET_IMMEDIATE to bypass the cache. Changed all callers. (get_one_do): Bypass the cache if the value would have been read - directly for v1.1 cards.It makes things a bit slower but obnly for + directly for v1.1 cards. It makes things a bit slower but only for 1.0 cards and there are not that many cards out in the wild. This is required to fix a caching bug when generating new keys; as a side effect of the retrieval of the the C4 DO from the 6E DO the Index: gnupg/g10/keygen.c diff -u gnupg/g10/keygen.c:1.141 gnupg/g10/keygen.c:1.142 --- gnupg/g10/keygen.c:1.141 Tue Dec 21 16:49:56 2004 +++ gnupg/g10/keygen.c Tue Jan 25 15:34:51 2005 @@ -2820,7 +2820,7 @@ get_parameter_uint (para, pKEYUSAGE)); } - if( get_parameter( para, pSUBKEYTYPE ) ) + if( !rc && get_parameter( para, pSUBKEYTYPE ) ) { if (!card) { @@ -2859,7 +2859,7 @@ did_sub = 1; } - if (card && get_parameter (para, pAUTHKEYTYPE)) + if (!rc && card && get_parameter (para, pAUTHKEYTYPE)) { rc = gen_card_key (PUBKEY_ALGO_RSA, 3, 0, pub_root, sec_root, get_parameter_u32 (para, pKEYEXPIRE), para); From cvs at cvs.gnupg.org Wed Jan 26 18:36:17 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Wed Jan 26 21:33:28 2005 Subject: gnupg/scripts (ChangeLog distfiles mk-w32-dist w32installer.nsi) Message-ID: Date: Wednesday, January 26, 2005 @ 18:44:48 Author: wk Path: /cvs/gnupg/gnupg/scripts Modified: ChangeLog distfiles mk-w32-dist w32installer.nsi * w32installer.nsi: Create a start menu entry and enhanced the build environment. * mk-w32-dist: Add more support for above. ------------------+ ChangeLog | 6 + distfiles | 1 mk-w32-dist | 67 +++++++++++++++++--- w32installer.nsi | 173 +++++++++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 224 insertions(+), 23 deletions(-) Index: gnupg/scripts/ChangeLog diff -u gnupg/scripts/ChangeLog:1.60 gnupg/scripts/ChangeLog:1.61 --- gnupg/scripts/ChangeLog:1.60 Tue Jan 11 13:03:22 2005 +++ gnupg/scripts/ChangeLog Wed Jan 26 18:44:48 2005 @@ -1,3 +1,9 @@ +2005-01-26 Werner Koch + + * w32installer.nsi: Create a start menu entry and enhanced the + build environment. + * mk-w32-dist: Add more support for above. + 2005-01-11 Werner Koch * w32installer.nsi: New. Index: gnupg/scripts/distfiles diff -u gnupg/scripts/distfiles:1.17 gnupg/scripts/distfiles:1.18 --- gnupg/scripts/distfiles:1.17 Sun Feb 23 06:14:57 2003 +++ gnupg/scripts/distfiles Wed Jan 26 18:44:47 2005 @@ -4,3 +4,4 @@ autogen.sh mk-gpg-texi mk-w32-dist +w32installer.nsi Index: gnupg/scripts/mk-w32-dist diff -u gnupg/scripts/mk-w32-dist:1.15 gnupg/scripts/mk-w32-dist:1.16 --- gnupg/scripts/mk-w32-dist:1.15 Thu Jan 20 12:42:02 2005 +++ gnupg/scripts/mk-w32-dist Wed Jan 26 18:44:47 2005 @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation, Inc. +# Copyright (C) 2000, 2001, 2002, 2004, 2005 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 @@ -10,14 +10,19 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - set -e - cd dist-w32 +tmp="`echo $0 | sed 's,.*gnupg-\([^/]*\)/.*,\1,'`" + +topdir= bindir=.. -if [ -f ../README ]; then +if [ -f "../gnupg-$tmp/README" ]; then + srcdir="../gnupg-$tmp" + bindir="../gnupg-$tmp" + topdir=".." +elif [ -f ../README ]; then srcdir=.. elif [ -f ../../README ]; then srcdir=../.. @@ -37,7 +42,12 @@ STRIP="mingw32 strip" fi +# If we don't have an installer we don't need to prepare for it. +if ! makensis -version >/dev/null 2>&1 ; then + topdir= +fi +# Figure out the version version=$(sed -n 's/^#[ ]*define[ ][ ]*VERSION[ ][ ]*\"\([0-9.a-z-]*\)\"/\1/p' $bindir/config.h) prod_version=$(echo "$version"|awk -F'[^0-9]' '{print $1 "." $2 "." $3 ".1"}') echo "building version $version ($prod_version)" @@ -79,6 +89,7 @@ for i in ${srcdir}/po/*.po; do lang=$(basename $i .po) grep -s $lang ${srcdir}/po/LINGUAS >/dev/null || continue + [ -f$lang.mo -a $lang.mo -nt $i ] && continue fromset=`sed -n '/^"Content-Type:/ s/.*charset=\([a-zA-Z0-9_-]*\).*/\1/p' $i` case "$fromset" in @@ -95,14 +106,50 @@ esac done -if makensis -version >/dev/null 2>&1 ; then - echo "invokin installer as:" - echo makensis -v3 -nocd -DVERSION="${version}" \ +# If we have a topdir, assume the full build environment and +# prepare the installer +if [ -n "$topdir" ]; then + winpt_defs= + src_defs= + buildinfo="`date -u '+%Y-%m-%d %H:%M UTC'`" + + # iconv.dll is a hard requirement + if [ ! -f "$topdir/iconv/iconv.dll" ]; then + echo "iconv.dll not availavle" >&2 + exit 1 + fi + ln "$topdir/iconv/iconv.dll" iconv.dll + for i in COPYING.LIB README.iconv; do + cp ${topdir}/iconv/$i $i.txt + todos $i.txt + done + + # WinPT is optional + if [ -f "$topdir/winpt/WinPT.exe" ]; then + ln "$topdir/winpt/WinPT.exe" WinPT.exe + ln "$topdir/winpt/PTD.dll" PTD.dll + cp "$topdir/winpt/README-0.9.txt" README.winpt.txt + cp "$topdir/winpt/NEWS-0.9.txt" NEWS.winpt.txt + cp "$topdir/winpt/keyserver.conf" keyserver.conf + winpt_defs="-DWITH_WINPT" + fi + + # See whether we should include the source. + if [ ! -d "$topdir/tarballs" ]; then + # FIXME + : + fi + + # Now run the installer + echo "invoking installer as:" + echo makensis -v2 -nocd -DVERSION="${version}" \ -DPROD_VERSION="${prod_version}" \ - -DGNUPG_SRCDIR="${srcdir}" ${srcdir}/scripts/w32installer.nsi - makensis -v3 -nocd -DVERSION="${version}" \ + -DGNUPG_SRCDIR="${srcdir}" ${winpt_defs} ${src_defs} \ + ${srcdir}/scripts/w32installer.nsi + BUILDINFO=$buildinfo makensis -v2 -nocd -DVERSION="${version}" \ -DPROD_VERSION="${prod_version}" \ - -DGNUPG_SRCDIR="${srcdir}" ${srcdir}/scripts/w32installer.nsi + -DGNUPG_SRCDIR="${srcdir}" ${winpt_defs} ${src_defs} \ + ${srcdir}/scripts/w32installer.nsi echo "Installer created" >&2 else zip -9 "gnupg-w32cli-${version}.zip" * Index: gnupg/scripts/w32installer.nsi diff -u gnupg/scripts/w32installer.nsi:1.3 gnupg/scripts/w32installer.nsi:1.4 --- gnupg/scripts/w32installer.nsi:1.3 Thu Jan 20 12:42:02 2005 +++ gnupg/scripts/w32installer.nsi Wed Jan 26 18:44:47 2005 @@ -15,12 +15,6 @@ ; using NSIS. It is usually used by the mk-w32-dist script. ;---------------------------------------------------------------------- -; TODO: -; - Display credit for the installer -; - Provide the location of the corresponding source -; - Translate all strings - - ; We use the modern UI. !include "MUI.nsh" @@ -29,7 +23,11 @@ ; ------------- Name "GNU Privacy Guard" +!ifdef WITH_WINPT +OutFile "gnupg-w32-${VERSION}.exe" +!else OutFile "gnupg-w32cli-${VERSION}.exe" +!endif InstallDir "$PROGRAMFILES\GNU\GnuPG" @@ -54,6 +52,15 @@ "GnuPG: Encryption and digital signature tool" VIAddVersionKey "FileVersion" "${PROD_VERSION}" +; ---------------------- +; Variable declarations +; ---------------------- + +Var MYTMP +Var STARTMENU_FOLDER + +Var DOC_INSTALLED +Var WINPT_INSTALLED ; ------------------ ; Interface Settings @@ -97,6 +104,13 @@ !insertmacro MUI_PAGE_COMPONENTS !insertmacro MUI_PAGE_DIRECTORY + +!define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKCU" +!define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\GNU\GnuPG" +!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder" + +!insertmacro MUI_PAGE_STARTMENU Application $STARTMENU_FOLDER + !insertmacro MUI_PAGE_INSTFILES !define MUI_FINISHPAGE_SHOWREADME "README.txt" @@ -156,8 +170,6 @@ WriteRegStr HKLM "Software\GNU\GnuPG" "Install Directory" $INSTDIR - WriteUninstaller "$INSTDIR\Uninstall.exe" - SectionEnd ; Section Base ;---------------------- @@ -180,6 +192,29 @@ SectionEnd ; Section Tools +;------------------ +!ifdef WITH_WINPT +Section "WinPT" SecWinPT +; SectionIn 1 + + SetOutPath "$INSTDIR" + + File "WinPT.exe" + File "PTD.dll" + File "keyserver.conf" + + SetOutPath "$INSTDIR\Doc" + + File "README.winpt.txt" + + WriteRegStr HKCU "Software\GNU\GnuPG" "gpgProgram" "$INSTDIR\gpg.exe" + + StrCpy $WINPT_INSTALLED 1 + +SectionEnd ; Section WinPT +!endif + + ;---------------------- Section "Documentation" SecDoc ; SectionIn 1 @@ -192,6 +227,12 @@ File "NEWS.txt" File "FAQ.txt" +!ifdef WITH_WINPT + File "NEWS.winpt.txt" +!endif ; WITH_WINPT + + StrCpy $DOC_INSTALLED 1 + SectionEnd ; Section Documentation @@ -204,15 +245,73 @@ ; Note that we include the uncompressed tarball because this allows ; far better compression results for the distribution. We might ; want to compress it again after installation. - File "gnupg-1.4.0.tar" + File "gnupg-${VERSION}.tar" SectionEnd ; Section Source !endif -;------------------ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; The last section is a hidden one; used to finish up things. +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +Section "-Finish" + + ;;-------------------------- + ;; Create the uninstaller + ;;-------------------------- + WriteUninstaller "$INSTDIR\uninst-gnupg.exe" + + ;;--------------------- + ;; Create Menu entries + ;;--------------------- + !insertmacro MUI_STARTMENU_WRITE_BEGIN Application + + CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER" + + CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\GnuPG README.lnk" \ + "$INSTDIR\Doc\README.txt" + CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\GnuPG NEWS.lnk" \ + "$INSTDIR\Doc\NEWS.txt" + + IntCmp $DOC_INSTALLED 1 0 +2 +2 + CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\GnuPG Manual Page.lnk" \ + "$INSTDIR\Doc\gpg.man" + + + IntCmp $WINPT_INSTALLED 1 0 no_winpt_menu no_winpt_menu + CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\winpt.lnk" \ + "$INSTDIR\winpt.exe" + CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\WinPT README.lnk" \ + "$INSTDIR\Doc\README.winpt.txt" + IntCmp $DOC_INSTALLED 1 0 +2 +2 + CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\WinPT NEWS.lnk" \ + "$INSTDIR\Doc\NEWS.winpt.txt" + + no_winpt_menu: + + CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\uninst-gnupg.lnk" \ + "$INSTDIR\uninst-gnupg.exe" + + + !insertmacro MUI_STARTMENU_WRITE_END + + +SectionEnd ; "-Finish" + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Create the section for the uninstaller +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Section "Uninstall" + ;;------------------------ + ;; Delete files + ;;------------------------ Delete "$INSTDIR\gpg.exe" Delete "$INSTDIR\gpgkeys_finger.exe" Delete "$INSTDIR\gpgkeys_hkp.exe" @@ -222,6 +321,8 @@ Delete "$INSTDIR\Doc\README.txt" Delete "$INSTDIR\Doc\README.W32" Delete "$INSTDIR\Doc\COPYING.txt" + Delete "$INSTDIR\Doc\COPYING.LIB.txt" + Delete "$INSTDIR\Doc\README.iconv.txt" Delete "$INSTDIR\iconv.dll" @@ -229,6 +330,11 @@ Delete "$INSTDIR\gpgsplit.exe" Delete "$INSTDIR\gpgv.exe" + Delete "$INSTDIR\WinPT.exe" + Delete "$INSTDIR\PTD.dll" + Delete "$INSTDIR\Doc\README.winpt.txt" + Delete "$INSTDIR\Doc\NEWS.winpt.txt" + Delete "$INSTDIR\Doc\keyserver.conf" Delete "$INSTDIR\Doc\gnupg.man" Delete "$INSTDIR\Doc\gpg.man" @@ -236,13 +342,36 @@ Delete "$INSTDIR\Doc\NEWS.txt" Delete "$INSTDIR\Doc\FAQ.txt" - Delete "$INSTDIR\Uninstall.exe" + Delete "$INSTDIR\uninst-gnupg.exe" + ;;------------------------ + ;; Delete directories + ;;------------------------ RMDir "$INSTDIR\Doc" RMDir "$INSTDIR\Src" RMDir "$INSTDIR\gnupg.nls" RMDir "$INSTDIR" + + ;;--------------------------------------------------- + ;; Delete the menu entries and any empty parent menus + ;;--------------------------------------------------- + !insertmacro MUI_STARTMENU_GETFOLDER Application $MYTMP + Delete "$SMPROGRAMS\$MYTMP\*.lnk" + StrCpy $MYTMP "$SMPROGRAMS\$MYTMP" + startMenuDeleteLoop: + ClearErrors + RMDir $MYTMP + GetFullPathName $MYTMP "$MYTMP\.." + IfErrors startMenuDeleteLoopDone + StrCmp $MYTMP $SMPROGRAMS startMenuDeleteLoopDone startMenuDeleteLoop + startMenuDeleteLoopDone: + + + ;;----------------------- + ;; Cleanup the registry + ;;----------------------- + DeleteRegValue HKCU "Software\GNU\GnuPG" "Start Menu Folder" DeleteRegValue HKLM "Software\GNU\GnuPG" "Install Directory" DeleteRegKey /ifempty HKLM "Software\GNU\GnuPG" @@ -314,6 +443,10 @@ SetOutPath "$INSTDIR" File "iconv.dll" + SetOutPath "$INSTDIR\doc" + File "COPYING.LIB.txt" + File "README.iconv.txt" + FunctionEnd @@ -327,11 +460,15 @@ It can be used to encrypt data and to create digital signatures. \ It includes an advanced key management facility and is compliant \ with the proposed OpenPGP Internet standard as described in RFC2440. \ - \r\n\r\nThis is GnuPG version ${VERSION}" + \r\n\r\n$_CLICK \ + \r\n\r\n\r\n\r\n\r\nThis is GnuPG version ${VERSION}\r\n\ + built on $%BUILDINFO%" LangString T_About ${LANG_GERMAN} \ "GnuPG is das Werzeug aus dem GNU Projekt zur sicheren Kommunikation \ sowie zum sicheren Speichern von Daten. \ - \r\n\r\nThis is GnuPG version ${VERSION}" + \r\n\r\n$_CLICK \ + \r\n\r\n\r\n\r\n\r\nDies ist GnuPG version ${VERSION}\r\n\ + erstellt am $%BUILDINFO%" LangString T_ShowReadme ${LANG_ENGLISH} "Show the README file" LangString T_ShowReadme ${LANG_GERMAN} "Die README Datei anzeigen" @@ -351,6 +488,13 @@ LangString DESC_SecTools ${LANG_GERMAN} \ "Weitere Tools wie gpgv und gpgsplit" +!ifdef WITH_WINPT +LangString DESC_SecWinPT ${LANG_ENGLISH} \ + "The Windows Privacy Tray (WinPT)" +LangString DESC_SecWinPT ${LANG_GERMAN} \ + "Der Windows Privacy Tray (WinPT)" +!endif + LangString DESC_SecDoc ${LANG_ENGLISH} \ "Manual pages and a FAQ" LangString DESC_SecDoc ${LANG_GERMAN} \ @@ -360,6 +504,9 @@ !insertmacro MUI_DESCRIPTION_TEXT ${SecBase} $(DESC_SecBase) !insertmacro MUI_DESCRIPTION_TEXT ${SecNLS} $(DESC_SecNLS) !insertmacro MUI_DESCRIPTION_TEXT ${SecTools} $(DESC_SecTools) +!ifdef WITH_WINPT + !insertmacro MUI_DESCRIPTION_TEXT ${SecWinPT} $(DESC_SecWinPT) +!endif !insertmacro MUI_DESCRIPTION_TEXT ${SecDoc} $(DESC_SecDoc) !insertmacro MUI_FUNCTION_DESCRIPTION_END From cvs at cvs.gnupg.org Wed Jan 26 22:11:56 2005 From: cvs at cvs.gnupg.org (cvs user dshaw) Date: Wed Jan 26 22:11:58 2005 Subject: gnupg/g10 (ChangeLog keyserver.c) Message-ID: Date: Wednesday, January 26, 2005 @ 22:20:30 Author: dshaw Path: /cvs/gnupg/gnupg/g10 Modified: ChangeLog keyserver.c * keyserver.c (parse_keyserver_uri): Allow RFC-2732 IPv6 [literal address] syntax in keyserver URLs. (keyserver_typemap): Map ftps if we are supporting it. -------------+ ChangeLog | 6 ++++++ keyserver.c | 40 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 42 insertions(+), 4 deletions(-) Index: gnupg/g10/ChangeLog diff -u gnupg/g10/ChangeLog:1.687 gnupg/g10/ChangeLog:1.688 --- gnupg/g10/ChangeLog:1.687 Tue Jan 25 15:34:51 2005 +++ gnupg/g10/ChangeLog Wed Jan 26 22:20:30 2005 @@ -1,3 +1,9 @@ +2005-01-26 David Shaw + + * keyserver.c (parse_keyserver_uri): Allow RFC-2732 IPv6 [literal + address] syntax in keyserver URLs. + (keyserver_typemap): Map ftps if we are supporting it. + 2005-01-25 Werner Koch * keygen.c (do_generate_keypair): Don't continue after an error; Index: gnupg/g10/keyserver.c diff -u gnupg/g10/keyserver.c:1.78 gnupg/g10/keyserver.c:1.79 --- gnupg/g10/keyserver.c:1.78 Sat Jan 22 04:33:12 2005 +++ gnupg/g10/keyserver.c Wed Jan 26 22:20:30 2005 @@ -166,12 +166,26 @@ /* Get the scheme */ for(idx=uri,count=0;*idx && *idx!=':';idx++) - count++; + { + count++; + + /* Do we see the start of an RFC-2732 ipv6 address here? If so, + there clearly isn't a scheme so get out early. */ + if(*idx=='[') + { + /* Was the '[' the first thing in the string? If not, we + have a mangled scheme with a [ in it so fail. */ + if(count==1) + break; + else + goto fail; + } + } if(count==0) goto fail; - if(*idx=='\0') + if(*idx=='\0' || *idx=='[') { if(require_scheme) return NULL; @@ -237,8 +251,22 @@ uri+=count+1; } - for(idx=uri,count=0;*idx && *idx!=':' && *idx!='/';idx++) - count++; + /* Is it an RFC-2732 ipv6 [literal address] ? */ + if(*uri=='[') + { + for(idx=uri+1,count=1;*idx + && (isxdigit(*idx) || *idx==':' || *idx=='.');idx++) + count++; + + /* Is the ipv6 literal address terminated? */ + if(*idx==']') + count++; + else + goto fail; + } + else + for(idx=uri,count=0;*idx && *idx!=':' && *idx!='/';idx++) + count++; if(count==0) goto fail; @@ -790,6 +818,10 @@ else if(strcmp(type,"ftp")==0) return "curl"; #endif +#ifdef FTPS_VIA_LIBCURL + else if(strcmp(type,"ftps")==0) + return "curl"; +#endif #ifdef HTTP_VIA_LIBCURL else if(strcmp(type,"http")==0) return "curl"; From cvs at cvs.gnupg.org Wed Jan 26 23:11:46 2005 From: cvs at cvs.gnupg.org (cvs user mo) Date: Wed Jan 26 23:11:48 2005 Subject: GNUPG-1-9-BRANCH gnupg/agent (ChangeLog Makefile.am agent.h findkey.c gpg-agent.c) Message-ID: Date: Wednesday, January 26, 2005 @ 23:20:21 Author: mo Path: /cvs/gnupg/gnupg/agent Tag: GNUPG-1-9-BRANCH Modified: ChangeLog Makefile.am agent.h findkey.c gpg-agent.c 2005-01-26 Moritz Schulte * command-ssh.c: New file. * Makefile.am (gpg_agent_SOURCES): New source file: command-ssh.c. * findkey.c (modify_description): New function. (agent_key_from_file): Support comment field in key s-expressions. * gpg-agent.c (enum cmd_and_opt_values): New item: oSSHSupport. (opts) New entry for oSSHSupport. New variable: socket_name_ssh. (cleanup_do): New function based on cleanup(). (cleanup): Use cleanup_do() for socket_name and socket_name_ssh. (main): New switch case for oSSHSupport. (main): Move socket name creation code to ... (create_socket_name): ... this new function. (main): Use create_socket_name() for creating socket names for socket_name and for socket_name_ssh in case ssh support is enabled. Move socket creation code to ... (create_server_socket): ... this new function. (main): Use create_server_socket() for creating sockets. In case standard_socket is set, do not only store a socket name in socket_name, but also in socket_name_ssh. Generate additional environment info strings for ssh support. Pass additional ssh socket argument to handle_connections. (start_connection_thread_ssh): New function. (handle_connections): Use select to multiplex between gpg-agent and ssh-agent protocol. * agent.h (struct opt): New member: ssh_support. Declare function: start_command_handler_ssh. -------------+ ChangeLog | 33 ++++ Makefile.am | 4 agent.h | 6 findkey.c | 144 ++++++++++++++++++++ gpg-agent.c | 399 +++++++++++++++++++++++++++++++++++++++++----------------- 5 files changed, 464 insertions(+), 122 deletions(-) Index: gnupg/agent/ChangeLog diff -u gnupg/agent/ChangeLog:1.59.2.56 gnupg/agent/ChangeLog:1.59.2.57 --- gnupg/agent/ChangeLog:1.59.2.56 Thu Jan 13 19:00:46 2005 +++ gnupg/agent/ChangeLog Wed Jan 26 23:20:21 2005 @@ -1,3 +1,36 @@ +2005-01-26 Moritz Schulte + + * command-ssh.c: New file. + * Makefile.am (gpg_agent_SOURCES): New source file: command-ssh.c. + + * findkey.c (modify_description): New function. + (agent_key_from_file): Support comment field in key s-expressions. + + * gpg-agent.c (enum cmd_and_opt_values): New item: oSSHSupport. + (opts) New entry for oSSHSupport. + New variable: socket_name_ssh. + (cleanup_do): New function based on cleanup(). + (cleanup): Use cleanup_do() for socket_name and socket_name_ssh. + (main): New switch case for oSSHSupport. + (main): Move socket name creation code to ... + (create_socket_name): ... this new function. + (main): Use create_socket_name() for creating socket names for + socket_name and for socket_name_ssh in case ssh support is + enabled. + Move socket creation code to ... + (create_server_socket): ... this new function. + (main): Use create_server_socket() for creating sockets. + In case standard_socket is set, do not only store a socket name in + socket_name, but also in socket_name_ssh. + Generate additional environment info strings for ssh support. + Pass additional ssh socket argument to handle_connections. + (start_connection_thread_ssh): New function. + (handle_connections): Use select to multiplex between gpg-agent + and ssh-agent protocol. + + * agent.h (struct opt): New member: ssh_support. + Declare function: start_command_handler_ssh. + 2005-01-04 Werner Koch * trustlist.c (agent_marktrusted): Use "Cancel" for the first Index: gnupg/agent/Makefile.am diff -u gnupg/agent/Makefile.am:1.22.2.5 gnupg/agent/Makefile.am:1.22.2.6 --- gnupg/agent/Makefile.am:1.22.2.5 Tue Dec 21 20:05:15 2004 +++ gnupg/agent/Makefile.am Wed Jan 26 23:20:21 2005 @@ -1,4 +1,4 @@ -# Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc. +# Copyright (C) 2001, 2003, 2004, 2005 Free Software Foundation, Inc. # # This file is part of GnuPG. # @@ -29,7 +29,7 @@ gpg_agent_SOURCES = \ gpg-agent.c agent.h \ - command.c \ + command.c command-ssh.c \ query.c \ cache.c \ trans.c \ Index: gnupg/agent/agent.h diff -u gnupg/agent/agent.h:1.32.2.12 gnupg/agent/agent.h:1.32.2.13 --- gnupg/agent/agent.h:1.32.2.12 Tue Dec 21 20:05:15 2004 +++ gnupg/agent/agent.h Wed Jan 26 23:20:21 2005 @@ -1,5 +1,5 @@ /* agent.h - Global definitions for the agent - * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -66,6 +66,7 @@ int allow_preset_passphrase; int keep_tty; /* don't switch the TTY (for pinentry) on request */ int keep_display; /* don't switch the DISPLAY (for pinentry) on request */ + int ssh_support; /* Enable ssh-agent emulation. */ } opt; @@ -136,6 +137,9 @@ /*-- command.c --*/ void start_command_handler (int, int); +/*-- command-ssh.c --*/ +void start_command_handler_ssh (int); + /*-- findkey.c --*/ int agent_write_private_key (const unsigned char *grip, const void *buffer, size_t length, int force); Index: gnupg/agent/findkey.c diff -u gnupg/agent/findkey.c:1.17.2.5 gnupg/agent/findkey.c:1.17.2.6 --- gnupg/agent/findkey.c:1.17.2.5 Mon Dec 13 16:49:56 2004 +++ gnupg/agent/findkey.c Wed Jan 26 23:20:21 2005 @@ -1,5 +1,5 @@ /* findkey.c - locate the secret key - * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -140,6 +140,108 @@ } +/* Modify a Key description, replacing certain special format + characters. List of currently supported replacements: + + %% -> % + %c -> . */ +static int +modify_description (const char *description, + const char *comment, size_t comment_length, + char **description_modified) +{ + size_t description_length; + size_t description_new_length; + gpg_error_t err; + char *description_new; + unsigned int i, j; + unsigned int special; + + description_length = strlen (description); + description_new_length = description_length; + description_new = NULL; + + /* Calculate length. */ + special = 0; + for (i = 0; i < description_length; i++) + { + if (description[i] == '%') + special = 1; + else + { + if (special) + { + description_new_length -= 2; + switch (description[i]) + { + case 'c': + /* Comment. */ + description_new_length += comment_length; + break; + + case '%': + description_new_length += 1; + break; + } + special = 0; + } + } + } + + /* Allocate. */ + description_new = xtrymalloc (description_new_length + 1); + if (! description_new) + { + err = gpg_error_from_errno (errno); + goto out; + } + + /* Fill. */ + for (i = j = 0; i < description_length; i++) + { + if (description[i] == '%') + special = 1; + else + { + if (special) + { + switch (description[i]) + { + case 'c': + /* Comment. */ + if (comment) + { + strncpy (description_new + j, comment, comment_length); + j += comment_length; + } + break; + + case '%': + description_new[j] = '%'; + j++; + break; + } + special = 0; + } + else + { + description_new[j] = description[i]; + j++; + } + } + } + + description_new[j] = 0; + *description_modified = description_new; + err = 0; + + out: + + return err; +} + + + /* Unprotect the canconical encoded S-expression key in KEYBUF. GRIP should be the hex encoded keygrip of that key to be used with the caching mechanism. DESC_TEXT may be set to override the default @@ -292,10 +394,42 @@ case PRIVATE_KEY_CLEAR: break; /* no unprotection needed */ case PRIVATE_KEY_PROTECTED: - rc = unprotect (ctrl, desc_text, &buf, grip, ignore_cache); - if (rc) - log_error ("failed to unprotect the secret key: %s\n", - gpg_strerror (rc)); + { + gcry_sexp_t comment_sexp; + size_t comment_length; + char *desc_text_final; + const char *comment; + + comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0); + if (comment_sexp) + comment = gcry_sexp_nth_data (comment_sexp, 1, &comment_length); + else + { + comment = NULL; + comment_length = 0; + } + + if (desc_text) + { + rc = modify_description (desc_text, + comment, comment_length, &desc_text_final); + if (rc) + log_error ("failed to modify description: %s\n", gpg_strerror (rc)); + } + else + desc_text_final = NULL; + + if (! rc) + { + rc = unprotect (ctrl, desc_text_final, &buf, grip, ignore_cache); + if (rc) + log_error ("failed to unprotect the secret key: %s\n", + gpg_strerror (rc)); + } + + gcry_sexp_release (comment_sexp); + xfree (desc_text_final); + } break; case PRIVATE_KEY_SHADOWED: if (shadow_info) Index: gnupg/agent/gpg-agent.c diff -u gnupg/agent/gpg-agent.c:1.31.2.30 gnupg/agent/gpg-agent.c:1.31.2.31 --- gnupg/agent/gpg-agent.c:1.31.2.30 Tue Dec 21 20:05:15 2004 +++ gnupg/agent/gpg-agent.c Wed Jan 26 23:20:21 2005 @@ -1,5 +1,6 @@ /* gpg-agent.c - The GnuPG Agent - * Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2000, 2001, 2002, 2003, + * 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -91,7 +92,8 @@ oAllowMarkTrusted, oAllowPresetPassphrase, oKeepTTY, - oKeepDISPLAY + oKeepDISPLAY, + oSSHSupport }; @@ -144,6 +146,7 @@ N_("allow clients to mark keys as \"trusted\"")}, { oAllowPresetPassphrase, "allow-preset-passphrase", 0, N_("allow presetting passphrase")}, + { oSSHSupport, "ssh-support", 0, "Enable SSH-Agent emulation" }, {0} }; @@ -163,6 +166,9 @@ /* Name of the communication socket */ static char *socket_name; +/* Name of the communication socket used for ssh-agent-emulation. */ +static char *socket_name_ssh; + /* Default values for options passed to the pinentry. */ static char *default_display; static char *default_ttyname; @@ -183,7 +189,7 @@ /* Local prototypes. */ static void create_directories (void); #ifdef USE_GNU_PTH -static void handle_connections (int listen_fd); +static void handle_connections (int listen_fd, int listen_fd_ssh); /* Pth wrapper function definitions. */ GCRY_THREAD_OPTION_PTH_IMPL; #endif /*USE_GNU_PTH*/ @@ -297,22 +303,29 @@ static void -cleanup (void) +cleanup_do (char *name) { - if (socket_name && *socket_name) + if (name && *name) { char *p; - remove (socket_name); - p = strrchr (socket_name, '/'); + remove (name); + p = strrchr (name, '/'); if (p) - { - *p = 0; - rmdir (socket_name); - *p = '/'; - } - *socket_name = 0; + { + *p = 0; + rmdir (name); + *p = '/'; + } + *name = 0; } +} + +static void +cleanup (void) +{ + cleanup_do (socket_name); + cleanup_do (socket_name_ssh); } @@ -404,6 +417,105 @@ } +static void +create_socket_name (char **name, int standard_socket, + struct sockaddr_un *serv_addr, + char *standard_identifier, char *identifier) +{ + char *p; + + if (standard_socket) + *name = make_filename (opt.homedir, standard_identifier, NULL); + else + { + *name = xstrdup (identifier); + p = strrchr (*name, '/'); + if (! p) + BUG (); + *p = 0; + if (!mkdtemp (*name)) + { + log_error (_("can't create directory `%s': %s\n"), + *name, strerror (errno)); + exit (1); + } + *p = '/'; + } + + if (strchr (*name, PATHSEP_C)) + { + log_error ("`%s' are not allowed in the socket name\n", PATHSEP_S); + exit (1); + } + if (strlen (*name) + 1 >= sizeof serv_addr->sun_path) + { + log_error ("name of socket too long\n"); + exit (1); + } +} + +static int +create_server_socket (struct sockaddr_un *serv_addr, + int standard_socket, const char *name) +{ + socklen_t len; + int fd; + int rc; + +#ifdef HAVE_W32_SYSTEM + fd = _w32_sock_new (AF_UNIX, SOCK_STREAM, 0); +#else + fd = socket (AF_UNIX, SOCK_STREAM, 0); +#endif + if (fd == -1) + { + log_error ("can't create socket: %s\n", strerror (errno)); + exit (1); + } + + memset (serv_addr, 0, sizeof *serv_addr); + serv_addr->sun_family = AF_UNIX; + strcpy (serv_addr->sun_path, name); + len = (offsetof (struct sockaddr_un, sun_path) + + strlen (serv_addr->sun_path) + 1); + +#ifdef HAVE_W32_SYSTEM + rc = _w32_sock_bind (fd, (struct sockaddr*) serv_addr, len); + if ((rc == -1) && standard_socket) + { + remove (name); + rc = bind (fd, (struct sockaddr*) serv_addr, len); + } +#else + rc = bind (fd, (struct sockaddr*) serv_addr, len); + if ((rc == -1) && standard_socket && (errno == EADDRINUSE)) + { + remove (name); + rc = bind (fd, (struct sockaddr*) serv_addr, len); + } +#endif + if (rc == -1) + { + log_error ("error binding socket to `%s': %s\n", + serv_addr->sun_path, strerror (errno)); + close (fd); + exit (1); + } + + if (listen (fd, 5 ) == -1) + { + log_error ("listen() failed: %s\n", strerror (errno)); + close (fd); + exit (1); + } + + if (opt.verbose) + log_info ("listening on socket `%s'\n", socket_name); + + return fd; +} + + int main (int argc, char **argv ) { @@ -596,6 +708,12 @@ case oKeepTTY: opt.keep_tty = 1; break; case oKeepDISPLAY: opt.keep_display = 1; break; + case oSSHSupport: + opt.ssh_support = 1; + opt.keep_tty = 1; + opt.keep_display = 1; + break; + default : pargs.err = configfp? 1:2; break; } } @@ -745,11 +863,10 @@ else { /* Regular server mode */ int fd; - int rc; + int fd_ssh; pid_t pid; - int len; struct sockaddr_un serv_addr; - char *p; + struct sockaddr_un serv_addr_ssh; /* Remove the DISPLAY variable so that a pinentry does not default to a specific display. There is still a default @@ -761,90 +878,26 @@ #endif /* Create the socket name . */ - if (standard_socket) - socket_name = make_filename (opt.homedir, "S.gpg-agent", NULL); + create_socket_name (&socket_name, standard_socket, &serv_addr, + "S.gpg-agent", "/tmp/gpg-XXXXXX/S.gpg-agent"); + if (opt.ssh_support) + create_socket_name (&socket_name_ssh, standard_socket, &serv_addr_ssh, + "S.gpg-agent.ssh", "/tmp/gpg-XXXXXX/S.gpg-agent.ssh"); + + fd = create_server_socket (&serv_addr, + standard_socket, socket_name); + if (opt.ssh_support) + fd_ssh = create_server_socket (&serv_addr_ssh, + standard_socket, socket_name_ssh); else - { - socket_name = xstrdup ("/tmp/gpg-XXXXXX/S.gpg-agent"); - p = strrchr (socket_name, '/'); - if (!p) - BUG (); - *p = 0;; - if (!mkdtemp(socket_name)) - { - log_error (_("can't create directory `%s': %s\n"), - socket_name, strerror(errno) ); - exit (1); - } - *p = '/'; - } - - if (strchr (socket_name, PATHSEP_C) ) - { - log_error ("`%s' are not allowed in the socket name\n", PATHSEP_S); - exit (1); - } - if (strlen (socket_name)+1 >= sizeof serv_addr.sun_path ) - { - log_error ("name of socket too long\n"); - exit (1); - } - -#ifdef HAVE_W32_SYSTEM - fd = _w32_sock_new (AF_UNIX, SOCK_STREAM, 0); -#else - fd = socket (AF_UNIX, SOCK_STREAM, 0); -#endif - if (fd == -1) - { - log_error ("can't create socket: %s\n", strerror(errno) ); - exit (1); - } - - memset (&serv_addr, 0, sizeof serv_addr); - serv_addr.sun_family = AF_UNIX; - strcpy (serv_addr.sun_path, socket_name); - len = (offsetof (struct sockaddr_un, sun_path) - + strlen(serv_addr.sun_path) + 1); - -#ifdef HAVE_W32_SYSTEM - rc = _w32_sock_bind (fd, (struct sockaddr*)&serv_addr, len); - if (rc == -1 && standard_socket) - { - remove (socket_name); - rc = bind (fd, (struct sockaddr*)&serv_addr, len); - } -#else - rc = bind (fd, (struct sockaddr*)&serv_addr, len); - if (rc == -1 && standard_socket && errno == EADDRINUSE) - { - remove (socket_name); - rc = bind (fd, (struct sockaddr*)&serv_addr, len); - } -#endif - if (rc == -1) - { - log_error ("error binding socket to `%s': %s\n", - serv_addr.sun_path, strerror (errno) ); - close (fd); - exit (1); - } - - if (listen (fd, 5 ) == -1) - { - log_error ("listen() failed: %s\n", strerror (errno)); - close (fd); - exit (1); - } - - if (opt.verbose) - log_info ("listening on socket `%s'\n", socket_name ); - + /* Make the compiler happy. */ + fd_ssh = -1; fflush (NULL); #ifdef HAVE_W32_SYSTEM pid = getpid (); printf ("set GPG_AGENT_INFO=%s;%lu;1\n", socket_name, (ulong)pid); + printf ("set GPG_AGENT_INFO=%s;%lu;1\n", socket_name, (ulong)pid); #else /*!HAVE_W32_SYSTEM*/ pid = fork (); if (pid == (pid_t)-1) @@ -854,7 +907,7 @@ } else if (pid) { /* We are the parent */ - char *infostr; + char *infostr, *infostr_ssh_sock, *infostr_ssh_pid; close (fd); @@ -866,8 +919,29 @@ kill (pid, SIGTERM); exit (1); } + if (opt.ssh_support) + { + if (asprintf (&infostr_ssh_sock, "SSH_AUTH_SOCK=%s", + socket_name_ssh) < 0) + { + log_error ("out of core\n"); + kill (pid, SIGTERM); + exit (1); + } + if (asprintf (&infostr_ssh_pid, "SSH_AGENT_PID=%u", + pid) < 0) + { + log_error ("out of core\n"); + kill (pid, SIGTERM); + exit (1); + } + } + *socket_name = 0; /* don't let cleanup() remove the socket - the child should do this from now on */ + if (opt.ssh_support) + *socket_name_ssh = 0; + if (argc) { /* run the program given on the commandline */ if (putenv (infostr)) @@ -877,6 +951,20 @@ kill (pid, SIGTERM ); exit (1); } + if (putenv (infostr_ssh_sock)) + { + log_error ("failed to set environment: %s\n", + strerror (errno) ); + kill (pid, SIGTERM ); + exit (1); + } + if (putenv (infostr_ssh_pid)) + { + log_error ("failed to set environment: %s\n", + strerror (errno) ); + kill (pid, SIGTERM ); + exit (1); + } execvp (argv[0], argv); log_error ("failed to run the command: %s\n", strerror (errno)); kill (pid, SIGTERM); @@ -890,12 +978,29 @@ { *strchr (infostr, '=') = ' '; printf ( "setenv %s\n", infostr); + if (opt.ssh_support) + { + *strchr (infostr_ssh_sock, '=') = ' '; + printf ( "setenv %s\n", infostr_ssh_sock); + *strchr (infostr_ssh_pid, '=') = ' '; + printf ( "setenv %s\n", infostr_ssh_pid); + } } else { printf ( "%s; export GPG_AGENT_INFO;\n", infostr); + if (opt.ssh_support) + { + printf ( "%s; export SSH_AUTH_SOCK;\n", infostr_ssh_sock); + printf ( "%s; export SSH_AGENT_PID;\n", infostr_ssh_pid); + } } free (infostr); + if (opt.ssh_support) + { + free (infostr_ssh_sock); + free (infostr_ssh_pid); + } exit (0); } /*NEVER REACHED*/ @@ -949,7 +1054,7 @@ sa.sa_flags = 0; sigaction (SIGPIPE, &sa, NULL); #endif - handle_connections (fd); + handle_connections (fd, opt.ssh_support ? fd_ssh : -1); } else #endif /*!USE_GNU_PTH*/ @@ -1230,16 +1335,37 @@ return NULL; } +static void * +start_connection_thread_ssh (void *arg) +{ + int fd = (int)arg; + + if (opt.verbose) + log_info ("ssh handler for fd %d started\n", fd); + + /* FIXME: Move this housekeeping into a ticker function. Calling it + for each connection should work but won't work anymore if our + cleints start to keep connections. */ + agent_trustlist_housekeeping (); + + start_command_handler_ssh (fd); + if (opt.verbose) + log_info ("ssh handler for fd %d terminated\n", fd); + + return NULL; +} static void -handle_connections (int listen_fd) +handle_connections (int listen_fd, int listen_fd_ssh) { pth_attr_t tattr; pth_event_t ev; sigset_t sigs; int signo; struct sockaddr_un paddr; - socklen_t plen = sizeof( paddr ); + socklen_t plen = sizeof ( paddr ); + fd_set fdset, read_fdset; + int ret; int fd; tattr = pth_attr_new(); @@ -1259,6 +1385,11 @@ ev = NULL; #endif + FD_ZERO (&fdset); + FD_SET (listen_fd, &fdset); + if (listen_fd_ssh != -1) + FD_SET (listen_fd_ssh, &fdset); + for (;;) { if (shutdown_pending) @@ -1275,28 +1406,68 @@ continue; } - fd = pth_accept_ev (listen_fd, (struct sockaddr *)&paddr, &plen, ev); - if (fd == -1) - { + read_fdset = fdset; + ret = pth_select (FD_SETSIZE, &read_fdset, NULL, NULL, NULL); + if (ret == -1) + { + log_error ("pth_select failed: %s - waiting 1s\n", + strerror (errno)); + pth_sleep (1); + continue; + } + + + if (FD_ISSET (listen_fd, &read_fdset)) + { + fd = pth_accept_ev (listen_fd, (struct sockaddr *)&paddr, &plen, ev); + if (fd == -1) + { #ifdef PTH_STATUS_OCCURRED /* This is Pth 2 */ - if (pth_event_status (ev) == PTH_STATUS_OCCURRED) + if (pth_event_status (ev) == PTH_STATUS_OCCURRED) #else - if (pth_event_occurred (ev)) + if (pth_event_occurred (ev)) #endif - { - handle_signal (signo); - continue; + { + handle_signal (signo); + continue; + } + log_error ("accept failed: %s - waiting 1s\n", strerror (errno)); + pth_sleep(1); + continue; + } + + if (!pth_spawn (tattr, start_connection_thread, (void*)fd)) + { + log_error ("error spawning connection handler: %s\n", + strerror (errno) ); + close (fd); } - log_error ("accept failed: %s - waiting 1s\n", strerror (errno)); - pth_sleep(1); - continue; } + else if ((listen_fd_ssh != -1) && FD_ISSET (listen_fd_ssh, &read_fdset)) + { + fd = pth_accept_ev (listen_fd_ssh, (struct sockaddr *)&paddr, &plen, ev); + if (fd == -1) + { +#ifdef PTH_STATUS_OCCURRED /* This is Pth 2 */ + if (pth_event_status (ev) == PTH_STATUS_OCCURRED) +#else + if (pth_event_occurred (ev)) +#endif + { + handle_signal (signo); + continue; + } + log_error ("accept failed: %s - waiting 1s\n", strerror (errno)); + pth_sleep(1); + continue; + } - if (!pth_spawn (tattr, start_connection_thread, (void*)fd)) - { - log_error ("error spawning connection handler: %s\n", - strerror (errno) ); - close (fd); + if (!pth_spawn (tattr, start_connection_thread_ssh, (void*)fd)) + { + log_error ("error spawning connection handler: %s\n", + strerror (errno) ); + close (fd); + } } } From cvs at cvs.gnupg.org Wed Jan 26 23:24:36 2005 From: cvs at cvs.gnupg.org (cvs user mo) Date: Wed Jan 26 23:24:40 2005 Subject: GNUPG-1-9-BRANCH gnupg/agent (ChangeLog command-ssh.c) Message-ID: Date: Wednesday, January 26, 2005 @ 23:33:11 Author: mo Path: /cvs/gnupg/gnupg/agent Tag: GNUPG-1-9-BRANCH Modified: ChangeLog command-ssh.c 2005-01-26 Moritz Schulte * command-ssh.c (ssh_handler_sign_request): Confirm to agent protocol in case of failure. ---------------+ ChangeLog | 4 ++++ command-ssh.c | 10 +++++----- 2 files changed, 9 insertions(+), 5 deletions(-) Index: gnupg/agent/ChangeLog diff -u gnupg/agent/ChangeLog:1.59.2.57 gnupg/agent/ChangeLog:1.59.2.58 --- gnupg/agent/ChangeLog:1.59.2.57 Wed Jan 26 23:20:21 2005 +++ gnupg/agent/ChangeLog Wed Jan 26 23:33:11 2005 @@ -1,6 +1,10 @@ 2005-01-26 Moritz Schulte + * command-ssh.c (ssh_handler_sign_request): Confirm to agent + protocol in case of failure. + * command-ssh.c: New file. + * Makefile.am (gpg_agent_SOURCES): New source file: command-ssh.c. * findkey.c (modify_description): New function. Index: gnupg/agent/command-ssh.c diff -u gnupg/agent/command-ssh.c:1.1.4.1 gnupg/agent/command-ssh.c:1.1.4.2 --- gnupg/agent/command-ssh.c:1.1.4.1 Wed Jan 26 23:25:36 2005 +++ gnupg/agent/command-ssh.c Wed Jan 26 23:33:11 2005 @@ -1706,14 +1706,14 @@ if (! bad) { /* Done. */ - es_write_byte (response, SSH_RESPONSE_SIGN_RESPONSE); - if (! es_ferror (response)) + if (! err) { - if (! err) + es_write_byte (response, SSH_RESPONSE_SIGN_RESPONSE); + if (! es_ferror (response)) es_write_string (response, sig, sig_n); - else - es_write_byte (response, SSH_RESPONSE_FAILURE); } + else + es_write_byte (response, SSH_RESPONSE_FAILURE); } gcry_sexp_release (key); From cvs at cvs.gnupg.org Thu Jan 27 00:07:07 2005 From: cvs at cvs.gnupg.org (cvs user mo) Date: Thu Jan 27 00:07:11 2005 Subject: GNUPG-1-9-BRANCH gnupg/doc (ChangeLog gpg-agent.texi) Message-ID: Date: Thursday, January 27, 2005 @ 00:15:43 Author: mo Path: /cvs/gnupg/gnupg/doc Tag: GNUPG-1-9-BRANCH Modified: ChangeLog gpg-agent.texi 2005-01-27 Moritz Schulte * gpg-agent.texi: Document ssh-agent emulation layer. ----------------+ ChangeLog | 4 ++++ gpg-agent.texi | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) Index: gnupg/doc/ChangeLog diff -u gnupg/doc/ChangeLog:1.39.2.23 gnupg/doc/ChangeLog:1.39.2.24 --- gnupg/doc/ChangeLog:1.39.2.23 Thu Jan 13 19:00:46 2005 +++ gnupg/doc/ChangeLog Thu Jan 27 00:15:42 2005 @@ -1,3 +1,7 @@ +2005-01-27 Moritz Schulte + + * gpg-agent.texi: Document ssh-agent emulation layer. + 2005-01-04 Werner Koch * gnupg.texi: Updated to use @copying. Index: gnupg/doc/gpg-agent.texi diff -u gnupg/doc/gpg-agent.texi:1.1.2.14 gnupg/doc/gpg-agent.texi:1.1.2.15 --- gnupg/doc/gpg-agent.texi:1.1.2.14 Tue Dec 21 20:05:15 2004 +++ gnupg/doc/gpg-agent.texi Thu Jan 27 00:15:42 2005 @@ -326,6 +326,37 @@ window system's @code{DISPLAY} variable. This is useful to lock the pinentry to pop up at the @sc{tty} or display you started the agent. +@item --ssh-support +@itemx --ssh-support +@opindex ssh-support +@opindex ssh + +Enable emulation of the OpenSSH Agent protocol. + +In this mode of operation, the agent does not only implement the +gpg-agent protocol, but also the agent protocol used by OpenSSH +(through a seperate socket). Consequently, it should possible to use +the gpg-agent as a drop-in replacement for the well known ssh-agent. + +SSH Keys, which are to be used through the agent, need to be added to +the gpg-agent initially through the ssh-add utility. When a key is +added, ssh-add will ask for the password of the provided key file and +send the unprotected key material to the agent; this causes the +gpg-agent to ask for a passphrase, which is to be used for encrypting +the newly received key and storing it in a gpg-agent specific +directory. + +Once, a key has been added to the gpg-agent this way, the gpg-agent +will be ready to use the key. + +Note: in case the gpg-agent receives a signature request, the user +might need to be prompted for a passphrased, which is necessary for +decrypting the stored key. Since the ssh-agent protocol does not +contain a mechanism for telling the agent on which display/terminal it +is running, gpg-agent's --ssh-support switch implies --keep-display +and --keep-tty. This strategy causes the gpg-agent to open a pinentry +on the display or on the terminal, on which it (the gpg-agent) was +started. @end table @@ -396,6 +427,9 @@ @node Agent Protocol @section Agent's Assuan Protocol +Note: this section does only document the protocol, which is used by +GnuPG components; it does not deal with the ssh-agent protocol. + The @command{gpg-agent} should be started by the login shell and set an environment variable to tell clients about the socket to be used. Clients should deny to access an agent with a socket name which does From cvs at cvs.gnupg.org Thu Jan 27 12:39:55 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Thu Jan 27 12:39:58 2005 Subject: gnupg/g10 (ChangeLog keyedit.c keygen.c) Message-ID: Date: Thursday, January 27, 2005 @ 12:48:33 Author: wk Path: /cvs/gnupg/gnupg/g10 Modified: ChangeLog keyedit.c keygen.c * keygen.c (generate_subkeypair): Detect primary key on-card and ask for the passphrase. Return an error if the primary key is a plain stub. * keyedit.c (change_passphrase): Don't ever change any stub key. Print a note if a key consists of only stub keys. Reported by Dany Nativel. These are bugs #401 and #402. -----------+ ChangeLog | 10 ++++++++++ keyedit.c | 51 ++++++++++++++++++++++++++++++++++++++++++--------- keygen.c | 32 +++++++++++++++++++++++--------- 3 files changed, 75 insertions(+), 18 deletions(-) Index: gnupg/g10/ChangeLog diff -u gnupg/g10/ChangeLog:1.689 gnupg/g10/ChangeLog:1.690 --- gnupg/g10/ChangeLog:1.689 Thu Jan 27 11:30:27 2005 +++ gnupg/g10/ChangeLog Thu Jan 27 12:48:33 2005 @@ -1,3 +1,13 @@ +2005-01-27 Werner Koch + + * keygen.c (generate_subkeypair): Detect primary key on-card and + ask for the passphrase. Return an error if the primary key is a + plain stub. + + * keyedit.c (change_passphrase): Don't ever change any stub key. + Print a note if a key consists of only stub keys. Reported by + Dany Nativel. These are bugs #401 and #402. + 2005-01-26 Werner Koch * ccid-driver.c (parse_ccid_descriptor): Need the CSM workaround Index: gnupg/g10/keyedit.c diff -u gnupg/g10/keyedit.c:1.168 gnupg/g10/keyedit.c:1.169 --- gnupg/g10/keyedit.c:1.168 Tue Jan 11 05:15:55 2005 +++ gnupg/g10/keyedit.c Thu Jan 27 12:48:33 2005 @@ -1069,6 +1069,7 @@ PKT_secret_key *sk; char *passphrase = NULL; int no_primary_secrets = 0; + int any; node = find_kbnode( keyblock, PKT_SECRET_KEY ); if( !node ) { @@ -1077,6 +1078,25 @@ } sk = node->pkt->pkt.secret_key; + for (any = 0, node=keyblock; node; node = node->next) { + if (node->pkt->pkttype == PKT_SECRET_KEY + || node->pkt->pkttype == PKT_SECRET_SUBKEY) { + PKT_secret_key *tmpsk = node->pkt->pkt.secret_key; + if (!(tmpsk->is_protected + && (tmpsk->protect.s2k.mode == 1001 + || tmpsk->protect.s2k.mode == 1002))) { + any = 1; + break; + } + } + } + if (!any) { + tty_printf (_("Key has only stub or on-card key items - " + "no passphrase to change.\n")); + goto leave; + } + + /* See how to handle this key. */ switch( is_secret_key_protected( sk ) ) { case -1: rc = G10ERR_PUBKEY_ALGO; @@ -1089,6 +1109,10 @@ tty_printf(_("Secret parts of primary key are not available.\n")); no_primary_secrets = 1; } + else if( sk->protect.s2k.mode == 1002 ) { + tty_printf(_("Secret parts of primary key are store on-card.\n")); + no_primary_secrets = 1; + } else { tty_printf(_("Key is protected.\n")); rc = check_secret_key( sk, 0 ); @@ -1098,14 +1122,18 @@ break; } - /* unprotect all subkeys (use the supplied passphrase or ask)*/ + /* Unprotect all subkeys (use the supplied passphrase or ask)*/ for(node=keyblock; !rc && node; node = node->next ) { if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) { PKT_secret_key *subsk = node->pkt->pkt.secret_key; - set_next_passphrase( passphrase ); - rc = check_secret_key( subsk, 0 ); - if( !rc && !passphrase ) - passphrase = get_last_passphrase(); + if ( !(subsk->is_protected + && (subsk->protect.s2k.mode == 1001 + || subsk->protect.s2k.mode == 1002))) { + set_next_passphrase( passphrase ); + rc = check_secret_key( subsk, 0 ); + if( !rc && !passphrase ) + passphrase = get_last_passphrase(); + } } } @@ -1149,13 +1177,18 @@ for(node=keyblock; !rc && node; node = node->next ) { if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) { PKT_secret_key *subsk = node->pkt->pkt.secret_key; - subsk->protect.algo = dek->algo; - subsk->protect.s2k = *s2k; - rc = protect_secret_key( subsk, dek ); + if ( !(subsk->is_protected + && (subsk->protect.s2k.mode == 1001 + || subsk->protect.s2k.mode == 1002))) { + subsk->protect.algo = dek->algo; + subsk->protect.s2k = *s2k; + rc = protect_secret_key( subsk, dek ); + } } } if( rc ) - log_error("protect_secret_key failed: %s\n", g10_errstr(rc) ); + log_error("protect_secret_key failed: %s\n", + g10_errstr(rc) ); else changed++; break; Index: gnupg/g10/keygen.c diff -u gnupg/g10/keygen.c:1.142 gnupg/g10/keygen.c:1.143 --- gnupg/g10/keygen.c:1.142 Tue Jan 25 15:34:51 2005 +++ gnupg/g10/keygen.c Thu Jan 27 12:48:33 2005 @@ -1,6 +1,6 @@ /* keygen.c - generate a key pair * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, - * 2004 Free Software Foundation, Inc. + * 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -3002,6 +3002,7 @@ DEK *dek = NULL; STRING2KEY *s2k = NULL; u32 cur_time; + int ask_pass = 0; /* break out the primary secret key */ node = find_kbnode( sec_keyblock, PKT_SECRET_KEY ); @@ -3032,20 +3033,31 @@ goto leave; } - /* unprotect to get the passphrase */ + if (pri_sk->is_protected && pri_sk->protect.s2k.mode == 1001) { + tty_printf(_("Secret parts of primary key are not available.\n")); + rc = G10ERR_NO_SECKEY; + goto leave; + } + + + /* Unprotect to get the passphrase. */ switch( is_secret_key_protected( pri_sk ) ) { case -1: rc = G10ERR_PUBKEY_ALGO; break; case 0: - tty_printf("This key is not protected.\n"); + tty_printf(_("This key is not protected.\n")); break; + case -2: + tty_printf(_("Secret parts of primary key are store on-card.\n")); + ask_pass = 1; + break; default: - tty_printf("Key is protected.\n"); - rc = check_secret_key( pri_sk, 0 ); - if( !rc ) - passphrase = get_last_passphrase(); - break; + tty_printf(_("Key is protected.\n")); + rc = check_secret_key( pri_sk, 0 ); + if( !rc ) + passphrase = get_last_passphrase(); + break; } if( rc ) goto leave; @@ -3058,7 +3070,9 @@ _("Really create? (y/N) "))) goto leave; - if( passphrase ) { + if (ask_pass) + dek = do_ask_passphrase (&s2k); + else if (passphrase) { s2k = m_alloc_secure( sizeof *s2k ); s2k->mode = opt.s2k_mode; s2k->hash_algo = S2K_DIGEST_ALGO; From cvs at cvs.gnupg.org Fri Jan 28 01:41:32 2005 From: cvs at cvs.gnupg.org (cvs user dshaw) Date: Fri Jan 28 05:32:02 2005 Subject: gnupg/g10 (ChangeLog keyedit.c keygen.c keyid.c) Message-ID: Date: Friday, January 28, 2005 @ 01:50:10 Author: dshaw Path: /cvs/gnupg/gnupg/g10 Modified: ChangeLog keyedit.c keygen.c keyid.c * keyid.c (keyid_from_sk, keyid_from_pk): Use 0xFFFFFFFFFFFFFFFF instead of 0x0000000000000000 for the invalid key ID since all-zeroes is reserved for the anonymous recipient. * keyedit.c (change_passphrase), keygen.c (generate_subkeypair): Fix a string ;) -----------+ ChangeLog | 9 +++++++++ keyedit.c | 2 +- keygen.c | 2 +- keyid.c | 8 ++++---- 4 files changed, 15 insertions(+), 6 deletions(-) Index: gnupg/g10/ChangeLog diff -u gnupg/g10/ChangeLog:1.690 gnupg/g10/ChangeLog:1.691 --- gnupg/g10/ChangeLog:1.690 Thu Jan 27 12:48:33 2005 +++ gnupg/g10/ChangeLog Fri Jan 28 01:50:10 2005 @@ -1,3 +1,12 @@ +2005-01-27 David Shaw + + * keyid.c (keyid_from_sk, keyid_from_pk): Use 0xFFFFFFFFFFFFFFFF + instead of 0x0000000000000000 for the invalid key ID since + all-zeroes is reserved for the anonymous recipient. + + * keyedit.c (change_passphrase), keygen.c (generate_subkeypair): + Fix a string ;) + 2005-01-27 Werner Koch * keygen.c (generate_subkeypair): Detect primary key on-card and Index: gnupg/g10/keyedit.c diff -u gnupg/g10/keyedit.c:1.169 gnupg/g10/keyedit.c:1.170 --- gnupg/g10/keyedit.c:1.169 Thu Jan 27 12:48:33 2005 +++ gnupg/g10/keyedit.c Fri Jan 28 01:50:10 2005 @@ -1110,7 +1110,7 @@ no_primary_secrets = 1; } else if( sk->protect.s2k.mode == 1002 ) { - tty_printf(_("Secret parts of primary key are store on-card.\n")); + tty_printf(_("Secret parts of primary key are stored on-card.\n")); no_primary_secrets = 1; } else { Index: gnupg/g10/keygen.c diff -u gnupg/g10/keygen.c:1.143 gnupg/g10/keygen.c:1.144 --- gnupg/g10/keygen.c:1.143 Thu Jan 27 12:48:33 2005 +++ gnupg/g10/keygen.c Fri Jan 28 01:50:10 2005 @@ -3049,7 +3049,7 @@ tty_printf(_("This key is not protected.\n")); break; case -2: - tty_printf(_("Secret parts of primary key are store on-card.\n")); + tty_printf(_("Secret parts of primary key are stored on-card.\n")); ask_pass = 1; break; default: Index: gnupg/g10/keyid.c diff -u gnupg/g10/keyid.c:1.52 gnupg/g10/keyid.c:1.53 --- gnupg/g10/keyid.c:1.52 Thu Dec 30 04:26:57 2004 +++ gnupg/g10/keyid.c Fri Jan 28 01:50:10 2005 @@ -280,7 +280,7 @@ sk->keyid[1]=keyid[1]; } else - sk->keyid[0]=sk->keyid[1]=keyid[0]=keyid[1]=lowbits=0; + sk->keyid[0]=sk->keyid[1]=keyid[0]=keyid[1]=lowbits=0xFFFFFFFF; } else { @@ -298,7 +298,7 @@ sk->keyid[1] = keyid[1]; } else - sk->keyid[0]=sk->keyid[1]=keyid[0]=keyid[1]=lowbits=0; + sk->keyid[0]=sk->keyid[1]=keyid[0]=keyid[1]=lowbits=0xFFFFFFFF; } return lowbits; @@ -334,7 +334,7 @@ pk->keyid[1] = keyid[1]; } else - pk->keyid[0]=pk->keyid[1]=keyid[0]=keyid[1]=lowbits=0; + pk->keyid[0]=pk->keyid[1]=keyid[0]=keyid[1]=lowbits=0xFFFFFFFF; } else { @@ -352,7 +352,7 @@ pk->keyid[1] = keyid[1]; } else - pk->keyid[0]=pk->keyid[1]=keyid[0]=keyid[1]=lowbits=0; + pk->keyid[0]=pk->keyid[1]=keyid[0]=keyid[1]=lowbits=0xFFFFFFFF; } return lowbits; From cvs at cvs.gnupg.org Tue Jan 4 21:44:03 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Fri Jan 28 12:17:26 2005 Subject: LIBGCRYPT-1-2-BRANCH libgcrypt (16 files) Message-ID: Date: Tuesday, January 4, 2005 @ 21:50:23 Author: wk Path: /cvs/libgcrypt/libgcrypt Tag: LIBGCRYPT-1-2-BRANCH Modified: ChangeLog INSTALL acinclude.m4 compile config.guess config.sub depcomp doc/ChangeLog doc/gcrypt.texi doc/mdate-sh doc/texinfo.tex install-sh missing mkinstalldirs src/ChangeLog src/gcrypt.h Updated for automake 1.9. -----------------+ ChangeLog | 6 INSTALL | 52 acinclude.m4 | 24 compile | 155 - config.guess | 95 config.sub | 57 depcomp | 104 - doc/ChangeLog | 8 doc/gcrypt.texi | 128 - doc/mdate-sh | 37 doc/texinfo.tex | 5594 ++++++++++++++++++++++++++++-------------------------- install-sh | 471 ++-- missing | 131 - mkinstalldirs | 69 src/ChangeLog | 4 src/gcrypt.h | 50 16 files changed, 3761 insertions(+), 3224 deletions(-) Index: libgcrypt/ChangeLog diff -u libgcrypt/ChangeLog:1.158.2.2 libgcrypt/ChangeLog:1.158.2.3 --- libgcrypt/ChangeLog:1.158.2.2 Sat Dec 18 12:05:54 2004 +++ libgcrypt/ChangeLog Tue Jan 4 21:50:23 2005 @@ -1,3 +1,9 @@ +2005-01-04 Werner Koch + + Updated to automake 1.9. + + * acinclude.m4: Updated for automake 1.9. + 2004-12-18 Werner Koch * autogen.sh: Added option --build-w32 to run W32 cross compiling Index: libgcrypt/INSTALL diff -u libgcrypt/INSTALL:1.28 libgcrypt/INSTALL:1.28.2.1 --- libgcrypt/INSTALL:1.28 Mon Dec 8 22:43:02 2003 +++ libgcrypt/INSTALL Tue Jan 4 21:50:23 2005 @@ -1,13 +1,16 @@ -Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software -Foundation, Inc. +Installation Instructions +************************* - This file is free documentation; the Free Software Foundation gives +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004 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. +These are generic installation instructions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses @@ -67,9 +70,9 @@ 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. +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 @@ -82,7 +85,7 @@ Compiling For Multiple Architectures ==================================== - You can compile the package for more than one kind of computer at the +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 @@ -99,19 +102,19 @@ Installation Names ================== - By default, `make install' will install the package's files in +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'. +option `--prefix=PREFIX'. 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. +give `configure' the option `--exec-prefix=PREFIX', the package will +use PREFIX 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 +options like `--bindir=DIR' 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. @@ -122,7 +125,7 @@ Optional Features ================= - Some packages pay attention to `--enable-FEATURE' options to +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 @@ -137,11 +140,11 @@ 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 +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: @@ -167,9 +170,9 @@ 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'. +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. @@ -178,7 +181,7 @@ Defining Variables ================== - Variables not defined in a site shell script can be set in the +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 @@ -192,8 +195,7 @@ `configure' Invocation ====================== - `configure' recognizes the following options to control how it -operates. +`configure' recognizes the following options to control how it operates. `--help' `-h' Index: libgcrypt/acinclude.m4 diff -u libgcrypt/acinclude.m4:1.43 libgcrypt/acinclude.m4:1.43.2.1 --- libgcrypt/acinclude.m4:1.43 Fri Oct 31 06:06:09 2003 +++ libgcrypt/acinclude.m4 Tue Jan 4 21:50:23 2005 @@ -21,14 +21,14 @@ dnl GNUPG_MSG_PRINT(STRING) dnl print a message dnl -define(GNUPG_MSG_PRINT, +define([GNUPG_MSG_PRINT], [ echo $ac_n "$1"" $ac_c" 1>&AS_MESSAGE_FD([]) ]) dnl GNUPG_CHECK_TYPEDEF(TYPE, HAVE_NAME) dnl Check whether a typedef exists and create a #define $2 if it exists dnl -AC_DEFUN(GNUPG_CHECK_TYPEDEF, +AC_DEFUN([GNUPG_CHECK_TYPEDEF], [ AC_MSG_CHECKING(for $1 typedef) AC_CACHE_VAL(gnupg_cv_typedef_$1, [AC_TRY_COMPILE([#define _GNU_SOURCE 1 @@ -50,7 +50,7 @@ dnl We must use a temp file in the current directory because make distcheck dnl install all sourcefiles RO. dnl -AC_DEFUN(GNUPG_FIX_HDR_VERSION, +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 @@ -72,7 +72,7 @@ dnl GNUPG_CHECK_GNUMAKE dnl -AC_DEFUN(GNUPG_CHECK_GNUMAKE, +AC_DEFUN([GNUPG_CHECK_GNUMAKE], [ if ${MAKE-make} --version 2>/dev/null | grep '^GNU ' >/dev/null 2>&1; then : @@ -93,7 +93,7 @@ # Does the compiler prefix global symbols with an underscore? # # Taken from GnuPG 1.2 and modified to use the libtool macros. -AC_DEFUN(GNUPG_SYS_SYMBOL_UNDERSCORE, +AC_DEFUN([GNUPG_SYS_SYMBOL_UNDERSCORE], [tmp_do_check="no" case "${target}" in i386-emx-os2 | i[3456]86-pc-os2*emx | i386-pc-msdosdjgpp) @@ -158,7 +158,7 @@ ###################################################################### dnl GNUPG_CHECK_MLOCK dnl -define(GNUPG_CHECK_MLOCK, +define([GNUPG_CHECK_MLOCK], [ AC_CHECK_FUNCS(mlock) if test "$ac_cv_func_mlock" = "no"; then AC_CHECK_HEADERS(sys/mman.h) @@ -244,7 +244,7 @@ ]) # GNUPG_SYS_LIBTOOL_CYGWIN32 - find tools needed on cygwin32 -AC_DEFUN(GNUPG_SYS_LIBTOOL_CYGWIN32, +AC_DEFUN([GNUPG_SYS_LIBTOOL_CYGWIN32], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(AS, as, false) ]) @@ -252,7 +252,7 @@ dnl LIST_MEMBER() dnl Check wether an element ist contained in a list. Set `found' to dnl `1' if the element is found in the list, to `0' otherwise. -AC_DEFUN(LIST_MEMBER, +AC_DEFUN([LIST_MEMBER], [ name=$1 list=$2 @@ -269,7 +269,7 @@ 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_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)]), @@ -363,7 +363,7 @@ dnl ## dnl dnl # auxilliary macros -AC_DEFUN(_AC_PTH_ERROR, [dnl +AC_DEFUN([_AC_PTH_ERROR], [dnl AC_MSG_RESULT([*FAILED*]) dnl define(_ac_pth_line,dnl dnl "+------------------------------------------------------------------------+") @@ -375,13 +375,13 @@ dnl undefine(_ac_pth_line) exit 1 ]) -AC_DEFUN(_AC_PTH_VERBOSE, [dnl +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 +AC_DEFUN([AC_CHECK_PTH], [dnl dnl dnl # prerequisites AC_REQUIRE([AC_PROG_CC])dnl Index: libgcrypt/compile diff -u libgcrypt/compile:1.1 libgcrypt/compile:1.1.2.1 --- libgcrypt/compile:1.1 Mon Mar 29 10:40:44 2004 +++ libgcrypt/compile Tue Jan 4 21:50:23 2005 @@ -1,8 +1,9 @@ #! /bin/sh - # Wrapper for compilers which do not understand `-c -o'. -# Copyright 1999, 2000 Free Software Foundation, Inc. +scriptversion=2004-10-12.08 + +# Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify @@ -24,84 +25,118 @@ # 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. - -# Usage statement added by Billy Biggs . -if [ -z $1 ]; then - echo "Wrapper for compilers which do not understand '-c -o'." - echo "usage: compile PROGRAM [ARGS]..." - echo "'-o FOO.o' is removed from the args passed to the actual compile." - exit 1 -fi - -prog=$1 -shift +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand `-c -o'. +Remove `-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file `INSTALL'. + +Report bugs to . +EOF + exit 0 + ;; + -v | --v*) + echo "compile $scriptversion" + exit 0 + ;; +esac 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 +eat= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as `compile cc -o foo foo.c'. + # So we strip `-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + 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 + # 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 "$@" fi # Name of file we expect compiler to create. -cofile=`echo $cfile | sed -e 's|^.*/||' -e 's/\.c$/.o/'` +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 +lockdir=`echo "$cofile" | sed -e 's|[/.-]|_|g'`.d while true; do - if mkdir $lockdir > /dev/null 2>&1; then - break - fi - sleep 1 + 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 +trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. -"$prog" $args -status=$? +"$@" +ret=$? if test -f "$cofile"; then - mv "$cofile" "$ofile" + mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + mv "${cofile}bj" "$ofile" fi -rmdir $lockdir -exit $status +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: Index: libgcrypt/config.guess diff -u libgcrypt/config.guess:1.2 libgcrypt/config.guess:1.2.2.1 --- libgcrypt/config.guess:1.2 Tue Apr 6 15:24:24 2004 +++ libgcrypt/config.guess Tue Jan 4 21:50:23 2005 @@ -1,9 +1,9 @@ #! /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. +# 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. -timestamp='2004-01-05' +timestamp='2004-08-13' # 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 @@ -53,7 +53,7 @@ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO @@ -197,15 +197,21 @@ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit 0 ;; + amd64:OpenBSD:*:*) + echo x86_64-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; amiga:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; - arc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} + cats:OpenBSD:*:*) + echo arm-unknown-openbsd${UNAME_RELEASE} exit 0 ;; hp300:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; + luna88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; mac68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; @@ -221,28 +227,33 @@ 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} + echo mips64-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 ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit 0 ;; + macppc:MirBSD:*:*) + echo powerppc-unknown-mirbsd${UNAME_RELEASE} + exit 0 ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit 0 ;; alpha:OSF1:*:*) - if test $UNAME_RELEASE = "V4.0"; then + case $UNAME_RELEASE in + *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - fi + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac # 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 @@ -280,14 +291,12 @@ "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac + # A Pn.n version is a patched version. # 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 + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit 0 ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? @@ -405,6 +414,9 @@ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit 0 ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit 0 ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit 0 ;; @@ -740,7 +752,7 @@ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; *:UNICOS/mp:*:*) - echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo craynv-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'` @@ -763,21 +775,7 @@ 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} + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit 0 ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin @@ -829,6 +827,9 @@ ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; @@ -1069,9 +1070,9 @@ M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit 0 ;; - M68*:*:R3V[567]*:*) + M68*:*:R3V[5678]*:*) 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) + 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 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` @@ -1169,9 +1170,10 @@ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Darwin:*:*) - case `uname -p` in + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in *86) UNAME_PROCESSOR=i686 ;; - powerpc) UNAME_PROCESSOR=powerpc ;; + unknown) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit 0 ;; @@ -1230,9 +1232,16 @@ SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit 0 ;; - *:DRAGONFLY:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly${UNAME_RELEASE} + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit 0 ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms && exit 0 ;; + I*) echo ia64-dec-vms && exit 0 ;; + V*) echo vax-dec-vms && exit 0 ;; + esac esac #echo '(No uname command or uname output not recognized.)' 1>&2 Index: libgcrypt/config.sub diff -u libgcrypt/config.sub:1.2 libgcrypt/config.sub:1.2.2.1 --- libgcrypt/config.sub:1.2 Tue Apr 6 15:24:24 2004 +++ libgcrypt/config.sub Tue Jan 4 21:50:23 2005 @@ -1,9 +1,9 @@ #! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +# 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. -timestamp='2004-01-05' +timestamp='2004-06-24' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software @@ -70,7 +70,7 @@ version="\ GNU config.sub ($timestamp) -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO @@ -145,7 +145,7 @@ -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) + -apple | -axis | -knuth | -cray) os= basic_machine=$1 ;; @@ -237,7 +237,7 @@ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ - | m32r | m68000 | m68k | m88k | mcore \ + | m32r | m32rle | m68000 | m68k | m88k | mcore \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ @@ -262,7 +262,7 @@ | 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 \ + | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv8 | sparcv9 | sparcv9b \ | strongarm \ | tahoe | thumb | tic4x | tic80 | tron \ | v850 | v850e \ @@ -300,7 +300,7 @@ | avr-* \ | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ - | clipper-* | cydra-* \ + | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ @@ -308,7 +308,7 @@ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ - | m32r-* \ + | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | mcore-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ @@ -326,8 +326,9 @@ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ + | mmix-* \ | msp430-* \ - | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ @@ -336,7 +337,7 @@ | 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?-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tron-* \ @@ -363,6 +364,9 @@ basic_machine=a29k-amd os=-udi ;; + abacus) + basic_machine=abacus-unknown + ;; adobe68k) basic_machine=m68010-adobe os=-scout @@ -442,12 +446,24 @@ basic_machine=j90-cray os=-unicos ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16c) + basic_machine=cr16c-unknown + os=-elf + ;; crds | unos) basic_machine=m68k-crds ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; da30 | da30-*) basic_machine=m68k-da30 ;; @@ -648,10 +664,6 @@ 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 @@ -732,10 +744,6 @@ np1) basic_machine=np1-gould ;; - nv1) - basic_machine=nv1-cray - os=-unicosmp - ;; nsr-tandem) basic_machine=nsr-tandem ;; @@ -1048,6 +1056,9 @@ romp) basic_machine=romp-ibm ;; + mmix) + basic_machine=mmix-knuth + ;; rs6000) basic_machine=rs6000-ibm ;; @@ -1070,7 +1081,7 @@ sh64) basic_machine=sh64-unknown ;; - sparc | sparcv9 | sparcv9b) + sparc | sparcv8 | sparcv9 | sparcv9b) basic_machine=sparc-sun ;; cydra) @@ -1143,8 +1154,9 @@ | -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* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* \ @@ -1362,6 +1374,9 @@ *-ibm) os=-aix ;; + *-knuth) + os=-mmixware + ;; *-wec) os=-proelf ;; Index: libgcrypt/depcomp diff -u libgcrypt/depcomp:1.1 libgcrypt/depcomp:1.1.2.1 --- libgcrypt/depcomp:1.1 Mon Dec 8 22:42:35 2003 +++ libgcrypt/depcomp Tue Jan 4 21:50:23 2005 @@ -1,7 +1,9 @@ #! /bin/sh - # depcomp - compile a program generating dependencies as side-effects -# Copyright 1999, 2000 Free Software Foundation, Inc. + +scriptversion=2004-05-31.23 + +# Copyright (C) 1999, 2000, 2003, 2004 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 @@ -25,22 +27,45 @@ # Originally written by Alexandre Oliva . +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by `PROGRAMS ARGS'. + object Object file output by `PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputing dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit 0 + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit 0 + ;; +esac + 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 +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" @@ -172,19 +197,25 @@ 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/'` + # in a .u file. In older versions, 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. + # Version 6 uses the directory in both cases. + stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` tmpdepfile="$stripped.u" - outname="$stripped.o" if test "$libtool" = yes; then "$@" -Wc,-M else "$@" -M fi - stat=$? + + if test -f "$tmpdepfile"; then : + else + stripped=`echo "$stripped" | sed 's,^.*/,,'` + tmpdepfile="$stripped.u" + fi + if test $stat -eq 0; then : else rm -f "$tmpdepfile" @@ -192,6 +223,7 @@ fi if test -f "$tmpdepfile"; then + outname="$stripped.o" # 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:'. @@ -255,31 +287,40 @@ base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then + # Dependencies are output in .lo.d with libtool 1.4. + # With libtool 1.5 they are output both in $dir.libs/$base.o.d + # and in $dir.libs/$base.o.d and $dir$base.o.d. We process the + # latter, because the former will be cleaned when $dir.libs is + # erased. tmpdepfile1="$dir.libs/$base.lo.d" - tmpdepfile2="$dir.libs/$base.d" + tmpdepfile2="$dir$base.o.d" + tmpdepfile3="$dir.libs/$base.d" "$@" -Wc,-MD else tmpdepfile1="$dir$base.o.d" tmpdepfile2="$dir$base.d" + tmpdepfile3="$dir$base.d" "$@" -MD fi stat=$? if test $stat -eq 0; then : else - rm -f "$tmpdepfile1" "$tmpdepfile2" + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi if test -f "$tmpdepfile1"; then tmpdepfile="$tmpdepfile1" - else + elif test -f "$tmpdepfile2"; then tmpdepfile="$tmpdepfile2" + else + tmpdepfile="$tmpdepfile3" 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" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi @@ -292,7 +333,7 @@ dashmstdout) # Important note: in order to support this mode, a compiler *must* - # always write the proprocessed file to stdout, regardless of -o. + # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. @@ -388,7 +429,7 @@ cpp) # Important note: in order to support this mode, a compiler *must* - # always write the proprocessed file to stdout. + # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. @@ -430,7 +471,7 @@ msvisualcpp) # Important note: in order to support this mode, a compiler *must* - # always write the proprocessed file to stdout, regardless of -o, + # always write the preprocessed file to stdout, regardless of -o, # because we must use -o when running libtool. "$@" || exit $? IFS=" " @@ -470,3 +511,12 @@ esac exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: Index: libgcrypt/doc/ChangeLog diff -u libgcrypt/doc/ChangeLog:1.38.2.2 libgcrypt/doc/ChangeLog:1.38.2.3 --- libgcrypt/doc/ChangeLog:1.38.2.2 Tue Jan 4 21:13:48 2005 +++ libgcrypt/doc/ChangeLog Tue Jan 4 21:50:23 2005 @@ -1,7 +1,13 @@ 2005-01-04 Werner Koch * gcrypt.texi: Updated to use @copying. Fixed list of copyright - years; we had real changes in 2004. + years; we had real changes in 2004. Fixed some formatting issues. + + Merged in changes from the devel branch by Moritz Schulte: + + * gcrypt.texi (Miscellaneous): Document gcry_mpi_randomize. + (Multi Threading): Document GCRY_THREAD_OPTION_PTH_IMPL, + GCRY_THREAD_OPTION_PTHREAD_IMPL. 2004-05-07 Moritz Schulte Index: libgcrypt/doc/gcrypt.texi diff -u libgcrypt/doc/gcrypt.texi:1.38.2.2 libgcrypt/doc/gcrypt.texi:1.38.2.3 --- libgcrypt/doc/gcrypt.texi:1.38.2.2 Tue Jan 4 21:13:48 2005 +++ libgcrypt/doc/gcrypt.texi Tue Jan 4 21:50:23 2005 @@ -39,7 +39,7 @@ @subtitle Version @value{VERSION} @subtitle @value{UPDATED} @author Werner Koch (@email{wk@@gnupg.org}) -@author Moritz Schulte (@email{mo@g10code.com}) +@author Moritz Schulte (@email{mo@@g10code.com}) @page @vskip 0pt plus 1filll @@ -64,7 +64,7 @@ * Preparation:: What you should do before using the library. * Generalities:: General library functions and data types. * Handler Functions:: Working with handler functions. -* Symmetric cryptography:: How to use symmetric crytography. +* Symmetric cryptography:: How to use symmetric cryptography. * Hashing:: How to use hashing. * Public Key cryptography (I):: How to use public key cryptography. * Public Key cryptography (II):: How to use public key cryptography, alternatively. @@ -96,12 +96,12 @@ Preparation * Header:: What header file you need to include. * Building sources:: How to build sources using the library. -* Building sources using Automake:: How to build sources with the help auf Automake. +* Building sources using Automake:: How to build sources with the help of Automake. * Initializing the library:: How to initialize the library. * Multi Threading:: How @acronym{Libgcrypt} can be used in a MT environment. Generalities -* Controlling the library:: Controlling @acronym{Libgcrypt}'s behaviour. +* Controlling the library:: Controlling @acronym{Libgcrypt}'s behavior. * Modules:: Description of extension modules. * Error Handling:: Error codes and such. @@ -153,7 +153,7 @@ * Calculations:: Performing MPI calculations. * Comparisons:: How to compare MPI values. * Bit manipulations:: How to access single bits of MPI values. -* Misc:: Miscellaneous MPI functions. +* Miscellaneous:: Miscellaneous MPI functions. Utilities * Memory allocation:: Functions related with memory allocation. @@ -219,16 +219,16 @@ @end table - @node Overview @section Overview +@noindent The `@acronym{Libgcrypt}' library is fully thread-safe, where it makes sense to be thread-safe. An exception for thread-safety are some cryptographic functions that modify a certain context stored in handles. If the user really intents to use such functions from different threads on the same handle, he has to take care of the -serialisation of such functions himself. If not described otherwise, +serialization of such functions himself. If not described otherwise, every function is thread-safe. @acronym{Libgcrypt} depends on the library `libgpg-error', which @@ -249,7 +249,7 @@ @menu * Header:: What header file you need to include. * Building sources:: How to build sources using the library. -* Building sources using Automake:: How to build sources with the help auf Automake. +* Building sources using Automake:: How to build sources with the help of Automake. * Initializing the library:: How to initialize the library. * Multi Threading:: How @acronym{Libgcrypt} can be used in a MT environment. @end menu @@ -390,24 +390,24 @@ @strong{before} any other function in the library. This is easy enough if you are indeed writing an application using -libgcrypt. It is rather problematic if you are writing a library +Libgcrypt. It is rather problematic if you are writing a library instead. Here are some tips what to do if you are writing a library: If your library requires a certain thread package, just initialize -gcrypt to use this thread package. If your library supports multiple +Libgcrypt to use this thread package. If your library supports multiple thread packages, but needs to be configured, you will have to implement a way to determine which thread package the application -wants to use with your library anyway. Then configure gcrypt to use +wants to use with your library anyway. Then configure Libgcrypt to use this thread package. If your library is fully reentrant without any special support by a thread package, then you are lucky indeed. Unfortunately, this does not relieve you from doing either of the two above, or use a third -option. The third option is to let the application initialize gcrypt -for you. Then you are not using gcrypt transparently, though. +option. The third option is to let the application initialize Libgcrypt +for you. Then you are not using Libgcrypt transparently, though. As if this was not difficult enough, a conflict may arise if two -libraries try to initialize gcrypt independently of each others, and +libraries try to initialize Libgcrypt independently of each others, and both such libraries are then linked into the same application. To make it a bit simpler for you, this will probably work, but only if both libraries have the same requirement for the thread package. This @@ -418,7 +418,7 @@ @item The function @code{gcry_check_version} must be called before any other function in the library, except the @code{GCRYCTL_SET_THREAD_CBS} -command (called via the @code{gcry_control} function0, because it +command (called via the @code{gcry_control} function), because it initializes the thread support subsystem in @acronym{Libgcrypt}. To achieve this in multi-threaded programs, you must synchronize the memory with respect to other threads that also want to use @@ -433,11 +433,42 @@ strict rules may apply.}. @item + As with the function @code{gpg_strerror}, @code{gcry_strerror} is not thread safe. You have to use @code{gpg_strerror_r} instead. @end itemize +@acronym{Libgcrypt} contains convenient macros, which define the +necessary thread callbacks for PThread and for GNU Pth: + +@table @code +@item GCRY_THREAD_OPTION_PTH_IMPL + +This macro defines the following (static) symbols: gcry_pth_init, +gcry_pth_mutex_init, gcry_pth_mutex_destroy, gcry_pth_mutex_lock, +gcry_pth_mutex_unlock, gcry_pth_read, gcry_pth_write, gcry_pth_select, +gcry_pth_waitpid, gcry_pth_accept, gcry_pth_connect, gcry_threads_pth. + +After including this macro, gcry_control() shall be used with a +command of GCRYCTL_SET_THREAD_CBS in order to register the thread +callback structure named ``gcry_threads_pth''. + +@item GCRY_THREAD_OPTION_PTHREAD_IMPL + +This macro defines the following (static) symbols: +gcry_pthread_mutex_init, gcry_pthread_mutex_destroy, gcry_mutex_lock, +gcry_mutex_unlock, gcry_threads_pthread. + +After including this macro, gcry_control() shall be used with a +command of GCRYCTL_SET_THREAD_CBS in order to register the thread +callback structure named ``gcry_threads_pthread''. +@end table + +Note that these macros need to be terminated with a semicolon. Keep +in mind that these are convenient macros for C programmers; C++ +programmers might have to wrap these macros in an ``extern C'' body. + @c ********************************************************** @c ******************* General **************************** @c ********************************************************** @@ -445,7 +476,7 @@ @chapter Generalities @menu -* Controlling the library:: Controlling @acronym{Libgcrypt}'s behaviour. +* Controlling the library:: Controlling @acronym{Libgcrypt}'s behavior. * Modules:: Description of extension modules. * Error Handling:: Error codes and such. @end menu @@ -455,7 +486,7 @@ @deftypefun gcry_error_t gcry_control (enum gcry_ctl_cmds @var{cmd}, ...) -This function can be used to influence the general behaviour of +This function can be used to influence the general behavior of @acronym{Libgcrypt} in several ways. Depending on @var{cmd}, more arguments can or have to be provided. @@ -476,7 +507,7 @@ specification structure' as input and return a value of @code{gcry_module_t} and an ID that is unique in the modules' category. This ID can be used to reference the newly registered -module. After registering a module successfuly, the new functionality +module. After registering a module successfully, the new functionality should be able to be used through the normal functions provided by @acronym{Libgcrypt} until it is unregistered again. @@ -524,7 +555,7 @@ Some error values do not indicate a system error or an error in the operation, but the result of an operation that failed properly. -GnuPG components, including libgcrypt, use an extra library named +GnuPG components, including Libgcrypt, use an extra library named libgpg-error to provide a common error handling scheme. For more information on libgpg-error, see the according manual. @@ -575,7 +606,7 @@ the error value are set to 0, too. Note that in @acronym{Libgcrypt}, the error source is used purely for -diagnostical purposes. Only the error code should be checked to test +diagnostic 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. @@ -621,7 +652,7 @@ 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. +errno numbers. @deftypefun {gcry_error_t} gcry_err_make_from_errno (@w{gcry_err_source_t @var{source}}, @w{int @var{err}}) The function @code{gcry_err_make_from_errno} is like @@ -1222,8 +1253,7 @@ To use a cipher algorithm, you must first allocate an according handle. This is to be done using the open function: -@deftypefun gcry_error_t gcry_cipher_open (gcry_cipher_hd_t *@var{hd}, -int @var{algo}, int @var{mode}, unsigned int @var{flags}) +@deftypefun gcry_error_t gcry_cipher_open (gcry_cipher_hd_t *@var{hd}, int @var{algo}, int @var{mode}, unsigned int @var{flags}) This function creates the context handle required for most of the other cipher functions and returns a handle to it in `hd'. In case of @@ -1698,8 +1728,7 @@ If the flag @code{GCRY_MD_FLAG_HMAC} was used, the key for the MAC must be set using the function: -@deftypefun gcry_error_t gcry_md_setkey (gcry_md_hd_t @var{h}, const void *@var{key}, -size_t @var{keylen}) +@deftypefun gcry_error_t gcry_md_setkey (gcry_md_hd_t @var{h}, const void *@var{key}, size_t @var{keylen}) For use with the HMAC feature, set the MAC key to the value of @var{key} of length @var{keylen}. @@ -2181,10 +2210,13 @@ @node Cryptographic Functions @section Cryptographic Functions +@noindent Note, that we will in future allow to use keys without p,q and u specified and may also support other parameters for performance reasons. +@noindent + Some functions operating on S-expressions support `flags', that influence the operation. These flags have to be listed in a sub-S-expression named `flags'; the following flags are known: @@ -2697,8 +2729,7 @@ Destroys the data set @var{data}. @end deftypefun -@deftypefun gcry_error_t gcry_ac_data_set (gcry_ac_data_t @var{data}, -unsigned int @var{flags}, char *@var{name}, gcry_mpi_t @var{mpi}) +@deftypefun gcry_error_t gcry_ac_data_set (gcry_ac_data_t @var{data}, unsigned int @var{flags}, char *@var{name}, gcry_mpi_t @var{mpi}) Add the value @var{mpi} to @var{data} with the label @var{name}. If @var{flags} contains GCRY_AC_FLAG_DATA_COPY, the data set will contain copies of @var{name} and @var{mpi}. If @var{flags} contains @@ -2716,16 +2747,13 @@ @var{data}. @end deftypefun -@deftypefun gcry_error_t gcry_ac_data_get_name (gcry_ac_data_t @var{data}, -unsigned int @var{flags}, char *@var{name}, gcry_mpi_t *@var{mpi}) +@deftypefun gcry_error_t gcry_ac_data_get_name (gcry_ac_data_t @var{data}, unsigned int @var{flags}, char *@var{name}, gcry_mpi_t *@var{mpi}) Store the value labelled with @var{name} found in @var{data} in @var{mpi}. If @var{flags} contains GCRY_AC_FLAG_COPY, store a copy of the @var{mpi} value contained in the data set. @var{mpi} may be NULL. @end deftypefun -@deftypefun gcry_error_t gcry_ac_data_get_index (gcry_ac_data_t @var{data}, -unsigned int flags, unsigned int @var{index}, -const char **@var{name}, gcry_mpi_t *@var{mpi}) +@deftypefun gcry_error_t gcry_ac_data_get_index (gcry_ac_data_t @var{data}, unsigned int flags, unsigned int @var{index}, const char **@var{name}, gcry_mpi_t *@var{mpi}) Stores in @var{name} and @var{mpi} the named @var{mpi} value contained in the data set @var{data} with the index @var{idx}. If @var{flags} contains GCRY_AC_FLAG_COPY, store copies of the values contained in @@ -2742,8 +2770,7 @@ In order to use an algorithm, an according handle must be created. This is done using the following function: -@deftypefun gcry_error_t gcry_ac_open (gcry_ac_handle_t *@var{handle}, -int @var{algorithm}, int @var{flags}) +@deftypefun gcry_error_t gcry_ac_open (gcry_ac_handle_t *@var{handle}, int @var{algorithm}, int @var{flags}) Creates a new handle for the algorithm @var{algorithm} and stores it in @var{handle}. @var{flags} is not used yet. @@ -2791,9 +2818,7 @@ contained in the data set @var{data} and stores it in @var{key}. @end deftypefun -@deftypefun gcry_error_t gcry_ac_key_pair_generate (gcry_ac_handle_t @var{handle}, -unsigned int @var{nbits}, void *@var{key_spec}, gcry_ac_key_pair_t *@var{key_pair}, -gcry_mpi_t **@var{misc_data}) +@deftypefun gcry_error_t gcry_ac_key_pair_generate (gcry_ac_handle_t @var{handle}, unsigned int @var{nbits}, void *@var{key_spec}, gcry_ac_key_pair_t *@var{key_pair}, gcry_mpi_t **@var{misc_data}) Generates a new key pair via the handle @var{handle} of @var{NBITS} bits and stores it in @var{key_pair}. @@ -2866,13 +2891,11 @@ Verifies that the private key @var{key} is sane via @var{handle}. @end deftypefun -@deftypefun gcry_error_t gcry_ac_key_get_nbits (gcry_ac_handle_t @var{handle}, -gcry_ac_key_t @var{key}, unsigned int *@var{nbits}) +@deftypefun gcry_error_t gcry_ac_key_get_nbits (gcry_ac_handle_t @var{handle}, gcry_ac_key_t @var{key}, unsigned int *@var{nbits}) Stores the number of bits of the key @var{key} in @var{nbits} via @var{handle}. @end deftypefun -@deftypefun gcry_error_t gcry_ac_key_get_grip (gcry_ac_handle_t @var{handle}, -gcry_ac_key_t @var{key}, unsigned char *@var{key_grip}) +@deftypefun gcry_error_t gcry_ac_key_get_grip (gcry_ac_handle_t @var{handle}, gcry_ac_key_t @var{key}, unsigned char *@var{key_grip}) Writes the 20 byte long key grip of the key @var{key} to @var{key_grip} via @var{handle}. @end deftypefun @@ -3248,7 +3271,7 @@ * Calculations:: Performing MPI calculations. * Comparisons:: How to compare MPI values. * Bit manipulations:: How to access single bits of MPI values. -* Misc:: Misc, fixme. +* Miscellaneous:: Miscellaneous MPI functions. @end menu Public key cryptography is based on mathematics with large numbers. To @@ -3559,19 +3582,15 @@ result in @var{x}. @end deftypefun -@node Misc -@section Misc - -@noindent -The remaining MPI functions take care of very special properties of the -implementation: +@node Miscellaneous +@section Miscellanous @deftypefun gcry_mpi_t gcry_mpi_set_opaque (@w{gcry_mpi_t @var{a}}, @w{void *@var{p}}, @w{unsigned int @var{nbits}}) Store @var{nbits} of the value @var{p} points to in @var{a} and mark @var{a} as an opaque value (i.e. an value that can't be used for any math calculation and is only used to store an arbitrary bit pattern in -@var{a}. +@var{a}). WARNING: Never use an opaque MPI for actual math operations. The only valid functions are gcry_mpi_get_opaque and gcry_mpi_release. Use @@ -3605,6 +3624,14 @@ Return true when the @var{flag} is set for @var{a}. @end deftypefun +@deftypefun void gcry_mpi_randomize (@w{gcry_mpi_t @var{w}}, @w{unsigned int @var{nbits}}, @w{enum gcry_random_level @var{level}}) + +Set the big integer @var{w} to a random value of @var{nbits}, using +random data quality of level @var{level}. In case @var{nbits} is not +a multiple of a byte, @var{nbits} is rounded up to the next byte +boundary. +@end deftypefun + @node Utilities @chapter Utilities @@ -3724,3 +3751,6 @@ @c LocalWords: int HD + + + Index: libgcrypt/doc/mdate-sh diff -u libgcrypt/doc/mdate-sh:1.1 libgcrypt/doc/mdate-sh:1.1.2.1 --- libgcrypt/doc/mdate-sh:1.1 Mon Dec 8 22:42:34 2003 +++ libgcrypt/doc/mdate-sh Tue Jan 4 21:50:23 2005 @@ -1,5 +1,8 @@ #!/bin/sh # Get modification time of a file or directory and pretty-print it. + +scriptversion=2003-11-09.00 + # Copyright (C) 1995, 1996, 1997, 2003 Free Software Foundation, Inc. # written by Ulrich Drepper , June 1995 # @@ -22,6 +25,31 @@ # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +case $1 in + '') + echo "$0: No file. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: mdate-sh [--help] [--version] FILE + +Pretty-print the modification time of FILE. + +Report bugs to . +EOF + exit 0 + ;; + -v | --v*) + echo "mdate-sh $scriptversion" + exit 0 + ;; +esac + # Prevent date giving response in another language. LANG=C export LANG @@ -131,3 +159,12 @@ # The result. echo $day $month $year + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: Index: libgcrypt/doc/texinfo.tex diff -u libgcrypt/doc/texinfo.tex:1.1 libgcrypt/doc/texinfo.tex:1.1.2.1 --- libgcrypt/doc/texinfo.tex:1.1 Mon Dec 8 22:42:34 2003 +++ libgcrypt/doc/texinfo.tex Tue Jan 4 21:50:23 2005 @@ -3,10 +3,11 @@ % 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} +\def\texinfoversion{2004-10-31.06} % % Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995, -% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 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 @@ -23,21 +24,16 @@ % 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! +% As a special exception, when this file is read by TeX when processing +% a Texinfo source document, you may use the result without +% restriction. (This has been our intent since Texinfo was invented.) % % 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) +% http://www.gnu.org/software/texinfo/ (the Texinfo home page), or % 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 +% (and all CTAN mirrors, see http://www.ctan.org). +% The texinfo.tex in any given 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 @@ -59,6 +55,9 @@ % 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. +% +% The GNU Texinfo home page is http://www.gnu.org/software/texinfo. + \message{Loading texinfo [version \texinfoversion]:} @@ -85,10 +84,13 @@ \let\ptexend=\end \let\ptexequiv=\equiv \let\ptexexclam=\! +\let\ptexfootnote=\footnote \let\ptexgtr=> \let\ptexhat=^ \let\ptexi=\i \let\ptexindent=\indent +\let\ptexnoindent=\noindent +\let\ptexinsert=\insert \let\ptexlbrace=\{ \let\ptexless=< \let\ptexplus=+ @@ -101,6 +103,15 @@ % starts a new line in the output. \newlinechar = `^^J +% 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{l.\the\inputlineno:\space} +\fi + % Set up fixed words for English if not already set. \ifx\putwordAppendix\undefined \gdef\putwordAppendix{Appendix}\fi \ifx\putwordChapter\undefined \gdef\putwordChapter{Chapter}\fi @@ -139,43 +150,81 @@ \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 = `\_ +\chardef\spaceChar = `\ % +\chardef\spacecat = 10 +\def\spaceisspace{\catcode\spaceChar=\spacecat} + % 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}% +% The following is used inside several \edef's. +\def\makecsname#1{\expandafter\noexpand\csname#1\endcsname} % Hyphenation fixes. -\hyphenation{ap-pen-dix} -\hyphenation{eshell} -\hyphenation{mini-buf-fer mini-buf-fers} -\hyphenation{time-stamp} -\hyphenation{white-space} +\hyphenation{ + Flor-i-da Ghost-script Ghost-view Mac-OS Post-Script + ap-pen-dix bit-map bit-maps + data-base data-bases eshell fall-ing half-way long-est man-u-script + man-u-scripts mini-buf-fer mini-buf-fers over-view par-a-digm + par-a-digms rath-er rec-tan-gu-lar ro-bot-ics se-vere-ly set-up spa-ces + spell-ing spell-ings + stand-alone strong-est time-stamp time-stamps which-ever white-space + wide-spread wrap-around +} % Margin to add to right of even pages, to left of odd pages. \newdimen\bindingoffset \newdimen\normaloffset \newdimen\pagewidth \newdimen\pageheight +% 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} + +% @| 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 + }% + }% +} + % 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 @@ -200,7 +249,7 @@ \tracingassigns1 \fi \tracingcommands3 % 3 gives us more in etex - \errorcontextlines\maxdimen + \errorcontextlines16 }% % add check for \lastpenalty to plain's definitions. If the last thing @@ -258,7 +307,7 @@ % 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 + \ifpdfmakepagedest \pdfdest name{\the\pageno} xyz\fi % \ifcropmarks \vbox to \outervsize\bgroup \hsize = \outerhsize @@ -339,132 +388,162 @@ % 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% +\def\parsearg{\parseargusing{}} +\def\parseargusing#1#2{% + \def\next{#2}% \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 + \spaceisspace + #1% + \parseargline\empty% Insert the \empty token, see \finishparsearg below. } -% 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}% + \argremovecomment #1\comment\ArgTerm% }% } -% 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}} +% First remove any @comment, then any @c comment. +\def\argremovecomment#1\comment#2\ArgTerm{\argremovec #1\c\ArgTerm} +\def\argremovec#1\c#2\ArgTerm{\argcheckspaces#1\^^M\ArgTerm} -% \argremovec{,omment} might leave us with trailing spaces, though; e.g., +% Each occurence of `\^^M' or `\^^M' is replaced by a single space. +% +% \argremovec might leave us with trailing space, 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. +% This space token undergoes the same procedure and is eventually removed +% by \finishparsearg. % -\def\removeactivespaces#1{% - \begingroup - \ignoreactivespaces - \edef\temp{#1}% - \global\toks0 = \expandafter{\temp}% - \endgroup +\def\argcheckspaces#1\^^M{\argcheckspacesX#1\^^M \^^M} +\def\argcheckspacesX#1 \^^M{\argcheckspacesY#1\^^M} +\def\argcheckspacesY#1\^^M#2\^^M#3\ArgTerm{% + \def\temp{#3}% + \ifx\temp\empty + % We cannot use \next here, as it holds the macro to run; + % thus we reuse \temp. + \let\temp\finishparsearg + \else + \let\temp\argcheckspaces + \fi + % Put the space token in: + \temp#1 #3\ArgTerm } -% Change the active space to expand to nothing. +% If a _delimited_ argument is enclosed in braces, they get stripped; so +% to get _exactly_ the rest of the line, we had to prevent such situation. +% We prepended an \empty token at the very beginning and we expand it now, +% just before passing the control to \next. +% (Similarily, we have to think about #3 of \argcheckspacesY above: it is +% either the null string, or it ends with \^^M---thus there is no danger +% that a pair of braces would be stripped. % -\begingroup - \obeyspaces - \gdef\ignoreactivespaces{\obeyspaces\let =\empty} -\endgroup +% But first, we have to remove the trailing space token. +% +\def\finishparsearg#1 \ArgTerm{\expandafter\next\expandafter{#1}} +% \parseargdef\foo{...} +% is roughly equivalent to +% \def\foo{\parsearg\Xfoo} +% \def\Xfoo#1{...} +% +% Actually, I use \csname\string\foo\endcsname, ie. \\foo, as it is my +% favourite TeX trick. --kasal, 16nov03 -\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} +\def\parseargdef#1{% + \expandafter \doparseargdef \csname\string#1\endcsname #1% +} +\def\doparseargdef#1#2{% + \def#2{\parsearg#1}% + \def#1##1% +} -%% 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 +% Several utility definitions with active space: +{ + \obeyspaces + \gdef\obeyedspace{ } -% @begin foo is the same as @foo, for now. -\newhelp\EMsimple{Press RETURN to continue.} + % 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. + % + \gdef\sepspaces{\obeyspaces\let =\tie} + + % 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 \ ). + \gdef\unsepspaces{\let =\space} +} -\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} +\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} -% @end foo executes the definition of \Efoo. +% Define the framework for environments in texinfo.tex. It's used like this: % -\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 +% \envdef\foo{...} +% \def\Efoo{...} +% +% It's the responsibility of \envdef to insert \begingroup before the +% actual body; @end closes the group after calling \Efoo. \envdef also +% defines \thisenv, so the current environment is known; @end checks +% whether the environment name matches. The \checkenv macro can also be +% used to check whether the current environment is the one expected. +% +% Non-false conditionals (@iftex, @ifset) don't fit into this, so they +% are not treated as enviroments; they don't open a group. (The +% implementation of @end takes care not to call \endgroup in this +% special case.) + + +% At runtime, environments start with this: +\def\startenvironment#1{\begingroup\def\thisenv{#1}} +% initialize +\let\thisenv\empty + +% ... but they get defined via ``\envdef\foo{...}'': +\long\def\envdef#1#2{\def#1{\startenvironment#1#2}} +\def\envparseargdef#1#2{\parseargdef#1{\startenvironment#1#2}} + +% Check whether we're in the right environment: +\def\checkenv#1{% + \def\temp{#1}% + \ifx\thisenv\temp \else - % Everything's ok; the right environment has been started. - \csname E\endthing\endcsname + \badenverr \fi } -% There is an environment #1, but it hasn't been started. Give an error. -% -\def\unmatchedenderror#1{% +% Evironment mismatch, #1 expected: +\def\badenverr{% \errhelp = \EMsimple - \errmessage{This `@end #1' doesn't have a matching `@#1'}% + \errmessage{This command can appear only \inenvironment\temp, + not \inenvironment\thisenv}% +} +\def\inenvironment#1{% + \ifx#1\empty + out of any environment% + \else + in environment \expandafter\string#1% + \fi } -% Define the control sequence \E#1 to give an unmatched @end error. +% @end foo executes the definition of \Efoo. +% But first, it executes a specialized version of \checkenv % -\def\defineunmatchedend#1{% - \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}% +\parseargdef\end{% + \if 1\csname iscond.#1\endcsname + \else + % The general wording of \badenverr may not be ideal, but... --kasal, 06nov03 + \expandafter\checkenv\csname#1\endcsname + \csname E#1\endcsname + \endgroup + \fi } +\newhelp\EMsimple{Press RETURN to continue.} + %% Simple single-character @ commands @@ -496,6 +575,9 @@ !gdef!rbraceatcmd[@}]% !endgroup +% @comma{} to avoid , parsing problems. +\let\comma = , + % Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent % Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H. \let\, = \c @@ -505,10 +587,12 @@ \let\ubaraccent = \b \let\udotaccent = \d -% Other special characters: @questiondown @exclamdown +% Other special characters: @questiondown @exclamdown @ordf @ordm % Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss. \def\questiondown{?`} \def\exclamdown{!`} +\def\ordf{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{a}}} +\def\ordm{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{o}}} % Dotless i and dotless j, used for accents. \def\imacro{i} @@ -521,6 +605,25 @@ \fi\fi } +% The \TeX{} logo, as in plain, but resetting the spacing so that a +% period following counts as ending a sentence. (Idea found in latex.) +% +\edef\TeX{\TeX \spacefactor=1000 } + +% @LaTeX{} logo. Not quite the same results as the definition in +% latex.ltx, since we use a different font for the raised A; it's most +% convenient for us to use an explicitly smaller font, rather than using +% the \scriptstyle font (since we don't reset \scriptstyle and +% \scriptscriptstyle). +% +\def\LaTeX{% + L\kern-.36em + {\setbox0=\hbox{T}% + \vbox to \ht0{\hbox{\selectfonts\lllsize A}\vss}}% + \kern-.15em + \TeX +} + % 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 @@ -574,59 +677,14 @@ \newbox\groupbox \def\vfilllimit{0.7} % -\def\group{\begingroup - \ifnum\catcode13=\active \else +\envdef\group{% + \ifnum\catcode`\^^M=\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. - }% + \startsavinginserts % \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 @@ -636,6 +694,32 @@ \comment } % +% The \vtop 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. Thus, space below is not quite equal to space +% above. But it's pretty close. +\def\Egroup{% + % To get correct interline space between the last line of the group + % and the first line afterwards, we have to propagate \prevdepth. + \endgraf % Not \par, as it may have been set to \lisppar. + \global\dimen1 = \prevdepth + \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 + \box\groupbox + \prevdepth = \dimen1 + \checkinserts +} +% % TeX puts in an \escapechar (i.e., `@') at the beginning of the help % message, so this ends up printing `@group can only ...'. % @@ -648,10 +732,8 @@ \newdimen\mil \mil=0.001in -\def\need{\parsearg\needx} - % Old definition--didn't work. -%\def\needx #1{\par % +%\parseargdef\need{\par % %% This method tries to make TeX break the page naturally %% if the depth of the box does not fit. %{\baselineskip=0pt% @@ -659,7 +741,7 @@ %\prevdepth=-1000pt %}} -\def\needx#1{% +\parseargdef\need{% % Ensure vertical mode, so we don't make a big box in the middle of a % paragraph. \par @@ -698,35 +780,10 @@ \fi } -% @br forces paragraph break +% @br forces paragraph break (and is undocumented). \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} @@ -739,13 +796,11 @@ \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}} +\parseargdef\exdent{\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}}}} +\parseargdef\nofillexdent{{\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 @@ -797,8 +852,19 @@ } % @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 +% +\def\include{\parseargusing\filenamecatcodes\includezzz} +\def\includezzz#1{% + \pushthisfilestack + \def\thisfile{#1}% + {% + \makevalueexpandable + \def\temp{\input #1 }% + \expandafter + }\temp + \popthisfilestack +} +\def\filenamecatcodes{% \catcode`\\=\other \catcode`~=\other \catcode`^=\other @@ -807,33 +873,50 @@ \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} + \catcode`-=\other +} + +\def\pushthisfilestack{% + \expandafter\pushthisfilestackX\popthisfilestack\StackTerm +} +\def\pushthisfilestackX{% + \expandafter\pushthisfilestackY\thisfile\StackTerm +} +\def\pushthisfilestackY #1\StackTerm #2\StackTerm {% + \gdef\popthisfilestack{\gdef\thisfile{#1}\gdef\popthisfilestack{#2}}% +} + +\def\popthisfilestack{\errthisfilestackempty} +\def\errthisfilestackempty{\errmessage{Internal error: + the stack of filenames is empty.}} \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 -}} +\parseargdef\center{% + \ifhmode + \let\next\centerH + \else + \let\next\centerV + \fi + \next{\hfil \ignorespaces#1\unskip \hfil}% +} +\def\centerH#1{% + {% + \hfil\break + \advance\hsize by -\leftskip + \advance\hsize by -\rightskip + \line{#1}% + \break + }% +} +\def\centerV#1{\line{\kern\leftskip #1\kern\rightskip}} % @sp n outputs n lines of vertical space -\def\sp{\parsearg\spxxx} -\def\spxxx #1{\vskip #1\baselineskip} +\parseargdef\sp{\vskip #1\baselineskip} % @comment ...line which is ignored... % @c is the same as @comment @@ -854,8 +937,7 @@ \def\asisword{asis} % no translation, these are keywords \def\noneword{none} % -\def\paragraphindent{\parsearg\doparagraphindent} -\def\doparagraphindent#1{% +\parseargdef\paragraphindent{% \def\temp{#1}% \ifx\temp\asisword \else @@ -872,8 +954,7 @@ % 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{% +\parseargdef\exampleindent{% \def\temp{#1}% \ifx\temp\asisword \else @@ -887,21 +968,18 @@ % @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 +% after a section heading. If WORD is `insert', then do indent at 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. +% \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{% +\parseargdef\firstparagraphindent{% \def\temp{#1}% \ifx\temp\noneword \let\suppressfirstparagraphindent = \dosuppressfirstparagraphindent @@ -921,15 +999,24 @@ % \gdef\dosuppressfirstparagraphindent{% \gdef\indent{% - \global\let\indent=\ptexindent - \global\everypar = {}% + \restorefirstparagraphindent + \indent + }% + \gdef\noindent{% + \restorefirstparagraphindent + \noindent }% \global\everypar = {% - \kern-\parindent - \global\let\indent=\ptexindent - \global\everypar = {}% + \kern -\parindent + \restorefirstparagraphindent }% -}% +} + +\gdef\restorefirstparagraphindent{% + \global \let \indent = \ptexindent + \global \let \noindent = \ptexnoindent + \global \everypar = {}% +} % @asis just yields its argument. Used with @table, for example. @@ -937,23 +1024,18 @@ \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}% -}} -% +% _ active, 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 @@ -964,15 +1046,16 @@ % \def\math{% \tex - \mathcode`\_="8000 \mathunderscore + \mathunderscore \let\\ = \mathbackslash \mathactive - \implicitmath\finishmath} -\def\finishmath#1{#1\implicitmath\Etex} + $\finishmath +} +\def\finishmath#1{#1$\endgroup} % Close the group opened by \tex. % 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). +% We have to reset their definitions in case the @math was an argument +% to a command which sets the catcodes (such as @item or @section). % { \catcode`^ = \active @@ -988,8 +1071,33 @@ } % @bullet and @minus need the same treatment as @math, just above. -\def\bullet{\implicitmath\ptexbullet\implicitmath} -\def\minus{\implicitmath-\implicitmath} +\def\bullet{$\ptexbullet$} +\def\minus{$-$} + +% @dots{} outputs 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 + .\hfil.\hfil.% + \hskip 0pt plus 0.5fil + }% +} + +% @enddots{} is an end-of-sentence ellipsis. +% +\def\enddots{% + \dots + \spacefactor=3000 +} + +% @comma{} is so commas can be inserted into text without messing up +% Texinfo's parsing. +% +\let\comma = , % @refill is a no-op. \let\refill=\relax @@ -1005,20 +1113,20 @@ % 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{% + \fixbackslash % Turn off hack to swallow `\input texinfo'. \iflinks - \readauxfile + \tryauxfile + % Open the new aux file. TeX will close it automatically at exit. + \immediate\openout\auxfile=\jobname.aux \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. + \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 + \ifeof 1 \else \input texinfo.cnf \fi + \closein 1 % \comment % Ignore the actual filename. } @@ -1054,17 +1162,23 @@ \newif\ifpdf \newif\ifpdfmakepagedest +% when pdftex is run in dvi mode, \pdfoutput is defined (so \pdfoutput=1 +% can be set). So we test for \relax and 0 as well as \undefined, +% borrowed from ifpdf.sty. \ifx\pdfoutput\undefined - \pdffalse - \let\pdfmkdest = \gobble - \let\pdfurl = \gobble - \let\endlink = \relax - \let\linkcolor = \relax - \let\pdfmakeoutlines = \relax \else - \pdftrue - \pdfoutput = 1 + \ifx\pdfoutput\relax + \else + \ifcase\pdfoutput + \else + \pdftrue + \fi + \fi +\fi +% +\ifpdf \input pdfcolor + \pdfcatalog{/PageMode /UseOutlines}% \def\dopdfimage#1#2#3{% \def\imagewidth{#2}% \def\imageheight{#3}% @@ -1085,7 +1199,13 @@ \ifnum\pdftexversion < 14 \else \pdfrefximage \pdflastximage \fi} - \def\pdfmkdest#1{{\normalturnoffactive \pdfdest name{#1} xyz}} + \def\pdfmkdest#1{{% + % We have to set dummies so commands such as @code in a section title + % aren't expanded. + \atdummies + \normalturnoffactive + \pdfdest name{#1} xyz% + }} \def\pdfmkpgn#1{#1} \let\linkcolor = \Blue % was Cyan, but that seems light? \def\endlink{\Black\pdfendlink} @@ -1094,48 +1214,94 @@ \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 + \advance\tempnum by 1 \expandafter\xdef\csname#1\endcsname{\the\tempnum}} - \def\pdfmakeoutlines{{% - \openin 1 \jobname.toc - \ifeof 1\else\begingroup - \closein 1 + % + % #1 is the section text. #2 is the pdf expression for the number + % of subentries (or empty, for subsubsections). #3 is the node + % text, which might be empty if this toc entry had no + % corresponding node. #4 is the page number. + % + \def\dopdfoutline#1#2#3#4{% + % Generate a link to the node text if that exists; else, use the + % page number. We could generate a destination for the section + % text in the case where a section has no node, but it doesn't + % seem worthwhile, since most documents are normally structured. + \def\pdfoutlinedest{#3}% + \ifx\pdfoutlinedest\empty \def\pdfoutlinedest{#4}\fi + % + \pdfoutline goto name{\pdfmkpgn{\pdfoutlinedest}}#2{#1}% + } + % + \def\pdfmakeoutlines{% + \begingroup % 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 + % Read toc silently, to get counts of subentries for \pdfoutline. + \def\numchapentry##1##2##3##4{% + \def\thischapnum{##2}% + \let\thissecnum\empty + \let\thissubsecnum\empty + }% + \def\numsecentry##1##2##3##4{% + \advancenumber{chap\thischapnum}% + \def\thissecnum{##2}% + \let\thissubsecnum\empty + }% + \def\numsubsecentry##1##2##3##4{% + \advancenumber{sec\thissecnum}% + \def\thissubsecnum{##2}% + }% + \def\numsubsubsecentry##1##2##3##4{% + \advancenumber{subsec\thissubsecnum}% + }% + \let\thischapnum\empty + \let\thissecnum\empty + \let\thissubsecnum\empty + % + % use \def rather than \let here because we redefine \chapentry et + % al. a second time, below. + \def\appentry{\numchapentry}% + \def\appsecentry{\numsecentry}% + \def\appsubsecentry{\numsubsecentry}% + \def\appsubsubsecentry{\numsubsubsecentry}% + \def\unnchapentry{\numchapentry}% + \def\unnsecentry{\numsecentry}% + \def\unnsubsecentry{\numsubsecentry}% + \def\unnsubsubsecentry{\numsubsubsecentry}% \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. + % Read toc second time, this time actually producing the outlines. + % The `-' means take the \expnumber as the absolute number of + % subentries, which we calculated on our first read of the .toc above. + % + % We use the node names as the destinations. + \def\numchapentry##1##2##3##4{% + \dopdfoutline{##1}{count-\expnumber{chap##2}}{##3}{##4}}% + \def\numsecentry##1##2##3##4{% + \dopdfoutline{##1}{count-\expnumber{sec##2}}{##3}{##4}}% + \def\numsubsecentry##1##2##3##4{% + \dopdfoutline{##1}{count-\expnumber{subsec##2}}{##3}{##4}}% + \def\numsubsubsecentry##1##2##3##4{% count is always zero + \dopdfoutline{##1}{}{##3}{##4}}% + % + % PDF outlines are displayed using system fonts, instead of + % document fonts. Therefore we cannot use special characters, + % since the encoding is unknown. For example, the eogonek from + % Latin 2 (0xea) gets translated to a | character. Info from + % Staszek Wawrykiewicz, 19 Jan 2004 04:09:24 +0100. % + % xx to do this right, we have to translate 8-bit characters to + % their "best" equivalent, based on the @documentencoding. Right + % now, I guess we'll just let the pdf reader have its way. \indexnofonts - \let\tt=\relax \turnoffactive \input \jobname.toc - \endgroup\fi - }} + \endgroup + } + % \def\makelinks #1,{% \def\params{#1}\def\E{END}% \ifx\params\E @@ -1166,7 +1332,6 @@ \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 @@ -1184,18 +1349,17 @@ \def\pdfurl#1{% \begingroup \normalturnoffactive\def\@{@}% - \let\value=\expandablevalue + \makevalueexpandable \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| + \expandafter\poptoks\the\toksA|ENDTOKS|\relax \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 @@ -1215,20 +1379,44 @@ \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 +\else + \let\pdfmkdest = \gobble + \let\pdfurl = \gobble + \let\endlink = \relax + \let\linkcolor = \relax + \let\pdfmakeoutlines = \relax +\fi % \ifx\pdfoutput \message{fonts,} -% Font-change commands. + +% Change the current font style to #1, remembering it in \curfontstyle. +% For now, we do not accumulate font styles: @b{@i{foo}} prints foo in +% italics, not bold italics. +% +\def\setfontstyle#1{% + \def\curfontstyle{#1}% not as a control sequence, because we are \edef'd. + \csname ten#1\endcsname % change the current font +} + +% Select #1 fonts with the current style. +% +\def\selectfonts#1{\csname #1fonts\endcsname \csname\curfontstyle\endcsname} + +\def\rm{\fam=0 \setfontstyle{rm}} +\def\it{\fam=\itfam \setfontstyle{it}} +\def\sl{\fam=\slfam \setfontstyle{sl}} +\def\bf{\fam=\bffam \setfontstyle{bf}} +\def\tt{\fam=\ttfam \setfontstyle{tt}} % 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. +% So we set up a \sf. \newfam\sffam -\def\sf{\fam=\sffam \tensf} +\def\sf{\fam=\sffam \setfontstyle{sf}} \let\li = \sf % Sometimes we call it \li, not \sf. -% We don't need math for this one. -\def\ttsl{\tenttsl} +% We don't need math for this font style. +\def\ttsl{\setfontstyle{ttsl}} % Default leading. \newdimen\textleading \textleading = 13.2pt @@ -1279,6 +1467,7 @@ \def\scshape{csc} \def\scbshape{csc} +% Text fonts (11.2pt, magstep1). \newcount\mainmagstep \ifx\bigger\relax % not really supported. @@ -1290,10 +1479,6 @@ \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} @@ -1303,10 +1488,11 @@ \font\texti=cmmi10 scaled \mainmagstep \font\textsy=cmsy10 scaled \mainmagstep -% A few fonts for @defun, etc. -\setfont\defbf\bxshape{10}{\magstep1} %was 1314 +% A few fonts for @defun names and args. +\setfont\defbf\bfshape{10}{\magstep1} \setfont\deftt\ttshape{10}{\magstep1} -\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf} +\setfont\defttsl\ttslshape{10}{\magstep1} +\def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf} % Fonts for indices, footnotes, small examples (9pt). \setfont\smallrm\rmshape{9}{1000} @@ -1332,7 +1518,7 @@ \font\smalleri=cmmi8 \font\smallersy=cmsy8 -% Fonts for title page: +% Fonts for title page (20.4pt): \setfont\titlerm\rmbshape{12}{\magstep3} \setfont\titleit\itbshape{10}{\magstep4} \setfont\titlesl\slbshape{10}{\magstep4} @@ -1378,11 +1564,21 @@ \setfont\ssecttsl\ttslshape{10}{1315} \setfont\ssecsf\sfbshape{12}{\magstephalf} \let\ssecbf\ssecrm -\setfont\ssecsc\scbshape{10}{\magstep1} +\setfont\ssecsc\scbshape{10}{1315} \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. + +% Reduced fonts for @acro in text (10pt). +\setfont\reducedrm\rmshape{10}{1000} +\setfont\reducedtt\ttshape{10}{1000} +\setfont\reducedbf\bfshape{10}{1000} +\setfont\reducedit\itshape{10}{1000} +\setfont\reducedsl\slshape{10}{1000} +\setfont\reducedsf\sfshape{10}{1000} +\setfont\reducedsc\scshape{10}{1000} +\setfont\reducedttsl\ttslshape{10}{1000} +\font\reducedi=cmmi10 +\font\reducedsy=cmsy10 % In order for the font changes to affect most math symbols and letters, % we have to define the \textfont of the standard families. Since @@ -1397,50 +1593,72 @@ } % 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. +% of just \STYLE. We do this because \STYLE needs to also set the +% current \fam for math mode. Our \STYLE (e.g., \rm) commands hardwire +% \tenSTYLE to set the current font. +% +% Each font-changing command also sets the names \lsize (one size lower) +% and \lllsize (three sizes lower). These relative commands are used in +% the LaTeX logo and acronyms. +% +% This all needs generalizing, badly. +% \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 + \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy + \let\tenttsl=\textttsl + \def\lsize{reduced}\def\lllsize{smaller}% \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 + \def\lsize{chap}\def\lllsize{subsec}% \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 + \def\lsize{sec}\def\lllsize{text}% \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 + \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy + \let\tenttsl=\secttsl + \def\lsize{subsec}\def\lllsize{reduced}% \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 + \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy + \let\tenttsl=\ssecttsl + \def\lsize{text}\def\lllsize{small}% \resetmathfonts \setleading{15pt}} -\let\subsubsecfonts = \subsecfonts % Maybe make sssec fonts scaled magstephalf? +\let\subsubsecfonts = \subsecfonts +\def\reducedfonts{% + \let\tenrm=\reducedrm \let\tenit=\reducedit \let\tensl=\reducedsl + \let\tenbf=\reducedbf \let\tentt=\reducedtt \let\reducedcaps=\reducedsc + \let\tensf=\reducedsf \let\teni=\reducedi \let\tensy=\reducedsy + \let\tenttsl=\reducedttsl + \def\lsize{small}\def\lllsize{smaller}% + \resetmathfonts \setleading{10.5pt}} \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 + \def\lsize{smaller}\def\lllsize{smaller}% \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 + \def\lsize{smaller}\def\lllsize{smaller}% \resetmathfonts \setleading{9.5pt}} % Set the fonts to use with the @small... environments. @@ -1449,7 +1667,7 @@ % 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: +% If we use \scriptfonts (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. @@ -1457,14 +1675,13 @@ % 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. -% +% I wish the USA used A4 paper. % --karl, 24jan03. % Set up the default fonts, so we can use them for creating boxes. % -\textfonts +\textfonts \rm % Define these so they can be easily changed for other fonts. \def\angleleft{$\langle$} @@ -1475,7 +1692,7 @@ % Fonts for short table of contents. \setfont\shortcontrm\rmshape{12}{1000} -\setfont\shortcontbf\bxshape{12}{1000} +\setfont\shortcontbf\bfshape{10}{\magstep1} % no cmb12 \setfont\shortcontsl\slshape{12}{1000} \setfont\shortconttt\ttshape{12}{1000} @@ -1489,11 +1706,19 @@ \def\smartslanted#1{{\ifusingtt\ttsl\sl #1}\futurelet\next\smartitalicx} \def\smartitalic#1{{\ifusingtt\ttsl\it #1}\futurelet\next\smartitalicx} +% like \smartslanted except unconditionally uses \ttsl. +% @var is set to this for defun arguments. +\def\ttslanted#1{{\ttsl #1}\futurelet\next\smartitalicx} + +% like \smartslanted except unconditionally use \sl. We never want +% ttsl for book titles, do we? +\def\cite#1{{\sl #1}\futurelet\next\smartitalicx} + \let\i=\smartitalic +\let\slanted=\smartslanted \let\var=\smartslanted \let\dfn=\smartslanted \let\emph=\smartitalic -\let\cite=\smartslanted \def\b#1{{\bf #1}} \let\strong=\b @@ -1520,7 +1745,6 @@ {\tt \rawbackslash \frenchspacing #1}% \null } -\let\ttfont=\t \def\samp#1{`\tclose{#1}'\null} \setfont\keyrm\rmshape{8}{1000} \font\keysy=cmsy9 @@ -1561,7 +1785,7 @@ \null } -% We *must* turn on hyphenation at `-' and `_' in \code. +% 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. @@ -1579,10 +1803,6 @@ \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{-} @@ -1606,8 +1826,7 @@ % @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{% +\parseargdef\kbdinputstyle{% \def\arg{#1}% \ifx\arg\worddistinct \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}% @@ -1633,8 +1852,8 @@ \else{\tclose{\kbdfont\look}}\fi \else{\tclose{\kbdfont\look}}\fi} -% For @url, @env, @command quotes seem unnecessary, so use \code. -\let\url=\code +% For @indicateurl, @env, @command quotes seem unnecessary, so use \code. +\let\indicateurl=\code \let\env=\code \let\command=\code @@ -1666,6 +1885,10 @@ \endlink \endgroup} +% @url synonym for @uref, since that's how everyone uses it. +% +\let\url=\uref + % rms does not like angle brackets --karl, 17may97. % So now @email is just like @uref, unless we are pdf. % @@ -1707,22 +1930,53 @@ \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}}} +% @acronym for "FBI", "NATO", and the like. +% We print this one point size smaller, since it's intended for +% all-uppercase. +% +\def\acronym#1{\doacronym #1,,\finish} +\def\doacronym#1,#2,#3\finish{% + {\selectfonts\lsize #1}% + \def\temp{#2}% + \ifx\temp\empty \else + \space ({\unsepspaces \ignorespaces \temp \unskip})% + \fi +} + +% @abbr for "Comput. J." and the like. +% No font change, but don't do end-of-sentence spacing. +% +\def\abbr#1{\doabbr #1,,\finish} +\def\doabbr#1,#2,#3\finish{% + {\frenchspacing #1}% + \def\temp{#2}% + \ifx\temp\empty \else + \space ({\unsepspaces \ignorespaces \temp \unskip})% + \fi +} -% @pounds{} is a sterling sign. +% @pounds{} is a sterling sign, which Knuth put in the CM italic font. +% \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. +% @registeredsymbol - R in a circle. The font for the R should really +% be smaller yet, but lllsize is the best we can do for now. % Adapted from the plain.tex definition of \copyright. % \def\registeredsymbol{% - $^{{\ooalign{\hfil\raise.07ex\hbox{$\scriptstyle\rm R$}\hfil\crcr\Orb}}% + $^{{\ooalign{\hfil\raise.07ex\hbox{\selectfonts\lllsize R}% + \hfil\crcr\Orb}}% }$% } +% Laurent Siebenmann reports \Orb undefined with: +% Textures 1.7.7 (preloaded format=plain 93.10.14) (68K) 16 APR 2004 02:38 +% so we'll define it if necessary. +% +\ifx\Orb\undefined +\def\Orb{\mathhexbox20D} +\fi + \message{page headings,} @@ -1741,87 +1995,103 @@ \newif\ifsetshortcontentsaftertitlepage \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue -\def\shorttitlepage{\parsearg\shorttitlepagezzz} -\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}% +\parseargdef\shorttitlepage{\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{% +\envdef\titlepage{% + % Open one extra group, as we want to close it in the middle of \Etitlepage. + \begingroup + \parindent=0pt \textfonts + % Leave some space at the very top of the page. + \vglue\titlepagetopglue + % No rule at page bottom unless we print one at the top with @title. + \finishedtitlepagetrue + % + % 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 + \finishtitlepage \fi - \oldpage \let\page = \oldpage - \hbox{}}% -% \def\page{\oldpage \hbox{}} + \page + \null + }% } \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 + \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 + \vskip4pt \hrule height 2pt width \hsize + \vskip\titlepagebottomglue + \finishedtitlepagetrue +} + +%%% Macros to be used within @titlepage: + +\let\subtitlerm=\tenrm +\def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines} + +\def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines + \let\tt=\authortt} + +\parseargdef\title{% + \checkenv\titlepage + \leftline{\titlefonts\rm #1} + % print a rule at the page bottom also. + \finishedtitlepagefalse + \vskip4pt \hrule height 4pt width \hsize \vskip4pt +} + +\parseargdef\subtitle{% + \checkenv\titlepage + {\subtitlefont \rightline{#1}}% +} + +% @author should come last, but may come many times. +% It can also be used inside @quotation. +% +\parseargdef\author{% + \def\temp{\quotation}% + \ifx\thisenv\temp + \def\quotationauthor{#1}% printed in \Equotation. + \else + \checkenv\titlepage + \ifseenauthor\else \vskip 0pt plus 1filll \seenauthortrue \fi + {\authorfont \leftline{#1}}% + \fi } + %%% Set up page headings and footings. \let\thispage=\folio @@ -1831,7 +2101,7 @@ \newtoks\evenfootline % footline on even pages \newtoks\oddfootline % footline on odd pages -% Now make Tex use those variables +% Now make TeX use those variables \headline={{\textfonts\rm \ifodd\pageno \the\oddheadline \else \the\evenheadline \fi}} \footline={{\textfonts\rm \ifodd\pageno \the\oddfootline @@ -1845,32 +2115,27 @@ % @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{% +\def\evenheading{\parsearg\evenheadingxxx} +\def\evenheadingxxx #1{\evenheadingyyy #1\|\|\|\|\finish} +\def\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{% +\def\oddheading{\parsearg\oddheadingxxx} +\def\oddheadingxxx #1{\oddheadingyyy #1\|\|\|\|\finish} +\def\oddheadingyyy #1\|#2\|#3\|#4\finish{% \global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} -\gdef\everyheadingxxx#1{\oddheadingxxx{#1}\evenheadingxxx{#1}}% +\parseargdef\everyheading{\oddheadingxxx{#1}\evenheadingxxx{#1}}% -\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish} -\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{% +\def\evenfooting{\parsearg\evenfootingxxx} +\def\evenfootingxxx #1{\evenfootingyyy #1\|\|\|\|\finish} +\def\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{% +\def\oddfooting{\parsearg\oddfootingxxx} +\def\oddfootingxxx #1{\oddfootingyyy #1\|\|\|\|\finish} +\def\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 @@ -1879,9 +2144,8 @@ \global\advance\vsize by -\baselineskip } -\gdef\everyfootingxxx#1{\oddfootingxxx{#1}\evenfootingxxx{#1}} -% -}% unbind the catcode of @. +\parseargdef\everyfooting{\oddfootingxxx{#1}\evenfootingxxx{#1}} + % @headings double turns headings on for double-sided printing. % @headings single turns headings on for single-sided printing. @@ -1895,7 +2159,7 @@ \def\headings #1 {\csname HEADINGS#1\endcsname} -\def\HEADINGSoff{ +\def\HEADINGSoff{% \global\evenheadline={\hfil} \global\evenfootline={\hfil} \global\oddheadline={\hfil} \global\oddfootline={\hfil}} \HEADINGSoff @@ -1904,7 +2168,7 @@ % 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{ +\def\HEADINGSdouble{% \global\pageno=1 \global\evenfootline={\hfil} \global\oddfootline={\hfil} @@ -1916,7 +2180,7 @@ % For single-sided printing, chapter title goes across top left of page, % page number on top right. -\def\HEADINGSsingle{ +\def\HEADINGSsingle{% \global\pageno=1 \global\evenfootline={\hfil} \global\oddfootline={\hfil} @@ -1963,12 +2227,11 @@ % @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}} +\def\settitle{\parsearg{\gdef\thistitle}} \message{tables,} -% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(x). +% Tables -- @table, @ftable, @vtable, @item(x). % default indentation of table text \newdimen\tableindent \tableindent=.8in @@ -1980,7 +2243,7 @@ % used internally for \itemindent minus \itemmargin \newdimen\itemmax -% Note @table, @vtable, and @vtable define @item, @itemx, etc., with +% Note @table, @ftable, 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). @@ -1992,22 +2255,10 @@ \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}}% + \setbox0=\hbox{\itemindicate{#1}}% \itemindex{#1}% \nobreak % This prevents a break before @itemx. % @@ -2031,17 +2282,13 @@ % \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...) + % Stop a page break at the \parskip glue coming up. However, if + % what follows is an environment such as @example, there will be no + % \parskip glue; then the negative vskip we just inserted 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. Section titles are handled this way also. + % \penalty 10001 \endgroup \itemxneedsnegativevskipfalse @@ -2061,81 +2308,72 @@ \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}{}{}{}{}} +\def\item{\errmessage{@item while not in a list environment}} +\def\itemx{\errmessage{@itemx while not in a list environment}} % @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 % +\envdef\table{% + \let\itemindex\gobble + \tablecheck{table}% +} +\envdef\ftable{% + \def\itemindex ##1{\doind {fn}{\code{##1}}}% + \tablecheck{ftable}% +} +\envdef\vtable{% + \def\itemindex ##1{\doind {vr}{\code{##1}}}% + \tablecheck{vtable}% +} +\def\tablecheck#1{% + \ifnum \the\catcode`\^^M=\active + \endgroup + \errmessage{This command won't work in this context; perhaps the problem is + that we are \inenvironment\thisenv}% + \def\next{\doignore{#1}}% + \else + \let\next\tablex + \fi + \next +} +\def\tablex#1{% + \def\itemindicate{#1}% + \parsearg\tabley } +\def\tabley#1{% + {% + \makevalueexpandable + \edef\temp{\noexpand\tablez #1\space\space\space}% + \expandafter + }\temp \endtablez +} +\def\tablez #1 #2 #3 #4\endtablez{% + \aboveenvbreak + \ifnum 0#1>0 \advance \leftskip by #1\mil \fi + \ifnum 0#2>0 \tableindent=#2\mil \fi + \ifnum 0#3>0 \advance \rightskip by #3\mil \fi + \itemmax=\tableindent + \advance \itemmax by -\itemmargin + \advance \leftskip by \tableindent + \exdentamount=\tableindent + \parindent = 0pt + \parskip = \smallskipamount + \ifdim \parskip=0pt \parskip=2pt \fi + \let\item = \internalBitem + \let\itemx = \internalBitemx +} +\def\Etable{\endgraf\afterenvbreak} +\let\Eftable\Etable +\let\Evtable\Etable +\let\Eitemize\Etable +\let\Eenumerate\Etable % This is the counter used by @enumerate, which is really @itemize \newcount \itemno -\def\itemize{\parsearg\itemizezzz} +\envdef\itemize{\parsearg\doitemize} -\def\itemizezzz #1{% - \begingroup % ended by the @end itemize - \itemizey {#1}{\Eitemize} -} - -\def\itemizey#1#2{% +\def\doitemize#1{% \aboveenvbreak \itemmax=\itemindent \advance\itemmax by -\itemmargin @@ -2144,13 +2382,33 @@ \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 } +% Definition of @item while inside @itemize and @enumerate. +% +\def\itemizeitem{% + \advance\itemno by 1 % for enumerations + {\let\par=\endgraf \smallbreak}% reasonable place to break + {% + % If the document has an @itemize directly after a section title, a + % \nobreak will be last on the list, and \sectionheading will have + % done a \vskip-\parskip. In that case, we don't want to zero + % parskip, or the item text will crash with the heading. On the + % other hand, when there is normal text preceding the item (as there + % usually is), we do want to zero parskip, or there would be too much + % space. In that case, we won't have a \nobreak before. At least + % that's the theory. + \ifnum\lastpenalty<10000 \parskip=0in \fi + \noindent + \hbox to 0pt{\hss \itemcontents \kern\itemmargin}% + \vadjust{\penalty 1200}}% not good to break after first line of item. + \flushcr +} + % \splitoff TOKENS\endmark defines \first to be the first token in % TOKENS, and \rest to be the remainder. % @@ -2160,11 +2418,8 @@ % 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} +\envparseargdef\enumerate{\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 @@ -2235,13 +2490,13 @@ }% } -% Call itemizey, adding a period to the first argument and supplying the +% Call \doitemize, 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 + \doitemize{#1.}\flushcr } % @alphaenumerate and @capsenumerate are abbreviations for giving an arg @@ -2252,16 +2507,6 @@ \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 @@ -2288,24 +2533,14 @@ % @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. +% @item, @tab do not need to be on their own lines, but it will not hurt +% if they are. % Sample multitable: @@ -2349,13 +2584,12 @@ \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 {% +% #1 is the @columnfraction, usually a decimal number like .5, but might +% be just 1. We just use it, whatever it is. +% +\def\pickupwholefraction#1 {% \global\advance\colcount by 1 - \expandafter\xdef\csname col\the\colcount\endcsname{.#2\hsize}% + \expandafter\xdef\csname col\the\colcount\endcsname{#1\hsize}% \setuptable } @@ -2388,18 +2622,33 @@ \go } +% multitable-only commands. +% +% @headitem starts a heading row, which we typeset in bold. +% Assignments have to be global since we are inside the implicit group +% of an alignment entry. Note that \everycr resets \everytab. +\def\headitem{\checkenv\multitable \crcr \global\everytab={\bf}\the\everytab}% +% +% 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. +\def\tab{\checkenv\multitable &\the\everytab}% + % @multitable ... @end multitable definitions: % -\def\multitable{\parsearg\dotable} -\def\dotable#1{\bgroup +\newtoks\everytab % insert after every tab. +% +\envdef\multitable{% \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 + \startsavinginserts + % + % @item within a multitable starts a normal row. + % We use \def instead of \let so that if one of the multitable entries + % contains an @itemize, we don't choke on the \item (seen as \crcr aka + % \endtemplate) expanding \doitemize. + \def\item{\crcr}% + % \tolerance=9500 \hbadness=9500 \setmultitablespacing @@ -2407,85 +2656,93 @@ \parindent=\multitableparindent \overfullrule=0pt \global\colcount=0 - \def\Emultitable{% - \global\setpercentfalse - \crcrwithfootnotes\crcr - \egroup\egroup + % + \everycr = {% + \noalign{% + \global\everytab={}% + \global\colcount=0 % Reset the column counter. + % Check for saved footnotes, etc. + \checkinserts + % Keeps underfull box messages off when table breaks over pages. + %\filbreak + % 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. + }% }% % + \parsearg\domultitable +} +\def\domultitable#1{% % 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 + \halign\bgroup &% + \global\advance\colcount by 1 + \multistrut + \vtop{% + % Use the current \colcount to find the correct column width: + \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\Emultitable{% + \crcr + \egroup % end the \halign + \global\setpercentfalse +} + +\def\setmultitablespacing{% + \def\multistrut{\strut}% just use the standard line spacing % - % 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. + % Compute \multitablelinespace (if not defined by user) for use in + % \multitableparskip calculation. We used define \multistrut based on + % this, but (ironically) that caused the spacing to be off. + % See bug-texinfo report from Werner Lemberg, 31 Oct 2004 12:52:20 +0100. \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 +\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. @@ -2500,163 +2757,33 @@ %% 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 -} + +% @iftex, @ifnotdocbook, @ifnothtml, @ifnotinfo, @ifnotplaintext, +% @ifnotxml always succeed. They currently do nothing; we don't +% attempt to check whether the conditionals are properly nested. But we +% have to remember that they are conditionals, so that @end doesn't +% attempt to close an environment group. +% +\def\makecond#1{% + \expandafter\let\csname #1\endcsname = \relax + \expandafter\let\csname iscond.#1\endcsname = 1 +} +\makecond{iftex} +\makecond{ifnotdocbook} +\makecond{ifnothtml} +\makecond{ifnotinfo} +\makecond{ifnotplaintext} +\makecond{ifnotxml} % Ignore @ignore, @ifhtml, @ifinfo, and the like. % \def\direntry{\doignore{direntry}} -\def\documentdescriptionword{documentdescription} \def\documentdescription{\doignore{documentdescription}} +\def\docbook{\doignore{docbook}} \def\html{\doignore{html}} +\def\ifdocbook{\doignore{ifdocbook}} \def\ifhtml{\doignore{ifhtml}} \def\ifinfo{\doignore{ifinfo}} \def\ifnottex{\doignore{ifnottex}} @@ -2666,198 +2793,133 @@ \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'. +% Ignore text until a line `@end #1', keeping track of nested conditionals. % +% A count to remember the depth of nesting. +\newcount\doignorecount + \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}% + % Scan in ``verbatim'' mode: + \catcode`\@ = \other + \catcode`\{ = \other + \catcode`\} = \other % % Make sure that spaces turn into tokens that match what \doignoretext wants. - \catcode\spaceChar = 10 + \spaceisspace % - % 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 + % Count number of #1's that we've seen. + \doignorecount = 0 + % + % Swallow text until we reach the matching `@end #1'. + \dodoignore{#1}% +} + +{ \catcode`_=11 % We want to use \_STOP_ which cannot appear in texinfo source. + \obeylines % + % + \gdef\dodoignore#1{% + % #1 contains the command name as a string, e.g., `ifinfo'. % - % 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}}% + % Define a command to find the next `@end #1', which must be on a line + % by itself. + \long\def\doignoretext##1^^M@end #1{\doignoretextyyy##1^^M@#1\_STOP_}% + % And this command to find another #1 command, at the beginning of a + % line. (Otherwise, we would consider a line `@c @ifset', for + % example, to count as an @ifset for nesting.) + \long\def\doignoretextyyy##1^^M@#1##2\_STOP_{\doignoreyyy{##2}\_STOP_}% + % + % And now expand that command. + \obeylines % + \doignoretext ^^M% + }% +} + +\def\doignoreyyy#1{% + \def\temp{#1}% + \ifx\temp\empty % Nothing found. + \let\next\doignoretextzzz + \else % Found a nested condition, ... + \advance\doignorecount by 1 + \let\next\doignoretextyyy % ..., look for another. + % If we're here, #1 ends with ^^M\ifinfo (for example). + \fi + \next #1% the token \_STOP_ is present just after this macro. +} + +% We have to swallow the remaining "\_STOP_". +% +\def\doignoretextzzz#1{% + \ifnum\doignorecount = 0 % We have just found the outermost @end. + \let\next\enddoignore + \else % Still inside a nested condition. + \advance\doignorecount by -1 + \let\next\doignoretext % Look for the next @end. + \fi + \next } +% Finish off ignored text. +\def\enddoignore{\endgroup\ignorespaces} + + % @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. +% didn't need it. +% We rely on the fact that \parsearg sets \catcode`\ =10. % -\def\set{\begingroup\catcode` =10 - \catcode`\-=12 \catcode`\_=12 % Allow - and _ in VAR. - \parsearg\setxxx} -\def\setxxx#1{\setyyy#1 \endsetyyy} +\parseargdef\set{\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 + {% + \makevalueexpandable + \def\temp{#2}% + \edef\next{\gdef\makecsname{SET#1}}% + \ifx\temp\empty + \next{}% + \else + \setzzz#2\endsetzzz + \fi + }% } -% 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}} +% Remove the trailing space \setxxx inserted. +\def\setzzz#1 \endsetzzz{\next{#1}} % @clear VAR clears (i.e., unsets) the variable VAR. % -\def\clear{\parsearg\clearxxx} -\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax} +\parseargdef\clear{% + {% + \makevalueexpandable + \global\expandafter\let\csname SET#1\endcsname=\relax + }% +} % @value{foo} gets the text saved in variable foo. +\def\value{\begingroup\makevalueexpandable\valuexxx} +\def\valuexxx#1{\expandablevalue{#1}\endgroup} { - \catcode`\_ = \active + \catcode`\- = \active \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 + \gdef\makevalueexpandable{% + \let\value = \expandablevalue + % We don't want these characters active, ... \catcode`\-=\other \catcode`\_=\other - \indexbreaks \let_\normalunderscore - \valuexxx} + % ..., but we might end up with active ones in the argument if + % we're called from @code, as @code{@value{foo-bar_}}, though. + % So \let them to their normal equivalents. + \let-\realdash \let_\normalunderscore + } } -\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). +% properly in indexes (we call \makevalueexpandable in \indexdummies). +% 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 @@ -2871,55 +2933,36 @@ % @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 +% To get special treatment of `@end ifset,' call \makeond and the redefine. +% +\makecond{ifset} +\def\ifset{\parsearg{\doifset{\let\next=\ifsetfail}}} +\def\doifset#1#2{% + {% + \makevalueexpandable + \let\next=\empty + \expandafter\ifx\csname SET#2\endcsname\relax + #1% If not set, redefine \next. + \fi + \expandafter + }\next } -\def\ifsetsucceed{\conditionalsucceed{ifset}} -\def\ifsetfail{\nestedignore{ifset}} -\defineunmatchedend{ifset} +\def\ifsetfail{\doignore{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}% -} +% The `\else' inside the `\doifset' parameter is a trick to reuse the +% above code: if the variable is not set, do nothing, if it is set, +% then redefine \next to \ifclearfail. +% +\makecond{ifclear} +\def\ifclear{\parsearg{\doifset{\else \let\next=\ifclearfail}}} +\def\ifclearfail{\doignore{ifclear}} + +% @dircategory CATEGORY -- specify a category of the dir file +% which this file should belong to. Ignore this in TeX. +\let\dircategory=\comment % @defininfoenclose. \let\definfoenclose=\comment @@ -3044,6 +3087,7 @@ \def\definedummyletter##1{% \expandafter\def\csname ##1\endcsname{\realbackslash ##1}% }% + \let\definedummyaccent\definedummyletter % % Do the redefinitions. \commondummies @@ -3066,6 +3110,7 @@ \def\definedummyletter##1{% \expandafter\def\csname ##1\endcsname{@##1}% }% + \let\definedummyaccent\definedummyletter % % Do the redefinitions. \commondummies @@ -3078,26 +3123,11 @@ % \normalturnoffactive % - % Control letters and accents. + \commondummiesnofonts + % \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. + % Non-English letters. \definedummyword{AA}% \definedummyword{AE}% \definedummyword{L}% @@ -3109,6 +3139,10 @@ \definedummyword{oe}% \definedummyword{o}% \definedummyword{ss}% + \definedummyword{exclamdown}% + \definedummyword{questiondown}% + \definedummyword{ordf}% + \definedummyword{ordm}% % % Although these internal commands shouldn't show up, sometimes they do. \definedummyword{bf}% @@ -3120,37 +3154,14 @@ \definedummyword{tclose}% \definedummyword{tt}% % - % Texinfo font commands. - \definedummyword{b}% - \definedummyword{i}% - \definedummyword{r}% - \definedummyword{sc}% - \definedummyword{t}% - % + \definedummyword{LaTeX}% \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{comma}% \definedummyword{copyright}% + \definedummyword{registeredsymbol}% \definedummyword{dots}% \definedummyword{enddots}% \definedummyword{equiv}% @@ -3162,10 +3173,9 @@ \definedummyword{print}% \definedummyword{result}% % - % Handle some cases of @value -- where the variable name does not - % contain - or _, and the value does not contain any + % Handle some cases of @value -- where it does not contain any % (non-fully-expandable) commands. - \let\value = \expandablevalue + \makevalueexpandable % % Normal spaces, not active ones. \unsepspaces @@ -3174,45 +3184,97 @@ \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}} - +% \commondummiesnofonts: common to \commondummies and \indexnofonts. +% +% Better have this without active chars. +{ + \catcode`\~=\other + \gdef\commondummiesnofonts{% + % Control letters and accents. + \definedummyletter{!}% + \definedummyaccent{"}% + \definedummyaccent{'}% + \definedummyletter{*}% + \definedummyaccent{,}% + \definedummyletter{.}% + \definedummyletter{/}% + \definedummyletter{:}% + \definedummyaccent{=}% + \definedummyletter{?}% + \definedummyaccent{^}% + \definedummyaccent{`}% + \definedummyaccent{~}% + \definedummyword{u}% + \definedummyword{v}% + \definedummyword{H}% + \definedummyword{dotaccent}% + \definedummyword{ringaccent}% + \definedummyword{tieaccent}% + \definedummyword{ubaraccent}% + \definedummyword{udotaccent}% + \definedummyword{dotless}% + % + % Texinfo font commands. + \definedummyword{b}% + \definedummyword{i}% + \definedummyword{r}% + \definedummyword{sc}% + \definedummyword{t}% + % + % Commands that take arguments. + \definedummyword{acronym}% + \definedummyword{cite}% + \definedummyword{code}% + \definedummyword{command}% + \definedummyword{dfn}% + \definedummyword{emph}% + \definedummyword{env}% + \definedummyword{file}% + \definedummyword{kbd}% + \definedummyword{key}% + \definedummyword{math}% + \definedummyword{option}% + \definedummyword{samp}% + \definedummyword{strong}% + \definedummyword{tie}% + \definedummyword{uref}% + \definedummyword{url}% + \definedummyword{var}% + \definedummyword{verb}% + \definedummyword{w}% + } +} % \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{% + % Accent commands should become @asis. + \def\definedummyaccent##1{% + \expandafter\let\csname ##1\endcsname\asis + }% + % We can just ignore other control letters. + \def\definedummyletter##1{% + \expandafter\def\csname ##1\endcsname{}% + }% + % Hopefully, all control words can become @asis. + \let\definedummyword\definedummyaccent + % + \commondummiesnofonts + % + % 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 + % \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. + % Non-English letters. \def\AA{AA}% \def\AE{AE}% \def\L{L}% @@ -3226,130 +3288,169 @@ \def\ss{ss}% \def\exclamdown{!}% \def\questiondown{?}% + \def\ordf{a}% + \def\ordm{o}% % - % 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 + \def\LaTeX{LaTeX}% + \def\TeX{TeX}% + % + % Assorted special characters. + % (The following {} will end up in the sort string, but that's ok.) + \def\bullet{bullet}% + \def\comma{,}% + \def\copyright{copyright}% + \def\registeredsymbol{R}% + \def\dots{...}% + \def\enddots{...}% + \def\equiv{==}% + \def\error{error}% + \def\expansion{==>}% + \def\minus{-}% + \def\pounds{pounds}% + \def\point{.}% + \def\print{-|}% + \def\result{=>}% % - % 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 + % Don't write macro names. + \emptyusermacros } \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} +% #1 is the index name, #2 is the entry text. +\def\doind#1#2{\dosubind{#1}{#2}{}} % 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. +% empty if called from \doind, as we usually are (the main exception +% is with most defuns, which call us directly). % \def\dosubind#1#2#3{% + \iflinks + {% + % Store the main index entry text (including the third arg). + \toks0 = {#2}% + % If third arg is present, precede it with a space. + \def\thirdarg{#3}% + \ifx\thirdarg\empty \else + \toks0 = \expandafter{\the\toks0 \space #3}% + \fi + % + \edef\writeto{\csname#1indfile\endcsname}% + % + \ifvmode + \dosubindsanitize + \else + \dosubindwrite + \fi + }% + \fi +} + +% Write the entry in \toks0 to the index file: +% +\def\dosubindwrite{% % Put the index entry in the margin if desired. \ifx\SETmarginindex\relax\else - \insert\margin{\hbox{\vrule height8pt depth3pt width0pt #2}}% + \insert\margin{\hbox{\vrule height8pt depth3pt width0pt \the\toks0}}% \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 + % + % Remember, we are within a group. + \indexdummies % Must do this here, since \bf, etc expand at this stage + \escapechar=`\\ + \def\backslashcurfont{\indexbackslash}% \indexbackslash isn't defined now + % so it will be output as is; and it will print as backslash. + % + % 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\writeto{% + \string\entry{\indexsorttmp}{\noexpand\folio}{\the\toks0}}% }% + \temp +} + +% Take care of unwanted page breaks: +% +% 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. +% +% But wait, there is a catch there: +% We'll have to check whether \lastskip is zero skip. \ifdim is not +% sufficient for this purpose, as it ignores stretch and shrink parts +% of the skip. The only way seems to be to check the textual +% representation of the skip. +% +% The following is almost like \def\zeroskipmacro{0.0pt} except that +% the ``p'' and ``t'' characters have catcode \other, not 11 (letter). +% +\edef\zeroskipmacro{\expandafter\the\csname z@skip\endcsname} +% +% ..., ready, GO: +% +\def\dosubindsanitize{% + % \lastskip and \lastpenalty cannot both be nonzero simultaneously. + \skip0 = \lastskip + \edef\lastskipmacro{\the\lastskip}% + \count255 = \lastpenalty + % + % If \lastskip is nonzero, that means the last item was a + % skip. And since a skip is discardable, that means this + % -\skip0 glue we're inserting is preceded by a + % non-discardable item, therefore it is not a potential + % breakpoint, therefore no \nobreak needed. + \ifx\lastskipmacro\zeroskipmacro + \else + \vskip-\skip0 + \fi + % + \dosubindwrite + % + \ifx\lastskipmacro\zeroskipmacro + % If \lastskip was zero, perhaps the last item was a penalty, and + % perhaps it was >=10000, e.g., a \nobreak. In that case, we want + % to re-insert the same penalty (values >10000 are used for various + % signals); since we just inserted a non-discardable item, any + % following glue (such as a \parskip) would be a breakpoint. For example: + % + % @deffn deffn-whatever + % @vindex index-whatever + % Description. + % would allow a break between the index-whatever whatsit + % and the "Description." paragraph. + \ifnum\count255>9999 \penalty\count255 \fi + \else + % On the other hand, if we had a nonzero \lastskip, + % this make-up glue would be preceded by a non-discardable item + % (the whatsit from the \write), so we must insert a \nobreak. + \nobreak\vskip\skip0 + \fi } % The index entry written in the file actually looks like @@ -3387,14 +3488,12 @@ % @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 +\parseargdef\printindex{\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 @@ -3421,7 +3520,7 @@ % 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}% + \def\indexbackslash{\backslashcurfont}% \catcode`\\ = 0 \escapechar = `\\ \begindoublecolumns @@ -3443,7 +3542,10 @@ \removelastskip % % We like breaks before the index initials, so insert a bonus. - \penalty -300 + \nobreak + \vskip 0pt plus 3\baselineskip + \penalty 0 + \vskip 0pt plus -3\baselineskip % % Typeset the initial. Making this add up to a whole number of % baselineskips increases the chance of the dots lining up from column @@ -3453,80 +3555,100 @@ % 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 + \vskip .33\baselineskip plus .1\baselineskip }} -% 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. +% \entry typesets a paragraph consisting of the text (#1), dot leaders, and +% then page number (#2) flushed to the right margin. It is used for index +% and table of contents entries. The paragraph is indented by \leftskip. +% +% A straightforward implementation would start like this: +% \def\entry#1#2{... +% But this frozes the catcodes in the argument, and can cause problems to +% @code, which sets - active. This problem was fixed by a kludge--- +% ``-'' was active throughout whole index, but this isn't really right. +% +% The right solution is to prevent \entry from swallowing the whole text. +% --kasal, 21nov03 +\def\entry{% + \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 + % + % Swallow the left brace of the text (first parameter): + \afterassignment\doentry + \let\temp = +} +\def\doentry{% + \bgroup % Instead of the swallowed brace. + \noindent + \aftergroup\finishentry + % And now comes the text of the entry. +} +\def\finishentry#1{% + % #1 is the page number. + % + % 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{#1}% + \edef\tempc{\tempa}% + \edef\tempd{\tempb}% + \ifx\tempc\tempd + \ % \else - \ #2% The page number ends the paragraph. + % + % 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#1.% + \ \the\toksA + \else + \ #1% + \fi \fi - \fi% - \par -\endgroup} + \par + \endgroup +} % Like \dotfill except takes at least 1 em. \def\indexdotfill{\cleaders @@ -3695,6 +3817,12 @@ \message{sectioning,} % Chapters, sections, etc. +% \unnumberedno is an oxymoron, of course. But we count the unnumbered +% sections so that we can refer to them unambiguously in the pdf +% outlines by their "section number". We avoid collisions with chapter +% numbers by starting them at 10000. (If a document ever has 10000 +% chapters, we're in trouble anyway, I'm sure.) +\newcount\unnumberedno \unnumberedno = 10000 \newcount\chapno \newcount\secno \secno=0 \newcount\subsecno \subsecno=0 @@ -3702,9 +3830,12 @@ % 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 +% We do the following ugly conditional instead of the above simple +% construct 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% @@ -3742,11 +3873,12 @@ % Each @chapter defines this as the name of the chapter. % page headings and footings can use it. @section does likewise. +% However, they are not reliable, because we don't use marks. \def\thischapter{} \def\thissection{} \newcount\absseclevel % used to calculate proper heading level -\newcount\secbase\secbase=0 % @raise/lowersections modify this count +\newcount\secbase\secbase=0 % @raisesections/@lowersections modify this count % @raisesections: treat @section as chapter, @subsection as section, etc. \def\raisesections{\global\advance\secbase by -1} @@ -3756,121 +3888,142 @@ \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} +% we only have subsub. +\chardef\maxseclevel = 3 +% +% A numbered section within an unnumbered changes to unnumbered too. +% To achive this, remember the "biggest" unnum. sec. we are currently in: +\chardef\unmlevel = \maxseclevel +% +% Trace whether the current chapter is an appendix or not: +% \chapheadtype is "N" or "A", unnumbered chapters are ignored. +\def\chapheadtype{N} + +% Choose a heading macro +% #1 is heading type +% #2 is heading level +% #3 is text for heading +\def\genhead#1#2#3{% + % Compute the abs. sec. level: + \absseclevel=#2 + \advance\absseclevel by \secbase + % Make sure \absseclevel doesn't fall outside the range: + \ifnum \absseclevel < 0 + \absseclevel = 0 \else - \numberedsubsubseczzz{#2} + \ifnum \absseclevel > 3 + \absseclevel = 3 + \fi \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} + % The heading type: + \def\headtype{#1}% + \if \headtype U% + \ifnum \absseclevel < \unmlevel + \chardef\unmlevel = \absseclevel + \fi \else - \appendixsubsubseczzz{#2} + % Check for appendix sections: + \ifnum \absseclevel = 0 + \edef\chapheadtype{\headtype}% + \else + \if \headtype A\if \chapheadtype N% + \errmessage{@appendix... within a non-appendix chapter}% + \fi\fi + \fi + % Check for numbered within unnumbered: + \ifnum \absseclevel > \unmlevel + \def\headtype{U}% + \else + \chardef\unmlevel = 3 + \fi \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} + % Now print the heading: + \if \headtype U% + \ifcase\absseclevel + \unnumberedzzz{#3}% + \or \unnumberedseczzz{#3}% + \or \unnumberedsubseczzz{#3}% + \or \unnumberedsubsubseczzz{#3}% + \fi \else - \unnumberedsubsubseczzz{#2} + \if \headtype A% + \ifcase\absseclevel + \appendixzzz{#3}% + \or \appendixsectionzzz{#3}% + \or \appendixsubseczzz{#3}% + \or \appendixsubsubseczzz{#3}% + \fi + \else + \ifcase\absseclevel + \chapterzzz{#3}% + \or \seczzz{#3}% + \or \numberedsubseczzz{#3}% + \or \numberedsubsubseczzz{#3}% + \fi + \fi \fi -\fi -\suppressfirstparagraphindent + \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 +% an interface: +\def\numhead{\genhead N} +\def\apphead{\genhead A} +\def\unnmhead{\genhead U} + +% @chapter, @appendix, @unnumbered. Increment top-level counter, reset +% all lower-level sectioning counters to zero. +% +% Also set \chaplevelprefix, which we prepend to @float sequence numbers +% (e.g., figures), q.v. By default (before any chapter), that is empty. +\let\chaplevelprefix = \empty +% +\outer\parseargdef\chapter{\numhead0{#1}} % normally numhead0 calls chapterzzz +\def\chapterzzz#1{% + % section resetting is \global in case the chapter is in a group, such + % as an @include file. + \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 + \global\advance\chapno by 1 + % + % Used for \float. + \gdef\chaplevelprefix{\the\chapno.}% + \resetallfloatnos + % + \message{\putwordChapter\space \the\chapno}% + % + % Write the actual heading. + \chapmacro{#1}{Ynumbered}{\the\chapno}% + % + % So @section and the like are numbered underneath this chapter. \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 +\outer\parseargdef\appendix{\apphead0{#1}} % normally apphead0 calls appendixzzz +\def\appendixzzz#1{% + \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 + \global\advance\appendixno by 1 + \gdef\chaplevelprefix{\appendixletter.}% + \resetallfloatnos + % + \def\appendixnum{\putwordAppendix\space \appendixletter}% + \message{\appendixnum}% + % + \chapmacro{#1}{Yappendix}{\appendixletter}% + % \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 +\outer\parseargdef\unnumbered{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz +\def\unnumberedzzz#1{% + \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 + \global\advance\unnumberedno by 1 + % + % Since an unnumbered has no number, no prefix for figures. + \global\let\chaplevelprefix = \empty + \resetallfloatnos % % This used to be simply \message{#1}, but TeX fully expands the % argument to \message. Therefore, if #1 contained @-commands, TeX @@ -3883,134 +4036,98 @@ % \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)}% + \toks0 = {#1}% + \message{(\the\toks0)}% + % + \chapmacro{#1}{Ynothing}{\the\unnumberedno}% % - \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 +% @centerchap is like @unnumbered, but the heading is centered. +\outer\parseargdef\centerchap{% + % Well, we could do the following in a group, but that would break + % an assumption that \chapmacro is called at the outermost level. + % Thus we are safer this way: --kasal, 24feb04 + \let\centerparametersmaybe = \centerparameters + \unnmhead0{#1}% + \let\centerparametersmaybe = \relax } -\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 -} +% @top is like @unnumbered. +\let\top\unnumbered -\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 +% Sections. +\outer\parseargdef\numberedsec{\numhead1{#1}} % normally calls seczzz +\def\seczzz#1{% + \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 + \sectionheading{#1}{sec}{Ynumbered}{\the\chapno.\the\secno}% +} + +\outer\parseargdef\appendixsection{\apphead1{#1}} % normally calls appendixsectionzzz +\def\appendixsectionzzz#1{% + \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 + \sectionheading{#1}{sec}{Yappendix}{\appendixletter.\the\secno}% +} +\let\appendixsec\appendixsection + +\outer\parseargdef\unnumberedsec{\unnmhead1{#1}} % normally calls unnumberedseczzz +\def\unnumberedseczzz#1{% + \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 + \sectionheading{#1}{sec}{Ynothing}{\the\unnumberedno.\the\secno}% } % 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 +\outer\parseargdef\numberedsubsec{\numhead2{#1}} % normally calls numberedsubseczzz +\def\numberedsubseczzz#1{% + \global\subsubsecno=0 \global\advance\subsecno by 1 + \sectionheading{#1}{subsec}{Ynumbered}{\the\chapno.\the\secno.\the\subsecno}% +} + +\outer\parseargdef\appendixsubsec{\apphead2{#1}} % normally calls appendixsubseczzz +\def\appendixsubseczzz#1{% + \global\subsubsecno=0 \global\advance\subsecno by 1 + \sectionheading{#1}{subsec}{Yappendix}% + {\appendixletter.\the\secno.\the\subsecno}% +} + +\outer\parseargdef\unnumberedsubsec{\unnmhead2{#1}} %normally calls unnumberedsubseczzz +\def\unnumberedsubseczzz#1{% + \global\subsubsecno=0 \global\advance\subsecno by 1 + \sectionheading{#1}{subsec}{Ynothing}% + {\the\unnumberedno.\the\secno.\the\subsecno}% } % 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 +\outer\parseargdef\numberedsubsubsec{\numhead3{#1}} % normally numberedsubsubseczzz +\def\numberedsubsubseczzz#1{% + \global\advance\subsubsecno by 1 + \sectionheading{#1}{subsubsec}{Ynumbered}% + {\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno}% +} + +\outer\parseargdef\appendixsubsubsec{\apphead3{#1}} % normally appendixsubsubseczzz +\def\appendixsubsubseczzz#1{% + \global\advance\subsubsecno by 1 + \sectionheading{#1}{subsubsec}{Yappendix}% + {\appendixletter.\the\secno.\the\subsecno.\the\subsubsecno}% +} + +\outer\parseargdef\unnumberedsubsubsec{\unnmhead3{#1}} %normally unnumberedsubsubseczzz +\def\unnumberedsubsubseczzz#1{% + \global\advance\subsubsecno by 1 + \sectionheading{#1}{subsubsec}{Ynothing}% + {\the\unnumberedno.\the\secno.\the\subsecno.\the\subsubsecno}% } -% 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 +\let\section = \numberedsec +\let\subsection = \numberedsubsec +\let\subsubsection = \numberedsubsubsec % Define @majorheading, @heading and @subheading @@ -4023,23 +4140,27 @@ % if justification is not attempted. Hence \raggedright. -\def\majorheading{\parsearg\majorheadingzzz} -\def\majorheadingzzz #1{% +\def\majorheading{% {\advance\chapheadingskip by 10pt \chapbreak }% - {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 - \parindent=0pt\raggedright - \rm #1\hfill}}\bigskip \par\penalty 200} + \parsearg\chapheadingzzz +} -\def\chapheading{\parsearg\chapheadingzzz} -\def\chapheadingzzz #1{\chapbreak % +\def\chapheading{\chapbreak \parsearg\chapheadingzzz} +\def\chapheadingzzz#1{% {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 \parindent=0pt\raggedright - \rm #1\hfill}}\bigskip \par\penalty 200} + \rm #1\hfill}}% + \bigskip \par\penalty 200\relax + \suppressfirstparagraphindent +} % @heading, @subheading, @subsubheading. -\def\heading{\parsearg\plainsecheading} -\def\subheading{\parsearg\plainsubsecheading} -\def\subsubheading{\parsearg\plainsubsubsecheading} +\parseargdef\heading{\sectionheading{#1}{sec}{Yomitfromtoc}{} + \suppressfirstparagraphindent} +\parseargdef\subheading{\sectionheading{#1}{subsec}{Yomitfromtoc}{} + \suppressfirstparagraphindent} +\parseargdef\subsubheading{\sectionheading{#1}{subsubsec}{Yomitfromtoc}{} + \suppressfirstparagraphindent} % These macros generate a chapter, section, etc. heading only % (including whitespace, linebreaking, etc. around it), @@ -4048,8 +4169,6 @@ %%% 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) @@ -4072,7 +4191,7 @@ \global\let\pagealignmacro=\chappager \global\def\HEADINGSon{\HEADINGSsingle}} -\def\CHAPPAGodd{ +\def\CHAPPAGodd{% \global\let\contentsalignmacro = \chapoddpage \global\let\pchapsepmacro=\chapoddpage \global\let\pagealignmacro=\chapoddpage @@ -4080,116 +4199,193 @@ \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{% +% Chapter opening. +% +% #1 is the text, #2 is the section type (Ynumbered, Ynothing, +% Yappendix, Yomitfromtoc), #3 the chapter number. +% +% To test against our argument. +\def\Ynothingkeyword{Ynothing} +\def\Yomitfromtockeyword{Yomitfromtoc} +\def\Yappendixkeyword{Yappendix} +% +\def\chapmacro#1#2#3{% \pchapsepmacro {% \chapfonts \rm - \def\chapnum{#2}% - \setbox0 = \hbox{#2\ifx\chapnum\empty\else\enspace\fi}% + % + % Have to define \thissection before calling \donoderef, because the + % xref code eventually uses it. On the other hand, it has to be called + % after \pchapsepmacro, or the headline will change too soon. + \gdef\thissection{#1}% + \gdef\thischaptername{#1}% + % + % Only insert the separating space if we have a chapter/appendix + % number, and don't print the unnumbered ``number''. + \def\temptype{#2}% + \ifx\temptype\Ynothingkeyword + \setbox0 = \hbox{}% + \def\toctype{unnchap}% + \def\thischapter{#1}% + \else\ifx\temptype\Yomitfromtockeyword + \setbox0 = \hbox{}% contents like unnumbered, but no toc entry + \def\toctype{omit}% + \xdef\thischapter{}% + \else\ifx\temptype\Yappendixkeyword + \setbox0 = \hbox{\putwordAppendix{} #3\enspace}% + \def\toctype{app}% + % We don't substitute the actual chapter name into \thischapter + % because we don't want its macros evaluated now. And we don't + % use \thissection because that changes with each section. + % + \xdef\thischapter{\putwordAppendix{} \appendixletter: + \noexpand\thischaptername}% + \else + \setbox0 = \hbox{#3\enspace}% + \def\toctype{numchap}% + \xdef\thischapter{\putwordChapter{} \the\chapno: + \noexpand\thischaptername}% + \fi\fi\fi + % + % Write the toc entry for this chapter. Must come before the + % \donoderef, because we include the current node name in the toc + % entry, and \donoderef resets it to empty. + \writetocentry{\toctype}{#1}{#3}% + % + % For pdftex, we have to write out the node definition (aka, make + % the pdfdest) after any page break, but before the actual text has + % been typeset. If the destination for the pdf outline is after the + % text, then jumping from the outline may wind up with the text not + % being visible, for instance under high magnification. + \donoderef{#2}% + % + % Typeset the actual heading. \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright - \hangindent = \wd0 \centerparametersmaybe + \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}{}% -}} +\def\centerparameters{% + \advance\rightskip by 3\rightskip + \leftskip = \rightskip + \parfillskip = 0pt +} -\CHAPFplain % The default +% I don't think this chapter style is supported any more, so I'm not +% updating it with the new noderef stuff. We'll see. --karl, 11aug03. +% +\def\setchapterstyle #1 {\csname CHAPF#1\endcsname} +% \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\centerchapmacro=\centerchfopen} -\def\CHAPFopen{ -\global\let\chapmacro=\chfopen -\global\let\unnumbchapmacro=\unnchfopen -\global\let\centerchapmacro=\centerchfopen} - -% Section titles. +% Section titles. These macros combine the section number parts and +% call the generic \sectionheading to do the printing. +% \newskip\secheadingskip -\def\secheadingbreak{\dobreak \secheadingskip {-1000}} -\def\secheading#1#2#3{\sectionheading{sec}{#2.#3}{#1}} -\def\plainsecheading#1{\sectionheading{sec}{}{#1}} +\def\secheadingbreak{\dobreak \secheadingskip{-1000}} % 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}} +\newskip\subsecheadingskip +\def\subsecheadingbreak{\dobreak \subsecheadingskip{-500}} % 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}} +\def\subsubsecheadingskip{\subsecheadingskip} +\def\subsubsecheadingbreak{\subsecheadingbreak} -% Print any size section title. +% Print any size, any type, 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 - }% +% #1 is the text, #2 is the section level (sec/subsec/subsubsec), #3 is +% the section type for xrefs (Ynumbered, Ynothing, Yappendix), #4 is the +% section number. +% +\def\sectionheading#1#2#3#4{% {% % Switch to the right set of fonts. - \csname #1fonts\endcsname \rm + \csname #2fonts\endcsname \rm + % + % Insert space above the heading. + \csname #2headingbreak\endcsname % - % Only insert the separating space if we have a section number. - \def\secnum{#2}% - \setbox0 = \hbox{#2\ifx\secnum\empty\else\enspace\fi}% + % Only insert the space after the number if we have a section number. + \def\sectionlevel{#2}% + \def\temptype{#3}% + % + \ifx\temptype\Ynothingkeyword + \setbox0 = \hbox{}% + \def\toctype{unn}% + \gdef\thissection{#1}% + \else\ifx\temptype\Yomitfromtockeyword + % for @headings -- no section number, don't include in toc, + % and don't redefine \thissection. + \setbox0 = \hbox{}% + \def\toctype{omit}% + \let\sectionlevel=\empty + \else\ifx\temptype\Yappendixkeyword + \setbox0 = \hbox{#4\enspace}% + \def\toctype{app}% + \gdef\thissection{#1}% + \else + \setbox0 = \hbox{#4\enspace}% + \def\toctype{num}% + \gdef\thissection{#1}% + \fi\fi\fi + % + % Write the toc entry (before \donoderef). See comments in \chfplain. + \writetocentry{\toctype\sectionlevel}{#1}{#4}% + % + % Write the node reference (= pdf destination for pdftex). + % Again, see comments in \chfplain. + \donoderef{#3}% % + % Output the actual section heading. \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright - \hangindent = \wd0 % zero if no section number - \unhbox0 #3}% + \hangindent=\wd0 % zero if no section number + \unhbox0 #1}% }% - % 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 + % Add extra space after the heading -- half of whatever came above it. + % Don't allow stretch, though. + \kern .5 \csname #2headingskip\endcsname + % + % Do not let the kern be a potential breakpoint, as it would be if it + % was followed by glue. \nobreak + % + % We'll almost certainly start a paragraph next, so don't let that + % glue accumulate. (Not a breakpoint because it's preceded by a + % discardable item.) + \vskip-\parskip + % + % This is purely so the last item on the list is a known \penalty > + % 10000. This is so \startdefun can avoid allowing breakpoints after + % section headings. Otherwise, it would insert a valid breakpoint between: + % + % @section sec-whatever + % @deffn def-whatever + \penalty 10001 } @@ -4198,119 +4394,152 @@ \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. +% Called from @chapter, etc. +% +% Example usage: \writetocentry{sec}{Section Name}{\the\chapno.\the\secno} +% We append the current node name (if any) and page number as additional +% arguments for the \{chap,sec,...}entry macros which will eventually +% read this. The node name is used in the pdf outlines as the +% destination to jump to. % -% 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. +% But if #1 is `omit', then we don't do anything. This is used for the +% table of contents chapter openings themselves. % \newif\iftocfileopened +\def\omitkeyword{omit}% +% \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 + \edef\writetoctype{#1}% + \ifx\writetoctype\omitkeyword \else + \iftocfileopened\else + \immediate\openout\tocfile = \jobname.toc + \global\tocfileopenedtrue + \fi + % + \iflinks + \toks0 = {#2}% + \toks2 = \expandafter{\lastnode}% + \edef\temp{\write\tocfile{\realbackslash #1entry{\the\toks0}{#3}% + {\the\toks2}{\noexpand\folio}}}% + \temp + \fi \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 + % Tell \shipout to create a pdf destination on each page, if we're + % writing pdf. These are used in the table of contents. We can't + % just write one 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 \global\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. +% 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 + % 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. + \def\thischapter{}% + \chapmacro{#1}{Yomitfromtoc}{}% + % + \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 + \startcontents{\putwordTOC}% + \openin 1 \jobname.toc + \ifeof 1 \else + \input \jobname.toc + \fi + \vfill \eject + \contentsalignmacro % in case @setchapternewpage odd is in effect + \ifeof 1 \else + \pdfmakeoutlines + \fi + \closein 1 + \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 + \startcontents{\putwordShortTOC}% + % + \let\numchapentry = \shortchapentry + \let\appentry = \shortchapentry + \let\unnchapentry = \shortunnchapentry + % 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\numsecentry##1##2##3##4{} + \let\appsecentry = \numsecentry + \let\unnsecentry = \numsecentry + \let\numsubsecentry = \numsecentry + \let\appsubsecentry = \numsecentry + \let\unnsubsecentry = \numsecentry + \let\numsubsubsecentry = \numsecentry + \let\appsubsubsecentry = \numsecentry + \let\unnsubsubsecentry = \numsecentry + \openin 1 \jobname.toc + \ifeof 1 \else + \input \jobname.toc + \fi + \closein 1 + \vfill \eject + \contentsalignmacro % in case @setchapternewpage odd is in effect + \endgroup + \lastnegativepageno = \pageno + \global\pageno = \savepageno } \let\shortcontents = \summarycontents -\ifpdf - \pdfcatalog{/PageMode /UseOutlines}% -\fi +% Typeset the label for a chapter or appendix for the short contents. +% The arg is, e.g., `A' for an appendix, or `3' for a chapter. +% +\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.) + % + % We'd like to right-justify chapter numbers, but that looks strange + % with appendix letters. And right-justifying numbers and + % left-justifying letters looks strange when there is less than 10 + % chapters. Have to read the whole toc once to know how many chapters + % there are before deciding ... + \hbox to 1em{#1\hss}% +} % These macros generate individual entries in the table of contents. % The first argument is the chapter or section name. @@ -4318,58 +4547,46 @@ % 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}} +\def\numchapentry#1#2#3#4{\dochapentry{#2\labelspace#1}{#4}} % % 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}% +\def\shortchapentry#1#2#3#4{% + \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno\bgroup#4\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. +% Need the word Appendix, and a fixed-size box. % -\newdimen\shortappendixwidth +\def\appendixbox#1{% + % We use M since it's probably the widest letter. + \setbox0 = \hbox{\putwordAppendix{} M}% + \hbox to \wd0{\putwordAppendix{} #1\hss}} % -\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}% -} +\def\appentry#1#2#3#4{\dochapentry{\appendixbox{#2}\labelspace#1}{#4}} % Unnumbered chapters. -\def\unnumbchapentry#1#2#3{\dochapentry{#1}{#3}} -\def\shortunnumberedentry#1#2#3{\tocentry{#1}{\doshortpageno\bgroup#3\egroup}} +\def\unnchapentry#1#2#3#4{\dochapentry{#1}{#4}} +\def\shortunnchapentry#1#2#3#4{\tocentry{#1}{\doshortpageno\bgroup#4\egroup}} % Sections. -\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}} -\def\unnumbsecentry#1#2#3#4{\dosecentry{#1}{#4}} +\def\numsecentry#1#2#3#4{\dosecentry{#2\labelspace#1}{#4}} +\let\appsecentry=\numsecentry +\def\unnsecentry#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}} +\def\numsubsecentry#1#2#3#4{\dosubsecentry{#2\labelspace#1}{#4}} +\let\appsubsecentry=\numsubsecentry +\def\unnsubsecentry#1#2#3#4{\dosubsecentry{#1}{#4}} % 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}} +\def\numsubsubsecentry#1#2#3#4{\dosubsubsecentry{#2\labelspace#1}{#4}} +\let\appsubsubsecentry=\numsubsubsecentry +\def\unnsubsubsecentry#1#2#3#4{\dosubsubsecentry{#1}{#4}} % This parameter controls the indentation of the various levels. -\newdimen\tocindent \tocindent = 3pc +% Same as \defaultparindent. +\newdimen\tocindent \tocindent = 15pt % Now for the actual typesetting. In all these, #1 is the text and #2 is the % page number. @@ -4400,17 +4617,8 @@ \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} +% We use the same \entry macro as for the index entries. +\let\tocentry = \entry % Space between chapter (or whatever) number and the title. \def\labelspace{\hskip1em \relax} @@ -4420,8 +4628,8 @@ \def\chapentryfonts{\secfonts \rm} \def\secentryfonts{\textfonts} -\let\subsecentryfonts = \textfonts -\let\subsubsecentryfonts = \textfonts +\def\subsecentryfonts{\textfonts} +\def\subsubsecentryfonts{\textfonts} \message{environments,} @@ -4448,10 +4656,10 @@ % 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 +\setbox\errorbox=\hbox to \dimen0{\hfil \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right. \advance\hsize by -2\dimen2 % Rules. - \vbox{ + \vbox{% \hrule height\dimen2 \hbox{\vrule width\dimen2 \kern3pt % Space to left of text. \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below. @@ -4465,14 +4673,13 @@ % One exception: @ is still an escape character, so that @end tex works. % But \@ or @@ will get a plain tex @ character. -\def\tex{\begingroup +\envdef\tex{% \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 @@ -4488,6 +4695,7 @@ \let\!=\ptexexclam \let\i=\ptexi \let\indent=\ptexindent + \let\noindent=\ptexnoindent \let\{=\ptexlbrace \let\+=\tabalign \let\}=\ptexrbrace @@ -4498,10 +4706,11 @@ \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}% \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}% \def\@{@}% -\let\Etex=\endgroup} +} +% There is no need to define \Etex. % Define @lisp ... @end lisp. -% @lisp does a \begingroup so it can rebind things, +% @lisp environment forms a group so it can rebind things, % including the definition of @end lisp (which normally is erroneous). % Amount to narrow the margins by for @lisp. @@ -4512,19 +4721,6 @@ % 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 @@ -4534,7 +4730,8 @@ % start of the next paragraph will insert \parskip. % \def\aboveenvbreak{{% - % =10000 instead of <10000 because of a special case in \itemzzz, q.v. + % =10000 instead of <10000 because of a special case in \itemzzz and + % \sectionheading, q.v. \ifnum \lastpenalty=10000 \else \advance\envskipamount by \parskip \endgraf @@ -4542,7 +4739,7 @@ \removelastskip % it's not a good place to break if the last penalty was \nobreak % or better ... - \ifnum\lastpenalty>10000 \else \penalty-50 \fi + \ifnum\lastpenalty<10000 \penalty-50 \fi \vskip\envskipamount \fi \fi @@ -4574,52 +4771,52 @@ % \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 +\envdef\cartouche{% + \ifhmode\par\fi % can't be in the midst of a paragraph. + \startsavinginserts + \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 + \kern3pt + \hsize=\cartinner + \baselineskip=\normbskip + \lineskip=\normlskip + \parskip=\normpskip + \vskip -\parskip + \comment % For explanation, see the end of \def\group. +} \def\Ecartouche{% - \endgroup - \kern3pt - \egroup - \kern3pt\vrule - \hskip\rskip - \egroup - \cartbot - \egroup -\endgroup -}} + \ifhmode\par\fi + \kern3pt + \egroup + \kern3pt\vrule + \hskip\rskip + \egroup + \cartbot + \egroup + \checkinserts +} % 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 @@ -4632,103 +4829,99 @@ \ifx\nonarrowing\relax \advance \leftskip by \lispnarrowing \exdentamount=\lispnarrowing - \let\exdent=\nofillexdent - \let\nonarrowing=\relax \fi + \let\exdent=\nofillexdent } -% 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. +% If you want all examples etc. small: @set dispenvsize small. +% If you want even small examples the full size: @set dispenvsize nosmall. +% This affects the following displayed environments: +% @example, @display, @format, @lisp % -\def\nonfillfinish{\afterenvbreak\endgroup} +\def\smallword{small} +\def\nosmallword{nosmall} +\let\SETdispenvsize\relax +\def\setnormaldispenv{% + \ifx\SETdispenvsize\smallword + \smallexamplefonts \rm + \fi +} +\def\setsmalldispenv{% + \ifx\SETdispenvsize\nosmallword + \else + \smallexamplefonts \rm + \fi +} -% @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 +% We often define two environments, @foo and @smallfoo. +% Let's do it by one command: +\def\makedispenv #1#2{ + \expandafter\envdef\csname#1\endcsname {\setnormaldispenv #2} + \expandafter\envdef\csname small#1\endcsname {\setsmalldispenv #2} + \expandafter\let\csname E#1\endcsname \afterenvbreak + \expandafter\let\csname Esmall#1\endcsname \afterenvbreak } -% @example: Same as @lisp. -\def\example{\begingroup \def\Eexample{\nonfillfinish\endgroup}\lisp} +% Define two synonyms: +\def\maketwodispenvs #1#2#3{ + \makedispenv{#1}{#3} + \makedispenv{#2}{#3} +} +% @lisp: indented, narrowed, typewriter font; @example: same as @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 +% +\maketwodispenvs {lisp}{example}{% + \nonfillstart + \tt + \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special. + \gobble % eat return } -\let\smallexample = \smalllisp - -% @display: same as @lisp except keep current font. +% @display/@smalldisplay: same as @lisp except keep current font. % -\def\display{\begingroup +\makedispenv {display}{% \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. +% @format/@smallformat: same as @display except don't narrow margins. % -\def\format{\begingroup - \let\nonarrowing = t +\makedispenv{format}{% + \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} +% @flushleft: same as @format, but doesn't obey \SETdispenvsize. +\envdef\flushleft{% + \let\nonarrowing = t% + \nonfillstart + \gobble +} +\let\Eflushleft = \afterenvbreak % @flushright. % -\def\flushright{\begingroup - \let\nonarrowing = t +\envdef\flushright{% + \let\nonarrowing = t% \nonfillstart - \let\Eflushright = \nonfillfinish \advance\leftskip by 0pt plus 1fill \gobble } +\let\Eflushright = \afterenvbreak % @quotation does normal linebreaking (hence we can't use \nonfillstart) -% and narrows the margins. +% and narrows the margins. We keep \parskip nonzero in general, since +% we're doing normal filling. So, when using \aboveenvbreak and +% \afterenvbreak, temporarily make \parskip 0. % -\def\quotation{% - \begingroup\inENV %This group ends at the end of the @quotation body +\envdef\quotation{% {\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 @@ -4737,6 +4930,27 @@ \exdentamount = \lispnarrowing \let\nonarrowing = \relax \fi + \parsearg\quotationlabel +} + +% We have retained a nonzero parskip for the environment, since we're +% doing normal filling. +% +\def\Equotation{% + \par + \ifx\quotationauthor\undefined\else + % indent a bit. + \leftline{\kern 2\leftskip \sl ---\quotationauthor}% + \fi + {\parskip=0pt \afterenvbreak}% +} + +% If we're given an argument, typeset it in bold with a colon after. +\def\quotationlabel#1{% + \def\temp{#1}% + \ifx\temp\empty \else + {\bf #1: }% + \fi } @@ -4758,7 +4972,7 @@ % % [Knuth] p. 380 \def\uncatcodespecials{% - \def\do##1{\catcode`##1=12}\dospecials} + \def\do##1{\catcode`##1=\other}\dospecials} % % [Knuth] pp. 380,381,391 % Disable Spanish ligatures ?` and !` of \tt font @@ -4806,6 +5020,8 @@ } \endgroup \def\setupverbatim{% + \nonfillstart + \advance\leftskip by -\defbodyindent % Easiest (and conventionally used) font for verbatim \tt \def\par{\leavevmode\egroup\box0\endgraf}% @@ -4827,7 +5043,7 @@ % % [Knuth] p. 382; only eat outer {} \begingroup - \catcode`[=1\catcode`]=2\catcode`\{=12\catcode`\}=12 + \catcode`[=1\catcode`]=2\catcode`\{=\other\catcode`\}=\other \gdef\doverb{#1[\def\next##1#1}[##1\endgroup]\next] \endgroup % @@ -4844,13 +5060,6 @@ % 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 @@ -4858,54 +5067,32 @@ % 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}}% + \xdef\doverbatim#1^^M#2@end verbatim{#2\noexpand\end\gobble verbatim}% + % We really want {...\end verbatim} in the body of the macro, but + % without the active space; thus we have to use \xdef and \gobble. \endgroup % -\def\verbatim{% - \def\Everbatim{\nonfillfinish\endgroup}% - \begingroup - \nonfillstart - \advance\leftskip by -\defbodyindent - \begingroup\setupverbatim\doverbatim +\envdef\verbatim{% + \setupverbatim\doverbatim } +\let\Everbatim = \afterenvbreak + % @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\verbatiminclude{\parseargusing\filenamecatcodes\doverbatiminclude} % \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 + {% + \makevalueexpandable + \setupverbatim + \input #1 + \afterenvbreak + }% } % @copying ... @end copying. -% Save the text away for @insertcopying later. Many commands won't be -% allowed in this context, but that's ok. +% Save the text away for @insertcopying later. % % We save the uninterpreted tokens, rather than creating a box. % Saving the text in a box would be much easier, but then all the @@ -4914,670 +5101,392 @@ % 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}% +\def\copying{\checkenv{}\begingroup\scanargctxt\docopying} +\def\docopying#1@end copying{\endgroup\def\copyingtext{#1}} +% +\def\insertcopying{% + \begingroup + \parindent = 0pt % paragraph indentation looks wrong on title page + \scanexp\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{}% +% Start the processing of @deffn: +\def\startdefun{% + \ifnum\lastpenalty<10000 + \medbreak \else - \def\defnametype{[\rm #2]}% + % 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 need to allow a + % break somewhere. Check specifically for penalty 10002, inserted + % by \defargscommonending, instead of 10000, since the sectioning + % commands also insert a nobreak penalty, and we don't want to allow + % a break between a section heading and a defun. + % + \ifnum\lastpenalty=10002 \penalty2000 \fi + % + % Similarly, after a section heading, do not allow a break. + % But do insert the glue. + \medskip % preceded by discardable penalty, so not a breakpoint \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 +\def\dodefunx#1{% + % First, check whether we are in the right environment: + \checkenv#1% % - \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}}% + % As above, allow line break if we have multiple x headers in a row. + % It's not a great place, though. + \ifnum\lastpenalty=10002 \penalty3000 \fi + % + % And now, it's time to reuse the body of the original defun: + \expandafter\gobbledefun#1% } +\def\gobbledefun#1\startdefun{} -% 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. +% \printdefunline \deffnheader{text} % -\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}}% +\def\printdefunline#1#2{% + \begingroup + % call \deffnheader: + #1#2 \endheader + % common ending: + \interlinepenalty = 10000 + \advance\rightskip by 0pt plus 1fil + \endgraf + \nobreak\vskip -\parskip + \penalty 10002 % signal to \startdefun and \dodefunx + % Some of the @defun-type tags do not enable magic parentheses, + % rendering the following check redundant. But we don't optimize. + \checkparencounts + \endgroup } -% 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}}% -} +\def\Edefun{\endgraf\medbreak} -% 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. +% \makedefun{deffn} creates \deffn, \deffnx and \Edeffn; +% the only thing remainnig is to define \deffnheader. % -\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}}% +\def\makedefun#1{% + \expandafter\let\csname E#1\endcsname = \Edefun + \edef\temp{\noexpand\domakedefun + \makecsname{#1}\makecsname{#1x}\makecsname{#1header}}% + \temp } -% 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 +% \domakedefun \deffn \deffnx \deffnheader % -% 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. +% Define \deffn and \deffnx, without parameters. +% \deffnheader has to be defined explicitly. % -\def\deftpparsebody #1#2#3#4 {% - \parsebodycommon{#1}{#2}{#3}% - \def#2##1 {\defxbodycommon \spacesplit{#3{##1}}}% - \begingroup\obeylines - \spacesplit{\parsetpheaderline{#3{#4}}}\empty +\def\domakedefun#1#2#3{% + \envdef#1{% + \startdefun + \parseargusing\activeparens{\printdefunline#3}% + }% + \def#2{\dodefunx#1}% + \def#3% } -% 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}% -}% +%%% Untyped functions: -% 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}% -} +% @deffn category name args +\makedefun{deffn}{\deffngeneral{}} -% Define @defun. +% @deffn category class name args +\makedefun{defop}#1 {\defopon{#1\ \putwordon}} -% 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. -} +% \defopon {category on}class name args +\def\defopon#1#2 {\deffngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } -% This expands the args and terminates the paragraph they comprise. +% \deffngeneral {subind}category name args % -\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\deffngeneral#1#2 #3 #4\endheader{% + % Remember that \dosubind{fn}{foo}{} is equivalent to \doind{fn}{foo}. + \dosubind{fn}{\code{#3}}{#1}% + \defname{#2}{}{#3}\magicamp\defunargs{#4\unskip}% } -\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 -} +%%% Typed functions: -% Do complete processing of one @defun or @defunx line already parsed. +% @deftypefn category type name args +\makedefun{deftypefn}{\deftypefngeneral{}} -% @deffn Command forward-char nchars +% @deftypeop category class type name args +\makedefun{deftypeop}#1 {\deftypeopon{#1\ \putwordon}} -\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader} +% \deftypeopon {category on}class type name args +\def\deftypeopon#1#2 {\deftypefngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } -\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 +% \deftypefngeneral {subind}category type name args +% +\def\deftypefngeneral#1#2 #3 #4 #5\endheader{% + \dosubind{fn}{\code{#4}}{#1}% + \defname{#2}{#3}{#4}\defunargs{#5\unskip}% } -% @defun == @deffn Function - -\def\defun{\defparsebody\Edefun\defunx\defunheader} +%%% Typed variables: -\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 -} +% @deftypevr category type var args +\makedefun{deftypevr}{\deftypecvgeneral{}} -% @deftypefun int foobar (int @var{foo}, float @var{bar}) +% @deftypecv category class type var args +\makedefun{deftypecv}#1 {\deftypecvof{#1\ \putwordof}} -\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader} +% \deftypecvof {category of}class type var args +\def\deftypecvof#1#2 {\deftypecvgeneral{\putwordof\ \code{#2}}{#1\ \code{#2}} } -% #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 +% \deftypecvgeneral {subind}category type var args +% +\def\deftypecvgeneral#1#2 #3 #4 #5\endheader{% + \dosubind{vr}{\code{#4}}{#1}% + \defname{#2}{#3}{#4}\defunargs{#5\unskip}% } -% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar}) - -\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader} +%%% Untyped variables: -% \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} +% @defvr category var args +\makedefun{defvr}#1 {\deftypevrheader{#1} {} } -% #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 +% @defcv category class var args +\makedefun{defcv}#1 {\defcvof{#1\ \putwordof}} -\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader} +% \defcvof {category of}class var args +\def\defcvof#1#2 {\deftypecvof{#1}#2 {} } -\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 +%%% Type: +% @deftp category name args +\makedefun{deftp}#1 #2 #3\endheader{% + \doind{tp}{\code{#2}}% + \defname{#1}{}{#2}\defunargs{#3\unskip}% } -% @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 -} +% Remaining @defun-like shortcuts: +\makedefun{defun}{\deffnheader{\putwordDeffunc} } +\makedefun{defmac}{\deffnheader{\putwordDefmac} } +\makedefun{defspec}{\deffnheader{\putwordDefspec} } +\makedefun{deftypefun}{\deftypefnheader{\putwordDeffunc} } +\makedefun{defvar}{\defvrheader{\putwordDefvar} } +\makedefun{defopt}{\defvrheader{\putwordDefopt} } +\makedefun{deftypevar}{\deftypevrheader{\putwordDefvar} } +\makedefun{defmethod}{\defopon\putwordMethodon} +\makedefun{deftypemethod}{\deftypeopon\putwordMethodon} +\makedefun{defivar}{\defcvof\putwordInstanceVariableof} +\makedefun{deftypeivar}{\deftypecvof\putwordInstanceVariableof} -% @defop CATEGORY CLASS OPERATION ARG... +% \defname, which formats the name of the @def (not the args). +% #1 is the category, such as "Function". +% #2 is the return type, if any. +% #3 is the function name. % -\def\defop #1 {\def\defoptype{#1}% -\defopparsebody\Edefop\defopx\defopheader\defoptype} +% We are followed by (but not passed) the arguments, if any. % -\def\defopheader#1#2#3{% - \dosubind{fn}{\code{#2}}{\putwordon\ \code{#1}}% function index entry - \begingroup - \defname{#2}{\defoptype\ \putwordon\ #1}% - \defunargs{#3}% - \endgroup +\def\defname#1#2#3{% + % Get the values of \leftskip and \rightskip as they were outside the @def... + \advance\leftskip by -\defbodyindent + % + % How we'll format 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. + \def\temp{#1}% + \setbox0=\hbox{\kern\deflastargmargin \ifx\temp\empty\else [\rm\temp]\fi} + % + % Figure out line sizes for the paragraph shape. + % The first line needs space for \box0; but if \rightskip is nonzero, + % we need only space for the part of \box0 which exceeds it: + \dimen0=\hsize \advance\dimen0 by -\wd0 \advance\dimen0 by \rightskip + % The continuations: + \dimen2=\hsize \advance\dimen2 by -\defargsindent + % (plain.tex says that \dimen1 should be used only as global.) + \parshape 2 0in \dimen0 \defargsindent \dimen2 + % + % Put the type name to the right margin. + \noindent + \hbox to 0pt{% + \hfil\box0 \kern-\hsize + % \hsize has to be shortened this way: + \kern\leftskip + % Intentionally do not respect \rightskip, since we need the space. + }% + % + % Allow all lines to be underfull without complaint: + \tolerance=10000 \hbadness=10000 + \exdentamount=\defbodyindent + {% + % defun fonts. We use typewriter by default (used to be bold) because: + % . we're printing identifiers, they should be in tt in principle. + % . in languages with many accents, such as Czech or French, it's + % common to leave accents off identifiers. The result looks ok in + % tt, but exceedingly strange in rm. + % . we don't want -- and --- to be treated as ligatures. + % . this still does not fix the ?` and !` ligatures, but so far no + % one has made identifiers using them :). + \df \tt + \def\temp{#2}% return value type + \ifx\temp\empty\else \tclose{\temp} \fi + #3% output function name + }% + {\rm\enskip}% hskip 0.5 em of \tenrm + % + \boldbrax + % arguments will be output next, if any. } -% @deftypeop CATEGORY CLASS TYPE OPERATION ARG... +% Print arguments in slanted roman (not ttsl), inconsistently with using +% tt for the name. This is because literal text is sometimes needed in +% the argument list (groff manual), and ttsl and tt are not very +% distinguishable. Prevent hyphenation at `-' chars. % -\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 +\def\defunargs#1{% + % use sl by default (not ttsl), + % tt for the names. + \df \sl \hyphenchar\font=0 + % + % On the other hand, if an argument has two dashes (for instance), we + % want a way to get ttsl. Let's try @var for that. + \let\var=\ttslanted + #1% + \sl\hyphenchar\font=45 } -% @deftypemethod CLASS TYPE METHOD ARG... -% -\def\deftypemethod{% - \deftypemethparsebody\Edeftypemethod\deftypemethodx\deftypemethodheader} +% We want ()&[] to print specially on the defun line. % -% #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 +\def\activeparens{% + \catcode`\(=\active \catcode`\)=\active + \catcode`\[=\active \catcode`\]=\active + \catcode`\&=\active } -% @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 -} +% Make control sequences which act like normal parenthesis chars. +\let\lparen = ( \let\rparen = ) -% @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 +% 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. +{ + \activeparens + \global\let(=\lparen \global\let)=\rparen + \global\let[=\lbrack \global\let]=\rbrack + \global\let& = \& + + \gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} + \gdef\magicamp{\let&=\amprm} } -% @defcv {Class Option} foo-class foo-flag +\newcount\parencount -\def\defcv #1 {\def\defcvtype{#1}% -\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype} +% If we encounter &foo, then turn on ()-hacking afterwards +\newif\ifampseen +\def\amprm#1 {\ampseentrue{\bf\ }} -\def\defcvarheader #1#2#3{% - \dosubind{vr}{\code{#2}}{\putwordof\ \code{#1}}% variable index entry - \begingroup - \defname{#2}{\defcvtype\ \putwordof\ #1}% - \defvarargs{#3}% - \endgroup +\def\parenfont{% + \ifampseen + % At the first level, print parens in roman, + % otherwise use the default font. + \ifnum \parencount=1 \rm \fi + \else + % The \sf parens (in \boldbrax) actually are a little bolder than + % the contained text. This is especially needed for [ and ] . + \sf + \fi } - -% @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 +\def\infirstlevel#1{% + \ifampseen + \ifnum\parencount=1 + #1% + \fi + \fi } +\def\bfafterword#1 {#1 \bf} -% @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 +\def\opnr{% + \global\advance\parencount by 1 + {\parenfont(}% + \infirstlevel \bfafterword } - -% @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 % +\def\clnr{% + {\parenfont)}% + \infirstlevel \sl + \global\advance\parencount by -1 } -% @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 % +\newcount\brackcount +\def\lbrb{% + \global\advance\brackcount by 1 + {\bf[}% +} +\def\rbrb{% + {\bf]}% + \global\advance\brackcount by -1 } -% @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}} +\def\checkparencounts{% + \ifnum\parencount=0 \else \badparencount \fi + \ifnum\brackcount=0 \else \badbrackcount \fi +} +\def\badparencount{% + \errmessage{Unbalanced parentheses in @def}% + \global\parencount=0 +} +\def\badbrackcount{% + \errmessage{Unbalanced square braces in @def}% + \global\brackcount=0 +} \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 +% 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\scantokens#1{% + \toks0={#1}% + \immediate\openout\macscribble=\jobname.tmp + \immediate\write\macscribble{\the\toks0}% + \immediate\closeout\macscribble + \input \jobname.tmp + } +\fi + +\def\scanmacro#1{% + \begingroup + \newlinechar`\^^M + \let\xeatspaces\eatspaces + % Undo catcode changes of \startcontents and \doprintindex + % When called from @insertcopying or (short)caption, we need active + % backslash to get it printed correctly. Previously, we had + % \catcode`\\=\other instead. We'll see whether a problem appears + % with macro expansion. --kasal, 19aug04 + \catcode`\@=0 \catcode`\\=\active \escapechar=`\@ + % ... and \example + \spaceisspace + % + % Append \endinput to make sure that TeX does not see the ending newline. + % + % I've verified that it is necessary both for e-TeX and for ordinary TeX + % --kasal, 29nov03 + \scantokens{#1\endinput}% + \endgroup +} + +\def\scanexp#1{% + \edef\temp{\noexpand\scanmacro{#1}}% + \temp } -\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 @@ -5586,13 +5495,15 @@ % \do\macro1\do\macro2... % Utility routines. -% Thisdoes \let #1 = #2, except with \csnames. +% This does \let #1 = #2, with \csnames; that is, +% \let \csname#1\endcsname = \csname#2\endcsname +% (except of course we have to play expansion games). +% \def\cslet#1#2{% -\expandafter\expandafter -\expandafter\let -\expandafter\expandafter -\csname#1\endcsname -\csname#2\endcsname} + \expandafter\let + \csname#1\expandafter\endcsname + \csname#2\endcsname +} % Trim leading and trailing spaces off a string. % Concepts from aro-bend problem 15 (see CTAN). @@ -5619,30 +5530,36 @@ % done by making ^^M (\endlinechar) catcode 12 when reading the macro % body, and then making it the \newlinechar in \scanmacro. -\def\macrobodyctxt{% - \catcode`\~=\other +\def\scanctxt{% + \catcode`\"=\other + \catcode`\+=\other + \catcode`\<=\other + \catcode`\>=\other + \catcode`\@=\other \catcode`\^=\other \catcode`\_=\other \catcode`\|=\other - \catcode`\<=\other - \catcode`\>=\other - \catcode`\+=\other + \catcode`\~=\other +} + +\def\scanargctxt{% + \scanctxt + \catcode`\\=\other + \catcode`\^^M=\other +} + +\def\macrobodyctxt{% + \scanctxt \catcode`\{=\other \catcode`\}=\other - \catcode`\@=\other \catcode`\^^M=\other - \usembodybackslash} + \usembodybackslash +} \def\macroargctxt{% - \catcode`\~=\other - \catcode`\^=\other - \catcode`\_=\other - \catcode`\|=\other - \catcode`\<=\other - \catcode`\>=\other - \catcode`\+=\other - \catcode`\@=\other - \catcode`\\=\other} + \scanctxt + \catcode`\\=\other +} % \mbodybackslash is the definition of \ in @macro bodies. % It maps \foo\ => \csname macarg.foo\endcsname => #N @@ -5683,8 +5600,7 @@ \else \expandafter\parsemacbody \fi} -\def\unmacro{\parsearg\dounmacro} -\def\dounmacro#1{% +\parseargdef\unmacro{% \if1\csname ismacro.#1\endcsname \global\cslet{#1}{macsave.#1}% \global\expandafter\let \csname ismacro.#1\endcsname=0% @@ -5825,25 +5741,41 @@ \expandafter\parsearg \fi \next} -% We mant to disable all macros during \shipout so that they are not +% We want 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} +% For \indexnofonts, we need to get rid of all macros, leaving only the +% arguments (if present). Of course this is not nearly correct, but it +% is the best we can do for now. makeinfo does not expand macros in the +% argument to @deffn, which ends up writing an index entry, and texindex +% isn't prepared for an index sort entry that starts with \. +% +% Since macro invocations are followed by braces, we can just redefine them +% to take a single TeX argument. The case of a macro invocation that +% goes to end-of-line is not handled. +% +\def\emptyusermacros{\begingroup + \def\do##1{\let\noexpand##1=\noexpand\asis}% + \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\alias{\parseargusing\obeyspaces\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} +\def\aliasyyy #1=#2\relax{% + {% + \expandafter\let\obeyedspace=\empty + \xdef\next{\global\let\makecsname{#1}=\makecsname{#2}}% + }% + \next +} \message{cross references,} -% @xref etc. \newwrite\auxfile @@ -5855,64 +5787,70 @@ \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}} +% @node's only job in TeX is to define \lastnode, which is used in +% cross-references. The @node line might or might not have commas, and +% might or might not have spaces before the first comma, like: +% @node foo , bar , ... +% We don't want such trailing spaces in the node name. +% +\parseargdef\node{\checkenv{}\donode #1 ,\finishnodeparse} +% +% also remove a trailing comma, in case of something like this: +% @node Help-Cross, , , Cross-refs +\def\donode#1 ,#2\finishnodeparse{\dodonode #1,\finishnodeparse} +\def\dodonode#1,#2\finishnodeparse{\gdef\lastnode{#1}} + \let\nwnode=\node -\let\lastnode=\relax +\let\lastnode=\empty -% 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 +% Write a cross-reference definition for the current node. #1 is the +% type (Ynumbered, Yappendix, Ynothing). +% +\def\donoderef#1{% + \ifx\lastnode\empty\else + \setref{\lastnode}{#1}% + \global\let\lastnode=\empty \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} +% +\def\savesf{\relax \ifhmode \savesfregister=\spacefactor \fi} +\def\restoresf{\relax \ifhmode \spacefactor=\savesfregister \fi} +\def\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. +% anchor), which consists of three parts: +% 1) NAME-title - the current sectioning name taken from \thissection, +% or the anchor name. +% 2) NAME-snt - section number and type, passed as the SNT arg, or +% empty for anchors. +% 3) NAME-pg - the page number. +% +% This is called from \donoderef, \anchor, and \dofloat. In the case of +% floats, there is an additional part, which is not written here: +% 4) NAME-lof - the text as it should appear in a @listoffloats. % -\def\setref#1#2{{% - \atdummies +\def\setref#1#2{% \pdfmkdest{#1}% - % - \turnoffactive - \dosetq{#1-title}{Ytitle}% - \dosetq{#1-pg}{Ypagenumber}% - \dosetq{#1-snt}{#2}% -}} + \iflinks + {% + \atdummies % preserve commands, but don't expand them + \turnoffactive + \otherbackslash + \edef\writexrdef##1##2{% + \write\auxfile{@xrdef{#1-% #1 of \setref, expanded by the \edef + ##1}{##2}}% these are parameters of \writexrdef + }% + \toks0 = \expandafter{\thissection}% + \immediate \writexrdef{title}{\the\toks0 }% + \immediate \writexrdef{snt}{\csname #2\endcsname}% \Ynumbered etc. + \writexrdef{pg}{\folio}% will be written later, during \shipout + }% + \fi +} % @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 @@ -5925,38 +5863,33 @@ \def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup \unsepspaces \def\printedmanual{\ignorespaces #5}% - \def\printednodename{\ignorespaces #3}% - \setbox1=\hbox{\printedmanual}% - \setbox0=\hbox{\printednodename}% + \def\printedrefname{\ignorespaces #3}% + \setbox1=\hbox{\printedmanual\unskip}% + \setbox0=\hbox{\printedrefname\unskip}% \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}% + \def\printedrefname{\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}% + \def\printedrefname{\ignorespaces #1}% \else \ifhavexrefs % We know the real title if we have the xref values. - \def\printednodename{\refx{#1-title}{}}% + \def\printedrefname{\refx{#1-title}{}}% \else % Otherwise just copy the Info node name. - \def\printednodename{\ignorespaces #1}% + \def\printedrefname{\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. + % Make link in pdf output. \ifpdf \leavevmode \getfilename{#4}% @@ -5966,64 +5899,86 @@ goto file{\the\filename.pdf} name{#1}% \else \startlink attr{/Border [0 0 0]}% - goto name{#1}% + goto name{\pdfmkpgn{#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 + % Float references are printed completely differently: "Figure 1.2" + % instead of "[somenode], p.3". We distinguish them by the + % LABEL-title being set to a magic string. + {% + % Have to otherify everything special to allow the \csname to + % include an _ in the xref name, etc. + \indexnofonts + \turnoffactive + \otherbackslash + \expandafter\global\expandafter\let\expandafter\Xthisreftitle + \csname XR#1-title\endcsname + }% + \iffloat\Xthisreftitle + % If the user specified the print name (third arg) to the ref, + % print it instead of our usual "Figure 1.2". + \ifdim\wd0 = 0pt + \refx{#1-snt}% + \else + \printedrefname + \fi % - % But we always want a comma and a space: - ,\space + % if the user also gave the printed manual name (fifth arg), append + % "in MANUALNAME". + \ifdim \wd1 > 0pt + \space \putwordin{} \cite{\printedmanual}% + \fi + \else + % node/anchor (non-float) references. % - % output the `page 3'. - \turnoffactive \otherbackslash \putwordpage\tie\refx{#1-pg}{}% + % 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. + \ifdim \wd1 > 0pt + \putwordsection{} ``\printedrefname'' \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 so it can be overridden. + \xrefprintnodename\printedrefname + % + % But we always want a comma and a space: + ,\space + % + % output the `page 3'. + \turnoffactive \otherbackslash \putwordpage\tie\refx{#1-pg}{}% + \fi \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 +% since square brackets don't work well 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. +% Things referred to by \setref. % -\def\Ypagenumber{\folio} -\def\Ytitle{\thissection} \def\Ynothing{} -\def\Ysectionnumberandtype{% +\def\Yomitfromtoc{} +\def\Ynumbered{% \ifnum\secno=0 \putwordChapter@tie \the\chapno \else \ifnum\subsecno=0 @@ -6034,8 +5989,7 @@ \putwordSection@tie \the\chapno.\the\secno.\the\subsecno.\the\subsubsecno \fi\fi\fi } - -\def\Yappendixletterandtype{% +\def\Yappendix{% \ifnum\secno=0 \putwordAppendix@tie @char\the\appendixno{}% \else \ifnum\subsecno=0 @@ -6048,15 +6002,6 @@ \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. % @@ -6065,7 +6010,7 @@ \indexnofonts \otherbackslash \expandafter\global\expandafter\let\expandafter\thisrefX - \csname X#1\endcsname + \csname XR#1\endcsname }% \ifx\thisrefX\relax % If not defined, say something at least. @@ -6087,11 +6032,44 @@ #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} +% This is the macro invoked by entries in the aux file. Usually it's +% just a \def (we prepend XR to the control sequence name to avoid +% collisions). But if this is a float type, we have more work to do. +% +\def\xrdef#1#2{% + \expandafter\gdef\csname XR#1\endcsname{#2}% remember this xref value. + % + % Was that xref control sequence that we just defined for a float? + \expandafter\iffloat\csname XR#1\endcsname + % it was a float, and we have the (safe) float type in \iffloattype. + \expandafter\let\expandafter\floatlist + \csname floatlist\iffloattype\endcsname + % + % Is this the first time we've seen this float type? + \expandafter\ifx\floatlist\relax + \toks0 = {\do}% yes, so just \do + \else + % had it before, so preserve previous elements in list. + \toks0 = \expandafter{\floatlist\do}% + \fi + % + % Remember this xref in the control sequence \floatlistFLOATTYPE, + % for later use in \listoffloats. + \expandafter\xdef\csname floatlist\iffloattype\endcsname{\the\toks0{#1}}% + \fi +} % Read the last existing aux file, if any. No error if none exists. +% +\def\tryauxfile{% + \openin 1 \jobname.aux + \ifeof 1 \else + \readauxfile + \global\havexrefstrue + \fi + \closein 1 +} + \def\readauxfile{\begingroup \catcode`\^^@=\other \catcode`\^^A=\other @@ -6150,7 +6128,16 @@ \catcode`\%=\other \catcode`+=\other % avoid \+ for paranoia even though we've turned it off % - % Make the characters 128-255 be printing characters + % This is to support \ in node names and titles, since the \ + % characters end up in a \csname. It's easier than + % leaving it active and making its active definition an actual \ + % character. What I don't understand is why it works in the *value* + % of the xrdef. Seems like it should be a catcode12 \, and that + % should not typeset properly. But it works, so I'm moving on for + % now. --karl, 15jan04. + \catcode`\\=\other + % + % Make the characters 128-255 be printing characters. {% \count 1=128 \def\loop{% @@ -6160,31 +6147,17 @@ }% }% % - % 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. + % @ is our escape character in .aux files, and we need braces. \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 + \input \jobname.aux \endgroup} -% Footnotes. +\message{insertions,} +% including footnotes. \newcount \footnoteno @@ -6198,13 +6171,12 @@ % @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 + \let\noindent=\ptexnoindent \global\advance\footnoteno by \@ne \edef\thisfootno{$^{\the\footnoteno}$}% % @@ -6222,17 +6194,12 @@ % 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 +% Oh yes, they do; otherwise, @ifset (and anything else that uses +% \parseargline) fails 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 + \insert\footins\bgroup % 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. @@ -6268,40 +6235,66 @@ } }%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 - }% - }% +% In case a @footnote appears in a vbox, save the footnote text and create +% the real \insert just after the vbox finished. Otherwise, the insertion +% would be lost. +% Similarily, if 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. +% And the same can be done for other insert classes. --kasal, 16nov03. + +% Replace the \insert primitive by a cheating macro. +% Deeper inside, just make sure that the saved insertions are not spilled +% out prematurely. +% +\def\startsavinginserts{% + \ifx \insert\ptexinsert + \let\insert\saveinsert + \else + \let\checkinserts\relax + \fi } -% 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). +% This \insert replacement works for both \insert\footins{foo} and +% \insert\footins\bgroup foo\egroup, but it doesn't work for \insert27{foo}. % -\def\finalout{\overfullrule=0pt} +\def\saveinsert#1{% + \edef\next{\noexpand\savetobox \makeSAVEname#1}% + \afterassignment\next + % swallow the left brace + \let\temp = +} +\def\makeSAVEname#1{\makecsname{SAVE\expandafter\gobble\string#1}} +\def\savetobox#1{\global\setbox#1 = \vbox\bgroup \unvbox#1} + +\def\checksaveins#1{\ifvoid#1\else \placesaveins#1\fi} + +\def\placesaveins#1{% + \ptexinsert \csname\expandafter\gobblesave\string#1\endcsname + {\box#1}% +} + +% eat @SAVE -- beware, all of them have catcode \other: +{ + \def\dospecials{\do S\do A\do V\do E} \uncatcodespecials % ;-) + \gdef\gobblesave @SAVE{} +} + +% initialization: +\def\newsaveins #1{% + \edef\next{\noexpand\newsaveinsX \makeSAVEname#1}% + \next +} +\def\newsaveinsX #1{% + \csname newbox\endcsname #1% + \expandafter\def\expandafter\checkinserts\expandafter{\checkinserts + \checksaveins #1}% +} + +% initialize: +\let\checkinserts\empty +\newsaveins\footins +\newsaveins\margin + % @image. We use the macros from epsf.tex to support this. % If epsf.tex is not installed and @image is used, we complain. @@ -6311,12 +6304,12 @@ % 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 +\closein 1 % % We will only complain once about lack of epsf.tex. \newif\ifwarnednoepsf @@ -6372,6 +6365,269 @@ \endgroup} +% @float FLOATTYPE,LABEL,LOC ... @end float for displayed figures, tables, +% etc. We don't actually implement floating yet, we always include the +% float "here". But it seemed the best name for the future. +% +\envparseargdef\float{\eatcommaspace\eatcommaspace\dofloat#1, , ,\finish} + +% There may be a space before second and/or third parameter; delete it. +\def\eatcommaspace#1, {#1,} + +% #1 is the optional FLOATTYPE, the text label for this float, typically +% "Figure", "Table", "Example", etc. Can't contain commas. If omitted, +% this float will not be numbered and cannot be referred to. +% +% #2 is the optional xref label. Also must be present for the float to +% be referable. +% +% #3 is the optional positioning argument; for now, it is ignored. It +% will somehow specify the positions allowed to float to (here, top, bottom). +% +% We keep a separate counter for each FLOATTYPE, which we reset at each +% chapter-level command. +\let\resetallfloatnos=\empty +% +\def\dofloat#1,#2,#3,#4\finish{% + \let\thiscaption=\empty + \let\thisshortcaption=\empty + % + % don't lose footnotes inside @float. + % + % BEWARE: when the floats start float, we have to issue warning whenever an + % insert appears inside a float which could possibly float. --kasal, 26may04 + % + \startsavinginserts + % + % We can't be used inside a paragraph. + \par + % + \vtop\bgroup + \def\floattype{#1}% + \def\floatlabel{#2}% + \def\floatloc{#3}% we do nothing with this yet. + % + \ifx\floattype\empty + \let\safefloattype=\empty + \else + {% + % the floattype might have accents or other special characters, + % but we need to use it in a control sequence name. + \indexnofonts + \turnoffactive + \xdef\safefloattype{\floattype}% + }% + \fi + % + % If label is given but no type, we handle that as the empty type. + \ifx\floatlabel\empty \else + % We want each FLOATTYPE to be numbered separately (Figure 1, + % Table 1, Figure 2, ...). (And if no label, no number.) + % + \expandafter\getfloatno\csname\safefloattype floatno\endcsname + \global\advance\floatno by 1 + % + {% + % This magic value for \thissection is output by \setref as the + % XREFLABEL-title value. \xrefX uses it to distinguish float + % labels (which have a completely different output format) from + % node and anchor labels. And \xrdef uses it to construct the + % lists of floats. + % + \edef\thissection{\floatmagic=\safefloattype}% + \setref{\floatlabel}{Yfloat}% + }% + \fi + % + % start with \parskip glue, I guess. + \vskip\parskip + % + % Don't suppress indentation if a float happens to start a section. + \restorefirstparagraphindent +} + +% we have these possibilities: +% @float Foo,lbl & @caption{Cap}: Foo 1.1: Cap +% @float Foo,lbl & no caption: Foo 1.1 +% @float Foo & @caption{Cap}: Foo: Cap +% @float Foo & no caption: Foo +% @float ,lbl & Caption{Cap}: 1.1: Cap +% @float ,lbl & no caption: 1.1 +% @float & @caption{Cap}: Cap +% @float & no caption: +% +\def\Efloat{% + \let\floatident = \empty + % + % In all cases, if we have a float type, it comes first. + \ifx\floattype\empty \else \def\floatident{\floattype}\fi + % + % If we have an xref label, the number comes next. + \ifx\floatlabel\empty \else + \ifx\floattype\empty \else % if also had float type, need tie first. + \appendtomacro\floatident{\tie}% + \fi + % the number. + \appendtomacro\floatident{\chaplevelprefix\the\floatno}% + \fi + % + % Start the printed caption with what we've constructed in + % \floatident, but keep it separate; we need \floatident again. + \let\captionline = \floatident + % + \ifx\thiscaption\empty \else + \ifx\floatident\empty \else + \appendtomacro\captionline{: }% had ident, so need a colon between + \fi + % + % caption text. + \appendtomacro\captionline{\scanexp\thiscaption}% + \fi + % + % If we have anything to print, print it, with space before. + % Eventually this needs to become an \insert. + \ifx\captionline\empty \else + \vskip.5\parskip + \captionline + % + % Space below caption. + \vskip\parskip + \fi + % + % If have an xref label, write the list of floats info. Do this + % after the caption, to avoid chance of it being a breakpoint. + \ifx\floatlabel\empty \else + % Write the text that goes in the lof to the aux file as + % \floatlabel-lof. Besides \floatident, we include the short + % caption if specified, else the full caption if specified, else nothing. + {% + \atdummies \turnoffactive \otherbackslash + % since we read the caption text in the macro world, where ^^M + % is turned into a normal character, we have to scan it back, so + % we don't write the literal three characters "^^M" into the aux file. + \scanexp{% + \xdef\noexpand\gtemp{% + \ifx\thisshortcaption\empty + \thiscaption + \else + \thisshortcaption + \fi + }% + }% + \immediate\write\auxfile{@xrdef{\floatlabel-lof}{\floatident + \ifx\gtemp\empty \else : \gtemp \fi}}% + }% + \fi + \egroup % end of \vtop + % + % place the captured inserts + % + % BEWARE: when the floats start float, we have to issue warning whenever an + % insert appears inside a float which could possibly float. --kasal, 26may04 + % + \checkinserts +} + +% Append the tokens #2 to the definition of macro #1, not expanding either. +% +\def\appendtomacro#1#2{% + \expandafter\def\expandafter#1\expandafter{#1#2}% +} + +% @caption, @shortcaption +% +\def\caption{\docaption\thiscaption} +\def\shortcaption{\docaption\thisshortcaption} +\def\docaption{\checkenv\float \bgroup\scanargctxt\defcaption} +\def\defcaption#1#2{\egroup \def#1{#2}} + +% The parameter is the control sequence identifying the counter we are +% going to use. Create it if it doesn't exist and assign it to \floatno. +\def\getfloatno#1{% + \ifx#1\relax + % Haven't seen this figure type before. + \csname newcount\endcsname #1% + % + % Remember to reset this floatno at the next chap. + \expandafter\gdef\expandafter\resetallfloatnos + \expandafter{\resetallfloatnos #1=0 }% + \fi + \let\floatno#1% +} + +% \setref calls this to get the XREFLABEL-snt value. We want an @xref +% to the FLOATLABEL to expand to "Figure 3.1". We call \setref when we +% first read the @float command. +% +\def\Yfloat{\floattype@tie \chaplevelprefix\the\floatno}% + +% Magic string used for the XREFLABEL-title value, so \xrefX can +% distinguish floats from other xref types. +\def\floatmagic{!!float!!} + +% #1 is the control sequence we are passed; we expand into a conditional +% which is true if #1 represents a float ref. That is, the magic +% \thissection value which we \setref above. +% +\def\iffloat#1{\expandafter\doiffloat#1==\finish} +% +% #1 is (maybe) the \floatmagic string. If so, #2 will be the +% (safe) float type for this float. We set \iffloattype to #2. +% +\def\doiffloat#1=#2=#3\finish{% + \def\temp{#1}% + \def\iffloattype{#2}% + \ifx\temp\floatmagic +} + +% @listoffloats FLOATTYPE - print a list of floats like a table of contents. +% +\parseargdef\listoffloats{% + \def\floattype{#1}% floattype + {% + % the floattype might have accents or other special characters, + % but we need to use it in a control sequence name. + \indexnofonts + \turnoffactive + \xdef\safefloattype{\floattype}% + }% + % + % \xrdef saves the floats as a \do-list in \floatlistSAFEFLOATTYPE. + \expandafter\ifx\csname floatlist\safefloattype\endcsname \relax + \ifhavexrefs + % if the user said @listoffloats foo but never @float foo. + \message{\linenumber No `\safefloattype' floats to list.}% + \fi + \else + \begingroup + \leftskip=\tocindent % indent these entries like a toc + \let\do=\listoffloatsdo + \csname floatlist\safefloattype\endcsname + \endgroup + \fi +} + +% This is called on each entry in a list of floats. We're passed the +% xref label, in the form LABEL-title, which is how we save it in the +% aux file. We strip off the -title and look up \XRLABEL-lof, which +% has the text we're supposed to typeset here. +% +% Figures without xref labels will not be included in the list (since +% they won't appear in the aux file). +% +\def\listoffloatsdo#1{\listoffloatsdoentry#1\finish} +\def\listoffloatsdoentry#1-title\finish{{% + % Can't fully expand XR#1-lof because it can contain anything. Just + % pass the control sequence. On the other hand, XR#1-pg is just the + % page number, and we want to fully expand that so we can get a link + % in pdf output. + \toksA = \expandafter{\csname XR#1-lof\endcsname}% + % + % use the same \entry macro we use to generate the TOC and index. + \edef\writeentry{\noexpand\entry{\the\toksA}{\csname XR#1-pg\endcsname}}% + \writeentry +}} + \message{localization,} % and i18n. @@ -6380,19 +6636,17 @@ % 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{% +\parseargdef\documentlanguage{% \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 + % Read the file if it exists. + \openin 1 txi-#1.tex + \ifeof 1 + \errhelp = \nolanghelp + \errmessage{Cannot read language file txi-#1.tex}% + \else + \input txi-#1.tex + \fi + \closein 1 \endgroup } \newhelp\nolanghelp{The given language definition file cannot be found or @@ -6575,8 +6829,7 @@ % 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} +\parseargdef\pagesizes{\pagesizesyyy #1,,\finish} \def\pagesizesyyy#1,#2,#3\finish{{% \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \hsize=#2\relax \fi \globaldefs = 1 @@ -6623,8 +6876,8 @@ \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, +% This macro is used to make a character print one way in \tt +% (where it can probably be output as-is), 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 @@ -6672,13 +6925,6 @@ \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. @@ -6687,15 +6933,16 @@ \catcode`\@=0 -% \rawbackslashxx outputs one backslash character in current font, +% \backslashcurfont outputs one backslash character in current font, % as in \char`\\. -\global\chardef\rawbackslashxx=`\\ +\global\chardef\backslashcurfont=`\\ +\global\let\rawbackslashxx=\backslashcurfont % let existing .??s files work -% \rawbackslash defines an active \ to do \rawbackslashxx. +% \rawbackslash defines an active \ to do \backslashcurfont. % \otherbackslash defines an active \ to be a literal `\' character with % catcode other. {\catcode`\\=\active - @gdef@rawbackslash{@let\=@rawbackslashxx} + @gdef@rawbackslash{@let\=@backslashcurfont} @gdef@otherbackslash{@let\=@realbackslash} } @@ -6703,7 +6950,7 @@ {\catcode`\\=\other @gdef@realbackslash{\}} % \normalbackslash outputs one backslash in fixed width font. -\def\normalbackslash{{\tt\rawbackslashxx}} +\def\normalbackslash{{\tt\backslashcurfont}} \catcode`\\=\active @@ -6720,6 +6967,7 @@ @let>=@normalgreater @let+=@normalplus @let$=@normaldollar %$ font-lock fix + @unsepspaces } % Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of @@ -6759,10 +7007,6 @@ @catcode`@# = @other @catcode`@% = @other -@c Set initial fonts. -@textfonts -@rm - @c Local variables: @c eval: (add-hook 'write-file-hooks 'time-stamp) @@ -6771,3 +7015,9 @@ @c time-stamp-format: "%:y-%02m-%02d.%02H" @c time-stamp-end: "}" @c End: + +@c vim:sw=2: + +@ignore + arch-tag: e1b36e32-c96e-4135-a41a-0b2efa2ea115 +@end ignore Index: libgcrypt/install-sh diff -u libgcrypt/install-sh:1.1 libgcrypt/install-sh:1.1.2.1 --- libgcrypt/install-sh:1.1 Mon Dec 8 22:42:35 2003 +++ libgcrypt/install-sh Tue Jan 4 21:50:23 2005 @@ -1,7 +1,8 @@ #!/bin/sh -# # install - install a program, script, or datafile -# + +scriptversion=2004-10-22.00 + # 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. @@ -41,13 +42,11 @@ # 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}" @@ -59,236 +58,266 @@ rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" -transformbasename="" -transform_arg="" -instcmd="$mvprog" chmodcmd="$chmodprog 0755" -chowncmd="" -chgrpcmd="" -stripcmd="" +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 +src= +dst= +dir_arg= +dstarg= +no_target_directory= + +usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: +-c (ignored) +-d create directories instead of installing files. +-g GROUP $chgrpprog installed files to GROUP. +-m MODE $chmodprog installed files to MODE. +-o USER $chownprog installed files to USER. +-s $stripprog installed files. +-t DIRECTORY install into DIRECTORY. +-T report an error if DSTFILE is a directory. +--help display this help and exit. +--version display version info and exit. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG +" + +while test -n "$1"; do + case $1 in + -c) shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + --help) echo "$usage"; exit 0;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -s) stripcmd=$stripprog + shift + continue;; -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='' + -t) dstarg=$2 + shift + shift + continue;; -while [ $# -ne 0 ] ; do - pathcomp=$pathcomp$1 + -T) no_target_directory=true shift + continue;; - if [ ! -d "$pathcomp" ] ; - then - $mkdirprog "$pathcomp" - else - : - fi + --version) echo "$0 $scriptversion"; exit 0;; - pathcomp=$pathcomp/ + *) # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + test -n "$dir_arg$dstarg" && break + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dstarg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dstarg" + shift # fnord + fi + shift # arg + dstarg=$arg + done + break;; + esac 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. +if test -z "$1"; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi - $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src ;; + esac + + if test -n "$dir_arg"; then + dst=$src + src= + + if test -d "$dst"; then + mkdircmd=: + chmodcmd= + else + mkdircmd=$mkdirprog + fi + else + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dstarg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dstarg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst ;; + esac -fi && + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dstarg: Is a directory" >&2 + exit 1 + fi + dst=$dst/`basename "$src"` + fi + fi + + # This sed command emulates the dirname command. + dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` + + # Make sure that the destination directory exists. + + # Skip lots of stat calls in the usual case. + if test ! -d "$dstdir"; then + defaultIFS=' + ' + IFS="${IFS-$defaultIFS}" + + oIFS=$IFS + # Some sh's can't handle IFS=/ for some reason. + IFS='%' + set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` + shift + IFS=$oIFS + + pathcomp= + + while test $# -ne 0 ; do + pathcomp=$pathcomp$1 + shift + if test ! -d "$pathcomp"; then + $mkdirprog "$pathcomp" + # mkdir can fail with a `File exist' error in case several + # install-sh are creating the directory concurrently. This + # is OK. + test -d "$pathcomp" || exit + fi + pathcomp=$pathcomp/ + done + fi + + if test -n "$dir_arg"; then + $doit $mkdircmd "$dst" \ + && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } + + else + dstfile=`basename "$dst"` + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + trap '(exit $?); exit' 1 2 13 15 + + # Copy the file name to the temp name. + $doit $cpprog "$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 $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && + + # Now rename the file to the real destination. + { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ + || { + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + + # 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 test -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 || { (exit 1); exit; } +done # The final little trick to "correctly" pass the exit status to the exit trap. - { - (exit 0); exit + (exit 0); exit } + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: Index: libgcrypt/missing diff -u libgcrypt/missing:1.1 libgcrypt/missing:1.1.2.1 --- libgcrypt/missing:1.1 Mon Dec 8 22:42:35 2003 +++ libgcrypt/missing Tue Jan 4 21:50:23 2005 @@ -1,6 +1,10 @@ #! /bin/sh # Common stub for a few missing GNU programs while installing. -# Copyright (C) 1996, 1997, 1999, 2000, 2002 Free Software Foundation, Inc. + +scriptversion=2004-09-07.08 + +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004 +# Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify @@ -38,18 +42,24 @@ configure_ac=configure.in fi +msg="missing on your system" + case "$1" in --run) # Try to run requested program, and just exit if it succeeds. run= shift "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi ;; -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 "\ @@ -74,11 +84,15 @@ 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]" + yacc create \`y.tab.[ch]', if possible, from existing .[ch] + +Send bug reports to ." + exit 0 ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) - echo "missing 0.4 - GNU automake" + echo "missing $scriptversion (GNU Automake)" + exit 0 ;; -*) @@ -87,14 +101,44 @@ exit 1 ;; - aclocal*) +esac + +# Now exit if we have it, but it failed. Also exit now if we +# don't have it and --version was passed (most likely to detect +# the program). +case "$1" in + lex|yacc) + # Not GNU programs, they don't have --version. + ;; + + tar) + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + exit 1 + fi + ;; + + *) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + # Could not run --version or --help. This is probably someone + # running `$TOOL --version' or `$TOOL --help' to check whether + # $TOOL exists and not knowing $TOOL uses missing. + exit 1 fi + ;; +esac +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case "$1" in + aclocal*) echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if +WARNING: \`$1' is $msg. 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." @@ -102,13 +146,8 @@ ;; 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 +WARNING: \`$1' is $msg. 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." @@ -116,13 +155,8 @@ ;; 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 +WARNING: \`$1' is $msg. 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." @@ -140,13 +174,8 @@ ;; 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 +WARNING: \`$1' is $msg. 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." @@ -156,16 +185,11 @@ ;; 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 +WARNING: \`$1' is needed, but is $msg. + 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 + You can get \`$1' as part of \`Autoconf' from any GNU archive site." file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` @@ -185,7 +209,7 @@ bison|yacc) echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if +WARNING: \`$1' $msg. 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." @@ -215,7 +239,7 @@ lex|flex) echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if +WARNING: \`$1' is $msg. 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." @@ -237,13 +261,8 @@ ;; 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 +WARNING: \`$1' is $msg. 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." @@ -262,13 +281,8 @@ ;; 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 +WARNING: \`$1' is $msg. 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, @@ -284,10 +298,6 @@ 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 @@ -323,10 +333,10 @@ *) 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 +WARNING: \`$1' is needed, and is $msg. + 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 + it often tells you about the needed prerequisites 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 @@ -334,3 +344,10 @@ esac exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: Index: libgcrypt/mkinstalldirs diff -u libgcrypt/mkinstalldirs:1.1 libgcrypt/mkinstalldirs:1.1.2.1 --- libgcrypt/mkinstalldirs:1.1 Mon Dec 8 22:42:35 2003 +++ libgcrypt/mkinstalldirs Tue Jan 4 21:50:23 2005 @@ -1,20 +1,32 @@ #! /bin/sh # mkinstalldirs --- make directory hierarchy -# Author: Noah Friedman + +scriptversion=2004-02-15.20 + +# Original author: Noah Friedman # Created: 1993-05-16 -# Public domain +# Public domain. +# +# This file is maintained in Automake, please report +# bugs to or send patches to +# . errstatus=0 dirmode="" usage="\ -Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..." +Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ... + +Create each directory DIR (with mode MODE, if specified), including all +leading file name components. + +Report bugs to ." # process command line arguments while test $# -gt 0 ; do case $1 in -h | --help | --h*) # -h for help - echo "$usage" 1>&2 + echo "$usage" exit 0 ;; -m) # -m PERM arg @@ -23,6 +35,10 @@ dirmode=$1 shift ;; + --version) + echo "$0 $scriptversion" + exit 0 + ;; --) # stop option processing shift break @@ -50,17 +66,37 @@ 0) exit 0 ;; esac +# Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and +# mkdir -p a/c at the same time, both will detect that a is missing, +# one will create a, then the other will try to create a and die with +# a "File exists" error. This is a problem when calling mkinstalldirs +# from a parallel make. We use --version in the probe to restrict +# ourselves to GNU mkdir, which is thread-safe. case $dirmode in '') - if mkdir -p -- . 2>/dev/null; then + if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then echo "mkdir -p -- $*" exec mkdir -p -- "$@" + else + # On NextStep and OpenStep, the `mkdir' command does not + # recognize any option. It will interpret all options as + # directories to create, and then abort because `.' already + # exists. + test -d ./-p && rmdir ./-p + test -d ./--version && rmdir ./--version fi ;; *) - if mkdir -m "$dirmode" -p -- . 2>/dev/null; then + if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 && + test ! -d ./--version; then echo "mkdir -m $dirmode -p -- $*" exec mkdir -m "$dirmode" -p -- "$@" + else + # Clean up after NextStep and OpenStep mkdir. + for d in ./-m ./-p ./--version "./$dirmode"; + do + test -d $d && rmdir $d + done fi ;; esac @@ -84,17 +120,17 @@ mkdir "$pathcomp" || lasterr=$? if test ! -d "$pathcomp"; then - errstatus=$lasterr + errstatus=$lasterr else - if test ! -z "$dirmode"; then + if test ! -z "$dirmode"; then echo "chmod $dirmode $pathcomp" - lasterr="" - chmod "$dirmode" "$pathcomp" || lasterr=$? + lasterr="" + chmod "$dirmode" "$pathcomp" || lasterr=$? - if test ! -z "$lasterr"; then - errstatus=$lasterr - fi - fi + if test ! -z "$lasterr"; then + errstatus=$lasterr + fi + fi fi fi @@ -107,5 +143,8 @@ # Local Variables: # mode: shell-script # sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" # End: -# mkinstalldirs ends here Index: libgcrypt/src/ChangeLog diff -u libgcrypt/src/ChangeLog:1.151.2.9 libgcrypt/src/ChangeLog:1.151.2.10 --- libgcrypt/src/ChangeLog:1.151.2.9 Mon Dec 6 18:36:34 2004 +++ libgcrypt/src/ChangeLog Tue Jan 4 21:50:23 2005 @@ -1,3 +1,7 @@ +2004-12-20 Werner Koch + + * gcrypt.h (GCRY_THREAD_OPTION_PTH_IMPL): Tweaks for W32. + 2004-12-06 Werner Koch * g10lib.h (stpcpy, strcasecmp): Prefix them with _gcry_ and add Index: libgcrypt/src/gcrypt.h diff -u libgcrypt/src/gcrypt.h:1.125.2.3 libgcrypt/src/gcrypt.h:1.125.2.4 --- libgcrypt/src/gcrypt.h:1.125.2.3 Fri Nov 26 17:27:08 2004 +++ libgcrypt/src/gcrypt.h Tue Jan 4 21:50:22 2005 @@ -162,6 +162,19 @@ GCRY_THREAD_OPTION_PTHREAD = 3 }; +/* Do avoid inclusing of too much W32 stuff, we redefine some types. */ +#ifdef _WIN32 +#define _GCRY_PTH_FD_SET void +#define _GCRY_PTH_SOCKADDR void +#define _GCRY_PTH_SOCKLEN_T int +#define _GCRY_PTH_MSGHDR void +#else +#define _GCRY_PTH_FD_SET fd_set +#define _GCRY_PTH_SOCKADDR struct sockaddr +#define _GCRY_PTH_SOCKLEN_T socklen_t +#define _GCRY_PTH_MSGHDR struct msghdr +#endif + /* Wrapper for struct ath_ops. */ struct gcry_thread_cbs { @@ -173,23 +186,15 @@ int (*mutex_unlock) (void **priv); ssize_t (*read) (int fd, void *buf, size_t nbytes); ssize_t (*write) (int fd, const void *buf, size_t nbytes); -#ifdef _WIN32 - ssize_t (*select) (int nfd, void *rset, void *wset, void *eset, - struct timeval *timeout); - ssize_t (*waitpid) (pid_t pid, int *status, int options); - int (*accept) (int s, void *addr, int *length_ptr); - int (*connect) (int s, void *addr, int length); - int (*sendmsg) (int s, const void *msg, int flags); - int (*recvmsg) (int s, void *msg, int flags); -#else - ssize_t (*select) (int nfd, fd_set *rset, fd_set *wset, fd_set *eset, - struct timeval *timeout); + ssize_t (*select) (int nfd, _GCRY_PTH_FD_SET *rset, _GCRY_PTH_FD_SET *wset, + _GCRY_PTH_FD_SET *eset, struct timeval *timeout); ssize_t (*waitpid) (pid_t pid, int *status, int options); - int (*accept) (int s, struct sockaddr *addr, socklen_t *length_ptr); - int (*connect) (int s, struct sockaddr *addr, socklen_t length); - int (*sendmsg) (int s, const struct msghdr *msg, int flags); - int (*recvmsg) (int s, struct msghdr *msg, int flags); -#endif + int (*accept) (int s, _GCRY_PTH_SOCKADDR *addr, + _GCRY_PTH_SOCKLEN_T *length_ptr); + int (*connect) (int s, _GCRY_PTH_SOCKADDR *addr, + _GCRY_PTH_SOCKLEN_T length); + int (*sendmsg) (int s, const _GCRY_PTH_MSGHDR *msg, int flags); + int (*recvmsg) (int s, _GCRY_PTH_MSGHDR *msg, int flags); }; #define GCRY_THREAD_OPTION_PTH_IMPL \ @@ -228,15 +233,18 @@ { return pth_read (fd, buf, nbytes); } \ static ssize_t gcry_pth_write (int fd, const void *buf, size_t nbytes) \ { return pth_write (fd, buf, nbytes); } \ -static ssize_t gcry_pth_select (int nfd, fd_set *rset, fd_set *wset, \ - fd_set *eset, struct timeval *timeout) \ +static ssize_t gcry_pth_select (int nfd, _GCRY_PTH_FD_SET *rset, \ + _GCRY_PTH_FD_SET *wset, \ + _GCRY_PTH_FD_SET *eset, \ + struct timeval *timeout) \ { return pth_select (nfd, rset, wset, eset, timeout); } \ static ssize_t gcry_pth_waitpid (pid_t pid, int *status, int options) \ { return pth_waitpid (pid, status, options); } \ -static int gcry_pth_accept (int s, struct sockaddr *addr, \ - socklen_t *length_ptr) \ +static int gcry_pth_accept (int s, _GCRY_PTH_SOCKADDR *addr, \ + _GCRY_PTH_SOCKLEN_T *length_ptr) \ { return pth_accept (s, addr, length_ptr); } \ -static int gcry_pth_connect (int s, struct sockaddr *addr, socklen_t length) \ +static int gcry_pth_connect (int s, _GCRY_PTH_SOCKADDR *addr, \ + _GCRY_PTH_SOCKLEN_T length) \ { return pth_connect (s, addr, length); } \ \ /* FIXME: GNU Pth is missing pth_sendmsg and pth_recvmsg. */ \ From cvs at cvs.gnupg.org Wed Jan 26 23:16:24 2005 From: cvs at cvs.gnupg.org (cvs user mo) Date: Fri Jan 28 12:17:29 2005 Subject: GNUPG-1-9-BRANCH gnupg/common (ChangeLog Makefile.am estream.c estream.h) Message-ID: Date: Wednesday, January 26, 2005 @ 23:24:59 Author: mo Path: /cvs/gnupg/gnupg/common Tag: GNUPG-1-9-BRANCH Added: estream.c estream.h Modified: ChangeLog Makefile.am 2005-01-26 Moritz Schulte * Makefile.am (libcommon_a_SOURCES): New source files: estream.c, estream.h. * estream.c, estream.h: New files. -------------+ ChangeLog | 6 Makefile.am | 3 estream.c | 2609 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ estream.h | 201 ++++ 4 files changed, 2818 insertions(+), 1 deletion(-) Index: gnupg/common/ChangeLog diff -u gnupg/common/ChangeLog:1.30.2.42 gnupg/common/ChangeLog:1.30.2.43 --- gnupg/common/ChangeLog:1.30.2.42 Mon Jan 3 12:30:43 2005 +++ gnupg/common/ChangeLog Wed Jan 26 23:24:59 2005 @@ -1,3 +1,9 @@ +2005-01-26 Moritz Schulte + + * Makefile.am (libcommon_a_SOURCES): New source files: estream.c, + estream.h. + * estream.c, estream.h: New files. + 2005-01-03 Werner Koch * asshelp.c (send_pinentry_environment): Fixed changed from Index: gnupg/common/Makefile.am diff -u gnupg/common/Makefile.am:1.15.2.11 gnupg/common/Makefile.am:1.15.2.12 --- gnupg/common/Makefile.am:1.15.2.11 Tue Dec 21 11:03:00 2004 +++ gnupg/common/Makefile.am Wed Jan 26 23:24:59 2005 @@ -44,7 +44,8 @@ simple-gettext.c \ w32reg.c \ signal.c \ - dynload.h + dynload.h \ + estream.c estream.h libcommon_a_LIBADD = @LIBOBJS@ Index: gnupg/common/estream.c diff -u /dev/null gnupg/common/estream.c:1.1.2.1 --- /dev/null Wed Jan 26 23:24:59 2005 +++ gnupg/common/estream.c Wed Jan 26 23:24:59 2005 @@ -0,0 +1,2609 @@ +/* estream.c - Extended stream I/O/ Library + Copyright (C) 2004 g10 Code GmbH + + This file is part of Libestream. + + Libestream 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. + + Libestream 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 Libestream; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifdef USE_ESTREAM_SUPPORT_H +# include +#endif + +#ifdef USE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_PTH +# include +#endif + +#ifndef HAVE_MKSTEMP +int mkstemp (char *template); +#endif + +#ifndef HAVE_MEMRCHR +void *memrchr (const void *block, int c, size_t size); +#endif + +#include + + + +/* Generally used types. */ + +typedef void *(*func_realloc_t) (void *mem, size_t size); +typedef void (*func_free_t) (void *mem); + + + +/* Buffer management layer. */ + +#define BUFFER_BLOCK_SIZE BUFSIZ +#define BUFFER_UNREAD_SIZE 16 + + + +/* Macros. */ + +#define BUFFER_ROUND_TO_BLOCK(size, block_size) \ + (((size) + (block_size - 1)) / block_size) + + + +/* Locking. */ + +#ifdef HAVE_PTH + +typedef pth_mutex_t estream_mutex_t; +# define ESTREAM_MUTEX_INITIALIZER PTH_MUTEX_INIT +# define ESTREAM_MUTEX_LOCK(mutex) \ + pth_mutex_acquire (&(mutex), 0, NULL) +# define ESTREAM_MUTEX_UNLOCK(mutex) \ + pth_mutex_release (&(mutex)) +# define ESTREAM_MUTEX_TRYLOCK(mutex) \ + ((pth_mutex_acquire (&(mutex), 1, NULL) == TRUE) ? 0 : -1) +# define ESTREAM_MUTEX_INITIALIZE(mutex) \ + pth_mutex_init (&(mutex)) +# define ESTREAM_THREADING_INIT() ((pth_init () == TRUE) ? 0 : -1) + +#else + +typedef void *estream_mutex_t; +# define ESTREAM_MUTEX_INITIALIZER NULL +# define ESTREAM_MUTEX_LOCK(mutex) (void) 0 +# define ESTREAM_MUTEX_UNLOCK(mutex) (void) 0 +# define ESTREAM_MUTEX_TRYLOCK(mutex) 0 +# define ESTREAM_MUTEX_INITIALIZE(mutex) (void) 0 +# define ESTREAM_THREADING_INIT() 0 + +#endif + +/* Memory allocator functions. */ + +#define MEM_ALLOC malloc +#define MEM_REALLOC realloc +#define MEM_FREE free + +/* Primitive system I/O. */ + +#ifdef HAVE_PTH +# define ESTREAM_SYS_READ pth_read +# define ESTREAM_SYS_WRITE pth_write +#else +# define ESTREAM_SYS_READ read +# define ESTREAM_SYS_WRITE write +#endif + +/* Misc definitions. */ + +#define ES_DEFAULT_OPEN_MODE (S_IRUSR | S_IWUSR) + +#define ES_FLAG_WRITING ES__FLAG_WRITING + +/* An internal stream object. */ + +struct estream_internal +{ + unsigned char buffer[BUFFER_BLOCK_SIZE]; + unsigned char unread_buffer[BUFFER_UNREAD_SIZE]; + estream_mutex_t lock; /* Lock. */ + void *cookie; /* Cookie. */ + void *opaque; /* Opaque data. */ + unsigned int flags; /* Flags. */ + off_t offset; + es_cookie_read_function_t func_read; + es_cookie_write_function_t func_write; + es_cookie_seek_function_t func_seek; + es_cookie_close_function_t func_close; + int strategy; + int fd; + struct + { + unsigned int err: 1; + unsigned int eof: 1; + } indicators; + unsigned int deallocate_buffer: 1; +}; + +typedef struct estream_internal *estream_internal_t; + +#define ESTREAM_LOCK(stream) ESTREAM_MUTEX_LOCK (stream->intern->lock) +#define ESTREAM_UNLOCK(stream) ESTREAM_MUTEX_UNLOCK (stream->intern->lock) +#define ESTREAM_TRYLOCK(stream) ESTREAM_MUTEX_TRYLOCK (stream->intern->lock) + +/* Stream list. */ + +typedef struct estream_list *estream_list_t; + +struct estream_list +{ + estream_t car; + estream_list_t cdr; + estream_list_t *prev_cdr; +}; + +static estream_list_t estream_list; +#ifdef HAVE_PTH +static estream_mutex_t estream_list_lock = ESTREAM_MUTEX_INITIALIZER; +#endif + +#define ESTREAM_LIST_LOCK ESTREAM_MUTEX_LOCK (estream_list_lock) +#define ESTREAM_LIST_UNLOCK ESTREAM_MUTEX_UNLOCK (estream_list_lock) + +#ifndef EOPNOTSUPP +# define EOPNOTSUPP ENOSYS +#endif + + + + +/* Macros. */ + +/* Calculate array dimension. */ +#define DIM(array) (sizeof (array) / sizeof (*array)) + +/* Evaluate EXPRESSION, setting VARIABLE to the return code, if + VARIABLE is zero. */ +#define SET_UNLESS_NONZERO(variable, tmp_variable, expression) \ + do \ + { \ + tmp_variable = expression; \ + if ((! variable) && tmp_variable) \ + variable = tmp_variable; \ + } \ + while (0) + +/* + * List manipulation. + */ + +/* Add STREAM to the list of registered stream objects. */ +static int +es_list_add (estream_t stream) +{ + estream_list_t list_obj; + int ret; + + list_obj = MEM_ALLOC (sizeof (*list_obj)); + if (! list_obj) + ret = -1; + else + { + ESTREAM_LIST_LOCK; + list_obj->car = stream; + list_obj->cdr = estream_list; + list_obj->prev_cdr = &estream_list; + if (estream_list) + estream_list->prev_cdr = &list_obj->cdr; + estream_list = list_obj; + ESTREAM_LIST_UNLOCK; + ret = 0; + } + + return ret; +} + +/* Remove STREAM from the list of registered stream objects. */ +static void +es_list_remove (estream_t stream) +{ + estream_list_t list_obj; + + ESTREAM_LIST_LOCK; + for (list_obj = estream_list; list_obj; list_obj = list_obj->cdr) + if (list_obj->car == stream) + { + *list_obj->prev_cdr = list_obj->cdr; + if (list_obj->cdr) + list_obj->cdr->prev_cdr = list_obj->prev_cdr; + MEM_FREE (list_obj); + break; + } + ESTREAM_LIST_UNLOCK; +} + +/* Type of an stream-iterator-function. */ +typedef int (*estream_iterator_t) (estream_t stream); + +/* Iterate over list of registered streams, calling ITERATOR for each + of them. */ +static int +es_list_iterate (estream_iterator_t iterator) +{ + estream_list_t list_obj; + int ret = 0; + + ESTREAM_LIST_LOCK; + for (list_obj = estream_list; list_obj; list_obj = list_obj->cdr) + ret |= (*iterator) (list_obj->car); + ESTREAM_LIST_UNLOCK; + + return ret; +} + + + +/* + * Initialization. + */ + +static int +es_init_do (void) +{ + int err; + + err = ESTREAM_THREADING_INIT (); + + return err; +} + + + +/* + * I/O methods. + */ + +/* Implementation of Memory I/O. */ + +/* Cookie for memory objects. */ +typedef struct estream_cookie_mem +{ + unsigned int flags; /* Open flags. */ + char *memory; /* Data. */ + size_t memory_size; /* Size of MEMORY. */ + size_t offset; /* Current offset in MEMORY. */ + size_t data_len; /* Length of data in MEMORY. */ + size_t block_size; /* Block size. */ + unsigned int grow: 1; /* MEMORY is allowed to grow. */ + unsigned int append_zero: 1; /* Append zero after data. */ + unsigned int dont_free: 1; /* Append zero after data. */ + char **ptr; + size_t *size; + func_realloc_t func_realloc; + func_free_t func_free; +} *estream_cookie_mem_t; + +/* Create function for memory objects. */ +static int +es_func_mem_create (void *ES__RESTRICT *ES__RESTRICT cookie, + unsigned char *ES__RESTRICT data, size_t data_n, + size_t data_len, + size_t block_size, unsigned int grow, + unsigned int append_zero, unsigned int dont_free, + char **ptr, size_t *size, + func_realloc_t func_realloc, func_free_t func_free, + unsigned int flags) +{ + estream_cookie_mem_t mem_cookie; + int err; + + mem_cookie = MEM_ALLOC (sizeof (*mem_cookie)); + if (! mem_cookie) + err = -1; + else + { + mem_cookie->flags = flags; + mem_cookie->memory = data; + mem_cookie->memory_size = data_n; + mem_cookie->offset = 0; + mem_cookie->data_len = data_len; + mem_cookie->block_size = block_size; + mem_cookie->grow = grow ? 1 : 0; + mem_cookie->append_zero = append_zero ? 1 : 0; + mem_cookie->dont_free = dont_free ? 1 : 0; + mem_cookie->ptr = ptr; + mem_cookie->size = size; + mem_cookie->func_realloc = func_realloc ? func_realloc : MEM_REALLOC; + mem_cookie->func_free = func_free ? func_free : MEM_FREE; + mem_cookie->offset = 0; + *cookie = mem_cookie; + err = 0; + } + + return err; +} + +/* Read function for memory objects. */ +static ssize_t +es_func_mem_read (void *cookie, char *buffer, size_t size) +{ + estream_cookie_mem_t mem_cookie = cookie; + ssize_t ret; + + if (size > mem_cookie->data_len - mem_cookie->offset) + size = mem_cookie->data_len - mem_cookie->offset; + + if (size) + { + memcpy (buffer, mem_cookie->memory + mem_cookie->offset, size); + mem_cookie->offset += size; + } + + ret = size; + + return ret; +} + +/* Write function for memory objects. */ +static ssize_t +es_func_mem_write (void *cookie, const char *buffer, size_t size) +{ + estream_cookie_mem_t mem_cookie = cookie; + func_realloc_t func_realloc = mem_cookie->func_realloc; + char *memory_new; + size_t newsize; + ssize_t ret; + int err; + + if (size) + { + /* Regular write. */ + + if (mem_cookie->flags & O_APPEND) + /* Append to data. */ + mem_cookie->offset = mem_cookie->data_len; + + if (! mem_cookie->grow) + if (size > mem_cookie->memory_size - mem_cookie->offset) + size = mem_cookie->memory_size - mem_cookie->offset; + + err = 0; + + while (size > (mem_cookie->memory_size - mem_cookie->offset)) + { + memory_new = (*func_realloc) (mem_cookie->memory, + mem_cookie->memory_size + + mem_cookie->block_size); + if (! memory_new) + { + err = -1; + break; + } + else + { + if (mem_cookie->memory != memory_new) + mem_cookie->memory = memory_new; + mem_cookie->memory_size += mem_cookie->block_size; + } + } + if (err) + goto out; + + if (size) + { + memcpy (mem_cookie->memory + mem_cookie->offset, buffer, size); + if (mem_cookie->offset + size > mem_cookie->data_len) + mem_cookie->data_len = mem_cookie->offset + size; + mem_cookie->offset += size; + } + } + else + { + /* Flush. */ + + err = 0; + if (mem_cookie->append_zero) + { + if (mem_cookie->data_len >= mem_cookie->memory_size) + { + newsize = BUFFER_ROUND_TO_BLOCK (mem_cookie->data_len + 1, + mem_cookie->block_size) + * mem_cookie->block_size; + + memory_new = (*func_realloc) (mem_cookie->memory, newsize); + if (! memory_new) + { + err = -1; + goto out; + } + + if (mem_cookie->memory != memory_new) + mem_cookie->memory = memory_new; + mem_cookie->memory_size = newsize; + } + + mem_cookie->memory[mem_cookie->data_len + 1] = 0; + } + + /* Return information to user if necessary. */ + if (mem_cookie->ptr) + *mem_cookie->ptr = (char *) mem_cookie->memory; + if (mem_cookie->size) + *mem_cookie->size = mem_cookie->data_len; + } + + out: + + if (err) + ret = -1; + else + ret = size; + + return ret; +} + +/* Seek function for memory objects. */ +static int +es_func_mem_seek (void *cookie, off_t *offset, int whence) +{ + estream_cookie_mem_t mem_cookie = cookie; + off_t pos_new; + int err = 0; + + switch (whence) + { + case SEEK_SET: + pos_new = *offset; + break; + + case SEEK_CUR: + pos_new = mem_cookie->offset += *offset; + break; + + case SEEK_END: + pos_new = mem_cookie->data_len += *offset; + break; + + default: + /* Never reached. */ + pos_new = 0; + } + + if (pos_new > mem_cookie->memory_size) + { + /* Grow buffer if possible. */ + + if (mem_cookie->grow) + { + func_realloc_t func_realloc = mem_cookie->func_realloc; + size_t newsize; + void *p; + + newsize = BUFFER_ROUND_TO_BLOCK (pos_new, mem_cookie->block_size); + p = (*func_realloc) (mem_cookie->memory, newsize); + if (! p) + { + err = -1; + goto out; + } + else + { + if (mem_cookie->memory != p) + mem_cookie->memory = p; + mem_cookie->memory_size = newsize; + } + } + else + { + errno = EINVAL; + err = -1; + goto out; + } + } + + if (pos_new > mem_cookie->data_len) + /* Fill spare space with zeroes. */ + memset (mem_cookie->memory + mem_cookie->data_len, + 0, pos_new - mem_cookie->data_len); + + mem_cookie->offset = pos_new; + *offset = pos_new; + + out: + + return err; +} + +/* Destroy function for memory objects. */ +static int +es_func_mem_destroy (void *cookie) +{ + estream_cookie_mem_t mem_cookie = cookie; + func_free_t func_free = mem_cookie->func_free; + + if (! mem_cookie->dont_free) + (*func_free) (mem_cookie->memory); + MEM_FREE (mem_cookie); + + return 0; +} + +static es_cookie_io_functions_t estream_functions_mem = + { + es_func_mem_read, + es_func_mem_write, + es_func_mem_seek, + es_func_mem_destroy, + }; + +/* Implementation of fd I/O. */ + +/* Cookie for fd objects. */ +typedef struct estream_cookie_fd +{ + int fd; +} *estream_cookie_fd_t; + +/* Create function for fd objects. */ +static int +es_func_fd_create (void **cookie, int fd, unsigned int flags) +{ + estream_cookie_fd_t fd_cookie; + int err; + + fd_cookie = MEM_ALLOC (sizeof (*fd_cookie)); + if (! fd_cookie) + err = -1; + else + { + fd_cookie->fd = fd; + *cookie = fd_cookie; + err = 0; + } + + return err; +} + +/* Read function for fd objects. */ +static ssize_t +es_func_fd_read (void *cookie, char *buffer, size_t size) + +{ + estream_cookie_fd_t file_cookie = cookie; + ssize_t bytes_read; + + bytes_read = ESTREAM_SYS_READ (file_cookie->fd, buffer, size); + + return bytes_read; +} + +/* Write function for fd objects. */ +static ssize_t +es_func_fd_write (void *cookie, const char *buffer, size_t size) + +{ + estream_cookie_fd_t file_cookie = cookie; + ssize_t bytes_written; + + bytes_written = ESTREAM_SYS_WRITE (file_cookie->fd, buffer, size); + + return bytes_written; +} + +/* Seek function for fd objects. */ +static int +es_func_fd_seek (void *cookie, off_t *offset, int whence) +{ + estream_cookie_fd_t file_cookie = cookie; + off_t offset_new; + int err; + + offset_new = lseek (file_cookie->fd, *offset, whence); + if (offset_new == -1) + err = -1; + else + { + *offset = offset_new; + err = 0; + } + + return err; +} + +/* Destroy function for fd objects. */ +static int +es_func_fd_destroy (void *cookie) +{ + estream_cookie_fd_t fd_cookie = cookie; + int err; + + if (fd_cookie) + { + err = close (fd_cookie->fd); + MEM_FREE (fd_cookie); + } + else + err = 0; + + return err; +} + +static es_cookie_io_functions_t estream_functions_fd = + { + es_func_fd_read, + es_func_fd_write, + es_func_fd_seek, + es_func_fd_destroy + }; + +/* Implementation of file I/O. */ + +/* Create function for file objects. */ +static int +es_func_file_create (void **cookie, int *filedes, + const char *path, unsigned int flags) +{ + estream_cookie_fd_t file_cookie; + int err; + int fd; + + err = 0; + fd = -1; + + file_cookie = MEM_ALLOC (sizeof (*file_cookie)); + if (! file_cookie) + { + err = -1; + goto out; + } + + fd = open (path, flags, ES_DEFAULT_OPEN_MODE); + if (fd == -1) + { + err = -1; + goto out; + } + + file_cookie->fd = fd; + *cookie = file_cookie; + *filedes = fd; + + out: + + if (err) + MEM_FREE (file_cookie); + + return err; +} + +static es_cookie_io_functions_t estream_functions_file = + { + es_func_fd_read, + es_func_fd_write, + es_func_fd_seek, + es_func_fd_destroy + }; + + + +/* Stream primitives. */ + +static int +es_convert_mode (const char *mode, unsigned int *flags) +{ + struct + { + const char *mode; + unsigned int flags; + } mode_flags[] = { { "r", + O_RDONLY }, + { "rb", + O_RDONLY }, + { "w", + O_WRONLY | O_TRUNC | O_CREAT }, + { "wb", + O_WRONLY | O_TRUNC | O_CREAT }, + { "a", + O_WRONLY | O_APPEND | O_CREAT }, + { "ab", + O_WRONLY | O_APPEND | O_CREAT }, + { "r+", + O_RDWR }, + { "rb+", + O_RDWR }, + { "r+b", + O_RDONLY | O_WRONLY }, + { "w+", + O_RDWR | O_TRUNC | O_CREAT }, + { "wb+", + O_RDWR | O_TRUNC | O_CREAT }, + { "w+b", + O_RDWR | O_TRUNC | O_CREAT }, + { "a+", + O_RDWR | O_CREAT | O_APPEND }, + { "ab+", + O_RDWR | O_CREAT | O_APPEND }, + { "a+b", + O_RDWR | O_CREAT | O_APPEND } }; + unsigned int i; + int err; + + for (i = 0; i < DIM (mode_flags); i++) + if (! strcmp (mode_flags[i].mode, mode)) + break; + if (i == DIM (mode_flags)) + { + errno = EINVAL; + err = -1; + } + else + { + err = 0; + *flags = mode_flags[i].flags; + } + + return err; +} + + + +/* + * Low level stream functionality. + */ + +static int +es_fill (estream_t stream) +{ + size_t bytes_read = 0; + int err; + + if (!stream->intern->func_read) + { + errno = EOPNOTSUPP; + err = -1; + } + else + { + es_cookie_read_function_t func_read = stream->intern->func_read; + ssize_t ret; + + ret = (*func_read) (stream->intern->cookie, + stream->buffer, stream->buffer_size); + if (ret == -1) + { + bytes_read = 0; + err = -1; + } + else + { + bytes_read = ret; + err = 0; + } + } + + if (err) + stream->intern->indicators.err = 1; + else if (!bytes_read) + stream->intern->indicators.eof = 1; + + stream->intern->offset += stream->data_len; + stream->data_len = bytes_read; + stream->data_offset = 0; + + return err; +} + +static int +es_flush (estream_t stream) +{ + es_cookie_write_function_t func_write = stream->intern->func_write; + int err; + + assert (stream->flags & ES_FLAG_WRITING); + + if (stream->data_offset) + { + size_t bytes_written; + size_t data_flushed; + ssize_t ret; + + if (! func_write) + { + err = EOPNOTSUPP; + goto out; + } + + /* Note: to prevent an endless loop caused by user-provided + write-functions that pretend to have written more bytes than + they were asked to write, we have to check for + "(stream->data_offset - data_flushed) > 0" instead of + "stream->data_offset - data_flushed". */ + + data_flushed = 0; + err = 0; + + while ((((ssize_t) (stream->data_offset - data_flushed)) > 0) && (! err)) + { + ret = (*func_write) (stream->intern->cookie, + stream->buffer + data_flushed, + stream->data_offset - data_flushed); + if (ret == -1) + { + bytes_written = 0; + err = -1; + } + else + bytes_written = ret; + + data_flushed += bytes_written; + if (err) + break; + } + + stream->data_flushed += data_flushed; + if (stream->data_offset == data_flushed) + { + stream->intern->offset += stream->data_offset; + stream->data_offset = 0; + stream->data_flushed = 0; + + /* Propagate flush event. */ + (*func_write) (stream->intern->cookie, NULL, 0); + } + } + else + err = 0; + + out: + + if (err) + stream->intern->indicators.err = 1; + + return err; +} + +/* Discard buffered data for STREAM. */ +static void +es_empty (estream_t stream) +{ + assert (! (stream->flags & ES_FLAG_WRITING)); + stream->data_len = 0; + stream->data_offset = 0; + stream->unread_data_len = 0; +} + +/* Initialize STREAM. */ +static void +es_initialize (estream_t stream, + void *cookie, int fd, es_cookie_io_functions_t functions) +{ + stream->intern->cookie = cookie; + stream->intern->opaque = NULL; + stream->intern->offset = 0; + stream->intern->func_read = functions.func_read; + stream->intern->func_write = functions.func_write; + stream->intern->func_seek = functions.func_seek; + stream->intern->func_close = functions.func_close; + stream->intern->strategy = _IOFBF; + stream->intern->fd = fd; + stream->intern->indicators.err = 0; + stream->intern->indicators.eof = 0; + stream->intern->deallocate_buffer = 0; + + stream->data_len = 0; + stream->data_offset = 0; + stream->data_flushed = 0; + stream->unread_data_len = 0; + stream->flags = 0; +} + +/* Deinitialize STREAM. */ +static int +es_deinitialize (estream_t stream) +{ + es_cookie_close_function_t func_close; + int err, tmp_err; + + func_close = stream->intern->func_close; + + err = 0; + if (stream->flags & ES_FLAG_WRITING) + SET_UNLESS_NONZERO (err, tmp_err, es_flush (stream)); + if (func_close) + SET_UNLESS_NONZERO (err, tmp_err, (*func_close) (stream->intern->cookie)); + + return err; +} + +/* Create a new stream object, initialize it. */ +static int +es_create (estream_t *stream, void *cookie, int fd, + es_cookie_io_functions_t functions) +{ + estream_internal_t stream_internal_new; + estream_t stream_new; + int err; + + stream_new = NULL; + stream_internal_new = NULL; + + stream_new = MEM_ALLOC (sizeof (*stream_new)); + if (! stream_new) + { + err = -1; + goto out; + } + + stream_internal_new = MEM_ALLOC (sizeof (*stream_internal_new)); + if (! stream_internal_new) + { + err = -1; + goto out; + } + + stream_new->buffer = stream_internal_new->buffer; + stream_new->buffer_size = sizeof (stream_internal_new->buffer); + stream_new->unread_buffer = stream_internal_new->unread_buffer; + stream_new->unread_buffer_size = sizeof (stream_internal_new->unread_buffer); + stream_new->intern = stream_internal_new; + + ESTREAM_MUTEX_INITIALIZE (stream_new->intern->lock); + es_initialize (stream_new, cookie, fd, functions); + + err = es_list_add (stream_new); + if (err) + goto out; + + *stream = stream_new; + + out: + + if (err) + { + if (stream_new) + { + es_deinitialize (stream_new); + MEM_FREE (stream_new); + } + } + + return err; +} + +/* Deinitialize a stream object and destroy it. */ +static int +es_destroy (estream_t stream) +{ + int err = 0; + + if (stream) + { + es_list_remove (stream); + err = es_deinitialize (stream); + MEM_FREE (stream->intern); + MEM_FREE (stream); + } + + return err; +} + +/* Try to read BYTES_TO_READ bytes FROM STREAM into BUFFER in + unbuffered-mode, storing the amount of bytes read in + *BYTES_READ. */ +static int +es_read_nbf (estream_t ES__RESTRICT stream, + unsigned char *ES__RESTRICT buffer, + size_t bytes_to_read, size_t *ES__RESTRICT bytes_read) +{ + es_cookie_read_function_t func_read = stream->intern->func_read; + size_t data_read; + ssize_t ret; + int err; + + data_read = 0; + err = 0; + + while (bytes_to_read - data_read) + { + ret = (*func_read) (stream->intern->cookie, + buffer + data_read, bytes_to_read - data_read); + if (ret == -1) + { + err = -1; + break; + } + else if (ret) + data_read += ret; + else + break; + } + + stream->intern->offset += data_read; + *bytes_read = data_read; + + return err; +} + +/* Try to read BYTES_TO_READ bytes FROM STREAM into BUFFER in + fully-buffered-mode, storing the amount of bytes read in + *BYTES_READ. */ +static int +es_read_fbf (estream_t ES__RESTRICT stream, + unsigned char *ES__RESTRICT buffer, + size_t bytes_to_read, size_t *ES__RESTRICT bytes_read) +{ + size_t data_available; + size_t data_to_read; + size_t data_read; + int err; + + data_read = 0; + err = 0; + + while ((bytes_to_read - data_read) && (! err)) + { + if (stream->data_offset == stream->data_len) + { + /* Nothing more to read in current container, try to + fill container with new data. */ + err = es_fill (stream); + if (! err) + if (! stream->data_len) + /* Filling did not result in any data read. */ + break; + } + + if (! err) + { + /* Filling resulted in some new data. */ + + data_to_read = bytes_to_read - data_read; + data_available = stream->data_len - stream->data_offset; + if (data_to_read > data_available) + data_to_read = data_available; + + memcpy (buffer + data_read, + stream->buffer + stream->data_offset, data_to_read); + stream->data_offset += data_to_read; + data_read += data_to_read; + } + } + + *bytes_read = data_read; + + return err; +} + +/* Try to read BYTES_TO_READ bytes FROM STREAM into BUFFER in + line-buffered-mode, storing the amount of bytes read in + *BYTES_READ. */ +static int +es_read_lbf (estream_t ES__RESTRICT stream, + unsigned char *ES__RESTRICT buffer, + size_t bytes_to_read, size_t *ES__RESTRICT bytes_read) +{ + int err; + + err = es_read_fbf (stream, buffer, bytes_to_read, bytes_read); + + return err; +} + +/* Try to read BYTES_TO_READ bytes FROM STREAM into BUFFER, storing + *the amount of bytes read in BYTES_READ. */ +static int +es_readn (estream_t ES__RESTRICT stream, + unsigned char *ES__RESTRICT buffer, + size_t bytes_to_read, size_t *ES__RESTRICT bytes_read) +{ + size_t data_read_unread, data_read; + int err; + + data_read_unread = 0; + data_read = 0; + err = 0; + + if (stream->flags & ES_FLAG_WRITING) + { + /* Switching to reading mode -> flush output. */ + err = es_flush (stream); + if (err) + goto out; + stream->flags &= ~ES_FLAG_WRITING; + } + + /* Read unread data first. */ + while ((bytes_to_read - data_read_unread) && stream->unread_data_len) + { + buffer[data_read_unread] + = stream->unread_buffer[stream->unread_data_len - 1]; + stream->unread_data_len--; + data_read_unread++; + } + + switch (stream->intern->strategy) + { + case _IONBF: + err = es_read_nbf (stream, + buffer + data_read_unread, + bytes_to_read - data_read_unread, &data_read); + break; + case _IOLBF: + err = es_read_lbf (stream, + buffer + data_read_unread, + bytes_to_read - data_read_unread, &data_read); + break; + case _IOFBF: + err = es_read_fbf (stream, + buffer + data_read_unread, + bytes_to_read - data_read_unread, &data_read); + break; + } + + out: + + if (bytes_read) + *bytes_read = data_read_unread + data_read; + + return err; +} + +/* Try to unread DATA_N bytes from DATA into STREAM, storing the + amount of bytes succesfully unread in *BYTES_UNREAD. */ +static void +es_unreadn (estream_t ES__RESTRICT stream, + const unsigned char *ES__RESTRICT data, size_t data_n, + size_t *ES__RESTRICT bytes_unread) +{ + size_t space_left; + + space_left = stream->unread_buffer_size - stream->unread_data_len; + + if (data_n > space_left) + data_n = space_left; + + if (! data_n) + goto out; + + memcpy (stream->unread_buffer + stream->unread_data_len, data, data_n); + stream->unread_data_len += data_n; + stream->intern->indicators.eof = 0; + + out: + + if (bytes_unread) + *bytes_unread = data_n; +} + +/* Seek in STREAM. */ +static int +es_seek (estream_t ES__RESTRICT stream, off_t offset, int whence, + off_t *ES__RESTRICT offset_new) +{ + es_cookie_seek_function_t func_seek = stream->intern->func_seek; + int err, ret; + off_t off; + + if (! func_seek) + { + errno = EOPNOTSUPP; + err = -1; + goto out; + } + + if (stream->flags & ES_FLAG_WRITING) + { + /* Flush data first in order to prevent flushing it to the wrong + offset. */ + err = es_flush (stream); + if (err) + goto out; + stream->flags &= ~ES_FLAG_WRITING; + } + + off = offset; + if (whence == SEEK_CUR) + { + off = off - stream->data_len + stream->data_offset; + off -= stream->unread_data_len; + } + + ret = (*func_seek) (stream->intern->cookie, &off, whence); + if (ret == -1) + { + err = -1; + goto out; + } + + err = 0; + es_empty (stream); + + if (offset_new) + *offset_new = off; + + stream->intern->indicators.eof = 0; + stream->intern->offset = off; + + out: + + if (err) + stream->intern->indicators.err = 1; + + return err; +} + +/* Write BYTES_TO_WRITE bytes from BUFFER into STREAM in + unbuffered-mode, storing the amount of bytes written in + *BYTES_WRITTEN. */ +static int +es_write_nbf (estream_t ES__RESTRICT stream, + const unsigned char *ES__RESTRICT buffer, + size_t bytes_to_write, size_t *ES__RESTRICT bytes_written) +{ + es_cookie_write_function_t func_write = stream->intern->func_write; + size_t data_written; + ssize_t ret; + int err; + + if (bytes_to_write && (! func_write)) + { + err = EOPNOTSUPP; + goto out; + } + + data_written = 0; + err = 0; + + while (bytes_to_write - data_written) + { + ret = (*func_write) (stream->intern->cookie, + buffer + data_written, + bytes_to_write - data_written); + if (ret == -1) + { + err = -1; + break; + } + else + data_written += ret; + } + + stream->intern->offset += data_written; + *bytes_written = data_written; + + out: + + return err; +} + +/* Write BYTES_TO_WRITE bytes from BUFFER into STREAM in + fully-buffered-mode, storing the amount of bytes written in + *BYTES_WRITTEN. */ +static int +es_write_fbf (estream_t ES__RESTRICT stream, + const unsigned char *ES__RESTRICT buffer, + size_t bytes_to_write, size_t *ES__RESTRICT bytes_written) +{ + size_t space_available; + size_t data_to_write; + size_t data_written; + int err; + + data_written = 0; + err = 0; + + while ((bytes_to_write - data_written) && (! err)) + { + if (stream->data_offset == stream->buffer_size) + /* Container full, flush buffer. */ + err = es_flush (stream); + + if (! err) + { + /* Flushing resulted in empty container. */ + + data_to_write = bytes_to_write - data_written; + space_available = stream->buffer_size - stream->data_offset; + if (data_to_write > space_available) + data_to_write = space_available; + + memcpy (stream->buffer + stream->data_offset, + buffer + data_written, data_to_write); + stream->data_offset += data_to_write; + data_written += data_to_write; + } + } + + *bytes_written = data_written; + + return err; +} + + +/* Write BYTES_TO_WRITE bytes from BUFFER into STREAM in + line-buffered-mode, storing the amount of bytes written in + *BYTES_WRITTEN. */ +static int +es_write_lbf (estream_t ES__RESTRICT stream, + const unsigned char *ES__RESTRICT buffer, + size_t bytes_to_write, size_t *ES__RESTRICT bytes_written) +{ + size_t data_flushed = 0; + size_t data_buffered = 0; + unsigned char *nlp; + int err = 0; + + nlp = memrchr (buffer, '\n', bytes_to_write); + if (nlp) + { + /* Found a newline, directly write up to (including) this + character. */ + err = es_flush (stream); + if (!err) + err = es_write_nbf (stream, buffer, nlp - buffer + 1, &data_flushed); + } + + if (!err) + { + /* Write remaining data fully buffered. */ + err = es_write_fbf (stream, buffer + data_flushed, + bytes_to_write - data_flushed, &data_buffered); + } + + *bytes_written = data_flushed + data_buffered; + return err; +} + + +/* Write BYTES_TO_WRITE bytes from BUFFER into STREAM in, storing the + amount of bytes written in BYTES_WRITTEN. */ +static int +es_writen (estream_t ES__RESTRICT stream, + const unsigned char *ES__RESTRICT buffer, + size_t bytes_to_write, size_t *ES__RESTRICT bytes_written) +{ + size_t data_written; + int err; + + data_written = 0; + err = 0; + + if (! (stream->flags & ES_FLAG_WRITING)) + { + /* Switching to writing mode -> discard input data and seek to + position at which reading has stopped. */ + + err = es_seek (stream, 0, SEEK_CUR, NULL); + if (err) + { + if (errno == ESPIPE) + err = 0; + else + goto out; + } + } + + switch (stream->intern->strategy) + { + case _IONBF: + err = es_write_nbf (stream, buffer, bytes_to_write, &data_written); + break; + + case _IOLBF: + err = es_write_lbf (stream, buffer, bytes_to_write, &data_written); + break; + + case _IOFBF: + err = es_write_fbf (stream, buffer, bytes_to_write, &data_written); + break; + } + + out: + + if (bytes_written) + *bytes_written = data_written; + if (data_written) + if (! (stream->flags & ES_FLAG_WRITING)) + stream->flags |= ES_FLAG_WRITING; + + return err; +} + + +static int +es_peek (estream_t ES__RESTRICT stream, unsigned char **ES__RESTRICT data, + size_t *ES__RESTRICT data_len) +{ + int err; + + if (stream->flags & ES_FLAG_WRITING) + { + /* Switching to reading mode -> flush output. */ + err = es_flush (stream); + if (err) + goto out; + stream->flags &= ~ES_FLAG_WRITING; + } + + if (stream->data_offset == stream->data_len) + { + /* Refill container. */ + err = es_fill (stream); + if (err) + goto out; + } + + if (data) + *data = stream->buffer + stream->data_offset; + if (data_len) + *data_len = stream->data_len - stream->data_offset; + err = 0; + + out: + + return err; +} + + +/* Skip SIZE bytes of input data contained in buffer. */ +static int +es_skip (estream_t stream, size_t size) +{ + int err; + + if (stream->data_offset + size > stream->data_len) + { + errno = EINVAL; + err = -1; + } + else + { + stream->data_offset += size; + err = 0; + } + + return err; +} + + +static int +es_read_line (estream_t ES__RESTRICT stream, size_t max_length, + char *ES__RESTRICT *ES__RESTRICT line, + size_t *ES__RESTRICT line_length) +{ + size_t space_left; + size_t line_size; + estream_t line_stream; + char *line_new; + void *line_stream_cookie; + char *newline; + unsigned char *data; + size_t data_len; + int err; + + line_new = NULL; + line_stream = NULL; + line_stream_cookie = NULL; + + err = es_func_mem_create (&line_stream_cookie, NULL, 0, 0, BUFFER_BLOCK_SIZE, + 1, 0, 0, NULL, 0, MEM_REALLOC, MEM_FREE, O_RDWR); + if (err) + goto out; + + err = es_create (&line_stream, line_stream_cookie, -1, + estream_functions_mem); + if (err) + goto out; + + space_left = max_length; + line_size = 0; + while (1) + { + if (max_length && (space_left == 1)) + break; + + err = es_peek (stream, &data, &data_len); + if (err || (! data_len)) + break; + + if (data_len > (space_left - 1)) + data_len = space_left - 1; + + newline = memchr (data, '\n', data_len); + if (newline) + { + data_len = (newline - (char *) data) + 1; + err = es_write (line_stream, data, data_len, NULL); + if (! err) + { + space_left -= data_len; + line_size += data_len; + es_skip (stream, data_len); + break; + } + } + else + { + err = es_write (line_stream, data, data_len, NULL); + if (! err) + { + space_left -= data_len; + line_size += data_len; + es_skip (stream, data_len); + } + } + if (err) + break; + } + if (err) + goto out; + + /* Complete line has been written to line_stream. */ + + if ((max_length > 1) && (! line_size)) + { + stream->intern->indicators.eof = 1; + goto out; + } + + err = es_seek (line_stream, 0, SEEK_SET, NULL); + if (err) + goto out; + + if (! *line) + { + line_new = MEM_ALLOC (line_size + 1); + if (! line_new) + { + err = -1; + goto out; + } + } + else + line_new = *line; + + err = es_read (line_stream, line_new, line_size, NULL); + if (err) + goto out; + + line_new[line_size] = '\0'; + + if (! *line) + *line = line_new; + if (line_length) + *line_length = line_size; + + out: + + if (line_stream) + es_destroy (line_stream); + else if (line_stream_cookie) + es_func_mem_destroy (line_stream_cookie); + + if (err) + { + if (! *line) + MEM_FREE (line_new); + stream->intern->indicators.err = 1; + } + + return err; +} + + +static int +es_print (estream_t ES__RESTRICT stream, + const char *ES__RESTRICT format, va_list ap) +{ + char data[BUFFER_BLOCK_SIZE]; + size_t bytes_written; + size_t bytes_read; + FILE *tmp_stream; + int err; + + bytes_written = 0; + tmp_stream = NULL; + err = 0; + + tmp_stream = tmpfile (); + if (! tmp_stream) + { + err = errno; + goto out; + } + + err = vfprintf (tmp_stream, format, ap); + if (err < 0) + goto out; + + err = fseek (tmp_stream, 0, SEEK_SET); + if (err) + goto out; + + while (1) + { + bytes_read = fread (data, 1, sizeof (data), tmp_stream); + if (ferror (tmp_stream)) + { + err = -1; + break; + } + + err = es_writen (stream, data, bytes_read, NULL); + if (err) + break; + else + bytes_written += bytes_read; + if (feof (tmp_stream)) + break; + } + if (err) + goto out; + + out: + + if (tmp_stream) + fclose (tmp_stream); + + return err ? -1 : bytes_written; +} + + +static void +es_set_indicators (estream_t stream, int ind_err, int ind_eof) +{ + if (ind_err != -1) + stream->intern->indicators.err = ind_err ? 1 : 0; + if (ind_eof != -1) + stream->intern->indicators.eof = ind_eof ? 1 : 0; +} + + +static int +es_get_indicator (estream_t stream, int ind_err, int ind_eof) +{ + int ret = 0; + + if (ind_err) + ret = stream->intern->indicators.err; + else if (ind_eof) + ret = stream->intern->indicators.eof; + + return ret; +} + + +static int +es_set_buffering (estream_t ES__RESTRICT stream, + char *ES__RESTRICT buffer, int mode, size_t size) +{ + int err; + + /* Flush or empty buffer depending on mode. */ + if (stream->flags & ES_FLAG_WRITING) + { + err = es_flush (stream); + if (err) + goto out; + } + else + es_empty (stream); + + es_set_indicators (stream, -1, 0); + + /* Free old buffer in case that was allocated by this function. */ + if (stream->intern->deallocate_buffer) + { + stream->intern->deallocate_buffer = 0; + MEM_FREE (stream->buffer); + stream->buffer = NULL; + } + + if (mode == _IONBF) + stream->buffer_size = 0; + else + { + void *buffer_new; + + if (buffer) + buffer_new = buffer; + else + { + buffer_new = MEM_ALLOC (size); + if (! buffer_new) + { + err = -1; + goto out; + } + } + + stream->buffer = buffer_new; + stream->buffer_size = size; + if (! buffer) + stream->intern->deallocate_buffer = 1; + } + stream->intern->strategy = mode; + err = 0; + + out: + + return err; +} + + +static off_t +es_offset_calculate (estream_t stream) +{ + off_t offset; + + offset = stream->intern->offset + stream->data_offset; + if (offset < stream->unread_data_len) + /* Offset undefined. */ + offset = 0; + else + offset -= stream->unread_data_len; + + return offset; +} + + +static void +es_opaque_ctrl (estream_t ES__RESTRICT stream, void *ES__RESTRICT opaque_new, + void **ES__RESTRICT opaque_old) +{ + if (opaque_old) + *opaque_old = stream->intern->opaque; + if (opaque_new) + stream->intern->opaque = opaque_new; +} + + +static int +es_get_fd (estream_t stream) +{ + return stream->intern->fd; +} + + + +/* API. */ + +int +es_init (void) +{ + int err; + + err = es_init_do (); + + return err; +} + +estream_t +es_fopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode) +{ + unsigned int flags; + int create_called; + estream_t stream; + void *cookie; + int err; + int fd; + + stream = NULL; + cookie = NULL; + create_called = 0; + + err = es_convert_mode (mode, &flags); + if (err) + goto out; + + err = es_func_file_create (&cookie, &fd, path, flags); + if (err) + goto out; + + create_called = 1; + err = es_create (&stream, cookie, fd, estream_functions_file); + if (err) + goto out; + + out: + + if (err && create_called) + (*estream_functions_file.func_close) (cookie); + + return stream; +} + + +estream_t +es_mopen (unsigned char *ES__RESTRICT data, size_t data_n, size_t data_len, + unsigned int grow, + func_realloc_t func_realloc, func_free_t func_free, + const char *ES__RESTRICT mode) +{ + unsigned int flags; + int create_called; + estream_t stream; + void *cookie; + int err; + + cookie = 0; + stream = NULL; + create_called = 0; + + err = es_convert_mode (mode, &flags); + if (err) + goto out; + + err = es_func_mem_create (&cookie, data, data_n, data_len, + BUFFER_BLOCK_SIZE, grow, 0, 0, + NULL, 0, func_realloc, func_free, flags); + if (err) + goto out; + + create_called = 1; + err = es_create (&stream, cookie, -1, estream_functions_mem); + + out: + + if (err && create_called) + (*estream_functions_mem.func_close) (cookie); + + return stream; +} + + +estream_t +es_open_memstream (char **ptr, size_t *size) +{ + unsigned int flags; + int create_called; + estream_t stream; + void *cookie; + int err; + + flags = O_RDWR; + create_called = 0; + stream = NULL; + cookie = 0; + + err = es_func_mem_create (&cookie, NULL, 0, 0, + BUFFER_BLOCK_SIZE, 1, 1, 1, + ptr, size, MEM_REALLOC, MEM_FREE, flags); + if (err) + goto out; + + create_called = 1; + err = es_create (&stream, cookie, -1, estream_functions_mem); + + out: + + if (err && create_called) + (*estream_functions_mem.func_close) (cookie); + + return stream; +} + + +estream_t +es_fopencookie (void *ES__RESTRICT cookie, + const char *ES__RESTRICT mode, + es_cookie_io_functions_t functions) +{ + unsigned int flags; + estream_t stream; + int err; + + stream = NULL; + flags = 0; + + err = es_convert_mode (mode, &flags); + if (err) + goto out; + + err = es_create (&stream, cookie, -1, functions); + if (err) + goto out; + + out: + + return stream; +} + + +estream_t +es_fdopen (int filedes, const char *mode) +{ + unsigned int flags; + int create_called; + estream_t stream; + void *cookie; + int err; + + stream = NULL; + cookie = NULL; + create_called = 0; + + err = es_convert_mode (mode, &flags); + if (err) + goto out; + + err = es_func_fd_create (&cookie, filedes, flags); + if (err) + goto out; + + create_called = 1; + err = es_create (&stream, cookie, filedes, estream_functions_fd); + + out: + + if (err && create_called) + (*estream_functions_fd.func_close) (cookie); + + return stream; +} + + +estream_t +es_freopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode, + estream_t ES__RESTRICT stream) +{ + int err; + + if (path) + { + unsigned int flags; + int create_called; + void *cookie; + int fd; + + cookie = NULL; + create_called = 0; + + ESTREAM_LOCK (stream); + + es_deinitialize (stream); + + err = es_convert_mode (mode, &flags); + if (err) + goto leave; + + err = es_func_file_create (&cookie, &fd, path, flags); + if (err) + goto leave; + + create_called = 1; + es_initialize (stream, cookie, fd, estream_functions_file); + + leave: + + if (err) + { + if (create_called) + es_func_fd_destroy (cookie); + + es_destroy (stream); + stream = NULL; + } + else + ESTREAM_UNLOCK (stream); + } + else + { + /* FIXME? We don't support re-opening at the moment. */ + errno = EINVAL; + es_deinitialize (stream); + es_destroy (stream); + stream = NULL; + } + + return stream; +} + + +int +es_fclose (estream_t stream) +{ + int err; + + err = es_destroy (stream); + + return err; +} + +int +es_fileno_unlocked (estream_t stream) +{ + return es_get_fd (stream); +} + + +void +es_flockfile (estream_t stream) +{ + ESTREAM_LOCK (stream); +} + + +int +es_ftrylockfile (estream_t stream) +{ + return ESTREAM_TRYLOCK (stream); +} + + +void +es_funlockfile (estream_t stream) +{ + ESTREAM_UNLOCK (stream); +} + + +int +es_fileno (estream_t stream) +{ + int ret; + + ESTREAM_LOCK (stream); + ret = es_fileno_unlocked (stream); + ESTREAM_UNLOCK (stream); + + return ret; +} + + +int +es_feof_unlocked (estream_t stream) +{ + return es_get_indicator (stream, 0, 1); +} + + +int +es_feof (estream_t stream) +{ + int ret; + + ESTREAM_LOCK (stream); + ret = es_feof_unlocked (stream); + ESTREAM_UNLOCK (stream); + + return ret; +} + + +int +es_ferror_unlocked (estream_t stream) +{ + return es_get_indicator (stream, 1, 0); +} + + +int +es_ferror (estream_t stream) +{ + int ret; + + ESTREAM_LOCK (stream); + ret = es_ferror_unlocked (stream); + ESTREAM_UNLOCK (stream); + + return ret; +} + + +void +es_clearerr_unlocked (estream_t stream) +{ + es_set_indicators (stream, 0, 0); +} + + +void +es_clearerr (estream_t stream) +{ + ESTREAM_LOCK (stream); + es_clearerr_unlocked (stream); + ESTREAM_UNLOCK (stream); +} + + +int +es_fflush (estream_t stream) +{ + int err; + + if (stream) + { + ESTREAM_LOCK (stream); + if (stream->flags & ES_FLAG_WRITING) + err = es_flush (stream); + else + { + es_empty (stream); + err = 0; + } + ESTREAM_UNLOCK (stream); + } + else + err = es_list_iterate (es_fflush); + + return err ? EOF : 0; +} + + +int +es_fseek (estream_t stream, long int offset, int whence) +{ + int err; + + ESTREAM_LOCK (stream); + err = es_seek (stream, offset, whence, NULL); + ESTREAM_UNLOCK (stream); + + return err; +} + + +int +es_fseeko (estream_t stream, off_t offset, int whence) +{ + int err; + + ESTREAM_LOCK (stream); + err = es_seek (stream, offset, whence, NULL); + ESTREAM_UNLOCK (stream); + + return err; +} + + +long int +es_ftell (estream_t stream) +{ + long int ret; + + ESTREAM_LOCK (stream); + ret = es_offset_calculate (stream); + ESTREAM_UNLOCK (stream); + + return ret; +} + + +off_t +es_ftello (estream_t stream) +{ + off_t ret = -1; + + ESTREAM_LOCK (stream); + ret = es_offset_calculate (stream); + ESTREAM_UNLOCK (stream); + + return ret; +} + + +void +es_rewind (estream_t stream) +{ + ESTREAM_LOCK (stream); + es_seek (stream, 0L, SEEK_SET, NULL); + es_set_indicators (stream, 0, -1); + ESTREAM_UNLOCK (stream); +} + + +int +_es_getc_underflow (estream_t stream) +{ + int err; + unsigned char c; + size_t bytes_read; + + err = es_readn (stream, &c, 1, &bytes_read); + + return (err || (! bytes_read)) ? EOF : c; +} + + +int +_es_putc_overflow (int c, estream_t stream) +{ + unsigned char d = c; + int err; + + err = es_writen (stream, &d, 1, NULL); + + return err ? EOF : c; +} + + +int +es_fgetc (estream_t stream) +{ + int ret; + + ESTREAM_LOCK (stream); + ret = es_getc_unlocked (stream); + ESTREAM_UNLOCK (stream); + + return ret; +} + + +int +es_fputc (int c, estream_t stream) +{ + int ret; + + ESTREAM_LOCK (stream); + ret = es_putc_unlocked (c, stream); + ESTREAM_UNLOCK (stream); + + return ret; +} + + +int +es_ungetc (int c, estream_t stream) +{ + unsigned char data = (unsigned char) c; + size_t data_unread; + + ESTREAM_LOCK (stream); + es_unreadn (stream, &data, 1, &data_unread); + ESTREAM_UNLOCK (stream); + + return data_unread ? c : EOF; +} + + +int +es_read (estream_t ES__RESTRICT stream, + char *ES__RESTRICT buffer, size_t bytes_to_read, + size_t *ES__RESTRICT bytes_read) +{ + int err; + + if (bytes_to_read) + { + ESTREAM_LOCK (stream); + err = es_readn (stream, buffer, bytes_to_read, bytes_read); + ESTREAM_UNLOCK (stream); + } + else + err = 0; + + return err; +} + + +int +es_write (estream_t ES__RESTRICT stream, + const char *ES__RESTRICT buffer, size_t bytes_to_write, + size_t *ES__RESTRICT bytes_written) +{ + int err; + + if (bytes_to_write) + { + ESTREAM_LOCK (stream); + err = es_writen (stream, buffer, bytes_to_write, bytes_written); + ESTREAM_UNLOCK (stream); + } + else + err = 0; + + return err; +} + + +size_t +es_fread (void *ES__RESTRICT ptr, size_t size, size_t nitems, + estream_t ES__RESTRICT stream) +{ + size_t ret, bytes; + int err; + + if (size * nitems) + { + ESTREAM_LOCK (stream); + err = es_readn (stream, ptr, size * nitems, &bytes); + ESTREAM_UNLOCK (stream); + + ret = bytes / size; + } + else + ret = 0; + + return ret; +} + + +size_t +es_fwrite (const void *ES__RESTRICT ptr, size_t size, size_t nitems, + estream_t ES__RESTRICT stream) +{ + size_t ret, bytes; + int err; + + if (size * nitems) + { + ESTREAM_LOCK (stream); + err = es_writen (stream, ptr, size * nitems, &bytes); + ESTREAM_UNLOCK (stream); + + ret = bytes / size; + } + else + ret = 0; + + return ret; +} + + +char * +es_fgets (char *ES__RESTRICT s, int n, estream_t ES__RESTRICT stream) +{ + char *ret = NULL; + + if (n) + { + int err; + + ESTREAM_LOCK (stream); + err = es_read_line (stream, n, &s, NULL); + ESTREAM_UNLOCK (stream); + if (! err) + ret = s; + } + + return ret; +} + + +int +es_fputs (const char *ES__RESTRICT s, estream_t ES__RESTRICT stream) +{ + size_t length; + int err; + + length = strlen (s); + ESTREAM_LOCK (stream); + err = es_writen (stream, s, length, NULL); + ESTREAM_UNLOCK (stream); + + return err ? EOF : 0; +} + + +ssize_t +es_getline (char *ES__RESTRICT *ES__RESTRICT lineptr, size_t *ES__RESTRICT n, + estream_t ES__RESTRICT stream) +{ + char *line = NULL; + size_t line_n = 0; + int err; + + ESTREAM_LOCK (stream); + err = es_read_line (stream, 0, &line, &line_n); + ESTREAM_UNLOCK (stream); + if (err) + goto out; + + if (*n) + { + /* Caller wants us to use his buffer. */ + + if (*n < (line_n + 1)) + { + /* Provided buffer is too small -> resize. */ + + void *p; + + p = MEM_REALLOC (*lineptr, line_n + 1); + if (! p) + err = -1; + else + { + if (*lineptr != p) + *lineptr = p; + } + } + + if (! err) + { + memcpy (*lineptr, line, line_n + 1); + if (*n != line_n) + *n = line_n; + } + MEM_FREE (line); + } + else + { + /* Caller wants new buffers. */ + *lineptr = line; + *n = line_n; + } + + out: + + return err ? err : line_n; +} + + +int +es_vfprintf (estream_t ES__RESTRICT stream, const char *ES__RESTRICT format, + va_list ap) +{ + int ret; + + ESTREAM_LOCK (stream); + ret = es_print (stream, format, ap); + ESTREAM_UNLOCK (stream); + + return ret; +} + + +int +es_fprintf (estream_t ES__RESTRICT stream, + const char *ES__RESTRICT format, ...) +{ + int ret; + + va_list ap; + va_start (ap, format); + ESTREAM_LOCK (stream); + ret = es_print (stream, format, ap); + ESTREAM_UNLOCK (stream); + va_end (ap); + + return ret; +} + +static int +tmpfd (void) +{ + FILE *fp; + int fp_fd; + int fd; + + fp = NULL; + fd = -1; + + fp = tmpfile (); + if (! fp) + goto out; + + fp_fd = fileno (fp); + fd = dup (fp_fd); + + out: + + if (fp) + fclose (fp); + + return fd; +} + +estream_t +es_tmpfile (void) +{ + unsigned int flags; + int create_called; + estream_t stream; + void *cookie; + int err; + int fd; + + create_called = 0; + stream = NULL; + flags = O_RDWR | O_TRUNC | O_CREAT; + cookie = NULL; + + fd = tmpfd (); + if (fd == -1) + { + err = -1; + goto out; + } + + err = es_func_fd_create (&cookie, fd, flags); + if (err) + goto out; + + create_called = 1; + err = es_create (&stream, cookie, fd, estream_functions_fd); + + out: + + if (err) + { + if (create_called) + es_func_fd_destroy (cookie); + else if (fd != -1) + close (fd); + stream = NULL; + } + + return stream; +} + + +int +es_setvbuf (estream_t ES__RESTRICT stream, + char *ES__RESTRICT buf, int type, size_t size) +{ + int err; + + if (((type == _IOFBF) || (type == _IOLBF) || (type == _IONBF)) + && (! ((! size) && (type != _IONBF)))) + { + ESTREAM_LOCK (stream); + err = es_set_buffering (stream, buf, type, size); + ESTREAM_UNLOCK (stream); + } + else + { + errno = EINVAL; + err = -1; + } + + return err; +} + + +void +es_setbuf (estream_t ES__RESTRICT stream, char *ES__RESTRICT buf) +{ + ESTREAM_LOCK (stream); + es_set_buffering (stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ); + ESTREAM_UNLOCK (stream); +} + +void +es_opaque_set (estream_t stream, void *opaque) +{ + ESTREAM_LOCK (stream); + es_opaque_ctrl (stream, opaque, NULL); + ESTREAM_UNLOCK (stream); +} + + +void * +es_opaque_get (estream_t stream) +{ + void *opaque; + + ESTREAM_LOCK (stream); + es_opaque_ctrl (stream, NULL, &opaque); + ESTREAM_UNLOCK (stream); + + return opaque; +} Index: gnupg/common/estream.h diff -u /dev/null gnupg/common/estream.h:1.1.2.1 --- /dev/null Wed Jan 26 23:24:59 2005 +++ gnupg/common/estream.h Wed Jan 26 23:24:59 2005 @@ -0,0 +1,201 @@ +/* estream.h - Extended stream I/O/ Library + Copyright (C) 2004 g10 Code GmbH + + This file is part of Libestream. + + Libestream 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. + + Libestream 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 Libestream; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifndef ESTREAM_H +#define ESTREAM_H + +#include +#include +#include + + +/* Forward declaration for the (opaque) internal type. */ +struct estream_internal; + +/* The definition of this struct is entirely private. You must not + use it for anything. It is only here so some functions can be + implemented as macros. */ +struct es__stream +{ + /* The layout of this struct must never change. It may be grown, + but only if all functions which access the new members are + versioned. */ + + /* A pointer to the stream buffer. */ + unsigned char *buffer; + + /* The size of the buffer in bytes. */ + size_t buffer_size; + + /* The length of the usable data in the buffer, only valid when in + read mode (see flags). */ + size_t data_len; + + /* The current position of the offset pointer, valid in read and + write mode. */ + size_t data_offset; + + size_t data_flushed; + unsigned char *unread_buffer; + size_t unread_buffer_size; + + /* The number of unread bytes. */ + size_t unread_data_len; + + /* Various flags. */ +#define ES__FLAG_WRITING (1 << 0) + unsigned int flags; + + /* A pointer to our internal data for this stream. */ + struct estream_internal *intern; +}; + +/* The opaque type for an estream. */ +typedef struct es__stream *estream_t; + + +typedef ssize_t (*es_cookie_read_function_t) (void *cookie, + char *buffer, size_t size); +typedef ssize_t (*es_cookie_write_function_t) (void *cookie, + const char *buffer, + size_t size); +typedef int (*es_cookie_seek_function_t) (void *cookie, + off_t *pos, int whence); +typedef int (*es_cookie_close_function_t) (void *cookie); + +typedef struct es_cookie_io_functions +{ + es_cookie_read_function_t func_read; + es_cookie_write_function_t func_write; + es_cookie_seek_function_t func_seek; + es_cookie_close_function_t func_close; +} es_cookie_io_functions_t; + + +#ifndef ES__RESTRICT +# if defined __GNUC__ && defined __GNUC_MINOR__ +# if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 92)) +# define ES__RESTRICT __restrict__ +# endif +# endif +#endif +#ifndef ES__RESTRICT +# define ES__RESTRICT +#endif + +int es_init (void); + +estream_t es_fopen (const char *ES__RESTRICT path, + const char *ES__RESTRICT mode); +estream_t es_mopen (unsigned char *ES__RESTRICT data, + size_t data_n, size_t data_len, + unsigned int grow, + void *(*func_realloc) (void *mem, size_t size), + void (*func_free) (void *mem), + const char *ES__RESTRICT mode); +estream_t es_open_memstream (char **ptr, size_t *size); +estream_t es_fdopen (int filedes, const char *mode); +estream_t es_freopen (const char *ES__RESTRICT path, + const char *ES__RESTRICT mode, + estream_t ES__RESTRICT stream); +estream_t es_fopencookie (void *ES__RESTRICT cookie, + const char *ES__RESTRICT mode, + es_cookie_io_functions_t functions); +int es_fclose (estream_t stream); +int es_fileno (estream_t stream); +int es_fileno_unlocked (estream_t stream); + +void es_flockfile (estream_t stream); +int es_ftrylockfile (estream_t stream); +void es_funlockfile (estream_t stream); + +int es_feof (estream_t stream); +int es_feof_unlocked (estream_t stream); +int es_ferror (estream_t stream); +int es_ferror_unlocked (estream_t stream); +void es_clearerr (estream_t stream); +void es_clearerr_unlocked (estream_t stream); + +int es_fflush (estream_t stream); +int es_fseek (estream_t stream, long int offset, int whence); +int es_fseeko (estream_t stream, off_t offset, int whence); +long int es_ftell (estream_t stream); +off_t es_ftello (estream_t stream); +void es_rewind (estream_t stream); + +int es_fgetc (estream_t stream); +int es_fputc (int c, estream_t stream); + +int _es_getc_underflow (estream_t stream); +int _es_putc_overflow (int c, estream_t stream); + +#define es_getc_unlocked(stream) \ + (((! ((stream)->flags & 1)) \ + && ((stream)->data_offset < (stream)->data_len) \ + && (! (stream)->unread_data_len)) \ + ? ((int) (stream)->buffer[((stream)->data_offset)++]) \ + : _es_getc_underflow ((stream))) + +#define es_putc_unlocked(c, stream) \ + ((((stream)->flags & 1) \ + && ((stream)->data_offset < (stream)->buffer_size) \ + && (c != '\n')) \ + ? ((int) ((stream)->buffer[((stream)->data_offset)++] = (c))) \ + : _es_putc_overflow ((c), (stream))) + +#define es_getc(stream) es_fgetc (stream) +#define es_putc(c, stream) es_fputc (c, stream) + +int es_ungetc (int c, estream_t stream); + +int es_read (estream_t ES__RESTRICT stream, + char *ES__RESTRICT buffer, size_t bytes_to_read, + size_t *ES__RESTRICT bytes_read); +int es_write (estream_t ES__RESTRICT stream, + const char *ES__RESTRICT buffer, size_t bytes_to_write, + size_t *ES__RESTRICT bytes_written); + +size_t es_fread (void *ES__RESTRICT ptr, size_t size, size_t nitems, + estream_t ES__RESTRICT stream); +size_t es_fwrite (const void *ES__RESTRICT ptr, size_t size, size_t memb, + estream_t ES__RESTRICT stream); + +char *es_fgets (char *ES__RESTRICT s, int n, estream_t ES__RESTRICT stream); +int es_fputs (const char *ES__RESTRICT s, estream_t ES__RESTRICT stream); + +ssize_t es_getline (char *ES__RESTRICT *ES__RESTRICT lineptr, + size_t *ES__RESTRICT n, + estream_t stream); + +int es_fprintf (estream_t ES__RESTRICT stream, + const char *ES__RESTRICT format, ...); +int es_vfprintf (estream_t ES__RESTRICT stream, + const char *ES__RESTRICT format, va_list ap); + +int es_setvbuf (estream_t ES__RESTRICT stream, + char *ES__RESTRICT buf, int mode, size_t size); +void es_setbuf (estream_t ES__RESTRICT stream, char *ES__RESTRICT buf); + +estream_t es_tmpfile (void); + +void es_opaque_set (estream_t ES__RESTRICT stream, void *ES__RESTRICT opaque); +void *es_opaque_get (estream_t stream); + +#endif From cvs at cvs.gnupg.org Wed Jan 26 23:17:01 2005 From: cvs at cvs.gnupg.org (cvs user mo) Date: Fri Jan 28 12:17:31 2005 Subject: GNUPG-1-9-BRANCH gnupg/agent (command-ssh.c) Message-ID: Date: Wednesday, January 26, 2005 @ 23:25:36 Author: mo Path: /cvs/gnupg/gnupg/agent Tag: GNUPG-1-9-BRANCH Added: command-ssh.c added missing file ---------------+ command-ssh.c | 2327 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 2327 insertions(+) Index: gnupg/agent/command-ssh.c diff -u /dev/null gnupg/agent/command-ssh.c:1.1.4.1 --- /dev/null Wed Jan 26 23:25:36 2005 +++ gnupg/agent/command-ssh.c Wed Jan 26 23:25:36 2005 @@ -0,0 +1,2327 @@ +/* command-ssh.c - gpg-agent's ssh-agent emulation layer + * Copyright (C) 2004, 2005 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "agent.h" + +#include + +#include "estream.h" + + + +/* Request types. */ +#define SSH_REQUEST_REQUEST_IDENTITIES 11 +#define SSH_REQUEST_SIGN_REQUEST 13 +#define SSH_REQUEST_ADD_IDENTITY 17 +#define SSH_REQUEST_REMOVE_IDENTITY 18 +#define SSH_REQUEST_REMOVE_ALL_IDENTITIES 19 +#define SSH_REQUEST_LOCK 22 +#define SSH_REQUEST_UNLOCK 23 +#define SSH_REQUEST_ADD_ID_CONSTRAINED 25 + +/* Options. */ +#define SSH_OPT_CONSTRAIN_LIFETIME 1 +#define SSH_OPT_CONSTRAIN_CONFIRM 2 + +/* Response types. */ +#define SSH_RESPONSE_SUCCESS 6 +#define SSH_RESPONSE_FAILURE 5 +#define SSH_RESPONSE_IDENTITIES_ANSWER 12 +#define SSH_RESPONSE_SIGN_RESPONSE 14 + + + + +/* Basic types. */ + +/* A "byte". */ +typedef unsigned char byte_t; + +typedef int (*ssh_request_handler_t) (ctrl_t ctrl, + estream_t request, estream_t response); + +typedef struct ssh_request_spec +{ + byte_t type; + ssh_request_handler_t handler; +} ssh_request_spec_t; + +typedef gpg_error_t (*ssh_key_modifier_t) (const char *elems, gcry_mpi_t *mpis); +typedef gpg_error_t (*ssh_signature_encoder_t) (estream_t signature_blob, + gcry_mpi_t *mpis); + +typedef struct ssh_key_type_spec +{ + const char *ssh_identifier; + const char *identifier; + const char *elems_key_secret; + const char *elems_key_public; + const char *elems_secret; + const char *elems_signature; + const char *elems_sexp_order; + ssh_key_modifier_t key_modifier; + ssh_signature_encoder_t signature_encoder; + unsigned int flags; +} ssh_key_type_spec_t; + + + +static uint32_t lifetime_default; + +/* General utility functions. */ + +static void * +realloc_secure (void *a, size_t n) +{ + void *p; + + if (a) + p = gcry_realloc (a, n); + else + p = gcry_malloc_secure (n); + + return p; +} + +/* Primitive I/O functions. */ + +static gpg_error_t +es_read_byte (estream_t stream, byte_t *b) +{ + gpg_error_t err; + int ret; + + ret = es_fgetc (stream); + if (ret == EOF) + { + if (es_ferror (stream)) + err = gpg_error_from_errno (errno); + else + err = gpg_error (GPG_ERR_EOF); + } + else + { + *b = ret & 0xFF; + err = 0; + } + + return err; +} + +static gpg_error_t +es_write_byte (estream_t stream, byte_t b) +{ + gpg_error_t err; + int ret; + + ret = es_fputc (b, stream); + if (ret == EOF) + err = gpg_error_from_errno (errno); + else + err = 0; + + return err; +} + +static gpg_error_t +es_read_uint32 (estream_t stream, uint32_t *uint32) +{ + unsigned char buffer[4]; + size_t bytes_read; + gpg_error_t err; + int ret; + + ret = es_read (stream, buffer, sizeof (buffer), &bytes_read); + if (ret) + err = gpg_error_from_errno (errno); + else + { + if (bytes_read != sizeof (buffer)) + err = gpg_error (GPG_ERR_EOF); + else + { + uint32_t n; + + n = (0 + | ((uint32_t) (buffer[0] << 24)) + | ((uint32_t) (buffer[1] << 16)) + | ((uint32_t) (buffer[2] << 8)) + | ((uint32_t) (buffer[3] << 0))); + *uint32 = n; + err = 0; + } + } + + return err; +} + +static gpg_error_t +es_write_uint32 (estream_t stream, uint32_t uint32) +{ + unsigned char buffer[4]; + gpg_error_t err; + int ret; + + buffer[0] = (uint32 >> 24) & 0xFF; + buffer[1] = (uint32 >> 16) & 0xFF; + buffer[2] = (uint32 >> 8) & 0xFF; + buffer[3] = (uint32 >> 0) & 0xFF; + + ret = es_write (stream, buffer, sizeof (buffer), NULL); + if (ret) + err = gpg_error_from_errno (errno); + else + err = 0; + + return err; +} + +static gpg_error_t +es_read_data (estream_t stream, unsigned char *buffer, size_t size) +{ + gpg_error_t err; + size_t bytes_read; + int ret; + + ret = es_read (stream, buffer, size, &bytes_read); + if (ret) + err = gpg_error_from_errno (errno); + else + { + if (bytes_read != size) + err = gpg_error (GPG_ERR_EOF); + else + err = 0; + } + + return err; +} + +static gpg_error_t +es_write_data (estream_t stream, const unsigned char *buffer, size_t size) +{ + gpg_error_t err; + int ret; + + ret = es_write (stream, buffer, size, NULL); + if (ret) + err = gpg_error_from_errno (errno); + else + err = 0; + + return err; +} + +static gpg_error_t +es_read_string (estream_t stream, unsigned int secure, + unsigned char **string, uint32_t *string_size) +{ + gpg_error_t err; + unsigned char *buffer; + uint32_t length; + + buffer = NULL; + + /* Read string length. */ + err = es_read_uint32 (stream, &length); + if (err) + goto out; + + /* Allocate space. */ + if (secure) + buffer = xtrymalloc_secure (length + 1); + else + buffer = xtrymalloc (length + 1); + if (! buffer) + { + /* FIXME: xtrymalloc_secure does not set errno, does it? */ + err = gpg_error_from_errno (errno); + abort (); + goto out; + } + + /* Read data. */ + err = es_read_data (stream, buffer, length); + if (err) + goto out; + + /* Finalize string object. */ + buffer[length] = 0; + *string = buffer; + if (string_size) + *string_size = length; + + out: + + if (err) + xfree (buffer); + + return err; +} + +static gpg_error_t +es_read_cstring (estream_t stream, char **string) +{ + unsigned char *buffer; + gpg_error_t err; + + err = es_read_string (stream, 0, &buffer, NULL); + if (err) + goto out; + + *string = (char *) buffer; + + out: + + return err; +} + +static gpg_error_t +es_write_string (estream_t stream, + const unsigned char *string, uint32_t string_n) +{ + gpg_error_t err; + + err = es_write_uint32 (stream, string_n); + if (err) + goto out; + + err = es_write_data (stream, string, string_n); + + out: + + return err; +} + +static gpg_error_t +es_write_cstring (estream_t stream, const char *string) +{ + gpg_error_t err; + + err = es_write_string (stream, + (const unsigned char *) string, strlen (string)); + + return err; +} + +static gpg_error_t +es_read_mpi (estream_t stream, unsigned int secure, gcry_mpi_t *mpint) +{ + unsigned char *mpi_data; + uint32_t mpi_data_size; + gpg_error_t err; + gcry_mpi_t mpi; + + mpi_data = NULL; + + err = es_read_string (stream, secure, &mpi_data, &mpi_data_size); + if (err) + goto out; + + err = gcry_mpi_scan (&mpi, GCRYMPI_FMT_STD, mpi_data, mpi_data_size, NULL); + if (err) + goto out; + + *mpint = mpi; + + out: + + xfree (mpi_data); + + return err; +} + +static gpg_error_t +es_write_mpi (estream_t stream, gcry_mpi_t mpint) +{ + unsigned char *mpi_buffer; + size_t mpi_buffer_n; + gpg_error_t err; + + mpi_buffer = NULL; + + err = gcry_mpi_aprint (GCRYMPI_FMT_STD, &mpi_buffer, &mpi_buffer_n, mpint); + if (err) + goto out; + + err = es_write_string (stream, mpi_buffer, mpi_buffer_n); + + out: + + xfree (mpi_buffer); + + return err; +} + +static gpg_error_t +es_read_file (const char *filename, unsigned char **buffer, size_t *buffer_n) +{ + unsigned char *buffer_new; + struct stat statbuf; + estream_t stream; + gpg_error_t err; + int ret; + + buffer_new = NULL; + err = 0; + + stream = es_fopen (filename, "r"); + if (! stream) + { + err = gpg_error_from_errno (errno); + goto out; + } + + ret = fstat (es_fileno (stream), &statbuf); + if (ret) + { + err = gpg_error_from_errno (errno); + goto out; + } + + buffer_new = xtrymalloc (statbuf.st_size); + if (! buffer_new) + { + err = gpg_error_from_errno (errno); + goto out; + } + + err = es_read_data (stream, buffer_new, statbuf.st_size); + if (err) + goto out; + + *buffer = buffer_new; + *buffer_n = statbuf.st_size; + + out: + + if (stream) + es_fclose (stream); + + if (err) + xfree (buffer_new); + + return err; +} + +static gpg_error_t +es_copy (estream_t dst, estream_t src) +{ + char buffer[BUFSIZ]; + size_t bytes_read; + gpg_error_t err; + int ret; + + err = 0; + while (1) + { + ret = es_read (src, buffer, sizeof (buffer), &bytes_read); + if (ret || (! bytes_read)) + { + if (ret) + err = gpg_error_from_errno (errno); + break; + } + ret = es_write (dst, buffer, bytes_read, NULL); + if (ret) + { + err = gpg_error_from_errno (errno); + break; + } + } + + return err; +} + + + +/* MPI lists. */ + +static void +mpint_list_free (gcry_mpi_t *mpi_list) +{ + if (mpi_list) + { + unsigned int i; + + for (i = 0; mpi_list[i]; i++) + gcry_mpi_release (mpi_list[i]); + xfree (mpi_list); + } +} + +static gpg_error_t +ssh_receive_mpint_list (estream_t stream, int secret, + ssh_key_type_spec_t key_spec, gcry_mpi_t **mpi_list) +{ + const char *elems_secret; + const char *elems; + unsigned int elems_n; + gcry_mpi_t *mpis; + unsigned int i; + gpg_error_t err; + int elem_is_secret; + + mpis = NULL; + err = 0; + + if (secret) + { + elems = key_spec.elems_key_secret; + elems_secret = key_spec.elems_secret; + } + else + { + elems = key_spec.elems_key_public; + elems_secret = ""; + } + elems_n = strlen (elems); + + mpis = xtrymalloc (sizeof (*mpis) * (elems_n + 1)); + if (! mpis) + { + err = gpg_error_from_errno (errno); + goto out; + } + + memset (mpis, 0, sizeof (*mpis) * (elems_n + 1)); + + for (i = 0; i < elems_n; i++) + { + elem_is_secret = strchr (elems_secret, elems[i]) ? 1 : 0; + err = es_read_mpi (stream, elem_is_secret, &mpis[i]); + if (err) + break; + } + if (err) + goto out; + + *mpi_list = mpis; + + out: + + if (err) + mpint_list_free (mpis); + + return err; +} + + + +static gpg_error_t +ssh_key_modifier_rsa (const char *elems, gcry_mpi_t *mpis) +{ + gcry_mpi_t p; + gcry_mpi_t q; + gcry_mpi_t u; + + if (strcmp (elems, "nedupq")) + /* Modifying only necessary for secret keys. */ + goto out; + + u = mpis[3]; + p = mpis[4]; + q = mpis[5]; + + if (gcry_mpi_cmp (p, q) > 0) + { + /* P shall be smaller then Q! Swap primes. iqmp becomes u. */ + gcry_mpi_t tmp; + + tmp = mpis[4]; + mpis[4] = mpis[5]; + mpis[5] = tmp; + } + else + /* U needs to be recomputed. */ + gcry_mpi_invm (u, p, q); + + out: + + return 0; +} + +static gpg_error_t +ssh_signature_encoder_rsa (estream_t signature_blob, gcry_mpi_t *mpis) +{ + unsigned char *data; + size_t data_n; + gpg_error_t err; + gcry_mpi_t s; + + s = mpis[0]; + + err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &data, &data_n, s); + if (err) + goto out; + + err = es_write_string (signature_blob, data, data_n); + xfree (data); + + out: + + return err; +} + +#define SSH_DSA_SIGNATURE_PADDING 20 +#define SSH_DSA_SIGNATURE_ELEMS 2 + +static gpg_error_t +ssh_signature_encoder_dsa (estream_t signature_blob, gcry_mpi_t *mpis) +{ + unsigned char buffer[SSH_DSA_SIGNATURE_PADDING * SSH_DSA_SIGNATURE_ELEMS]; + unsigned char *data; + size_t data_n; + gpg_error_t err; + int i; + + data = NULL; + + for (i = 0; i < 2; i++) + { + err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &data, &data_n, mpis[i]); + if (err) + break; + + if (data_n > SSH_DSA_SIGNATURE_PADDING) + { + err = gpg_error (GPG_ERR_INTERNAL); /* FIXME? */ + break; + } + + memset (buffer + (i * SSH_DSA_SIGNATURE_PADDING), 0, + SSH_DSA_SIGNATURE_PADDING - data_n); + memcpy (buffer + (i * SSH_DSA_SIGNATURE_PADDING) + + (SSH_DSA_SIGNATURE_PADDING - data_n), data, data_n); + + xfree (data); + data = NULL; + } + if (err) + goto out; + + err = es_write_string (signature_blob, buffer, sizeof (buffer)); + + out: + + xfree (data); + + return err; +} + +#define SPEC_FLAG_USE_PKCS1V2 (1 << 0) + + +/* Table holding key type specifications. */ +static ssh_key_type_spec_t ssh_key_types[] = + { + { + "ssh-rsa", "rsa", "nedupq", "en", "dupq", "s", "nedpqu", + ssh_key_modifier_rsa, ssh_signature_encoder_rsa, + SPEC_FLAG_USE_PKCS1V2 + }, + { + "ssh-dss", "dsa", "pqgyx", "pqgy", "x", "rs", "pqgyx", + NULL, ssh_signature_encoder_dsa, + 0 + }, + }; + + + +/* S-Expressions. */ + +static gpg_error_t +ssh_sexp_construct (gcry_sexp_t *sexp, + ssh_key_type_spec_t key_spec, int secret, + gcry_mpi_t *mpis, const char *comment) +{ + gcry_sexp_t sexp_new; + char *sexp_template; + size_t sexp_template_n; + gpg_error_t err; + const char *elems; + size_t elems_n; + unsigned int i; + unsigned int j; + void **arg_list; + + err = 0; + sexp_new = NULL; + arg_list = NULL; + if (secret) + elems = key_spec.elems_sexp_order; + else + elems = key_spec.elems_key_public; + elems_n = strlen (elems); + + sexp_template_n = 33 + strlen (key_spec.identifier) + (elems_n * 6) - (! secret); + sexp_template = xtrymalloc (sexp_template_n); + if (! sexp_template) + { + err = gpg_error_from_errno (errno); + goto out; + } + + arg_list = xtrymalloc (sizeof (*arg_list) * (elems_n + 1)); + if (! arg_list) + { + err = gpg_error_from_errno (errno); + goto out; + } + + sprintf (sexp_template, "(%s-key (%s ", + secret ? "private" : "public", key_spec.identifier); + for (i = 0; i < elems_n; i++) + { + sprintf (strchr (sexp_template, 0), "(%c %%m)", elems[i]); + if (secret) + { + for (j = 0; j < elems_n; j++) + if (key_spec.elems_key_secret[j] == elems[i]) + break; + } + else + j = i; + arg_list[i] = &mpis[j]; + } + arg_list[i] = &comment; + sprintf (strchr (sexp_template, 0), ") (comment %%s))"); + + err = gcry_sexp_build_array (&sexp_new, NULL, sexp_template, arg_list); + if (err) + goto out; + + *sexp = sexp_new; + + out: + + xfree (arg_list); + xfree (sexp_template); + + return err; +} + +static gpg_error_t +ssh_sexp_extract (gcry_sexp_t sexp, + ssh_key_type_spec_t key_spec, int *secret, + gcry_mpi_t **mpis, const char **comment) +{ + gpg_error_t err; + gcry_sexp_t value_list; + gcry_sexp_t value_pair; + gcry_sexp_t comment_list; + unsigned int i; + char *comment_new; + const char *data; + size_t data_n; + int is_secret; + size_t elems_n; + const char *elems; + gcry_mpi_t *mpis_new; + gcry_mpi_t mpi; + + err = 0; + value_list = NULL; + value_pair = NULL; + comment_list = NULL; + comment_new = NULL; + mpis_new = NULL; + + data = gcry_sexp_nth_data (sexp, 0, &data_n); + if (! data) + { + err = gpg_error (GPG_ERR_INV_SEXP); + goto out; + } + + if ((data_n == 10) && (! strncmp (data, "public-key", 10))) + { + is_secret = 0; + elems = key_spec.elems_key_public; + } + else if (((data_n == 11) && (! strncmp (data, "private-key", 11))) + || ((data_n == 21) && (! strncmp (data, "protected-private-key", 21)))) + { + is_secret = 1; + elems = key_spec.elems_key_secret; + } + else + { + err = gpg_error (GPG_ERR_INV_SEXP); + goto out; + } + + elems_n = strlen (elems); + mpis_new = xtrymalloc (sizeof (*mpis_new) * (elems_n + 1)); + if (! mpis_new) + { + err = gpg_error_from_errno (errno); /* FIXME, xtrymalloc+errno. */ + goto out; + } + memset (mpis_new, 0, sizeof (*mpis_new) * (elems_n + 1)); + + value_list = gcry_sexp_find_token (sexp, key_spec.identifier, 0); + if (! value_list) + { + err = gpg_error (GPG_ERR_INV_SEXP); + goto out; + } + + for (i = 0; i < elems_n; i++) + { + value_pair = gcry_sexp_find_token (value_list, elems + i, 1); + if (! value_pair) + { + err = gpg_error (GPG_ERR_INV_SEXP); + break; + } + + mpi = gcry_sexp_nth_mpi (value_pair, 1, GCRYMPI_FMT_USG); + if (! mpi) + { + err = gpg_error (GPG_ERR_INV_SEXP); + break; + } + mpis_new[i] = mpi; + gcry_sexp_release (value_pair); + value_pair = NULL; + } + if (err) + goto out; + + /* We do not require a comment sublist to be present here. */ + data = NULL; + data_n = 0; + + comment_list = gcry_sexp_find_token (sexp, "comment", 0); + if (comment_list) + data = gcry_sexp_nth_data (comment_list, 1, &data_n); + if (! data) + { + data = "(none)"; + data_n = 6; + } + + comment_new = xtrymalloc (data_n + 1); + if (! comment_new) + { + err = gpg_error_from_errno (errno); + goto out; + } + strncpy (comment_new, data, data_n); + comment_new[data_n] = 0; + + if (secret) + *secret = is_secret; + *mpis = mpis_new; + *comment = comment_new; + + out: + + gcry_sexp_release (value_list); + gcry_sexp_release (value_pair); + gcry_sexp_release (comment_list); + + if (err) + { + xfree (comment_new); + mpint_list_free (mpis_new); + } + + return err; +} + +static gpg_error_t +ssh_sexp_extract_key_type (gcry_sexp_t sexp, const char **key_type) +{ + gcry_sexp_t sublist; + char *key_type_new; + const char *data; + size_t data_n; + gpg_error_t err; + + err = 0; + key_type_new = NULL; + + sublist = gcry_sexp_nth (sexp, 1); + if (! sublist) + { + err = gpg_error (GPG_ERR_INV_SEXP); + goto out; + } + + data = gcry_sexp_nth_data (sublist, 0, &data_n); + if (! data) + { + err = gpg_error (GPG_ERR_INV_SEXP); + goto out; + } + + key_type_new = xtrymalloc (data_n + 1); + if (! key_type_new) + { + err = gpg_error_from_errno (errno); + goto out; + } + + strncpy (key_type_new, data, data_n); + key_type_new[data_n] = 0; + *key_type = key_type_new; + + out: + + gcry_sexp_release (sublist); + + return err; +} + + + +/* Key I/O. */ + +static gpg_error_t +ssh_key_type_lookup (const char *ssh_name, const char *name, + ssh_key_type_spec_t *spec) +{ + gpg_error_t err; + unsigned int i; + + for (i = 0; i < DIM (ssh_key_types); i++) + if ((ssh_name && (! strcmp (ssh_name, ssh_key_types[i].ssh_identifier))) + || (name && (! strcmp (name, ssh_key_types[i].identifier)))) + break; + + if (i == DIM (ssh_key_types)) + err = gpg_error (GPG_ERR_NOT_FOUND); + else + { + *spec = ssh_key_types[i]; + err = 0; + } + + return err; +} + +static gpg_error_t +ssh_receive_key (estream_t stream, gcry_sexp_t *key_new, int secret, int read_comment, + ssh_key_type_spec_t *key_spec) +{ + gpg_error_t err; + char *key_type; + char *comment; + gcry_sexp_t key; + ssh_key_type_spec_t spec; + gcry_mpi_t *mpi_list; + const char *elems; + + mpi_list = NULL; + key_type = NULL; + comment = ""; + key = NULL; + + err = es_read_cstring (stream, &key_type); + if (err) + goto out; + + err = ssh_key_type_lookup (key_type, NULL, &spec); + if (err) + goto out; + + err = ssh_receive_mpint_list (stream, secret, spec, &mpi_list); + if (err) + goto out; + + if (read_comment) + { + err = es_read_cstring (stream, &comment); + if (err) + goto out; + } + + if (secret) + elems = spec.elems_key_secret; + else + elems = spec.elems_key_public; + + if (spec.key_modifier) + { + err = (*spec.key_modifier) (elems, mpi_list); + if (err) + goto out; + } + + err = ssh_sexp_construct (&key, spec, secret, mpi_list, comment); + if (err) + goto out; + + if (key_spec) + *key_spec = spec; + *key_new = key; + + out: + + mpint_list_free (mpi_list); + xfree (key_type); + if (read_comment) + xfree (comment); + + return err; +} + +static gpg_error_t +ssh_convert_key_to_blob (unsigned char **blob, size_t *blob_size, + const char *type, gcry_mpi_t *mpis) +{ + unsigned char *blob_new; + long int blob_size_new; + estream_t stream; + gpg_error_t err; + unsigned int i; + + blob_new = NULL; + stream = NULL; + err = 0; + + stream = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+"); + if (! stream) + { + err = gpg_error_from_errno (errno); + goto out; + } + + err = es_write_cstring (stream, type); + if (err) + goto out; + + for (i = 0; mpis[i] && (! err); i++) + err = es_write_mpi (stream, mpis[i]); + if (err) + goto out; + + blob_size_new = es_ftell (stream); + if (blob_size_new == -1) + { + err = gpg_error_from_errno (errno); + goto out; + } + + err = es_fseek (stream, 0, SEEK_SET); + if (err) + goto out; + + blob_new = xtrymalloc (blob_size_new); + if (! blob_new) + { + err = gpg_error_from_errno (errno); + goto out; + } + + err = es_read_data (stream, blob_new, blob_size_new); + if (err) + goto out; + + *blob = blob_new; + *blob_size = blob_size_new; + + out: + + if (stream) + es_fclose (stream); + if (err) + xfree (blob_new); + + return err; +} + + +static gpg_error_t +ssh_send_key_public (estream_t stream, gcry_sexp_t key_public) +{ + ssh_key_type_spec_t spec; + gcry_mpi_t *mpi_list; + const char *key_type; + const char *comment; + unsigned char *blob; + size_t blob_n; + gpg_error_t err; + + key_type = NULL; + mpi_list = NULL; + comment = NULL; + blob = NULL; + + err = ssh_sexp_extract_key_type (key_public, &key_type); + if (err) + goto out; + + err = ssh_key_type_lookup (NULL, key_type, &spec); + if (err) + goto out; + + err = ssh_sexp_extract (key_public, spec, NULL, &mpi_list, &comment); + if (err) + goto out; + + err = ssh_convert_key_to_blob (&blob, &blob_n, spec.ssh_identifier, mpi_list); + if (err) + goto out; + + err = es_write_string (stream, blob, blob_n); + if (err) + goto out; + + err = es_write_cstring (stream, comment); + + out: + + mpint_list_free (mpi_list); + xfree ((void *) key_type); + xfree ((void *) comment); + xfree (blob); + + return err; +} + +static gpg_error_t +ssh_read_key_public_from_blob (unsigned char *blob, size_t blob_size, + gcry_sexp_t *key_public, + ssh_key_type_spec_t *key_spec) +{ + estream_t blob_stream; + gpg_error_t err; + + err = 0; + + blob_stream = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+"); + if (! blob_stream) + { + err = gpg_error_from_errno (errno); + goto out; + } + + err = es_write_data (blob_stream, blob, blob_size); + if (err) + goto out; + + err = es_fseek (blob_stream, 0, SEEK_SET); + if (err) + goto out; + + err = ssh_receive_key (blob_stream, key_public, 0, 0, key_spec); + + out: + + if (blob_stream) + es_fclose (blob_stream); + + return err; +} + + + +static gpg_error_t +key_secret_to_public (gcry_sexp_t *key_public, + ssh_key_type_spec_t spec, gcry_sexp_t key_secret) +{ + gpg_error_t err; + gcry_sexp_t value_pair; + unsigned int i; + gcry_mpi_t *mpis; + gcry_mpi_t mpi; + void **arglist; + size_t elems_n; + char *template; + size_t template_n; + const char *elems; + char *comment; + const char *data; + size_t data_n; + + err = 0; + mpis = NULL; + arglist = NULL; + comment = NULL; + template = NULL; + value_pair = NULL; + + elems = spec.elems_key_public; + elems_n = strlen (elems); + + data = NULL; + value_pair = gcry_sexp_find_token (key_secret, "comment", 0); + if (value_pair) + data = gcry_sexp_nth_data (value_pair, 1, &data_n); + if (! data) + { + data = ""; + data_n = 0; + } + + comment = xtrymalloc (data_n + 1); + if (! comment) + { + err = gpg_error_from_errno (errno); + goto out; + } + strncpy (comment, data, data_n); + comment[data_n] = 0; + + gcry_sexp_release (value_pair); + value_pair = NULL; + + template_n = 29 + strlen (spec.identifier) + (elems_n * 7) + 1; + template = xtrymalloc (template_n); + if (! template) + { + err = gpg_error_from_errno (errno); + goto out; + } + + mpis = xtrymalloc (sizeof (*mpis) * (elems_n + 1)); + if (! mpis) + { + err = gpg_error_from_errno (errno); /* FIXME: errno. */ + goto out; + } + memset (mpis, 0, sizeof (*mpis) * (elems_n + 1)); + + arglist = xtrymalloc (sizeof (*arglist) * (elems_n + 1)); + if (! arglist) + { + err = gpg_error_from_errno (errno); + goto out; + } + + for (i = 0; i < elems_n; i++) + { + value_pair = gcry_sexp_find_token (key_secret, elems + i, 1); + if (! value_pair) + { + err = gpg_error (GPG_ERR_INV_SEXP); + break; + } + mpi = gcry_sexp_nth_mpi (value_pair, 1, GCRYMPI_FMT_USG); + if (! mpi) + { + err = gpg_error (GPG_ERR_INV_SEXP); + break; + } + gcry_sexp_release (value_pair); + value_pair = NULL; + + mpis[i] = mpi; + arglist[i] = &mpis[i]; + mpi = NULL; + } + if (err) + goto out; + + sprintf (template, "(public-key (%s", spec.identifier); + for (i = 0; i < elems_n; i++) + sprintf (strchr (template, 0)," (%c %%m)", elems[i]); + sprintf (strchr (template, 0), ") (comment %%s))"); + arglist[i] = &comment; + + err = gcry_sexp_build_array (key_public, NULL, template, arglist); + + out: + + gcry_sexp_release (value_pair); + xfree (template); + mpint_list_free (mpis); + xfree (arglist); + xfree (comment); + + return err; +} + + + +static char * +make_cstring (const char *data, size_t data_n) +{ + char *s; + + s = xtrymalloc (data_n + 1); + if (s) + { + strncpy (s, data, data_n); + s[data_n] = 0; + } + + return s; +} + + + +/* Request handler. */ + +static int +ssh_handler_request_identities (ctrl_t ctrl, estream_t request, estream_t response) +{ + const char *key_type; + ssh_key_type_spec_t spec; + struct dirent *dir_entry; + char *key_directory; + size_t key_directory_n; + char *key_path; + unsigned char *buffer; + size_t buffer_n; + uint32_t key_counter; + estream_t key_blobs; + gcry_sexp_t key_secret; + gcry_sexp_t key_public; + DIR *dir; + gpg_error_t err; + int ret; + int bad; + + if (DBG_COMMAND) + log_debug ("[ssh-agent] request identities\n"); + + /* Prepare buffer stream. */ + + key_directory = NULL; + key_secret = NULL; + key_public = NULL; + key_type = NULL; + key_path = NULL; + key_counter = 0; + buffer = NULL; + dir = NULL; + bad = 0; + err = 0; + + key_blobs = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+"); + if (! key_blobs) + { + err = gpg_error_from_errno (errno); + goto out; + } + + /* Open key directory. */ + key_directory = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, NULL); + if (! key_directory) + { + err = gpg_err_code_from_errno (errno); + goto out; + } + key_directory_n = strlen (key_directory); + + key_path = xtrymalloc (key_directory_n + 46); + if (! key_path) + { + err = gpg_err_code_from_errno (errno); + goto out; + } + + sprintf (key_path, "%s/", key_directory); + sprintf (key_path + key_directory_n + 41, ".key"); + + dir = opendir (key_directory); + if (! dir) + { + err = gpg_err_code_from_errno (errno); + goto out; + } + + /* Iterate over key files. */ + + /* FIXME: make sure that buffer gets deallocated properly. */ + + while (1) + { + dir_entry = readdir (dir); + if (dir_entry) + { + if ((strlen (dir_entry->d_name) == 44) + && (! strncmp (dir_entry->d_name + 40, ".key", 4))) + { + strncpy (key_path + key_directory_n + 1, dir_entry->d_name, 40); + + /* Read file content. */ + err = es_read_file (key_path, &buffer, &buffer_n); + if (err) + break; + + err = gcry_sexp_sscan (&key_secret, NULL, buffer, buffer_n); + if (err) + break; + + xfree (buffer); + buffer = NULL; + + err = ssh_sexp_extract_key_type (key_secret, &key_type); + if (err) + break; + + err = ssh_key_type_lookup (NULL, key_type, &spec); + if (err) + break; + + xfree ((void *) key_type); + key_type = NULL; + + err = key_secret_to_public (&key_public, spec, key_secret); + if (err) + break; + + gcry_sexp_release (key_secret); + key_secret = NULL; + + err = ssh_send_key_public (key_blobs, key_public); + if (err) + break; + + gcry_sexp_release (key_public); + key_public = NULL; + + key_counter++; + } + } + else + break; + } + if (err) + goto out; + + ret = es_fseek (key_blobs, 0, SEEK_SET); + if (ret) + { + err = gpg_error_from_errno (errno); + goto out; + } + + out: + + /* Send response. */ + + gcry_sexp_release (key_secret); + gcry_sexp_release (key_public); + + es_write_byte (response, SSH_RESPONSE_IDENTITIES_ANSWER); + if (! es_ferror (response)) + es_write_uint32 (response, err ? 0 : key_counter); + if (! (err || es_ferror (response))) + es_copy (response, key_blobs); + + if (key_blobs) + es_fclose (key_blobs); + if (dir) + closedir (dir); + + free (key_directory); + xfree (key_path); + xfree (buffer); + xfree ((void *) key_type); /* FIXME? */ + + return bad; +} + +static gpg_error_t +data_hash (unsigned char *data, size_t data_n, + int md_algorithm, unsigned char *hash) +{ + gcry_md_hash_buffer (md_algorithm, hash, data, data_n); + + return 0; +} + +static gpg_error_t +data_sign (CTRL ctrl, ssh_signature_encoder_t sig_encoder, + unsigned char **sig, size_t *sig_n) +{ + char description[] = "Please provide the passphrase for key `%c':"; + gpg_error_t err; + gcry_sexp_t signature_sexp; + estream_t stream; + gcry_sexp_t valuelist; + gcry_sexp_t sublist; + gcry_mpi_t sig_value; + unsigned char *sig_blob; + size_t sig_blob_n; + const char *identifier; + const char *identifier_raw; + size_t identifier_n; + ssh_key_type_spec_t spec; + int ret; + unsigned int i; + const char *elems; + size_t elems_n; + gcry_mpi_t *mpis; + + signature_sexp = NULL; + identifier = NULL; + valuelist = NULL; + sublist = NULL; + sig_blob = NULL; + sig_blob_n = 0; + stream = NULL; + sig_value = NULL; + mpis = NULL; + + err = agent_pksign_do (ctrl, description, &signature_sexp, 0); + if (err) + goto out; + + valuelist = gcry_sexp_nth (signature_sexp, 1); + if (! valuelist) + { + err = gpg_error (GPG_ERR_INV_SEXP); + goto out; + } + + stream = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+"); + if (! stream) + { + err = gpg_error_from_errno (errno); + goto out; + } + + identifier_raw = gcry_sexp_nth_data (valuelist, 0, &identifier_n); + if (! identifier_raw) + { + err = gpg_error (GPG_ERR_INV_SEXP); + goto out; + } + + identifier = make_cstring (identifier_raw, identifier_n); + if (! identifier) + { + err = gpg_error_from_errno (errno); + goto out; + } + + err = ssh_key_type_lookup (NULL, identifier, &spec); + if (err) + goto out; + + err = es_write_cstring (stream, spec.ssh_identifier); + if (err) + goto out; + + elems = spec.elems_signature; + elems_n = strlen (elems); + + mpis = xtrymalloc (sizeof (*mpis) * (elems_n + 1)); + if (! mpis) + { + err = gpg_error_from_errno (errno); + goto out; + } + memset (mpis, 0, sizeof (*mpis) * (elems_n + 1)); + + for (i = 0; i < elems_n; i++) + { + sublist = gcry_sexp_find_token (valuelist, spec.elems_signature + i, 1); + if (! sublist) + { + err = gpg_error (GPG_ERR_INV_SEXP); + break; + } + + sig_value = gcry_sexp_nth_mpi (sublist, 1, GCRYMPI_FMT_USG); + if (! sig_value) + { + err = gpg_error (GPG_ERR_INTERNAL); /* FIXME? */ + break; + } + gcry_sexp_release (sublist); + sublist = NULL; + + mpis[i] = sig_value; + } + if (err) + goto out; + + err = (*sig_encoder) (stream, mpis); + if (err) + goto out; + + sig_blob_n = es_ftell (stream); + if (sig_blob_n == -1) + { + err = gpg_error_from_errno (errno); + goto out; + } + + sig_blob = xtrymalloc (sig_blob_n); + if (! sig_blob) + { + err = gpg_error_from_errno (errno); + goto out; + } + + ret = es_fseek (stream, 0, SEEK_SET); + if (ret) + { + err = gpg_error_from_errno (errno); + goto out; + } + + err = es_read_data (stream, sig_blob, sig_blob_n); + if (err) + goto out; + + *sig = (char *) sig_blob; + *sig_n = sig_blob_n; + + out: + + if (err) + xfree (sig_blob); + + if (stream) + es_fclose (stream); + gcry_sexp_release (valuelist); + gcry_sexp_release (signature_sexp); + gcry_sexp_release (sublist); + mpint_list_free (mpis); + xfree ((void *) identifier); + + return err; +} + +static int +ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response) +{ + gcry_sexp_t key; + ssh_key_type_spec_t spec; + unsigned char hash[MAX_DIGEST_LEN]; + unsigned int hash_n; + unsigned char key_grip[20]; + unsigned char *key_blob; + uint32_t key_blob_size; + unsigned char *data; + unsigned char *sig; + size_t sig_n; + uint32_t data_size; + uint32_t flags; + const void *p; + gpg_error_t err; + int bad; + + key_blob = NULL; + data = NULL; + sig = NULL; + key = NULL; + bad = 0; + + if (DBG_COMMAND) + log_debug ("[ssh-agent] sign request\n"); + + /* Receive key. */ + + err = es_read_string (request, 0, &key_blob, &key_blob_size); + if (err) + { + bad = 1; + goto out; + } + + err = ssh_read_key_public_from_blob (key_blob, key_blob_size, &key, &spec); + if (err) + { + bad = 1; + goto out; + } + + /* Receive data to sign. */ + err = es_read_string (request, 0, &data, &data_size); + if (err) + { + bad = 1; + goto out; + } + + /* FIXME? */ + err = es_read_uint32 (request, &flags); + if (err) + { + bad = 1; + goto out; + } + + /* Hash data. */ + hash_n = gcry_md_get_algo_dlen (GCRY_MD_SHA1); + if (! hash_n) + { + err = gpg_error (GPG_ERR_INTERNAL); + goto out; + } + err = data_hash (data, data_size, GCRY_MD_SHA1, hash); + if (err) + goto out; + + /* Calculate key grip. */ + p = gcry_pk_get_keygrip (key, key_grip); + if (! p) + { + err = gpg_error (GPG_ERR_INTERNAL); /* FIXME? */ + goto out; + } + + /* Sign data. */ + + ctrl->digest.algo = GCRY_MD_SHA1; + memcpy (ctrl->digest.value, hash, hash_n); + ctrl->digest.valuelen = hash_n; + ctrl->digest.raw_value = ! (spec.flags & SPEC_FLAG_USE_PKCS1V2); + ctrl->have_keygrip = 1; + memcpy (ctrl->keygrip, key_grip, 20); + + err = data_sign (ctrl, spec.signature_encoder, &sig, &sig_n); + + out: + + if (! bad) + { + /* Done. */ + es_write_byte (response, SSH_RESPONSE_SIGN_RESPONSE); + if (! es_ferror (response)) + { + if (! err) + es_write_string (response, sig, sig_n); + else + es_write_byte (response, SSH_RESPONSE_FAILURE); + } + } + + gcry_sexp_release (key); + xfree (key_blob); + xfree (data); + xfree (sig); + + return bad; +} + +static gpg_error_t +get_passphrase (const char *description, size_t passphrase_n, char *passphrase) +{ + struct pin_entry_info_s *pi; + gpg_error_t err; + + err = 0; + pi = gcry_calloc_secure (1, sizeof (*pi) + passphrase_n + 1); + if (! pi) + { + err = gpg_error (GPG_ERR_ENOMEM); + goto out; + } + + pi->min_digits = 0; /* We want a real passphrase. */ + pi->max_digits = 8; + pi->max_tries = 1; + pi->failed_tries = 0; + pi->check_cb = NULL; + pi->check_cb_arg = NULL; + pi->cb_errtext = NULL; + pi->max_length = 100; + + err = agent_askpin (NULL, description, NULL, pi); + if (err) + goto out; + + memcpy (passphrase, pi->pin, passphrase_n); + passphrase[passphrase_n] = 0; + + out: + + xfree (pi); + + return err; +} + +static gpg_error_t +ssh_key_extract_comment (gcry_sexp_t key, char **comment) +{ + gcry_sexp_t comment_list; + char *comment_new; + const char *data; + size_t data_n; + gpg_error_t err; + + comment_list = gcry_sexp_find_token (key, "comment", 0); + if (! comment_list) + { + err = gpg_error (GPG_ERR_INV_SEXP); + goto out; + } + + data = gcry_sexp_nth_data (comment_list, 1, &data_n); + if (! data) + { + err = gpg_error (GPG_ERR_INV_SEXP); + goto out; + } + + comment_new = xtrymalloc (data_n + 1); + if (! comment_new) + { + err = gpg_error_from_errno (errno); + goto out; + } + + strncpy (comment_new, data, data_n); + comment_new[data_n] = 0; + *comment = comment_new; + err = 0; + + out: + + gcry_sexp_release (comment_list); + + return err; +} + +static gpg_error_t +ssh_key_grip (gcry_sexp_t key, char *buffer) +{ + gpg_error_t err; + char *p; + + /* FIXME: unsigned vs. signed. */ + + p = gcry_pk_get_keygrip (key, buffer); + if (! p) + err = gpg_error (GPG_ERR_INTERNAL); /* FIXME? */ + else + err = 0; + + return err; +} + +static gpg_error_t +ssh_key_to_buffer (gcry_sexp_t key, const char *passphrase, + unsigned char **buffer, size_t *buffer_n) +{ + unsigned char *buffer_new; + unsigned int buffer_new_n; + gpg_error_t err; + + err = 0; + buffer_new_n = gcry_sexp_sprint (key, GCRYSEXP_FMT_CANON, NULL, 0); + buffer_new = xtrymalloc (buffer_new_n); + /* FIXME: secmem? */ + if (! buffer_new) + { + err = gpg_error_from_errno (errno); + goto out; + } + + gcry_sexp_sprint (key, GCRYSEXP_FMT_CANON, buffer_new, buffer_new_n); + /* FIXME: guarantee? */ + + err = agent_protect (buffer_new, passphrase, buffer, buffer_n); + + out: + + xfree (buffer_new); + + return err; +} + +static gpg_error_t +ssh_identity_register (gcry_sexp_t key, int ttl) +{ + unsigned char key_grip_raw[21]; + unsigned char *buffer; + unsigned int buffer_n; + char passphrase[100]; + size_t description_length; + char *description; + char key_grip[41]; + char *comment; + gpg_error_t err; + + int ret; + + if (DBG_COMMAND) + log_debug ("[ssh-agent] registering identity `%s'\n", key_grip); + + description = NULL; + comment = NULL; + buffer = NULL; + + err = ssh_key_grip (key, key_grip_raw); + if (err) + goto out; + + key_grip_raw[sizeof (key_grip_raw) - 1] = 0; + ret = agent_key_available (key_grip_raw); + if (! ret) + goto out; + + err = ssh_key_extract_comment (key, &comment); + if (err) + goto out; + + description_length = 95 + (comment ? strlen (comment) : 0); + description = malloc (description_length); + if (! description) + { + err = gpg_err_code_from_errno (errno); + goto out; + } + else + sprintf (description, + "Please provide the passphrase, which should be used " + "for protecting the received secret key `%s':", + comment ? comment : ""); + + err = get_passphrase (description, sizeof (passphrase), passphrase); + if (err) + goto out; + + err = ssh_key_to_buffer (key, passphrase, &buffer, &buffer_n); + if (err) + goto out; + + err = agent_write_private_key (key_grip_raw, buffer, buffer_n, 0); + if (err) + goto out; + + err = agent_put_cache (key_grip_raw, passphrase, ttl); + if (err) + goto out; + + out: + + xfree (buffer); + xfree (comment); + xfree (description); + /* FIXME: verify xfree vs free. */ + + return err; +} + +static gpg_error_t +ssh_identity_drop (gcry_sexp_t key) +{ + unsigned char key_grip[21] = { 0 }; + gpg_error_t err; + + err = ssh_key_grip (key, key_grip); + if (err) + goto out; + + key_grip[sizeof (key_grip) - 1] = 0; + + /* FIXME: What to do here - forgetting the passphrase or deleting + the key from key cache? */ + + if (DBG_COMMAND) + log_debug ("[ssh-agent] dropping identity `%s'\n", key_grip); + + out: + + return err; +} + +static int +ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response) +{ + gpg_error_t err; + gcry_sexp_t key; + byte_t b; + int confirm; + int death; + int bad; + + if (DBG_COMMAND) + log_debug ("[ssh-agent] add identity\n"); + + confirm = 0; + death = 0; + key = NULL; + bad = 0; + + /* FIXME? */ + err = ssh_receive_key (request, &key, 1, 1, NULL); + if (err) + { + bad = 1; + goto out; + } + + while (1) + { + err = es_read_byte (request, &b); + if (gpg_err_code (err) == GPG_ERR_EOF) + { + err = 0; + break; + } + + switch (b) + { + case SSH_OPT_CONSTRAIN_LIFETIME: + { + uint32_t n = 0; + + err = es_read_uint32 (request, &n); + if (! err) + death = time (NULL) + n; + break; + } + + case SSH_OPT_CONSTRAIN_CONFIRM: + { + confirm = 1; + break; + } + + default: + /* FIXME: log/bad? */ + break; + } + } + if (err) + goto out; + + if (lifetime_default && (! death)) + death = time (NULL) + lifetime_default; + + /* FIXME: are constraints used correctly? */ + + err = ssh_identity_register (key, death); + + out: + + gcry_sexp_release (key); + + if (! bad) + es_write_byte (response, err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); + + return bad; +} + +static int +ssh_handler_remove_identity (ctrl_t ctrl, estream_t request, estream_t response) +{ + unsigned char *key_blob; + uint32_t key_blob_size; + gcry_sexp_t key; + gpg_error_t err; + int bad; + + /* Receive key. */ + + if (DBG_COMMAND) + log_debug ("[ssh-agent] remove identity\n"); + + key_blob = NULL; + key = NULL; + bad = 0; + + err = es_read_string (request, 0, &key_blob, &key_blob_size); + if (err) + { + bad = 1; + goto out; + } + + err = ssh_read_key_public_from_blob (key_blob, key_blob_size, &key, NULL); + if (err) + { + bad = 1; + goto out; + } + + err = ssh_identity_drop (key); + + out: + + xfree (key_blob); + gcry_sexp_release (key); + + if (! bad) + es_write_byte (response, err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); + + return bad; +} + +static gpg_error_t +ssh_identities_remove_all (void) +{ + gpg_error_t err; + + if (DBG_COMMAND) + log_debug ("[ssh-agent] remove all identities\n"); + + err = 0; + + /* FIXME: shall we remove _all_ cache entries or only those + registered through the ssh emulation? */ + + return err; +} + +static int +ssh_handler_remove_all_identities (ctrl_t ctrl, estream_t request, estream_t response) +{ + gpg_error_t err; + + err = ssh_identities_remove_all (); + es_write_byte (response, err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); + + return 0; +} + +static gpg_error_t +ssh_lock (void) +{ + gpg_error_t err; + + if (DBG_COMMAND) + log_debug ("[ssh-agent] lock\n"); + + err = 0; + + return err; +} + +static gpg_error_t +ssh_unlock (void) +{ + gpg_error_t err; + + if (DBG_COMMAND) + log_debug ("[ssh-agent] unlock\n"); + + err = 0; + + return err; +} + +static int +ssh_handler_lock (ctrl_t ctrl, estream_t request, estream_t response) +{ + gpg_error_t err; + + err = ssh_lock (); + es_write_byte (response, err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); + + return 0; +} + +static int +ssh_handler_unlock (ctrl_t ctrl, estream_t request, estream_t response) +{ + gpg_error_t err; + + err = ssh_unlock (); + es_write_byte (response, err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); + + return 0; +} + + + +/* Associating request types with the corresponding request + handlers. */ + +static ssh_request_spec_t request_specs[] = + { + { SSH_REQUEST_REQUEST_IDENTITIES, ssh_handler_request_identities }, + { SSH_REQUEST_SIGN_REQUEST, ssh_handler_sign_request }, + { SSH_REQUEST_ADD_IDENTITY, ssh_handler_add_identity }, + { SSH_REQUEST_ADD_ID_CONSTRAINED, ssh_handler_add_identity }, + { SSH_REQUEST_REMOVE_IDENTITY, ssh_handler_remove_identity }, + { SSH_REQUEST_REMOVE_ALL_IDENTITIES, ssh_handler_remove_all_identities }, + { SSH_REQUEST_LOCK, ssh_handler_lock }, + { SSH_REQUEST_UNLOCK, ssh_handler_unlock }, + }; + + + +static gpg_error_t +ssh_request_process (ctrl_t ctrl, estream_t request, estream_t response) +{ + byte_t request_type; + gpg_error_t err; + unsigned int i; + int bad; + + err = es_read_byte (request, &request_type); + if (err) + goto out; + + if (DBG_COMMAND) + log_debug ("[ssh-agent] request: %u\n", request_type); + + for (i = 0; i < DIM (request_specs); i++) + if (request_specs[i].type == request_type) + break; + if (i == DIM (request_specs)) + { + err = es_write_byte (response, SSH_RESPONSE_FAILURE); + goto out; + } + + + bad = (*request_specs[i].handler) (ctrl, request, response); + if (bad) + err = GPG_ERR_PROTOCOL_VIOLATION; + + out: + + return err; +} + +void +start_command_handler_ssh (int sock_client) +{ + struct server_control_s ctrl; + gpg_error_t err; + estream_t stream_response; + estream_t stream_request; + estream_t stream_sock; + unsigned char *request; + uint32_t request_size; + size_t size; + int ret; + + /* Setup control structure. */ + + if (DBG_COMMAND) + log_debug ("[ssh-agent] Starting command handler\n"); + + memset (&ctrl, 0, sizeof (ctrl)); + ctrl.connection_fd = sock_client; + + stream_response = NULL; + stream_request = NULL; + stream_sock = NULL; + request = NULL; + + stream_sock = es_fdopen (sock_client, "r+"); + if (! stream_sock) + { + err = gpg_error_from_errno (errno); + goto out; + } + ret = es_setvbuf (stream_sock, NULL, _IONBF, 0); + if (ret) + { + err = gpg_error_from_errno (errno); + goto out; + } + + while (1) + { + /* Create memory streams for request/response data. The entire + request will be stored in secure memory, since it might + contain secret key material. The response does not have to + be stored in secure memory, since we never give out secret + keys. FIXME: wrong place. */ + + /* Retrieve request. */ + err = es_read_string (stream_sock, 1, &request, &request_size); + if (err) + break; + + if (DBG_COMMAND) + log_debug ("[ssh-agent] Received request of length: %u\n", + request_size); + + stream_request = es_mopen (NULL, 0, 0, 1, + realloc_secure, gcry_free, "r+"); + if (! stream_request) + { + err = gpg_error_from_errno (errno); + break; + } + ret = es_setvbuf (stream_request, NULL, _IONBF, 0); + if (ret) + { + err = gpg_error_from_errno (errno); + break; + } + err = es_write_data (stream_request, request, request_size); + if (err) + break; + es_rewind (stream_request); + + stream_response = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+"); + if (! stream_response) + { + err = gpg_error_from_errno (errno); + break; + } + + /* Process request. */ + err = ssh_request_process (&ctrl, stream_request, stream_response); + if (err) + break; + + /* Figure out size of response data. */ + size = es_ftell (stream_response); + err = es_fseek (stream_response, 0, SEEK_SET); + if (err) + break; + + /* Write response data to socket stream. */ + err = es_write_uint32 (stream_sock, size); + if (err) + break; + err = es_copy (stream_sock, stream_response); + if (err) + break; + + err = es_fflush (stream_sock); + if (err) + break; + + es_fclose (stream_request); + stream_request = NULL; + es_fclose (stream_response); + stream_response = NULL; + xfree (request); + request = NULL; + }; + + out: + + /* FIXME: logging. */ + + if (stream_sock) + es_fclose (stream_sock); + if (stream_request) + es_fclose (stream_request); + if (stream_response) + es_fclose (stream_response); + xfree (request); /* FIXME? */ + + if (DBG_COMMAND) + log_debug ("[ssh-agent] Leaving ssh command handler: %s\n", gpg_strerror (err)); +} From cvs at cvs.gnupg.org Thu Jan 27 11:21:54 2005 From: cvs at cvs.gnupg.org (cvs user wk) Date: Fri Jan 28 12:17:32 2005 Subject: gnupg (TODO doc/ChangeLog doc/faq.raw g10/ChangeLog g10/ccid-driver.c) Message-ID: Date: Thursday, January 27, 2005 @ 11:30:28 Author: wk Path: /cvs/gnupg/gnupg Modified: TODO doc/ChangeLog doc/faq.raw g10/ChangeLog g10/ccid-driver.c Updated to the version from 1.2.7. -------------------+ TODO | 5 doc/ChangeLog | 4 doc/faq.raw | 993 ++++++++++++++++++++++++++++++++++------------------ g10/ChangeLog | 8 g10/ccid-driver.c | 4 5 files changed, 676 insertions(+), 338 deletions(-) Index: gnupg/TODO diff -u gnupg/TODO:1.175 gnupg/TODO:1.176 --- gnupg/TODO:1.175 Fri Oct 15 18:08:15 2004 +++ gnupg/TODO Thu Jan 27 11:30:28 2005 @@ -1,3 +1,8 @@ +* BACKUP Filename requires a status message. !!!! + +* Delete a card key as well as a wiping. + + * From: Nicolas Sierro Date: Thu, 17 Jun 2004 12:31:24 +0200 Index: gnupg/doc/ChangeLog diff -u gnupg/doc/ChangeLog:1.91 gnupg/doc/ChangeLog:1.92 --- gnupg/doc/ChangeLog:1.91 Thu Jan 20 12:42:03 2005 +++ gnupg/doc/ChangeLog Thu Jan 27 11:30:27 2005 @@ -1,3 +1,7 @@ +2005-01-27 Werner Koch + + * faq.raw: Updated to the version from 1.2.7. + 2005-01-18 Werner Koch * gnupg-w32.reg: Remove the entry for the home directory. Index: gnupg/doc/faq.raw diff -u gnupg/doc/faq.raw:1.3 gnupg/doc/faq.raw:1.4 --- gnupg/doc/faq.raw:1.3 Fri Aug 23 10:43:46 2002 +++ gnupg/doc/faq.raw Thu Jan 27 11:30:27 2005 @@ -7,120 +7,159 @@ [$usenetheader= ] [$maintainer=David D. Scribner, ] -[$hGPG=http://www.gnupg.org] +[$hGPGHTTP=http://www.gnupg.org] +[$hGPGFTP=ftp://ftp.gnupg.org] +[$hVERSION=1.2.2] [H body bgcolor=#ffffff text=#000000 link=#1f00ff alink=#ff0000 vlink=#9900dd] -[H H1]GnuPG Frequently Asked Questions[H /H1] +[H h1]GnuPG Frequently Asked Questions[H /h1] [H p] -Version: 1.5.7[H br] -Last-Modified: Aug 21, 2002[H br] +Version: 1.6.3[H br] +Last-Modified: Jul 30, 2003[H br] Maintained-by: [$maintainer] [H /p] This is the GnuPG FAQ. The latest HTML version is available -[H a href=[$hGPG]/faq.html]here[H/a]. +[H a href=[$hGPGHTTP]/documentation/faqs.html]here[H/a]. -The index is generated automatically, so there may be errors here. Not -all questions may be in the section they belong to. Suggestions about -how to improve the structure of this FAQ are welcome. +The index is generated automatically, so there may be errors. Not all +questions may be in the section they belong to. Suggestions about how +to improve the structure of this FAQ are welcome. Please send additions and corrections to the maintainer. It would be most convenient if you could provide the answer to be included here -as well. Your help is very much appreciated. +as well. Your help is very much appreciated! -Please, don't send message like "This should be a FAQ - what's the answer?". -If it hasn't been asked before, it isn't a FAQ. In that case you could -search in the mailing list archive. +Please, don't send message like "This should be a FAQ - what's the +answer?". If it hasn't been asked before, it isn't a FAQ. In that case +you could search in the mailing list archive. -[H HR] +[H hr] -[H HR] +[H hr] GENERAL What is GnuPG? - [H a href=[$hGPG]]GnuPG[H /a] stands for GNU Privacy Guard and + [H a href=[$hGPGHTTP]]GnuPG[H /a] stands for GNU Privacy Guard and is GNU's tool for secure communication and data storage. It can be used to encrypt data and to create digital signatures. It includes an advanced key management facility and is compliant with the - proposed OpenPGP Internet standard as described in [H a href=http://www.gnupg.org/rfc2440.html]RFC 2440[H/a]. + proposed OpenPGP Internet standard as described in [H a href=http://www.rfc-editor.org/]RFC 2440[H/a]. As such, it is aimed to be compatible with PGP from NAI, Inc. Is GnuPG compatible with PGP? In general, yes. GnuPG and newer PGP releases should be implementing - the OpenPGP standard. But there are some interoperability - problems. See question for details. + the OpenPGP standard. But there are some interoperability problems. + See question for details. + + Is GnuPG free to use for personal or commercial use? + + Yes. GnuPG is part of the GNU family of tools and applications built + and provided in accordance with the Free Software Foundation (FSF) + General Public License (GPL). Therefore the software is free to copy, + use, modify and distribute in accordance with that license. Please + read the file titled COPYING that accompanies the application for + more information. + + What conventions are used in this FAQ? + + Although GnuPG is being developed for several operating systems + (often in parallel), the conventions used in this FAQ reflect a + UNIX shell environment. For Win32 users, references to a shell + prompt (`$') should be interpreted as a command prompt (`>'), + directory names separated by a forward slash (`/') may need to be + converted to a back slash (`\'), and a tilde (`~') represents a + user's "home" directory (reference question for an example). + + Some command-lines presented in this FAQ are too long to properly + display in some browsers for the web page version of this file, and + have been split into two or more lines. For these commands please + remember to enter the entire command-string on one line or the + command will error, or at minimum not give the desired results. + + Please keep in mind that this FAQ contains information that may not + apply to your particular version, as new features and bug fixes are + added on a continuing basis (reference the NEWS file included with + the source or package for noteworthy changes between versions). One + item to note is that starting with GnuPG version 1.1.92 the file + containing user options and settings has been renamed from "options" + to "gpg.conf". Information in the FAQ that relates to the options + file may be interchangable with the newer gpg.conf file in many + instances. See question for details. SOURCES of INFORMATION - Where can I find more information? + Where can I find more information on GnuPG? - Here's a list of on-line resources: + On-line resources: - [H UL] - [H LI]The documentation page is located at [H a href=[$hGPG]/docs.html]<[$hGPG]/docs.html>[H/a]. - Have a look at the HOWTOs and the GNU Privacy Handbook (GPH, available - in English, Spanish and Russian). The latter provides a detailed user's - guide to GnuPG. You'll also find a document about how to convert from - PGP 2.x to GnuPG. - - [H LI]On [H a href=http://lists.gnupg.org][H/a] you'll find an online archive of the - GnuPG mailing lists. Most interesting should be gnupg-users for all - user-related issues and gnupg-devel if you want to get in touch with - the developers. + [H ul] + [H li]The documentation page is located at [H a href=[$hGPGHTTP]/documentation/]<[$hGPGHTTP]/documentation/>[H/a]. + Also, have a look at the HOWTOs and the GNU Privacy Handbook (GPH, + available in English, Spanish and Russian). The latter provides a + detailed user's guide to GnuPG. You'll also find a document about how + to convert from PGP 2.x to GnuPG. + + [H li]At [H a href=[$hGPGHTTP]/documentation/mailing-lists.html]<[$hGPGHTTP]/documentation/mailing-lists.html>[H/a] you'll find + an online archive of the GnuPG mailing lists. Most interesting should + be gnupg-users for all user-related issues and gnupg-devel if you want + to get in touch with the developers. In addition, searchable archives can be found on MARC, e.g.: [H br] - GnuPG-users: [H a href=http://marc.theaimsgroup.com/?l=gnupg-users&r=1&w=2][H/a],[H br] - GnuPG-devel: [H a href=http://marc.theaimsgroup.com/?l=gnupg-devel&r=1&w=2][H/a].[H br] + gnupg-users: [H a href=http://marc.theaimsgroup.com/?l=gnupg-users&r=1&w=2][H/a][H br] + gnupg-devel: [H a href=http://marc.theaimsgroup.com/?l=gnupg-devel&r=1&w=2][H/a][H br] - [H B]PLEASE:[H/B] - Before posting to a list, read this FAQ and the available - documentation. In addition, search the list archive - maybe your - question has already been discussed. This way you help people focus - on topics that have not yet been resolved. - - [H LI]The GnuPG source distribution contains a subdirectory: - - [H PRE] - ./doc - [H /PRE] + [H b]PLEASE:[H /b] + Before posting to a list, read this FAQ and the available documentation. + In addition, search the list archive - maybe your question has already + been discussed. This way you help people focus on topics that have not + yet been resolved. + + [H li]The GnuPG source distribution contains a subdirectory: + + [H samp] + ./doc + [H /samp] where some additional documentation is located (mainly interesting for hackers, not the casual user). - [H /UL] + [H /ul] Where do I get GnuPG? You can download the GNU Privacy Guard from its primary FTP server - [H a href=ftp://ftp.gnupg.org/pub/gcrypt]ftp.gnupg.org[H /a] or from one of the mirrors: + [H a href=[$hGPGFTP]/gcrypt/]<[$hGPGFTP]/gcrypt/>[H /a] or from one of the mirrors: - [H a href=[$hGPG]/mirrors.html] - <[$hGPG]/mirror.html> + [H a href=[$hGPGHTTP]/download/mirrors.html] + <[$hGPGHTTP]/download/mirrors.html> [H /a] - The current version is 1.0.4, please upgrade to this version as it - fixes a security bug regarding the verification of multiple signatures. + The current stable version is [$hVERSION]. Please upgrade to this version as + it includes additional features, functions and security fixes that may + not have existed in prior versions. INSTALLATION Which OSes does GnuPG run on? - It should run on most Unices as well as Windows 95 and Windows NT. A - list of OSes reported to be OK is presented at: + It should run on most Unices as well as Windows versions (including + Windows NT/2000) and Macintosh OS/X. A list of OSes reported to be OK + is presented at: - [H a href=http://www.gnupg.org/backend.html#supsys] - + [H a href=[$hGPGHTTP]/download/supported_systems.html] + <[$hGPGHTTP]/download/supported_systems.html> [H /a] - Which random gatherer should I use? + Which random data gatherer should I use? "Good" random numbers are crucial for the security of your encryption. Different operating systems provide a variety of more or less quality @@ -129,72 +168,79 @@ systems. Also Solaris users with the SUNWski package installed have a /dev/random. In these cases, use the configure option: - [H pre] - --enable-static-rnd=linux - [H/pre] + [H samp] + --enable-static-rnd=linux + [H /samp] In addition, there's also the kernel random device by Andi Maier - [H a href= http://www.cosy.sbg.ac.at/~andi][H /a], but it's still beta. Use at your + [H a href= http://www.cosy.sbg.ac.at/~andi/SUNrand/][H /a], but it's still beta. Use at your own risk! On other systems, the Entropy Gathering Daemon (EGD) is a good choice. It is a perl-daemon that monitors system activity and hashes it into - random data. See the download page [H a href=http://www.gnupg.org/download.html][H /a] - to obtain egd. Use: + random data. See the download page [H a href=[$hGPGHTTP]/download/]<[$hGPGHTTP]/download/>[H /a] + to obtain EGD. Use: - [H pre] - --enable-static-rnd=egd - [H/pre] + [H samp] + --enable-static-rnd=egd + [H /samp] here. If the above options do not work, you can use the random number - generator "unix". This is [H B]very[H /B] slow and should be avoiced. The + generator "unix". This is [H B]very[H /B] slow and should be avoided. The random quality isn't very good so don't use it on sensitive data. How do I include support for RSA and IDEA? - RSA is included as of GnuPG 1.0.3. + RSA is included as of GnuPG version 1.0.3. - The official GnuPG distribution does not contain IDEA due to a - patent restriction. The patent does not expire before 2007 so don't - expect official support before then. - - However, there is an unofficial module to include it even - in earlier versions of GnuPG. It's available from - [H a href=ftp://ftp.gnupg.org/pub/gcrypt/contrib/][H /a]. Look for: + The official GnuPG distribution does not contain IDEA due to a patent + restriction. The patent does not expire before 2007 so don't expect + official support before then. + + However, there is an unofficial module to include it even in earlier + versions of GnuPG. It's available from + [H a href=ftp://ftp.gnupg.dk/pub/contrib-dk/][H /a]. Look for: [H pre] - idea.c + idea.c.gz (c module) + idea.c.gz.sig (signature file) [H /pre] - Compilation directives are in the headers of these files. Then add - the following line to your ~/.gnupg/options: - [H pre] - load-extension idea + ideadll.zip (c module and win32 dll) + ideadll.zip.sig (signature file) [H /pre] + Compilation directives are in the headers of these files. You will + then need to add the following line to your ~/.gnupg/gpg.conf or + ~/.gnupg/options file: + + [H samp] + load-extension idea + [H /samp] + USAGE What is the recommended key size? - 1024 bit for DSA signatures; even for plain ElGamal signatures - this is sufficient as the size of the hash is probably the weakest + 1024 bit for DSA signatures; even for plain ElGamal signatures. + This is sufficient as the size of the hash is probably the weakest link if the key size is larger than 1024 bits. Encryption keys may have greater sizes, but you should then check the fingerprint of this key: - [H pre] - gpg --fingerprint - [H /pre] + [H samp] + $ gpg --fingerprint + [H /samp] As for the key algorithms, you should stick with the default (i.e., - DSA signature and ElGamal encryption). A ElGamal signing key has the - following disadvantages: the signature is larger, it is hard to - create such a key useful for signatures which can withstand some + DSA signature and ElGamal encryption). An ElGamal signing key has + the following disadvantages: the signature is larger, it is hard + to create such a key useful for signatures which can withstand some real world attacks, you don't get any extra security compared to DSA, and there might be compatibility problems with certain PGP versions. It has only been introduced because at the time it was @@ -222,12 +268,12 @@ over your secret key ring (which is in most cases vulnerable to advanced dictionary attacks) - I strongly encourage everyone to only create keys on a local computer (a disconnected laptop is probably - the best choice) and if you need it on your connected box (I know: - We all do this) be sure to have a strong password for your account - and for your secret key and that you can trust your system + the best choice) and if you need it on your connected box (I know, + we all do this) be sure to have a strong password for both your + account and for your secret key, and that you can trust your system administrator. - When I check GnuPG on a remote system via ssh (I have no Alpha here + When I check GnuPG on a remote system via ssh (I have no Alpha here) ;-) I have the same problem. It takes a *very* long time to create the keys, so I use a special option, --quick-random, to generate insecure keys which are only good for some tests. @@ -236,69 +282,73 @@ If you do a 'gpg --help', you will get two separate lists. The first is a list of commands. The second is a list of options. Whenever you - run GPG, you [H B]must[H /B] pick exactly one command (with one exception, - see below). You [H B]may[H /B] pick one or more options. The command should, + run GPG, you [H b]must[H /b] pick exactly one command (with one exception, + see below). You [H b]may[H /b] pick one or more options. The command should, just by convention, come at the end of the argument list, after all the options. If the command takes a file (all the basic ones do), the filename comes at the very end. So the basic way to run gpg is: - [H pre] - gpg [--option something] [--option2] [--option3 something] --command file - [H/pre] + [H samp] + $ gpg [--option something] [--option2] [--option3 something] --command file + [H /samp] Some options take arguments. For example, the --output option (which - can be abbreviated -o) is an option that takes a filename. The + can be abbreviated as -o) is an option that takes a filename. The option's argument must follow immediately after the option itself, otherwise gpg doesn't know which option the argument is supposed to - go with. As an option, --output and its filename must come before - the command. The --recipient (-r) option takes a name or keyid to - encrypt the message to, which must come right after the -r argument. - The --encrypt (or -e) command comes after all the options followed - by the file you wish to encrypt. So use: - - [H pre] - gpg -r alice -o secret.txt -e test.txt - [H/pre] + paired with. As an option, --output and its filename must come before + the command. The --recipient (-r) option takes a name or keyID to + encrypt the message to, which must come right after the -r option. + The --encrypt (or -e) command comes after all the options and is + followed by the file you wish to encrypt. Therefore in this example + the command-line issued would be: + + [H samp] + $ gpg -r alice -o secret.txt -e test.txt + [H /samp] If you write the options out in full, it is easier to read: - [H pre] - gpg --recipient alice --output secret.txt --encrypt test.txt - [H/pre] - - If you're saving it in a file called ".txt" then you'd probably - expect to see ASCII-armored text in there, so you need to add the - --armor (-a) option, which doesn't take any arguments: - - [H pre] - gpg --armor --recipient alice --output secret.txt --encrypt test.txt - [H/pre] + [H samp] + $ gpg --recipient alice --output secret.txt --encrypt test.txt + [H /samp] + + If you're encrypting to a file with the extension ".txt", then you'd + probably expect to see ASCII-armored text in the file (not binary), + so you need to add the --armor (-a) option, which doesn't take any + arguments: + + [H samp] + $ gpg --armor --recipient alice --output secret.txt --encrypt test.txt + [H /samp] If you imagine square brackets around the optional parts, it becomes a bit clearer: - [H pre] - gpg [--armor] [--recipient alice] [--output secret.txt] --encrypt test.txt - [H/pre] + [H samp] + $ gpg [--armor] [--recipient alice] [--output secret.txt] --encrypt test.txt + [H /samp] The optional parts can be rearranged any way you want: - [H pre] - gpg --output secret.txt --recipient alice --armor --encrypt test.txt - [H/pre] + [H samp] + $ gpg --output secret.txt --recipient alice --armor --encrypt test.txt + [H /samp] If your filename begins with a hyphen (e.g. "-a.txt"), GnuPG assumes - this is an option and may complain. To avoid this you have either - to use "./-a.txt" or stop the option and command processing with two - hyphens: "-- -a.txt". [H B]The exception:[H /B] signing and encrypting at the - same time. Use: - - [H pre] - gpg [--options] --sign --encrypt foo.txt - [H/pre] + this is an option and may complain. To avoid this you have to either + use "./-a.txt", or stop the option and command processing with two + hyphens: "-- -a.txt". + + [H B]The exception to using only one command:[H /B] signing and encrypting + at the same time. For this you can combine both commands, such as in: + + [H samp] + $ gpg [--options] --sign --encrypt foo.txt + [H /samp] - I can't delete a user ID because it is already deleted on my public - keyring? + I can't delete a user ID on my secret keyring because it has + already been deleted on my public keyring. What can I do? Because you can only select from the public key ring, there is no direct way to do this. However it is not very complicated to do @@ -307,43 +357,50 @@ ring. Now select this user ID and delete it. Both user IDs will be removed from the secret ring. - I can't delete the secret key because my public key disappeared? + I can't delete my secret key because the public key disappeared. + What can I do? To select a key a search is always done on the public keyring, - therefore it is not possible to select an secret key without - having the public key. Normally it shoud never happen that the + therefore it is not possible to select a secret key without + having the public key. Normally it should never happen that the public key got lost but the secret key is still available. The reality is different, so GnuPG implements a special way to deal - with it: Simply use the long keyid which can be obtained by using - the --with-colons options (it is the fifth field in the lines - beginning with "sec"). + with it: Simply use the long keyID to specify the key to delete, + which can be obtained by using the --with-colons options (it is + the fifth field in the lines beginning with "sec"). + + If you've lost your public key and need to recreate it instead + for continued use with your secret key, you may be able to use + gpgsplit as detailed in question . What are trust, validity and ownertrust? - "ownertrust" is used instead of "trust" to make clear that this is - the value you have assigned to a key to express how much you trust - the owner of this key to correctly sign (and so introduce) other - keys. "validity", or calculated trust, is a value which says how - much GnuPG thinks a key is valid (that it really belongs to the one - who claims to be the owner of the key). For more see the chapter - "The Web of Trust" in the Manual. + With GnuPG, the term "ownertrust" is used instead of "trust" to + help clarify that this is the value you have assigned to a key + to express how much you trust the owner of this key to correctly + sign (and thereby introduce) other keys. The "validity", or + calculated trust, is a value which indicates how much GnuPG + considers a key as being valid (that it really belongs to the + one who claims to be the owner of the key). For more information + on trust values see the chapter "The Web of Trust" in The GNU + Privacy Handbook. How do I sign a patch file? Use "gpg --clearsign --not-dash-escaped ...". The problem with --clearsign is that all lines starting with a dash are quoted with "- "; obviously diff produces many lines starting with a dash and - these are then quoted and that is not good for a patch ;-). To use a - patch file without removing the cleartext signature, the special + these are then quoted and that is not good for a patch ;-). To use + a patch file without removing the cleartext signature, the special option --not-dash-escaped may be used to suppress generation of these escape sequences. You should not mail such a patch because spaces and line endings are also subject to the signature and a mailer may not preserve these. If you want to mail a file you can - simply sign it using your MUA. + simply sign it using your MUA (Mail User Agent). Where is the "encrypt-to-self" option? - Use "--encrypt-to your_keyid". You can use more than one of these + Use "--encrypt-to your_keyID". You can use more than one of these options. To temporarily override the use of this additional key, you can use the option "--no-encrypt-to". @@ -355,87 +412,142 @@ What does the "You are using the xxxx character set." mean? - This note is printed when UTF8 mapping has to be done. Make sure - that the displayed charset is the one you have activated on your - system. Since "iso-8859-1" is the charset most used, this is the - default. You can change the charset with the option "--charset". - It is important that your active character set matches the one - displayed - if not, restrict yourself to plain 7 bit ASCII and no - mapping has to be done. - - How can a get list of key IDs used to encrypt a message? - - [H pre] - gpg --batch --decrypt --list-only --status-fd 1 2>/dev/null | \ - awk '/^\[GNUPG:\] ENC_TO / { print $3 }' - [H /pre] - - I can't decrypt my symmetrical only (-c) encrypted message with - a new version of GnuPG. - - There used to be a bug in GnuPG < 1.0.1 which happens only if 3DES - or Twofish has been used for symmetric only encryption (this has - never been the default). The bug has been fixed but to enable you - to decrypt old messages, you should run gpg with the option - "--emulate-3des-s2k-bug", decrypt the message and encrypt it again - without this option. The option will be removed in 1.1, so better - re-encrypt your message now. + This note is printed when UTF-8 mapping has to be done. Make sure + that the displayed character set is the one you have activated on + your system. Since "iso-8859-1" is the character set most used, + this is the default. You can change the charset with the option + "--charset". It is important that your active character set matches + the one displayed - if not, restrict yourself to plain 7 bit ASCII + and no mapping has to be done. + + How can I get list of key IDs used to encrypt a message? + + [H samp] + $ gpg --batch --decrypt --list-only --status-fd 1 2>/dev/null | + awk '/^\[GNUPG:\] ENC_TO / { print $3 }' + [H /samp] + + Why can't I decrypt files encrypted as symmetrical-only (-c) with + a version of GnuPG prior to 1.0.1. + + There was a bug in GnuPG versions prior to 1.0.1 which affected files + only if 3DES or Twofish was used for symmetric-only encryption (this has + never been the default). The bug has been fixed, but to enable decryption + of old files you should run gpg with the option "--emulate-3des-s2k-bug", + decrypt the file and encrypt it again without this option. + + NOTE: This option was removed in GnuPG development version 1.1.0 and later + updates, so you will need to use a version between 1.0.1 and 1.0.7 to + re-encrypt any affected files. How can I use GnuPG in an automated environment? - You should use the option --batch and don't use pass phrases as - there is usually no way to store it more secure than the secret - keyring itself. The suggested way to create the keys for the + You should use the option --batch and don't use passphrases as + there is usually no way to store it more securely than on the + secret keyring itself. The suggested way to create keys for an automated environment is: On a secure machine: - [H OL] - [H LI] If you want to do automatic signing, create a signing - subkey for your key (edit menu, choose "addkey" and the DSA). - [H LI] Make sure that you use a passphrase (needed by the current + [H ol] + [H li] If you want to do automatic signing, create a signing subkey + for your key (use the interactive key editing menu by issueing + the command 'gpg --edit-key keyID', enter "addkey" and select + the DSA key type). + [H li] Make sure that you use a passphrase (needed by the current implementation). - [H LI] gpg --export-secret-subkeys --no-comment foo >secring.auto - [H LI] Copy secring.auto and the public keyring to a test directory. - [H LI] Change to this directory. - [H LI] gpg --homedir . --edit foo and use "passwd" to remove the - passphrase from the subkeys. You may also want to remove all + [H li] gpg --export-secret-subkeys --no-comment foo >secring.auto + [H li] Copy secring.auto and the public keyring to a test directory. + [H li] Change to this directory. + [H li] gpg --homedir . --edit foo and use "passwd" to remove the + passphrase from the subkeys. You may also want to remove all unused subkeys. - [H LI] Copy secring.auto to a floppy and carry it to the target box. - [H /OL] + [H li] Copy secring.auto to a floppy and carry it to the target box. + [H /ol] On the target machine: - [H OL] - [H LI] Install secring.auto as secret keyring. - [H LI] Now you can start your new service. It is a good idea to - install some intrusion detection system so that you hopefully + [H ol] + [H li] Install secring.auto as the secret keyring. + [H li] Now you can start your new service. It's also a good idea to + install an intrusion detection system so that you hopefully get a notice of an successful intrusion, so that you in turn can revoke all the subkeys installed on that machine and install new subkeys. - [H /OL] + [H /ol] Which email-client can I use with GnuPG? Using GnuPG to encrypt email is one of the most popular uses. - Several mail clients or mail user-agents (MUA) support GnuPG at + Several mail clients or mail user agents (MUAs) support GnuPG to varying degrees. Simplifying a bit, there are two ways mail can be - encrypted with GnuPG: the "old style" ASCII armor, i.e. plain text - encryption, and RFC2015 style (previously PGP/MIME, now OpenPGP). + encrypted with GnuPG: the "old style" ASCII armor (i.e. cleartext + encryption), and RFC 2015 style (previously PGP/MIME, now OpenPGP). The latter has full MIME support. Some MUAs support only one of them, so whichever you actually use depends on your needs as well - as the capabilities of your addressee. + as the capabilities of your addressee. As well, support may be + native to the MUA, or provided via "plug-ins" or external tools. - The following list is probably not exhaustive: + The following list is not exhaustive: - OpenPGP: Mutt (Unix), Emacs/Mew, Becky2 (Windows, with plugin), - TkRat (Unix). There is effort for a Mozilla plugin and - Emacs/GNUS has support in the current CVS. + [H pre] + MUA OpenPGP ASCII How? (N,P,T) + ------------------------------------------------------------- + Calypso N Y P (Unixmail) + Elm N Y T (mailpgp,morepgp) + Elm ME+ N Y N + Emacs/Gnus Y Y T (Mailcrypt,gpg.el) + Emacs/Mew Y Y N + Emacs/VM N Y T (Mailcrypt) + Evolution Y Y N + Exmh Y Y N + GNUMail.app Y Y P (PGPBundle) + GPGMail Y Y N + KMail (<=1.4.x) N Y N + KMail (1.5.x) Y(P) Y(N) P/N + Mozilla Y Y P (Enigmail) + Mulberry Y Y P + Mutt Y Y N + Sylpheed Y Y N + Sylpheed-claws Y Y N + TkRat Y Y N + XEmacs/Gnus Y Y T (Mailcrypt) + XEmacs/Mew Y Y N + XEmacs/VM N Y T (Mailcrypt) + XFmail Y Y N + + N - Native, P - Plug-in, T - External Tool + [H /pre] - ASCII: Emacs/{VM,GNUS}/MailCrypt, Mutt(Unix), Pine(Unix), and - probably many more. + The following table lists proprietary MUAs. The GNU Project + suggests against the use of these programs, but they are listed + for interoperability reasons for your convenience. + + [H pre] + MUA OpenPGP ASCII How? (N,P,T) + ------------------------------------------------------------- + Apple Mail Y Y P (GPGMail) + Becky2 Y Y P (BkGnuPG) + Eudora Y Y P (EuroraGPG) + Eudora Pro Y Y P (EudoraGPG) + Lotus Notes N Y P + Netscape 4.x N Y P + Netscape 7.x Y Y P (Enigmail) + Novell Groupwise N Y P + Outlook N Y P (G-Data) + Outlook Express N Y P (GPGOE) + Pegasus N Y P (QDPGP,PM-PGP) + Pine N Y T (pgpenvelope,(gpg|pgp)4pine) + Postme N Y P (GPGPPL) + The Bat! N Y P (Ritlabs) + [H /pre] - Good overviews of OpenPGP-support can be found at - [H a href=http://cryptorights.org/pgp-users/pgp-mail-clients.html]http://cryptorights.org/pgp-users/pgp-mail-clients.html[H /a] - and [H a href=http://www.geocities.com/openpgp/courrier_en.html]http://www.geocities.com/openpgp/courrier_en.html[H /a]. + Good overviews of OpenPGP-support can be found at:[H br] + [H a href=http://www.openpgp.fr.st/courrier_en.html][H /a] and[H br] + [H a href=http://www.bretschneidernet.de/tips/secmua.html][H /a]. + + Users of Win32 MUAs that lack OpenPGP support may look into + using GPGrelay [H a href=http://gpgrelay.sourceforge.net][H /a], a small + email-relaying server that uses GnuPG to enable many email clients + to send and receive emails that conform to PGP-MIME (RFC 2015). Can't we have a gpg library? @@ -443,7 +555,7 @@ of the GnuPG maintainers is that this would lead to several security issues and will therefore not be implemented in the foreseeable future. However, for some areas of application gpgme could do the - trick. You'll find it at [H a href=ftp://ftp.guug.de/pub/gcrypt/alpha/gpgme]ftp://ftp.guug.de/pub/gcrypt/alpha/gpgme[H /a]. + trick. You'll find it at [H a href=[$hGPGFTP]/gcrypt/alpha/gpgme]<[$hGPGFTP]/gcrypt/alpha/gpgme>[H /a]. I have successfully generated a revocation certificate, but I don't understand how to send it to the key servers. @@ -451,18 +563,19 @@ Most keyservers don't accept a 'bare' revocation certificate. You have to import the certificate into gpg first: - [H pre] - gpg --import my-revocation.asc - [H /pre] + [H samp] + $ gpg --import my-revocation.asc + [H /samp] then send the revoked key to the keyservers: - [H pre] - gpg --keyserver certserver.pgp.com --send-keys mykeyid - [H /pre] + [H samp] + $ gpg --keyserver certserver.pgp.com --send-keys mykeyid + [H /samp] (or use a keyserver web interface for this). + How do I put my keyring in a different directory? GnuPG keeps several files in a special homedir directory. These @@ -470,17 +583,87 @@ and others. GnuPG will always create and use these files. On unices, the homedir is usually ~/.gnupg; on Windows "C:\gnupg\". - If you want to put your keyrings somewhere else, use: + If you want to put your keyrings somewhere else, use the option: - [H pre] - --homedir /my/path/ - [H /pre] + [H samp] + --homedir /my/path/ + [H /samp] to make GnuPG create all its files in that directory. Your keyring will be "/my/path/pubring.gpg". This way you can store your secrets on a floppy disk. Don't use "--keyring" as its purpose is to specify additional keyring files. + How do I verify signed packages? + + Before you can verify the signature that accompanies a package, + you must first have the vendor, organisation, or issueing person's + key imported into your public keyring. To prevent GnuPG warning + messages the key should also be validated (or locally signed). + + You will also need to download the detached signature file along + with the package. These files will usually have the same name as + the package, with either a binary (.sig) or ASCII armor (.asc) + extension. + + Once their key has been imported, and the package and accompanying + signature files have been downloaded, use: + + [H samp] + $ gpg --verify sigfile signed-file + [H /samp] + + If the signature file has the same base name as the package file, + the package can also be verified by specifying just the signature + file, as GnuPG will derive the package's file name from the name + given (less the .sig or .asc extension). For example, to verify a + package named foobar.tar.gz against its detached binary signature + file, use: + + [H samp] + $ gpg --verify foobar.tar.gz.sig + [H /samp] + + How do I export a keyring with only selected signatures (keys)? + + If you're wanting to create a keyring with only a subset of keys + selected from a master keyring (for a club, user group, or company + department for example), simply specify the keys you want to export: + + [H samp] + $ gpg --armor --export key1 key2 key3 key4 > keys1-4.asc + [H /samp] + + + I still have my secret key, but lost my public key. What can I do? + + All OpenPGP secret keys have a copy of the public key inside them, + and in a worst-case scenario, you can create yourself a new public + key using the secret key. + + A tool to convert a secret key into a public one has been included + (it's actually a new option for gpgsplit) and is available with GnuPG + versions 1.2.1 or later (or can be found in CVS). It works like this: + + [H samp] + $ gpgsplit --no-split --secret-to-public secret.gpg >publickey.gpg + [H /samp] + + One should first try to export the secret key and convert just this + one. Using the entire secret keyring should work too. After this has + been done, the publickey.gpg file can be imported into GnuPG as usual. + + Clearsigned messages sent from my web-mail account have an invalid + signature. Why? + + Check to make sure the settings for your web-based email account + do not use HTML formatting for the pasted clearsigned message. This can + alter the message with embedded HTML markup tags or spaces, resulting + in an invalid signature. The recipient may be able to copy the signed + message block to a text file for verification, or the web email + service may allow you to attach the clearsigned message as a file + if plaintext messages are not an option. + COMPATIBILITY ISSUES @@ -489,34 +672,34 @@ It depends on the PGP version. - [H UL] - [H LI]PGP 2.x[H br] + [H ul] + [H li]PGP 2.x[H br] You can't do that because PGP 2.x normally uses IDEA which is not supported by GnuPG as it is patented (see ), but if you have a modified version of PGP you can try this: - [H pre] - gpg --rfc1991 --cipher-algo 3des ... - [H/pre] + [H samp] + $ gpg --rfc1991 --cipher-algo 3des ... + [H /samp] Please don't pipe the data to encrypt to gpg but provide it using a filename; otherwise, PGP 2 will not be able to handle it. As for conventional encryption, you can't do this for PGP 2. - [H LI]PGP 5.x and higher[H br] + [H li]PGP 5.x and higher[H br] You need to provide two additional options: - [H pre] - --compress-algo 1 --cipher-algo cast5 - [H/pre] + [H samp] + --compress-algo 1 --cipher-algo cast5 + [H /samp] You may also use "3des" instead of "cast5", and "blowfish" does not work with all versions of PGP 5. You may also want to put: - [H pre] - compress-algo 1 - [H/pre] + [H samp] + compress-algo 1 + [H /samp] into your ~/.gnupg/options file - this does not affect normal GnuPG operation. @@ -531,7 +714,7 @@ algorithm is still patented until 2007. Under certain conditions you may use IDEA even today. In that case, you may refer to Question about how to add IDEA support to GnuPG and read - [H a href=http://www.gnupg.org/gph/en/pgp2x.html]http://www.gnupg.org/gph/en/pgp2x.html[H /a] to perform the migration. + [H a href=[$hGPGHTTP]/gph/en/pgp2x.html]<[$hGPGHTTP]/gph/en/pgp2x.html>[H /a] to perform the migration. (removed) @@ -559,9 +742,9 @@ There is a script in the tools directory to help you. After you have imported the PGP keyring you can give this command: - [H pre] - $ lspgpot pgpkeyring | gpg --import-ownertrust - [H /pre] + [H samp] + $ lspgpot pgpkeyring | gpg --import-ownertrust + [H /samp] where pgpkeyring is the original keyring and not the GnuPG keyring you might have created in the first step. @@ -573,9 +756,9 @@ PGP is not really OpenPGP aware. A workaround is to export the secret keys with this command: - [H pre] - $ gpg --export-secret-keys --no-comment -a your-key-id - [H /pre] + [H samp] + $ gpg --export-secret-keys --no-comment -a your-KeyID + [H /samp] Another possibility is this: by default, GnuPG encrypts your secret key using the Blowfish symmetric algorithm. Older PGPs will only @@ -583,10 +766,10 @@ following method you can re-encrypt your secret gpg key with a different algo: - [H pre] - $ gpg --s2k-cipher-algo=CAST5 --s2k-digest-algo=SHA1 \ - --compress-algo=1 --edit-key - [H /pre] + [H samp] + $ gpg --s2k-cipher-algo=CAST5 --s2k-digest-algo=SHA1 + --compress-algo=1 --edit-key + [H /samp] Then use passwd to change the password (just change it to the same thing, but it will encrypt the key with CAST5 this time). @@ -595,10 +778,86 @@ For PGP 6.x the following options work to export a key: - [H pre] - $ gpg --s2k-cipher-algo 3des --compress-algo 1 --rfc1991 \ - --export-secret-keys - [H /pre] + [H samp] + $ gpg --s2k-cipher-algo 3des --compress-algo 1 --rfc1991 + --export-secret-keys + [H /samp] + + + GnuPG no longer installs a ~/.gnupg/options file. Is it missing? + + No. The ~/.gnupg/options file has been renamed to ~/.gnupg/gpg.conf for + new installs as of version 1.1.92. If an existing ~/.gnupg/options file + is found during an upgrade it will still be used, but this change was + required to have a more consistent naming scheme with forthcoming tools. + An existing options file can be renamed to gpg.conf for users upgrading, + or receiving the message that the "old default options file" is ignored + (occurs if both a gpg.conf and an options file are found). + + How do you export GnuPG keys for use with PGP? + + This has come up fairly often, so here's the HOWTO: + + PGP can (for most key types) use secret keys generated by GnuPG. The + problems that come up occasionally are generally because GnuPG + supports a few more features from the OpenPGP standard than PGP does. + If your secret key has any of those features in use, then PGP will + reject the key or you will have problems communicating later. Note + that PGP doesn't do ElGamal signing keys at all, so they are not + usable with any version. + + These instructions should work for GnuPG 1.0.7 and later, and PGP + 7.0.3 and later. + + Start by editing the key. Most of this line is not really necessary + as the default values are correct, but it does not hurt to repeat the + values, as this will override them in case you have something else set + in your options file. + + [H samp] + $ gpg --s2k-cipher-algo cast5 --s2k-digest-algo sha1 --s2k-mode 3 + --simple-sk-checksum --edit KeyID + [H /samp] + + Turn off some features. Set the list of preferred ciphers, hashes, + and compression algorithms to things that PGP can handle. (Yes, I + know this is an odd list of ciphers, but this is what PGP itself uses, + minus IDEA). + + [H samp] + > setpref S9 S8 S7 S3 S2 S10 H2 H3 Z1 Z0 + [H /samp] + + Now put the list of preferences onto the key. + + [H samp] + > updpref + [H /samp] + + Finally we must decrypt and re-encrypt the key, making sure that we + encrypt with a cipher that PGP likes. We set this up in the --edit + line above, so now we just need to change the passphrase to make it + take effect. You can use the same passphrase if you like, or take + this opportunity to actually change it. + + [H samp] + > passwd + [H /samp] + + Save our work. + + [H samp] + > save + [H /samp] + + Now we can do the usual export: + + [H samp] + $ gpg --export KeyID > mypublickey.pgp[H br] + $ gpg --export-secret-key KeyID > mysecretkey.pgp + [H /samp] + + Thanks to David Shaw for this information! PROBLEMS and ERROR MESSAGES @@ -612,28 +871,45 @@ memory your operating system supports locking without being root. The program drops root privileges as soon as locked memory is allocated. + To setuid(root) permissions on the gpg binary you can either use: + + [H samp] + $ chmod u+s /path/to/gpg + [H /samp] + + or + + [H samp] + $ chmod 4755 /path/to/gpg + [H /samp] + + Some refrain from using setuid(root) unless absolutely required for + security reasons. Please check with your system administrator if you + are not able to make these determinations yourself. + On UnixWare 2.x and 7.x you should install GnuPG with the 'plock' privilege to get the same effect: - [H pre] - filepriv -f plock /path/to/gpg - [H /pre] + [H samp] + $ filepriv -f plock /path/to/gpg + [H /samp] If you can't or don't want to install GnuPG setuid(root), you can use the option "--no-secmem-warning" or put: - [H pre] - no-secmem-warning - [H /pre] + [H samp] + no-secmem-warning + [H /samp] - in your ~/.gnupg/options file (this disables the warning). + in your ~/.gnupg/options or ~/.gnupg/gpg.conf file (this disables + the warning). On some systems (e.g., Windows) GnuPG does not lock memory pages and older GnuPG versions (<=1.0.4) issue the warning: - [H pre] - gpg: Please note that you don't have secure memory - [H /pre] + [H samp] + gpg: Please note that you don't have secure memory + [H /samp] This warning can't be switched off by the above option because it was thought to be too serious an issue. However, it confused users @@ -641,14 +917,14 @@ Large File Support doesn't work ... - LFS is correctly working in post-1.0.4 CVS. If configure doesn't - detect it correctly, try a different (i.e., better) compiler. egcs - 1.1.2 works fine, other gccs sometimes don't. BTW, several - compilation problems of GnuPG 1.0.3 and 1.0.4 on HP-UX and Solaris - were due to broken LFS support. + LFS works correctly in post-1.0.4 versions. If configure doesn't + detect it, try a different (i.e., better) compiler. egcs 1.1.2 works + fine, other gccs sometimes don't. BTW, several compilation problems + of GnuPG 1.0.3 and 1.0.4 on HP-UX and Solaris were due to broken LFS + support. - In the edit menu the trust values is not displayed correctly after - signing uids - why? + In the edit menu the trust values are not displayed correctly after + signing uids. Why? This happens because some information is stored immediately in the trustdb, but the actual trust calculation can be done after the @@ -704,25 +980,26 @@ I get "gpg: waiting for lock ..." - A previous gpg has most likely exited abnormally and left a lock - file. Go to ~/.gnupg and look for .*.lock files and remove them. + A previous instance of gpg has most likely exited abnormally and left + a lock file. Go to ~/.gnupg and look for .*.lock files and remove them. - Older gpg's (e.g., 1.0) have problems with keys from newer gpgs ... + Older gpg binaries (e.g., 1.0) have problems with keys from newer + gpg binaries ... As of 1.0.3, keys generated with gpg are created with preferences to TWOFISH (and AES since 1.0.4) and that also means that they have the capability to use the new MDC encryption method. This will go into - OpenPGP soon and is also suppoted by PGP 7. This new method avoids + OpenPGP soon, and is also suppoted by PGP 7. This new method avoids a (not so new) attack on all email encryption systems. - This in turn means that pre-1.0.3 gpg's have problems with newer - keys. Because of security fixes, you should keep your GnuPG - installation in a recent state anyway. As a workaround, you can + This in turn means that pre-1.0.3 gpg binaries have problems with + newer keys. Because of security and bug fixes, you should keep your + GnuPG installation in a recent state anyway. As a workaround, you can force gpg to use a previous default cipher algo by putting: - [H pre] - cipher-algo cast5 - [H /pre] + [H samp] + cipher-algo cast5 + [H /samp] into your options file. @@ -733,10 +1010,10 @@ cipher Rijndael that is incorrectly being referred as "deprecated". Ignore this warning, more recent versions of gpg are corrected. - Some dates are displayed as ????-??-??, why? + Some dates are displayed as ????-??-??. Why? Due to constraints in most libc implementations, dates beyond - 2038-01-19 can't be displayed correctly. 64 bit OSes are not + 2038-01-19 can't be displayed correctly. 64-bit OSes are not affected by this problem. To avoid printing wrong dates, GnuPG instead prints some question marks. To see the correct value, you can use the options --with-colons and --fixed-list-mode. @@ -748,13 +1025,13 @@ the list of reported bugs on the documentation page). If you're not sure about it being a bug, you can send mail to the gnupg-devel list. Otherwise, use the GUUG bug tracking system - [H a href=http://bugs.guug.de/Reporting.html]http://bugs.guug.de/Reporting.html[H /a]. + [H a href=http://bugs.guug.de/Reporting.html][H /a]. - Why doesn't GnuPG support X509 certificates? + Why doesn't GnuPG support X.509 certificates? GnuPG, first and foremost, is an implementation of the OpenPGP standard (RFC 2440), which is a competing infrastructure, different - from X509. + from X.509. They are both public-key cryptosystems, but how the public keys are actually handled is different. @@ -772,11 +1049,11 @@ This will be fixed after GnuPG has been upgraded to autoconf-2.50. Until then, find the line setting CDPATH in the configure script - and place a: + and place an: - [H pre] - unset CDPATH - [H /pre] + [H samp] + unset CDPATH + [H /samp] statement below it. @@ -785,9 +1062,55 @@ There is a small bug in 1.0.6 which didn't parse trust packets correctly. You may want to apply this patch if you can't upgrade: - [H pre] - http://www.gnupg.org/developer/gpg-woody-fix.txt - [H /pre] + [H a href=http://www.gnupg.org/developer/gpg-woody-fix.txt][H /a] + + I upgraded to GnuPG version 1.0.7 and now it takes longer to load my + keyrings. What can I do? + + The way signature states are stored has changed so that v3 signatures + can be supported. You can use the new --rebuild-keydb-caches migration + command, which was built into this release and increases the speed of + many operations for existing keyrings. + + Doesn't a fully trusted user ID on a key prevent warning messages + when encrypting to other IDs on the key? + + No. That was actually a key validity bug in GnuPG 1.2.1 and earlier + versions. As part of the development of GnuPG 1.2.2, a bug was + discovered in the key validation code. This bug causes keys with + more than one user ID to give all user IDs on the key the amount of + validity given to the most-valid key. The bug has been fixed in GnuPG + release 1.2.2, and upgrading is the recommended fix for this problem. + More information and a patch for a some pre-1.2.2 versions of GnuPG + can be found at: + + [H a href=http://lists.gnupg.org/pipermail/gnupg-announce/2003q2/000268.html][H /a] + + I just compiled GnuPG from source on my GNU/Linux RPM-based system + and it's not working. Why? + + Many GNU/Linux distributions that are RPM-based will install a + version of GnuPG as part of its standard installation, placing the + binaries in the /usr/bin directory. Later, compiling and installing + GnuPG from source other than from a source RPM won't normally + overwrite these files, as the default location for placement of + GnuPG binaries is in /usr/local/bin unless the '--prefix' switch + is used during compile to specify an alternate location. Since the + /usr/bin directory more than likely appears in your path before + /usr/local/bin, the older RPM-version binaries will continue to + be used when called since they were not replaced. + + To resolve this, uninstall the RPM-based version with 'rpm -e gnupg' + before installing the binaries compiled from source. If dependency + errors are displayed when attempting to uninstall the RPM (such as + when Red Hat's up2date is also installed, which uses GnuPG), uninstall + the RPM with 'rpm -e gnupg --nodeps' to force the uninstall. Any + dependent files should be automatically replaced during the install + of the compiled version. If the default /usr/local/bin directory is + used, some packages such as SuSE's Yast Online Update may need to be + configured to look for GnuPG binaries in the /usr/local/bin directory, + or symlinks can be created in /usr/bin that point to the binaries + located in /usr/local/bin. ADVANCED TOPICS @@ -796,9 +1119,9 @@ To generate a secret/public keypair, run: - [H pre] - gpg --gen-key - [H/pre] + [H samp] + $ gpg --gen-key + [H /samp] and choose the default values. @@ -811,7 +1134,7 @@ having the secret key and putting in the password to use his secret key. - GnuPG is also useful for signing things. Things that are encrypted + GnuPG is also useful for signing things. Files that are encrypted with the secret key can be decrypted with the public key. To sign something, a hash is taken of the data, and then the hash is in some form encoded with the secret key. If someone has your public key, they @@ -845,16 +1168,16 @@ person it says it comes from. You should be very sure that is really that person: You should verify the key fingerprint with: - [H pre] - gpg --fingerprint user-id - [H/pre] - - over the phone (if you really know the voice of the other person), at a - key signing party (which are often held at computer conferences), or at - a meeting of your local GNU/Linux User Group. + [H samp] + $ gpg --fingerprint KeyID + [H /samp] + + over the phone (if you really know the voice of the other person), at + a key signing party (which are often held at computer conferences), + or at a meeting of your local GNU/Linux User Group. - Hmm, what else. You may use the option "-o filename" to force output - to this filename (use "-" to force output to stdout). "-r" just lets + Hmm, what else. You may use the option '-o filename' to force output + to this filename (use '-' to force output to stdout). '-r' just lets you specify the recipient (which public key you encrypt with) on the command line instead of typing it interactively. @@ -888,45 +1211,45 @@ You can see the validity (calculated trust value) using this command. - [H pre] - gpg --list-keys --with-colons - [H/pre] + [H samp] + $ gpg --list-keys --with-colons + [H /samp] If the first field is "pub" or "uid", the second field shows you the trust: [H pre] - o = Unknown (this key is new to the system) - e = The key has expired - q = Undefined (no value assigned) - n = Don't trust this key at all - m = There is marginal trust in this key - f = The key is full trusted - u = The key is ultimately trusted; this is only used - for keys for which the secret key is also available. - r = The key has been revoked - d = The key has been disabled - [H/pre] + o = Unknown (this key is new to the system) + e = The key has expired + q = Undefined (no value assigned) + n = Don't trust this key at all + m = There is marginal trust in this key + f = The key is full trusted + u = The key is ultimately trusted; this is only used + for keys for which the secret key is also available. + r = The key has been revoked + d = The key has been disabled + [H /pre] The value in the "pub" record is the best one of all "uid" records. You can get a list of the assigned trust values (how much you trust the owner to correctly sign another person's key) with: - [H pre] - gpg --list-ownertrust - [H/pre] + [H samp] + $ gpg --list-ownertrust + [H /samp] The first field is the fingerprint of the primary key, the second field is the assigned value: [H pre] - - = No Ownertrust value yet assigned. - n = Never trust this keyholder to correctly verify others signatures. - m = Have marginal trust in the keyholders capability to sign other - keys. - f = Assume that the key holder really knows how to sign keys. - u = No need to trust ourself because we have the secret key. - [H/pre] + - = No ownertrust value yet assigned or calculated. + n = Never trust this keyholder to correctly verify others signatures. + m = Have marginal trust in the keyholders capability to sign other + keys. + f = Assume that the key holder really knows how to sign keys. + u = No need to trust ourself because we have the secret key. + [H /pre] Keep these values confidential because they express your opinions about others. PGP stores this information with the keyring thus it @@ -947,24 +1270,24 @@ information which is prefixed with information about the checked item. - [H pre] - "key 12345678.3456" - [H/pre] + [H samp] + "key 12345678.3456" + [H /samp] This is about the key with key ID 12345678 and the internal number 3456, which is the record number of the so called directory record in the trustdb. - [H pre] - "uid 12345678.3456/ACDE" - [H/pre] + [H samp] + "uid 12345678.3456/ACDE" + [H /samp] This is about the user ID for the same key. To identify the user ID the last two bytes of a ripe-md-160 over the user ID ring is printed. - [H pre] - "sig 12345678.3456/ACDE/9A8B7C6D" - [H/pre] + [H samp] + "sig 12345678.3456/ACDE/9A8B7C6D" + [H /samp] This is about the signature with key ID 9A8B7C6D for the above key and user ID, if it is a signature which is direct on a key, the user @@ -1003,17 +1326,17 @@ ACKNOWLEDGEMENTS Many thanks to Nils Ellmenreich for maintaining this FAQ file for - a long time, Werner Koch for the original FAQ file, and to all - posters to gnupg-users and gnupg-devel. They all provided most - of the answers. + such a long time, Werner Koch for the original FAQ file, and to all + posters to gnupg-users and gnupg-devel. They all provided most of + the answers. Also thanks to Casper Dik for providing us with a script to generate this FAQ (he uses it for the excellent Solaris2 FAQ). -[H HR] +[H hr] -Copyright (C) 2000-2002 Free Software Foundation, Inc., +Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA Verbatim copying and distribution of this entire article is permitted in -any medium, provided this notice is preserved. +any medium, provided this notice is preserved. \ No newline at end of file Index: gnupg/g10/ChangeLog diff -u gnupg/g10/ChangeLog:1.688 gnupg/g10/ChangeLog:1.689 --- gnupg/g10/ChangeLog:1.688 Wed Jan 26 22:20:30 2005 +++ gnupg/g10/ChangeLog Thu Jan 27 11:30:27 2005 @@ -1,3 +1,9 @@ +2005-01-26 Werner Koch + + * ccid-driver.c (parse_ccid_descriptor): Need the CSM workaround + also for newer firmware versions. Need to get a list of fixed + firmware versions and use that. + 2005-01-26 David Shaw * keyserver.c (parse_keyserver_uri): Allow RFC-2732 IPv6 [literal @@ -11135,7 +11141,7 @@ Copyright 1998, 1999, 2000, 2001, 2002, 2003, - 2004 Free Software Foundation, Inc. + 2004, 2005 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 Index: gnupg/g10/ccid-driver.c diff -u gnupg/g10/ccid-driver.c:1.20 gnupg/g10/ccid-driver.c:1.21 --- gnupg/g10/ccid-driver.c:1.20 Tue Dec 28 08:30:57 2004 +++ gnupg/g10/ccid-driver.c Thu Jan 27 11:30:27 2005 @@ -52,7 +52,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: ccid-driver.c,v 1.20 2004/12/28 07:30:57 wk Exp $ + * $Id: ccid-driver.c,v 1.21 2005/01/27 10:30:27 wk Exp $ */ @@ -450,7 +450,7 @@ if (handle->id_vendor == VENDOR_SCM /* FIXME: check whether it is the same firmware version for all drivers. */ - && handle->bcd_device < 0x0513 + && handle->bcd_device < 0x0519 && handle->max_ifsd > 48) { DEBUGOUT ("enabling workaround for buggy SCM readers\n"); From cvs at cvs.gnupg.org Fri Jan 28 17:05:44 2005 From: cvs at cvs.gnupg.org (cvs user stefan) Date: Fri Jan 28 17:05:49 2005 Subject: gnupgjava/src/java/com/freiheit/gnupg (1 file) Message-ID: Date: Friday, January 28, 2005 @ 17:05:44 Author: stefan Path: /cvs/gnupg/gnupgjava/src/java/com/freiheit/gnupg Modified: GnuPGPassphraseWindow.java Parent-JFrame was disposed when used with PassphraseWindow ----------------------------+ GnuPGPassphraseWindow.java | 13 ++++++++++--- 1 files changed, 10 insertions(+), 3 deletions(-) From cvs at cvs.gnupg.org Fri Jan 28 17:06:37 2005 From: cvs at cvs.gnupg.org (cvs user stefan) Date: Fri Jan 28 17:06:42 2005 Subject: gnupgjava/src/c (GnuPGKey.c) Message-ID: Date: Friday, January 28, 2005 @ 17:06:37 Author: stefan Path: /cvs/gnupg/gnupgjava/src/c Modified: GnuPGKey.c native method to get uid was not implemented ------------+ GnuPGKey.c | 7 +++++++ 1 files changed, 7 insertions(+) From cvs at cvs.gnupg.org Fri Jan 28 20:48:30 2005 From: cvs at cvs.gnupg.org (cvs user mo) Date: Fri Jan 28 20:48:44 2005 Subject: GNUPG-1-9-BRANCH gnupg/agent (ChangeLog command-ssh.c) Message-ID: Date: Friday, January 28, 2005 @ 20:57:14 Author: mo Path: /cvs/gnupg/gnupg/agent Tag: GNUPG-1-9-BRANCH Modified: ChangeLog command-ssh.c 2005-01-28 Moritz Schulte * command-ssh.c (ssh_handler_add_identity): Pass ctrl to ssh_identity_register(). (ssh_identity_register): New argument: ctrl; pass ctrl to get_passphrase(). (get_passphrase): Pass ctrl instead of NULL to agent_askpin(). (start_command_handler_ssh): Use agent_init_default_ctrl(); deallocate structure members, which might be dynamically allocated. (lifetime_default): Removed variable. (ssh_handler_add_identity): Fix ttl handling; renamed variable `death' to `ttl'. (ssh_identity_register): Fix key grip handling. ---------------+ ChangeLog | 15 +++++++++++++++ command-ssh.c | 38 ++++++++++++++++++++++---------------- 2 files changed, 37 insertions(+), 16 deletions(-) Index: gnupg/agent/ChangeLog diff -u gnupg/agent/ChangeLog:1.59.2.58 gnupg/agent/ChangeLog:1.59.2.59 --- gnupg/agent/ChangeLog:1.59.2.58 Wed Jan 26 23:33:11 2005 +++ gnupg/agent/ChangeLog Fri Jan 28 20:57:14 2005 @@ -1,3 +1,18 @@ +2005-01-28 Moritz Schulte + + * command-ssh.c (ssh_handler_add_identity): Pass ctrl to + ssh_identity_register(). + (ssh_identity_register): New argument: ctrl; pass ctrl to + get_passphrase(). + (get_passphrase): Pass ctrl instead of NULL to agent_askpin(). + (start_command_handler_ssh): Use agent_init_default_ctrl(); + deallocate structure members, which might be dynamically + allocated. + (lifetime_default): Removed variable. + (ssh_handler_add_identity): Fix ttl handling; renamed variable + `death' to `ttl'. + (ssh_identity_register): Fix key grip handling. + 2005-01-26 Moritz Schulte * command-ssh.c (ssh_handler_sign_request): Confirm to agent Index: gnupg/agent/command-ssh.c diff -u gnupg/agent/command-ssh.c:1.1.4.2 gnupg/agent/command-ssh.c:1.1.4.3 --- gnupg/agent/command-ssh.c:1.1.4.2 Wed Jan 26 23:33:11 2005 +++ gnupg/agent/command-ssh.c Fri Jan 28 20:57:14 2005 @@ -94,8 +94,6 @@ -static uint32_t lifetime_default; - /* General utility functions. */ static void * @@ -1725,7 +1723,8 @@ } static gpg_error_t -get_passphrase (const char *description, size_t passphrase_n, char *passphrase) +get_passphrase (ctrl_t ctrl, + const char *description, size_t passphrase_n, char *passphrase) { struct pin_entry_info_s *pi; gpg_error_t err; @@ -1747,7 +1746,7 @@ pi->cb_errtext = NULL; pi->max_length = 100; - err = agent_askpin (NULL, description, NULL, pi); + err = agent_askpin (ctrl, description, NULL, pi); if (err) goto out; @@ -1851,7 +1850,7 @@ } static gpg_error_t -ssh_identity_register (gcry_sexp_t key, int ttl) +ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl) { unsigned char key_grip_raw[21]; unsigned char *buffer; @@ -1862,11 +1861,11 @@ char key_grip[41]; char *comment; gpg_error_t err; - + unsigned int i; int ret; if (DBG_COMMAND) - log_debug ("[ssh-agent] registering identity `%s'\n", key_grip); + log_debug ("[ssh-agent] registering identity\n"); description = NULL; comment = NULL; @@ -1898,7 +1897,7 @@ "for protecting the received secret key `%s':", comment ? comment : ""); - err = get_passphrase (description, sizeof (passphrase), passphrase); + err = get_passphrase (ctrl, description, sizeof (passphrase), passphrase); if (err) goto out; @@ -1910,7 +1909,10 @@ if (err) goto out; - err = agent_put_cache (key_grip_raw, passphrase, ttl); + for (i = 0; i < 20; i++) + sprintf (key_grip + 2 * i, "%02X", key_grip_raw[i]); + + err = agent_put_cache (key_grip, passphrase, ttl); if (err) goto out; @@ -1954,15 +1956,15 @@ gcry_sexp_t key; byte_t b; int confirm; - int death; + int ttl; int bad; if (DBG_COMMAND) log_debug ("[ssh-agent] add identity\n"); confirm = 0; - death = 0; key = NULL; + ttl = 0; bad = 0; /* FIXME? */ @@ -1990,7 +1992,7 @@ err = es_read_uint32 (request, &n); if (! err) - death = time (NULL) + n; + ttl = n; break; } @@ -2008,12 +2010,9 @@ if (err) goto out; - if (lifetime_default && (! death)) - death = time (NULL) + lifetime_default; - /* FIXME: are constraints used correctly? */ - err = ssh_identity_register (key, death); + err = ssh_identity_register (ctrl, key, ttl); out: @@ -2217,6 +2216,7 @@ log_debug ("[ssh-agent] Starting command handler\n"); memset (&ctrl, 0, sizeof (ctrl)); + agent_init_default_ctrl (&ctrl); ctrl.connection_fd = sock_client; stream_response = NULL; @@ -2324,4 +2324,10 @@ if (DBG_COMMAND) log_debug ("[ssh-agent] Leaving ssh command handler: %s\n", gpg_strerror (err)); + + free (ctrl.display); + free (ctrl.ttyname); + free (ctrl.ttytype); + free (ctrl.lc_ctype); + free (ctrl.lc_messages); } From cvs at cvs.gnupg.org Sat Jan 29 23:34:10 2005 From: cvs at cvs.gnupg.org (cvs user mo) Date: Sat Jan 29 23:34:18 2005 Subject: GNUPG-1-9-BRANCH gnupg/agent (ChangeLog command-ssh.c) Message-ID: Date: Saturday, January 29, 2005 @ 23:43:00 Author: mo Path: /cvs/gnupg/gnupg/agent Tag: GNUPG-1-9-BRANCH Modified: ChangeLog command-ssh.c 2005-01-29 Moritz Schulte * command-ssh.c (ssh_handler_request_identities) (ssh_handler_sign_request, ssh_handler_add_identity) (ssh_handler_remove_identity, ssh_handler_remove_all_identities) (ssh_handler_lock, ssh_handler_unlock): Changed to return an error code instead of a boolean. (ssh_request_process): Changed to return a boolean instead of an error; adjust caller. (ssh_request_handle_t): Adjusted type. (ssh_request_spec): New member: identifier. (REQUEST_SPEC_DEFINE): New macro; use it for initialization of request_specs[]. (ssh_request_process): In debugging mode, log identifier of handler to execute. (start_command_handler_ssh): Moved most of the stream handling code ... (ssh_request_process): ... here. ---------------+ ChangeLog | 19 ++ command-ssh.c | 435 ++++++++++++++++++++++++++++---------------------------- 2 files changed, 240 insertions(+), 214 deletions(-) Index: gnupg/agent/ChangeLog diff -u gnupg/agent/ChangeLog:1.59.2.59 gnupg/agent/ChangeLog:1.59.2.60 --- gnupg/agent/ChangeLog:1.59.2.59 Fri Jan 28 20:57:14 2005 +++ gnupg/agent/ChangeLog Sat Jan 29 23:43:00 2005 @@ -1,3 +1,22 @@ +2005-01-29 Moritz Schulte + + * command-ssh.c (ssh_handler_request_identities) + (ssh_handler_sign_request, ssh_handler_add_identity) + (ssh_handler_remove_identity, ssh_handler_remove_all_identities) + (ssh_handler_lock, ssh_handler_unlock): Changed to return an error + code instead of a boolean. + (ssh_request_process): Changed to return a boolean instead of an + error; adjust caller. + (ssh_request_handle_t): Adjusted type. + (ssh_request_spec): New member: identifier. + (REQUEST_SPEC_DEFINE): New macro; use it for initialization of + request_specs[]. + (ssh_request_process): In debugging mode, log identifier of + handler to execute. + (start_command_handler_ssh): Moved most of the stream handling + code ... + (ssh_request_process): ... here. + 2005-01-28 Moritz Schulte * command-ssh.c (ssh_handler_add_identity): Pass ctrl to Index: gnupg/agent/command-ssh.c diff -u gnupg/agent/command-ssh.c:1.1.4.3 gnupg/agent/command-ssh.c:1.1.4.4 --- gnupg/agent/command-ssh.c:1.1.4.3 Fri Jan 28 20:57:14 2005 +++ gnupg/agent/command-ssh.c Sat Jan 29 23:43:00 2005 @@ -19,6 +19,8 @@ * 02111-1307, USA */ +/* Only v2 of the ssh-agent protocol is implemented. */ + #include #include #include @@ -65,13 +67,15 @@ /* A "byte". */ typedef unsigned char byte_t; -typedef int (*ssh_request_handler_t) (ctrl_t ctrl, - estream_t request, estream_t response); +typedef gpg_error_t (*ssh_request_handler_t) (ctrl_t ctrl, + estream_t request, + estream_t response); typedef struct ssh_request_spec { byte_t type; ssh_request_handler_t handler; + const char *identifier; } ssh_request_spec_t; typedef gpg_error_t (*ssh_key_modifier_t) (const char *elems, gcry_mpi_t *mpis); @@ -105,7 +109,7 @@ p = gcry_realloc (a, n); else p = gcry_malloc_secure (n); - + return p; } @@ -1283,7 +1287,7 @@ /* Request handler. */ -static int +static gpg_error_t ssh_handler_request_identities (ctrl_t ctrl, estream_t request, estream_t response) { const char *key_type; @@ -1300,11 +1304,8 @@ gcry_sexp_t key_public; DIR *dir; gpg_error_t err; + gpg_error_t ret_err; int ret; - int bad; - - if (DBG_COMMAND) - log_debug ("[ssh-agent] request identities\n"); /* Prepare buffer stream. */ @@ -1316,7 +1317,6 @@ key_counter = 0; buffer = NULL; dir = NULL; - bad = 0; err = 0; key_blobs = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+"); @@ -1426,11 +1426,25 @@ gcry_sexp_release (key_secret); gcry_sexp_release (key_public); - es_write_byte (response, SSH_RESPONSE_IDENTITIES_ANSWER); - if (! es_ferror (response)) - es_write_uint32 (response, err ? 0 : key_counter); - if (! (err || es_ferror (response))) - es_copy (response, key_blobs); + if (! err) + { + ret_err = es_write_byte (response, SSH_RESPONSE_IDENTITIES_ANSWER); + if (ret_err) + goto leave; + ret_err = es_write_uint32 (response, key_counter); + if (ret_err) + goto leave; + ret_err = es_copy (response, key_blobs); + if (ret_err) + goto leave; + } + else + { + ret_err = es_write_byte (response, SSH_RESPONSE_FAILURE); + goto leave; + }; + + leave: if (key_blobs) es_fclose (key_blobs); @@ -1442,7 +1456,7 @@ xfree (buffer); xfree ((void *) key_type); /* FIXME? */ - return bad; + return ret_err; } static gpg_error_t @@ -1609,7 +1623,7 @@ return err; } -static int +static gpg_error_t ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response) { gcry_sexp_t key; @@ -1626,48 +1640,32 @@ uint32_t flags; const void *p; gpg_error_t err; - int bad; + gpg_error_t ret_err; key_blob = NULL; data = NULL; sig = NULL; key = NULL; - bad = 0; - - if (DBG_COMMAND) - log_debug ("[ssh-agent] sign request\n"); /* Receive key. */ err = es_read_string (request, 0, &key_blob, &key_blob_size); if (err) - { - bad = 1; - goto out; - } + goto out; err = ssh_read_key_public_from_blob (key_blob, key_blob_size, &key, &spec); if (err) - { - bad = 1; - goto out; - } + goto out; /* Receive data to sign. */ err = es_read_string (request, 0, &data, &data_size); if (err) - { - bad = 1; - goto out; - } + goto out; /* FIXME? */ err = es_read_uint32 (request, &flags); if (err) - { - bad = 1; - goto out; - } + goto out; /* Hash data. */ hash_n = gcry_md_get_algo_dlen (GCRY_MD_SHA1); @@ -1701,25 +1699,32 @@ out: - if (! bad) + /* Done. */ + + if (! err) { - /* Done. */ - if (! err) - { - es_write_byte (response, SSH_RESPONSE_SIGN_RESPONSE); - if (! es_ferror (response)) - es_write_string (response, sig, sig_n); - } - else - es_write_byte (response, SSH_RESPONSE_FAILURE); + ret_err = es_write_byte (response, SSH_RESPONSE_SIGN_RESPONSE); + if (ret_err) + goto leave; + ret_err = es_write_string (response, sig, sig_n); + if (ret_err) + goto leave; + } + else + { + ret_err = es_write_byte (response, SSH_RESPONSE_FAILURE); + if (ret_err) + goto leave; } + leave: + gcry_sexp_release (key); xfree (key_blob); xfree (data); xfree (sig); - return bad; + return ret_err; } static gpg_error_t @@ -1864,9 +1869,6 @@ unsigned int i; int ret; - if (DBG_COMMAND) - log_debug ("[ssh-agent] registering identity\n"); - description = NULL; comment = NULL; buffer = NULL; @@ -1941,39 +1943,29 @@ /* FIXME: What to do here - forgetting the passphrase or deleting the key from key cache? */ - if (DBG_COMMAND) - log_debug ("[ssh-agent] dropping identity `%s'\n", key_grip); - out: return err; } -static int +static gpg_error_t ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response) { + gpg_error_t ret_err; gpg_error_t err; gcry_sexp_t key; byte_t b; int confirm; int ttl; - int bad; - if (DBG_COMMAND) - log_debug ("[ssh-agent] add identity\n"); - confirm = 0; key = NULL; ttl = 0; - bad = 0; /* FIXME? */ err = ssh_receive_key (request, &key, 1, 1, NULL); if (err) - { - bad = 1; - goto out; - } + goto out; while (1) { @@ -2018,43 +2010,33 @@ gcry_sexp_release (key); - if (! bad) - es_write_byte (response, err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); + ret_err = es_write_byte (response, + err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); - return bad; + return ret_err; } -static int +static gpg_error_t ssh_handler_remove_identity (ctrl_t ctrl, estream_t request, estream_t response) { unsigned char *key_blob; uint32_t key_blob_size; gcry_sexp_t key; + gpg_error_t ret_err; gpg_error_t err; - int bad; /* Receive key. */ - if (DBG_COMMAND) - log_debug ("[ssh-agent] remove identity\n"); - key_blob = NULL; key = NULL; - bad = 0; err = es_read_string (request, 0, &key_blob, &key_blob_size); if (err) - { - bad = 1; - goto out; - } + goto out; err = ssh_read_key_public_from_blob (key_blob, key_blob_size, &key, NULL); if (err) - { - bad = 1; - goto out; - } + goto out; err = ssh_identity_drop (key); @@ -2063,10 +2045,10 @@ xfree (key_blob); gcry_sexp_release (key); - if (! bad) - es_write_byte (response, err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); + ret_err = es_write_byte (response, + err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); - return bad; + return ret_err; } static gpg_error_t @@ -2074,9 +2056,6 @@ { gpg_error_t err; - if (DBG_COMMAND) - log_debug ("[ssh-agent] remove all identities\n"); - err = 0; /* FIXME: shall we remove _all_ cache entries or only those @@ -2085,15 +2064,17 @@ return err; } -static int +static gpg_error_t ssh_handler_remove_all_identities (ctrl_t ctrl, estream_t request, estream_t response) { + gpg_error_t ret_err; gpg_error_t err; err = ssh_identities_remove_all (); - es_write_byte (response, err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); + ret_err = es_write_byte (response, + err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); - return 0; + return ret_err; } static gpg_error_t @@ -2101,9 +2082,8 @@ { gpg_error_t err; - if (DBG_COMMAND) - log_debug ("[ssh-agent] lock\n"); - + /* FIXME */ + log_error ("[gpg-agent/ssh] lock command is not implemented\n"); err = 0; return err; @@ -2114,34 +2094,36 @@ { gpg_error_t err; - if (DBG_COMMAND) - log_debug ("[ssh-agent] unlock\n"); - + log_error ("[gpg-agent/ssh] unlock command is not implemented\n"); err = 0; return err; } -static int +static gpg_error_t ssh_handler_lock (ctrl_t ctrl, estream_t request, estream_t response) { + gpg_error_t ret_err; gpg_error_t err; err = ssh_lock (); - es_write_byte (response, err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); + ret_err = es_write_byte (response, + err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); - return 0; + return ret_err; } -static int +static gpg_error_t ssh_handler_unlock (ctrl_t ctrl, estream_t request, estream_t response) { + gpg_error_t ret_err; gpg_error_t err; - err = ssh_unlock (); - es_write_byte (response, err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); + err = ssh_unlock (); + ret_err = es_write_byte (response, + err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); - return 0; + return ret_err; } @@ -2149,181 +2131,206 @@ /* Associating request types with the corresponding request handlers. */ +#define REQUEST_SPEC_DEFINE(id, name) \ + { SSH_REQUEST_##id, ssh_handler_##name, #name } + static ssh_request_spec_t request_specs[] = { - { SSH_REQUEST_REQUEST_IDENTITIES, ssh_handler_request_identities }, - { SSH_REQUEST_SIGN_REQUEST, ssh_handler_sign_request }, - { SSH_REQUEST_ADD_IDENTITY, ssh_handler_add_identity }, - { SSH_REQUEST_ADD_ID_CONSTRAINED, ssh_handler_add_identity }, - { SSH_REQUEST_REMOVE_IDENTITY, ssh_handler_remove_identity }, - { SSH_REQUEST_REMOVE_ALL_IDENTITIES, ssh_handler_remove_all_identities }, - { SSH_REQUEST_LOCK, ssh_handler_lock }, - { SSH_REQUEST_UNLOCK, ssh_handler_unlock }, + REQUEST_SPEC_DEFINE (REQUEST_IDENTITIES, request_identities), + REQUEST_SPEC_DEFINE (SIGN_REQUEST, sign_request), + REQUEST_SPEC_DEFINE (ADD_IDENTITY, add_identity), + REQUEST_SPEC_DEFINE (ADD_ID_CONSTRAINED, add_identity), + REQUEST_SPEC_DEFINE (REMOVE_IDENTITY, remove_identity), + REQUEST_SPEC_DEFINE (REMOVE_ALL_IDENTITIES, remove_all_identities), + REQUEST_SPEC_DEFINE (LOCK, lock), + REQUEST_SPEC_DEFINE (UNLOCK, unlock) }; -static gpg_error_t -ssh_request_process (ctrl_t ctrl, estream_t request, estream_t response) +static int +ssh_request_process (ctrl_t ctrl, estream_t stream_sock) { + estream_t response; + estream_t request; byte_t request_type; gpg_error_t err; unsigned int i; - int bad; + int send_err; + int ret; + unsigned char *request_data; + uint32_t request_data_size; + uint32_t response_size; - err = es_read_byte (request, &request_type); + request_data = NULL; + response = NULL; + request = NULL; + send_err = 0; + + /* Create memory streams for request/response data. The entire + request will be stored in secure memory, since it might contain + secret key material. The response does not have to be stored in + secure memory, since we never give out secret keys. */ + + /* Retrieve request. */ + err = es_read_string (stream_sock, 1, &request_data, &request_data_size); + if (err) + goto out; + + if (opt.verbose) + log_debug ("[gpg-agent/ssh] Received request of length: %u\n", + request_data_size); + + request = es_mopen (NULL, 0, 0, 1, realloc_secure, gcry_free, "r+"); + if (! request) + { + err = gpg_error_from_errno (errno); + goto out; + } + ret = es_setvbuf (request, NULL, _IONBF, 0); + if (ret) + { + err = gpg_error_from_errno (errno); + goto out; + } + err = es_write_data (request, request_data, request_data_size); if (err) goto out; + es_rewind (request); - if (DBG_COMMAND) - log_debug ("[ssh-agent] request: %u\n", request_type); + response = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+"); + if (! response) + { + err = gpg_error_from_errno (errno); + goto out; + } + + err = es_read_byte (request, &request_type); + if (err) + { + send_err = 1; + goto out; + } for (i = 0; i < DIM (request_specs); i++) if (request_specs[i].type == request_type) break; if (i == DIM (request_specs)) { - err = es_write_byte (response, SSH_RESPONSE_FAILURE); + log_debug ("[gpg-agent/ssh] request %u is not supported\n", + request_type); + send_err = 1; goto out; } - - bad = (*request_specs[i].handler) (ctrl, request, response); - if (bad) - err = GPG_ERR_PROTOCOL_VIOLATION; + if (opt.verbose) + log_debug ("[gpg-agent/ssh] Executing request handler: %s (%u)\n", + request_specs[i].identifier, request_specs[i].type); + + err = (*request_specs[i].handler) (ctrl, request, response); + if (err) + { + send_err = 1; + goto out; + } + + response_size = es_ftell (response); + err = es_fseek (response, 0, SEEK_SET); + if (err) + { + send_err = 1; + goto out; + } + + err = es_write_uint32 (stream_sock, response_size); + if (err) + { + send_err = 1; + goto out; + } + + err = es_copy (stream_sock, response); + if (err) + goto out; + + err = es_fflush (stream_sock); + if (err) + goto out; out: - return err; + if (err && es_feof (stream_sock)) + log_error ("[gpg-agent/ssh] Error occured while processing request: %s\n", + gpg_strerror (err)); + + if (send_err) + { + err = es_write_uint32 (stream_sock, 1); + if (err) + goto leave; + err = es_write_byte (stream_sock, SSH_RESPONSE_FAILURE); + if (err) + goto leave; + } + + leave: + + if (request) + es_fclose (request); + if (response) + es_fclose (response); + xfree (request_data); /* FIXME? */ + + return !! err; } void start_command_handler_ssh (int sock_client) { struct server_control_s ctrl; - gpg_error_t err; - estream_t stream_response; - estream_t stream_request; estream_t stream_sock; - unsigned char *request; - uint32_t request_size; - size_t size; + gpg_error_t err; + int bad; int ret; /* Setup control structure. */ - if (DBG_COMMAND) - log_debug ("[ssh-agent] Starting command handler\n"); - memset (&ctrl, 0, sizeof (ctrl)); agent_init_default_ctrl (&ctrl); ctrl.connection_fd = sock_client; - stream_response = NULL; - stream_request = NULL; - stream_sock = NULL; - request = NULL; - + /* Create stream from socket. */ stream_sock = es_fdopen (sock_client, "r+"); if (! stream_sock) { err = gpg_error_from_errno (errno); + log_error ("[gpg-agent/ssh] Failed to create stream from socket: %s\n", + gpg_strerror (err)); goto out; } + /* We have to disable the estream buffering, because the estream + core doesn't know about secure memory. */ ret = es_setvbuf (stream_sock, NULL, _IONBF, 0); if (ret) { err = gpg_error_from_errno (errno); + log_error ("[gpg-agent/ssh] Failed to disable buffering " + "on socket stream: %s\n", gpg_strerror (err)); goto out; } while (1) { - /* Create memory streams for request/response data. The entire - request will be stored in secure memory, since it might - contain secret key material. The response does not have to - be stored in secure memory, since we never give out secret - keys. FIXME: wrong place. */ - - /* Retrieve request. */ - err = es_read_string (stream_sock, 1, &request, &request_size); - if (err) - break; - - if (DBG_COMMAND) - log_debug ("[ssh-agent] Received request of length: %u\n", - request_size); - - stream_request = es_mopen (NULL, 0, 0, 1, - realloc_secure, gcry_free, "r+"); - if (! stream_request) - { - err = gpg_error_from_errno (errno); - break; - } - ret = es_setvbuf (stream_request, NULL, _IONBF, 0); - if (ret) - { - err = gpg_error_from_errno (errno); - break; - } - err = es_write_data (stream_request, request, request_size); - if (err) - break; - es_rewind (stream_request); - - stream_response = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+"); - if (! stream_response) - { - err = gpg_error_from_errno (errno); - break; - } - /* Process request. */ - err = ssh_request_process (&ctrl, stream_request, stream_response); - if (err) - break; - - /* Figure out size of response data. */ - size = es_ftell (stream_response); - err = es_fseek (stream_response, 0, SEEK_SET); - if (err) + bad = ssh_request_process (&ctrl, stream_sock); + if (bad) break; - - /* Write response data to socket stream. */ - err = es_write_uint32 (stream_sock, size); - if (err) - break; - err = es_copy (stream_sock, stream_response); - if (err) - break; - - err = es_fflush (stream_sock); - if (err) - break; - - es_fclose (stream_request); - stream_request = NULL; - es_fclose (stream_response); - stream_response = NULL; - xfree (request); - request = NULL; }; out: - /* FIXME: logging. */ - if (stream_sock) es_fclose (stream_sock); - if (stream_request) - es_fclose (stream_request); - if (stream_response) - es_fclose (stream_response); - xfree (request); /* FIXME? */ - - if (DBG_COMMAND) - log_debug ("[ssh-agent] Leaving ssh command handler: %s\n", gpg_strerror (err)); free (ctrl.display); free (ctrl.ttyname);