diff --git a/common/estream-printf.c b/common/estream-printf.c index 848ff0301..e50eb7c05 100644 --- a/common/estream-printf.c +++ b/common/estream-printf.c @@ -1,1837 +1,1853 @@ /* estream-printf.c - Versatile mostly C-99 compliant printf formatting - * Copyright (C) 2007, 2008, 2009, 2010 g10 Code GmbH + * Copyright (C) 2007, 2008, 2009, 2010, 2012 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 * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Libestream; if not, see <http://www.gnu.org/licenses/>. * * ALTERNATIVELY, Libestream may be distributed under the terms of the * following license, in which case the provisions of this license are * required INSTEAD OF the GNU General Public License. If you wish to * allow use of your version of this file only under the terms of the * GNU General Public License, and not to allow others to use your * version of this file under the terms of the following license, * indicate your decision by deleting this paragraph and the license * below. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, and the entire permission notice in its entirety, * including the disclaimer of warranties. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ /* Required autoconf tests: AC_TYPE_LONG_LONG_INT defines HAVE_LONG_LONG_INT AC_TYPE_LONG_DOUBLE defines HAVE_LONG_DOUBLE AC_TYPE_INTMAX_T defines HAVE_INTMAX_T AC_TYPE_UINTMAX_T defines HAVE_UINTMAX_T AC_CHECK_TYPES([ptrdiff_t]) defines HAVE_PTRDIFF_T AC_CHECK_SIZEOF([unsigned long]) defines SIZEOF_UNSIGNED_LONG AC_CHECK_SIZEOF([void *]) defines SIZEOF_VOID_P HAVE_LANGINFO_THOUSANDS_SEP Note that the file estream.m4 provides the autoconf macro ESTREAM_PRINTF_INIT which runs all required checks. See estream-printf.h for ways to tune this code. Missing stuff: wchar and wint_t thousands_sep in pr_float. */ #ifdef HAVE_CONFIG_H # include <config.h> #endif #if defined(_WIN32) && !defined(HAVE_W32_SYSTEM) # define HAVE_W32_SYSTEM 1 # if defined(__MINGW32CE__) && !defined (HAVE_W32CE_SYSTEM) # define HAVE_W32CE_SYSTEM # endif #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <stdarg.h> #include <errno.h> #include <stddef.h> #include <assert.h> #if defined(HAVE_INTMAX_T) || defined(HAVE_UINTMAX_T) # ifdef HAVE_STDINT_H # include <stdint.h> # endif #endif #ifdef HAVE_LANGINFO_THOUSANDS_SEP #include <langinfo.h> #endif #ifdef HAVE_W32CE_SYSTEM #include <gpg-error.h> /* ERRNO replacement. */ #endif #ifdef _ESTREAM_PRINTF_EXTRA_INCLUDE # include _ESTREAM_PRINTF_EXTRA_INCLUDE #endif #include "estream-printf.h" /* #define DEBUG 1 */ -/* Allow redefinition of asprintf used malloc functions. */ -#if defined(_ESTREAM_PRINTF_MALLOC) -#define my_printf_malloc(a) _ESTREAM_PRINTF_MALLOC((a)) +/* Allow redefinition of asprintf used realloc function. */ +#if defined(_ESTREAM_PRINTF_REALLOC) +#define my_printf_realloc(a,b) _ESTREAM_PRINTF_REALLOC((a),(b)) #else -#define my_printf_malloc(a) malloc((a)) -#endif -#if defined(_ESTREAM_PRINTF_FREE) -#define my_printf_free(a) _ESTREAM_PRINTF_FREE((a)) -#else -#define my_printf_free(a) free((a)) +#define my_printf_realloc(a,b) fixed_realloc((a),(b)) #endif /* A wrapper to set ERRNO. */ #ifdef HAVE_W32CE_SYSTEM # define _set_errno(a) gpg_err_set_errno ((a)) #else # define _set_errno(a) do { errno = (a); } while (0) #endif /* Calculate array dimension. */ #ifndef DIM #define DIM(array) (sizeof (array) / sizeof (*array)) #endif /* We allow for that many args without requiring malloced memory. */ #define DEFAULT_MAX_ARGSPECS 5 /* We allow for that many values without requiring malloced memory. */ #define DEFAULT_MAX_VALUES 8 /* We allocate this many new array argspec elements each time. */ #define ARGSPECS_BUMP_VALUE 10 /* Special values for the field width and the precision. */ #define NO_FIELD_VALUE (-1) #define STAR_FIELD_VALUE (-2) /* Bit valuues used for the conversion flags. */ #define FLAG_GROUPING 1 #define FLAG_LEFT_JUST 2 #define FLAG_PLUS_SIGN 4 #define FLAG_SPACE_PLUS 8 #define FLAG_ALT_CONV 16 #define FLAG_ZERO_PAD 32 /* Constants used the length modifiers. */ typedef enum { LENMOD_NONE = 0, LENMOD_CHAR, /* "hh" */ LENMOD_SHORT, /* "h" */ LENMOD_LONG, /* "l" */ LENMOD_LONGLONG, /* "ll" */ LENMOD_INTMAX, /* "j" */ LENMOD_SIZET, /* "z" */ LENMOD_PTRDIFF, /* "t" */ LENMOD_LONGDBL /* "L" */ } lenmod_t; /* All the conversion specifiers. */ typedef enum { CONSPEC_UNKNOWN = 0, CONSPEC_DECIMAL, CONSPEC_OCTAL, CONSPEC_UNSIGNED, CONSPEC_HEX, CONSPEC_HEX_UP, CONSPEC_FLOAT, CONSPEC_FLOAT_UP, CONSPEC_EXP, CONSPEC_EXP_UP, CONSPEC_F_OR_G, CONSPEC_F_OR_G_UP, CONSPEC_HEX_EXP, CONSPEC_HEX_EXP_UP, CONSPEC_CHAR, CONSPEC_STRING, CONSPEC_POINTER, CONSPEC_STRERROR, CONSPEC_BYTES_SO_FAR } conspec_t; /* Constants describing all the suppoorted types. Note that we list all the types we know about even if certain types are not available on this system. */ typedef enum { VALTYPE_UNSUPPORTED = 0, /* Artificial type for error detection. */ VALTYPE_CHAR, VALTYPE_SCHAR, VALTYPE_UCHAR, VALTYPE_SHORT, VALTYPE_USHORT, VALTYPE_INT, VALTYPE_UINT, VALTYPE_LONG, VALTYPE_ULONG, VALTYPE_LONGLONG, VALTYPE_ULONGLONG, VALTYPE_DOUBLE, VALTYPE_LONGDOUBLE, VALTYPE_STRING, VALTYPE_INTMAX, VALTYPE_UINTMAX, VALTYPE_SIZE, VALTYPE_PTRDIFF, VALTYPE_POINTER, VALTYPE_CHAR_PTR, VALTYPE_SCHAR_PTR, VALTYPE_SHORT_PTR, VALTYPE_INT_PTR, VALTYPE_LONG_PTR, VALTYPE_LONGLONG_PTR, VALTYPE_INTMAX_PTR, VALTYPE_SIZE_PTR, VALTYPE_PTRDIFF_PTR } valtype_t; /* A union used to store the actual values. */ typedef union { char a_char; signed char a_schar; unsigned char a_uchar; short a_short; unsigned short a_ushort; int a_int; unsigned int a_uint; long int a_long; unsigned long int a_ulong; #ifdef HAVE_LONG_LONG_INT long long int a_longlong; unsigned long long int a_ulonglong; #endif double a_double; #ifdef HAVE_LONG_DOUBLE long double a_longdouble; #endif const char *a_string; #ifdef HAVE_INTMAX_T intmax_t a_intmax; #endif #ifdef HAVE_UINTMAX_T intmax_t a_uintmax; #endif size_t a_size; #ifdef HAVE_PTRDIFF_T ptrdiff_t a_ptrdiff; #endif void *a_void_ptr; char *a_char_ptr; signed char *a_schar_ptr; short *a_short_ptr; int *a_int_ptr; long *a_long_ptr; #ifdef HAVE_LONG_LONG_INT long long int *a_longlong_ptr; #endif #ifdef HAVE_INTMAX_T intmax_t *a_intmax_ptr; #endif size_t *a_size_ptr; #ifdef HAVE_PTRDIFF_T ptrdiff_t *a_ptrdiff_ptr; #endif } value_t; /* An object used to keep track of a format option and arguments. */ struct argspec_s { size_t length; /* The length of these args including the percent. */ unsigned int flags; /* The conversion flags (bits defined by FLAG_foo). */ int width; /* The field width. */ int precision; /* The precision. */ lenmod_t lenmod; /* The length modifier. */ conspec_t conspec; /* The conversion specifier. */ int arg_pos; /* The position of the argument. This one may be -1 to indicate that no value is expected (e.g. for "%m"). */ int width_pos; /* The position of the argument for a field width star's value. 0 for not used. */ int precision_pos; /* The position of the argument for the a precision star's value. 0 for not used. */ valtype_t vt; /* The type of the corresponding argument. */ }; typedef struct argspec_s *argspec_t; /* An object to build up a table of values and their types. */ struct valueitem_s { valtype_t vt; /* The type of the value. */ value_t value; /* The value. */ }; typedef struct valueitem_s *valueitem_t; + +/* Not all systems have a C-90 compliant realloc. To cope with this + we use this simple wrapper. */ +#ifndef _ESTREAM_PRINTF_REALLOC +static void * +fixed_realloc (void *a, size_t n) +{ + if (!a) + return malloc (n); + + if (!n) + { + free (a); + return NULL; + } + + return realloc (a, n); +} +#endif /*!_ESTREAM_PRINTF_REALLOC*/ + #ifdef DEBUG static void dump_argspecs (argspec_t arg, size_t argcount) { int idx; for (idx=0; argcount; argcount--, arg++, idx++) fprintf (stderr, "%2d: len=%u flags=%u width=%d prec=%d mod=%d " "con=%d vt=%d pos=%d-%d-%d\n", idx, (unsigned int)arg->length, arg->flags, arg->width, arg->precision, arg->lenmod, arg->conspec, arg->vt, arg->arg_pos, arg->width_pos, arg->precision_pos); } #endif /*DEBUG*/ /* Set the vt field for ARG. */ static void compute_type (argspec_t arg) { switch (arg->conspec) { case CONSPEC_UNKNOWN: arg->vt = VALTYPE_UNSUPPORTED; break; case CONSPEC_DECIMAL: switch (arg->lenmod) { case LENMOD_CHAR: arg->vt = VALTYPE_SCHAR; break; case LENMOD_SHORT: arg->vt = VALTYPE_SHORT; break; case LENMOD_LONG: arg->vt = VALTYPE_LONG; break; case LENMOD_LONGLONG: arg->vt = VALTYPE_LONGLONG; break; case LENMOD_INTMAX: arg->vt = VALTYPE_INTMAX; break; case LENMOD_SIZET: arg->vt = VALTYPE_SIZE; break; case LENMOD_PTRDIFF: arg->vt = VALTYPE_PTRDIFF; break; default: arg->vt = VALTYPE_INT; break; } break; case CONSPEC_OCTAL: case CONSPEC_UNSIGNED: case CONSPEC_HEX: case CONSPEC_HEX_UP: switch (arg->lenmod) { case LENMOD_CHAR: arg->vt = VALTYPE_UCHAR; break; case LENMOD_SHORT: arg->vt = VALTYPE_USHORT; break; case LENMOD_LONG: arg->vt = VALTYPE_ULONG; break; case LENMOD_LONGLONG: arg->vt = VALTYPE_ULONGLONG; break; case LENMOD_INTMAX: arg->vt = VALTYPE_UINTMAX; break; case LENMOD_SIZET: arg->vt = VALTYPE_SIZE; break; case LENMOD_PTRDIFF: arg->vt = VALTYPE_PTRDIFF; break; default: arg->vt = VALTYPE_UINT; break; } break; case CONSPEC_FLOAT: case CONSPEC_FLOAT_UP: case CONSPEC_EXP: case CONSPEC_EXP_UP: case CONSPEC_F_OR_G: case CONSPEC_F_OR_G_UP: case CONSPEC_HEX_EXP: case CONSPEC_HEX_EXP_UP: switch (arg->lenmod) { case LENMOD_LONGDBL: arg->vt = VALTYPE_LONGDOUBLE; break; case LENMOD_LONG: arg->vt = VALTYPE_DOUBLE; break; default: arg->vt = VALTYPE_DOUBLE; break; } break; case CONSPEC_CHAR: arg->vt = VALTYPE_INT; break; case CONSPEC_STRING: arg->vt = VALTYPE_STRING; break; case CONSPEC_POINTER: arg->vt = VALTYPE_POINTER; break; case CONSPEC_STRERROR: arg->vt = VALTYPE_STRING; break; case CONSPEC_BYTES_SO_FAR: switch (arg->lenmod) { case LENMOD_CHAR: arg->vt = VALTYPE_SCHAR_PTR; break; case LENMOD_SHORT: arg->vt = VALTYPE_SHORT_PTR; break; case LENMOD_LONG: arg->vt = VALTYPE_LONG_PTR; break; case LENMOD_LONGLONG: arg->vt = VALTYPE_LONGLONG_PTR; break; case LENMOD_INTMAX: arg->vt = VALTYPE_INTMAX_PTR; break; case LENMOD_SIZET: arg->vt = VALTYPE_SIZE_PTR; break; case LENMOD_PTRDIFF: arg->vt = VALTYPE_PTRDIFF_PTR; break; default: arg->vt = VALTYPE_INT_PTR; break; } break; } } /* Parse the FORMAT string and populate the specification array stored at the address ARGSPECS_ADDR. The caller has provided enough space to store up to MAX_ARGSPECS in that buffer. The function may however ignore the provided buffer and malloc a larger one. On success the addrrss of that larger buffer will be stored at ARGSPECS_ADDR. The actual number of specifications will be returned at R_ARGSPECS_COUNT. */ static int parse_format (const char *format, argspec_t *argspecs_addr, size_t max_argspecs, size_t *r_argspecs_count) { const char *s; argspec_t argspecs = *argspecs_addr; argspec_t arg; size_t argcount = 0; if (!format) goto leave_einval; for (; *format; format++) { unsigned int flags; int width, precision; lenmod_t lenmod; conspec_t conspec; int arg_pos, width_pos, precision_pos; if (*format != '%') continue; s = ++format; if (!*s) goto leave_einval; if (*s == '%') continue; /* Just a quoted percent. */ /* First check whether there is a positional argument. */ arg_pos = 0; /* No positional argument given. */ if (*s >= '1' && *s <= '9') { const char *save_s = s; arg_pos = (*s++ - '0'); for (; *s >= '0' && *s <= '9'; s++) arg_pos = 10*arg_pos + (*s - '0'); if (arg_pos < 0) goto leave_einval; /* Overflow during conversion. */ if (*s == '$') s++; else { arg_pos = 0; s = save_s; } } /* Parse the flags. */ flags = 0; for ( ; *s; s++) { switch (*s) { case '\'': flags |= FLAG_GROUPING; break; case '-': flags |= FLAG_LEFT_JUST; break; case '+': flags |= FLAG_PLUS_SIGN; break; case ' ': flags |= FLAG_SPACE_PLUS; break; case '#': flags |= FLAG_ALT_CONV; break; case '0': flags |= FLAG_ZERO_PAD; break; default: goto flags_parsed; } } flags_parsed: /* Parse the field width. */ width_pos = 0; if (*s == '*') { width = STAR_FIELD_VALUE; s++; /* If we have a positional argument, another one might also be used to give the position of the star's value. */ if (arg_pos && *s >= '1' && *s <= '9') { width_pos = (*s++ - '0'); for (; *s >= '0' && *s <= '9'; s++) width_pos = 10*width_pos + (*s - '0'); if (width_pos < 1) goto leave_einval; /* Overflow during conversion. */ if (*s != '$') goto leave_einval; /* Not followed by $. */ s++; } } else if ( *s >= '0' && *s <= '9') { width = (*s++ - '0'); for (; *s >= '0' && *s <= '9'; s++) { if (!width && *s == '0') goto leave_einval; /* Leading zeroes are not allowed. Fixme: check what other implementations do. */ width = 10*width + (*s - '0'); } if (width < 0) goto leave_einval; /* Overflow during conversion. */ } else width = NO_FIELD_VALUE; /* Parse the precision. */ precision_pos = 0; precision = NO_FIELD_VALUE; if (*s == '.') { int ignore_value = (s[1] == '-'); s++; if (*s == '*') { precision = STAR_FIELD_VALUE; s++; /* If we have a positional argument, another one might also be used to give the position of the star's value. */ if (arg_pos && *s >= '1' && *s <= '9') { precision_pos = (*s++ - '0'); for (; *s >= '0' && *s <= '9'; s++) precision_pos = 10*precision_pos + (*s - '0'); if (precision_pos < 1) goto leave_einval; /* Overflow during conversion. */ if (*s != '$') goto leave_einval; /* Not followed by $. */ s++; } } else if ( *s >= '0' && *s <= '9') { precision = (*s++ - '0'); for (; *s >= '0' && *s <= '9'; s++) { if (!precision && *s == '0') goto leave_einval; /* Leading zeroes are not allowed. Fixme: check what other implementations do. */ precision = 10*precision + (*s - '0'); } if (precision < 0) goto leave_einval; /* Overflow during conversion. */ } else precision = 0; if (ignore_value) precision = NO_FIELD_VALUE; } /* Parse the length modifiers. */ switch (*s) { case 'h': if (s[1] == 'h') { lenmod = LENMOD_CHAR; s++; } else lenmod = LENMOD_SHORT; s++; break; case 'l': if (s[1] == 'l') { lenmod = LENMOD_LONGLONG; s++; } else lenmod = LENMOD_LONG; s++; break; case 'j': lenmod = LENMOD_INTMAX; s++; break; case 'z': lenmod = LENMOD_SIZET; s++; break; case 't': lenmod = LENMOD_PTRDIFF; s++; break; case 'L': lenmod = LENMOD_LONGDBL; s++; break; default: lenmod = LENMOD_NONE; break; } /* Parse the conversion specifier. */ switch (*s) { case 'd': case 'i': conspec = CONSPEC_DECIMAL; break; case 'o': conspec = CONSPEC_OCTAL; break; case 'u': conspec = CONSPEC_UNSIGNED; break; case 'x': conspec = CONSPEC_HEX; break; case 'X': conspec = CONSPEC_HEX_UP; break; case 'f': conspec = CONSPEC_FLOAT; break; case 'F': conspec = CONSPEC_FLOAT_UP; break; case 'e': conspec = CONSPEC_EXP; break; case 'E': conspec = CONSPEC_EXP_UP; break; case 'g': conspec = CONSPEC_F_OR_G; break; case 'G': conspec = CONSPEC_F_OR_G_UP; break; case 'a': conspec = CONSPEC_HEX_EXP; break; case 'A': conspec = CONSPEC_HEX_EXP_UP; break; case 'c': conspec = CONSPEC_CHAR; break; case 's': conspec = CONSPEC_STRING; break; case 'p': conspec = CONSPEC_POINTER; break; case 'n': conspec = CONSPEC_BYTES_SO_FAR; break; case 'C': conspec = CONSPEC_CHAR; lenmod = LENMOD_LONG; break; case 'S': conspec = CONSPEC_STRING; lenmod = LENMOD_LONG; break; case 'm': conspec = CONSPEC_STRERROR; arg_pos = -1; break; default: conspec = CONSPEC_UNKNOWN; } /* Save the args. */ if (argcount >= max_argspecs) { /* We either need to allocate a new array instead of the caller provided one or realloc the array. Instead of using realloc we allocate a new one and release the original one then. */ size_t n, newmax; argspec_t newarg; newmax = max_argspecs + ARGSPECS_BUMP_VALUE; if (newmax <= max_argspecs) goto leave_einval; /* Too many arguments. */ newarg = calloc (newmax, sizeof *newarg); if (!newarg) goto leave; for (n=0; n < argcount; n++) newarg[n] = argspecs[n]; if (argspecs != *argspecs_addr) free (argspecs); argspecs = newarg; max_argspecs = newmax; } arg = argspecs + argcount; arg->length = s - format + 2; arg->flags = flags; arg->width = width; arg->precision = precision; arg->lenmod = lenmod; arg->conspec = conspec; arg->arg_pos = arg_pos; arg->width_pos = width_pos; arg->precision_pos = precision_pos; compute_type (arg); argcount++; format = s; } *argspecs_addr = argspecs; *r_argspecs_count = argcount; return 0; /* Success. */ leave_einval: _set_errno (EINVAL); leave: if (argspecs != *argspecs_addr) free (argspecs); *argspecs_addr = NULL; return -1; } /* This function reads all the values as specified by VALUETABLE into VALUETABLE. The values are expected in VAARGS. The function returns -1 if a specified type is not supported. */ static int read_values (valueitem_t valuetable, size_t valuetable_len, va_list vaargs) { int validx; for (validx=0; validx < valuetable_len; validx++) { value_t *value = &valuetable[validx].value; valtype_t vt = valuetable[validx].vt; switch (vt) { case VALTYPE_CHAR: value->a_char = va_arg (vaargs, int); break; case VALTYPE_CHAR_PTR: value->a_char_ptr = va_arg (vaargs, char *); break; case VALTYPE_SCHAR: value->a_schar = va_arg (vaargs, int); break; case VALTYPE_SCHAR_PTR: value->a_schar_ptr = va_arg (vaargs, signed char *); break; case VALTYPE_UCHAR: value->a_uchar = va_arg (vaargs, int); break; case VALTYPE_SHORT: value->a_short = va_arg (vaargs, int); break; case VALTYPE_USHORT: value->a_ushort = va_arg (vaargs, int); break; case VALTYPE_SHORT_PTR: value->a_short_ptr = va_arg (vaargs, short *); break; case VALTYPE_INT: value->a_int = va_arg (vaargs, int); break; case VALTYPE_INT_PTR: value->a_int_ptr = va_arg (vaargs, int *); break; case VALTYPE_UINT: value->a_uint = va_arg (vaargs, unsigned int); break; case VALTYPE_LONG: value->a_long = va_arg (vaargs, long); break; case VALTYPE_ULONG: value->a_ulong = va_arg (vaargs, unsigned long); break; case VALTYPE_LONG_PTR: value->a_long_ptr = va_arg (vaargs, long *); break; #ifdef HAVE_LONG_LONG_INT case VALTYPE_LONGLONG: value->a_longlong = va_arg (vaargs, long long int); break; case VALTYPE_ULONGLONG: value->a_ulonglong = va_arg (vaargs, unsigned long long int); break; case VALTYPE_LONGLONG_PTR: value->a_longlong_ptr = va_arg (vaargs, long long *); break; #endif case VALTYPE_DOUBLE: value->a_double = va_arg (vaargs, double); break; #ifdef HAVE_LONG_DOUBLE case VALTYPE_LONGDOUBLE: value->a_longdouble = va_arg (vaargs, long double); break; #endif case VALTYPE_STRING: value->a_string = va_arg (vaargs, const char *); break; case VALTYPE_POINTER: value->a_void_ptr = va_arg (vaargs, void *); break; #ifdef HAVE_INTMAX_T case VALTYPE_INTMAX: value->a_intmax = va_arg (vaargs, intmax_t); break; case VALTYPE_INTMAX_PTR: value->a_intmax_ptr = va_arg (vaargs, intmax_t *); break; #endif #ifdef HAVE_UINTMAX_T case VALTYPE_UINTMAX: value->a_uintmax = va_arg (vaargs, uintmax_t); break; #endif case VALTYPE_SIZE: value->a_size = va_arg (vaargs, size_t); break; case VALTYPE_SIZE_PTR: value->a_size_ptr = va_arg (vaargs, size_t *); break; #ifdef HAVE_PTRDIFF_T case VALTYPE_PTRDIFF: value->a_ptrdiff = va_arg (vaargs, ptrdiff_t); break; case VALTYPE_PTRDIFF_PTR: value->a_ptrdiff_ptr = va_arg (vaargs, ptrdiff_t *); break; #endif default: /* Unsupported type. */ return -1; } } return 0; } /* Output COUNT padding characters PADCHAR and update NBYTES by the number of bytes actually written. */ static int pad_out (estream_printf_out_t outfnc, void *outfncarg, int padchar, int count, size_t *nbytes) { char buf[32]; size_t n; int rc; while (count > 0) { n = (count <= sizeof buf)? count : sizeof buf; memset (buf, padchar, n); rc = outfnc (outfncarg, buf, n); if (rc) return rc; *nbytes += n; count -= n; } return 0; } /* "d,i,o,u,x,X" formatting. OUTFNC and OUTFNCARG describes the output routine, ARG gives the argument description and VALUE the actual value (its type is available through arg->vt). */ static int pr_integer (estream_printf_out_t outfnc, void *outfncarg, argspec_t arg, value_t value, size_t *nbytes) { int rc; #ifdef HAVE_LONG_LONG_INT unsigned long long aulong; #else unsigned long aulong; #endif char numbuf[100]; char *p, *pend; size_t n; char signchar = 0; int n_prec; /* Number of extra precision digits required. */ int n_extra; /* Extra number of prefix or sign characters. */ if (arg->conspec == CONSPEC_DECIMAL) { #ifdef HAVE_LONG_LONG_INT long long along; #else long along; #endif switch (arg->vt) { case VALTYPE_SHORT: along = value.a_short; break; case VALTYPE_INT: along = value.a_int; break; case VALTYPE_LONG: along = value.a_long; break; #ifdef HAVE_LONG_LONG_INT case VALTYPE_LONGLONG: along = value.a_longlong; break; case VALTYPE_SIZE: along = value.a_size; break; # ifdef HAVE_INTMAX_T case VALTYPE_INTMAX: along = value.a_intmax; break; # endif # ifdef HAVE_PTRDIFF_T case VALTYPE_PTRDIFF: along = value.a_ptrdiff; break; # endif #endif /*HAVE_LONG_LONG_INT*/ default: return -1; } if (along < 0) { aulong = -along; signchar = '-'; } else aulong = along; } else { switch (arg->vt) { case VALTYPE_USHORT: aulong = value.a_ushort; break; case VALTYPE_UINT: aulong = value.a_uint; break; case VALTYPE_ULONG: aulong = value.a_ulong; break; #ifdef HAVE_LONG_LONG_INT case VALTYPE_ULONGLONG: aulong = value.a_ulonglong; break; case VALTYPE_SIZE: aulong = value.a_size; break; # ifdef HAVE_UINTMAX_T case VALTYPE_UINTMAX: aulong = value.a_uintmax; break; # endif # ifdef HAVE_PTRDIFF_T case VALTYPE_PTRDIFF: aulong = value.a_ptrdiff; break; # endif #endif /*HAVE_LONG_LONG_INT*/ default: return -1; } } if (signchar == '-') ; else if ((arg->flags & FLAG_PLUS_SIGN)) signchar = '+'; else if ((arg->flags & FLAG_SPACE_PLUS)) signchar = ' '; n_extra = !!signchar; /* We build the string up backwards. */ p = pend = numbuf + DIM(numbuf); if ((!aulong && !arg->precision)) ; else if (arg->conspec == CONSPEC_DECIMAL || arg->conspec == CONSPEC_UNSIGNED) { int grouping = -1; const char * grouping_string = #ifdef HAVE_LANGINFO_THOUSANDS_SEP nl_langinfo(THOUSANDS_SEP); #else "'"; #endif do { if ((arg->flags & FLAG_GROUPING) && (++grouping == 3) && *grouping_string) { *--p = *grouping_string; grouping = 0; } *--p = '0' + (aulong % 10); aulong /= 10; } while (aulong); } else if (arg->conspec == CONSPEC_OCTAL) { do { *--p = '0' + (aulong % 8); aulong /= 8; } while (aulong); if ((arg->flags & FLAG_ALT_CONV) && *p != '0') *--p = '0'; } else /* HEX or HEXUP */ { const char *digits = ((arg->conspec == CONSPEC_HEX) ? "0123456789abcdef" : "0123456789ABCDEF"); do { *--p = digits[(aulong % 16)]; aulong /= 16; } while (aulong); if ((arg->flags & FLAG_ALT_CONV)) n_extra += 2; } n = pend - p; if ((arg->flags & FLAG_ZERO_PAD) && arg->precision == NO_FIELD_VALUE && !(arg->flags & FLAG_LEFT_JUST) && n && arg->width - n_extra > n ) n_prec = arg->width - n_extra - n; else if (arg->precision > 0 && arg->precision > n) n_prec = arg->precision - n; else n_prec = 0; if (!(arg->flags & FLAG_LEFT_JUST) && arg->width >= 0 && arg->width - n_extra > n && arg->width - n_extra - n >= n_prec ) { rc = pad_out (outfnc, outfncarg, ' ', arg->width - n_extra - n - n_prec, nbytes); if (rc) return rc; } if (signchar) { rc = outfnc (outfncarg, &signchar, 1); if (rc) return rc; *nbytes += 1; } if ((arg->flags & FLAG_ALT_CONV) && (arg->conspec == CONSPEC_HEX || arg->conspec == CONSPEC_HEX_UP)) { rc = outfnc (outfncarg, arg->conspec == CONSPEC_HEX? "0x": "0X", 2); if (rc) return rc; *nbytes += 2; } if (n_prec) { rc = pad_out (outfnc, outfncarg, '0', n_prec, nbytes); if (rc) return rc; } rc = outfnc (outfncarg, p, pend - p); if (rc) return rc; *nbytes += pend - p; if ((arg->flags & FLAG_LEFT_JUST) && arg->width >= 0 && arg->width - n_extra - n_prec > n) { rc = pad_out (outfnc, outfncarg, ' ', arg->width - n_extra - n_prec - n, nbytes); if (rc) return rc; } return 0; } /* "e,E,f,F,g,G,a,A" formatting. OUTFNC and OUTFNCARG describes the output routine, ARG gives the argument description and VALUE the actual value (its type is available through arg->vt). For portability reasons sprintf is used for the actual formatting. This is useful because sprint is the only standard function to convert a floating number into its ascii representation. To avoid using malloc we just pass the precision to sprintf and do the final formatting with our own code. */ static int pr_float (estream_printf_out_t outfnc, void *outfncarg, argspec_t arg, value_t value, size_t *nbytes) { int rc; #ifdef HAVE_LONG_DOUBLE long double adblfloat = 0; /* Just to please gcc. */ int use_dbl = 0; #endif double afloat; char numbuf[350]; char formatstr[20]; char *p, *pend; size_t n; char signchar = 0; int n_extra; /* Extra number of prefix or sign characters. */ switch (arg->vt) { case VALTYPE_DOUBLE: afloat = value.a_double; break; #ifdef HAVE_LONG_DOUBLE case VALTYPE_LONGDOUBLE: afloat = 0; /* Just to please gcc. */ adblfloat = value.a_longdouble; use_dbl=1; break; #endif default: return -1; } /* We build the string using sprint. */ p = formatstr + sizeof formatstr; *--p = 0; switch (arg->conspec) { case CONSPEC_FLOAT: *--p = 'f'; break; case CONSPEC_FLOAT_UP: *--p = 'F'; break; case CONSPEC_EXP: *--p = 'e'; break; case CONSPEC_EXP_UP: *--p = 'E'; break; case CONSPEC_F_OR_G: *--p = 'g'; break; case CONSPEC_F_OR_G_UP: *--p = 'G'; break; case CONSPEC_HEX_EXP: *--p = 'a'; break; case CONSPEC_HEX_EXP_UP: *--p = 'A'; break; default: return -1; /* Actually a bug. */ } #ifdef HAVE_LONG_DOUBLE if (use_dbl) *--p = 'L'; #endif if (arg->precision != NO_FIELD_VALUE) { /* Limit it to a meaningful value so that even a stupid sprintf won't overflow our buffer. */ n = arg->precision <= 100? arg->precision : 100; do { *--p = '0' + (n % 10); n /= 10; } while (n); *--p = '.'; } if ((arg->flags & FLAG_ALT_CONV)) *--p = '#'; *--p = '%'; #ifdef HAVE_LONG_DOUBLE if (use_dbl) sprintf (numbuf, p, adblfloat); else #endif /*HAVE_LONG_DOUBLE*/ sprintf (numbuf, p, afloat); p = numbuf; n = strlen (numbuf); pend = p + n; if (*p =='-') { signchar = '-'; p++; n--; } else if ((arg->flags & FLAG_PLUS_SIGN)) signchar = '+'; else if ((arg->flags & FLAG_SPACE_PLUS)) signchar = ' '; n_extra = !!signchar; if (!(arg->flags & FLAG_LEFT_JUST) && arg->width >= 0 && arg->width - n_extra > n) { rc = pad_out (outfnc, outfncarg, ' ', arg->width - n_extra - n, nbytes); if (rc) return rc; } if (signchar) { rc = outfnc (outfncarg, &signchar, 1); if (rc) return rc; *nbytes += 1; } rc = outfnc (outfncarg, p, pend - p); if (rc) return rc; *nbytes += pend - p; if ((arg->flags & FLAG_LEFT_JUST) && arg->width >= 0 && arg->width - n_extra > n) { rc = pad_out (outfnc, outfncarg, ' ', arg->width - n_extra - n, nbytes); if (rc) return rc; } return 0; } /* "c" formatting. */ static int pr_char (estream_printf_out_t outfnc, void *outfncarg, argspec_t arg, value_t value, size_t *nbytes) { int rc; char buf[1]; if (arg->vt != VALTYPE_INT) return -1; buf[0] = (unsigned int)value.a_int; rc = outfnc (outfncarg, buf, 1); if(rc) return rc; *nbytes += 1; return 0; } /* "s" formatting. */ static int pr_string (estream_printf_out_t outfnc, void *outfncarg, argspec_t arg, value_t value, size_t *nbytes) { int rc; size_t n; const char *string, *s; if (arg->vt != VALTYPE_STRING) return -1; string = value.a_string; if (!string) string = "(null)"; if (arg->precision >= 0) { for (n=0,s=string; *s && n < arg->precision; s++) n++; } else n = strlen (string); if (!(arg->flags & FLAG_LEFT_JUST) && arg->width >= 0 && arg->width > n ) { rc = pad_out (outfnc, outfncarg, ' ', arg->width - n, nbytes); if (rc) return rc; } rc = outfnc (outfncarg, string, n); if (rc) return rc; *nbytes += n; if ((arg->flags & FLAG_LEFT_JUST) && arg->width >= 0 && arg->width > n) { rc = pad_out (outfnc, outfncarg, ' ', arg->width - n, nbytes); if (rc) return rc; } return 0; } /* "p" formatting. */ static int pr_pointer (estream_printf_out_t outfnc, void *outfncarg, argspec_t arg, value_t value, size_t *nbytes) { int rc; #if defined(HAVE_LONG_LONG_INT) && (SIZEOF_UNSIGNED_LONG < SIZEOF_VOID_P) unsigned long long aulong; #else unsigned long aulong; #endif char numbuf[100]; char *p, *pend; if (arg->vt != VALTYPE_POINTER) return -1; /* We assume that a pointer can be converted to an unsigned long. That is not correct for a 64 bit Windows, but then we assume that long long is supported and usable for storing a pointer. */ #if defined(HAVE_LONG_LONG_INT) && (SIZEOF_UNSIGNED_LONG < SIZEOF_VOID_P) aulong = (unsigned long long)value.a_void_ptr; #else aulong = (unsigned long)value.a_void_ptr; #endif p = pend = numbuf + DIM(numbuf); do { *--p = "0123456789abcdefx"[(aulong % 16)]; aulong /= 16; } while (aulong); while ((pend-p) < 2*sizeof (aulong)) *--p = '0'; *--p = 'x'; *--p = '0'; rc = outfnc (outfncarg, p, pend - p); if (rc) return rc; *nbytes += pend - p; return 0; } /* "n" pesudo format operation. */ static int pr_bytes_so_far (estream_printf_out_t outfnc, void *outfncarg, argspec_t arg, value_t value, size_t *nbytes) { (void)outfnc; (void)outfncarg; switch (arg->vt) { case VALTYPE_SCHAR_PTR: *value.a_schar_ptr = (signed char)(unsigned int)(*nbytes); break; case VALTYPE_SHORT_PTR: *value.a_short_ptr = (short)(unsigned int)(*nbytes); break; case VALTYPE_LONG_PTR: *value.a_long_ptr = (long)(*nbytes); break; #ifdef HAVE_LONG_LONG_INT case VALTYPE_LONGLONG_PTR: *value.a_longlong_ptr = (long long)(*nbytes); break; #endif #ifdef HAVE_INTMAX_T case VALTYPE_INTMAX_PTR: *value.a_intmax_ptr = (intmax_t)(*nbytes); break; #endif case VALTYPE_SIZE_PTR: *value.a_size_ptr = (*nbytes); break; #ifdef HAVE_PTRDIFF_T case VALTYPE_PTRDIFF_PTR: *value.a_ptrdiff_ptr = (ptrdiff_t)(*nbytes); break; #endif case VALTYPE_INT_PTR: *value.a_int_ptr = (int)(*nbytes); break; default: return -1; /* An unsupported type has been used. */ } return 0; } /* Run the actual formatting. OUTFNC and OUTFNCARG are the output functions. FORMAT is format string ARGSPECS is the parsed format string, ARGSPECS_LEN the number of items in ARGSPECS. VALUETABLE holds the values and may be directly addressed using the position arguments given by ARGSPECS. MYERRNO is used for the "%m" conversion. NBYTES well be updated to reflect the number of bytes send to the output function. */ static int do_format (estream_printf_out_t outfnc, void *outfncarg, const char *format, argspec_t argspecs, size_t argspecs_len, valueitem_t valuetable, int myerrno, size_t *nbytes) { int rc = 0; const char *s; argspec_t arg = argspecs; int argidx = 0; /* Only used for assertion. */ size_t n; value_t value; s = format; while ( *s ) { if (*s != '%') { s++; continue; } if (s != format) { rc = outfnc (outfncarg, format, (n=s-format)); if (rc) return rc; *nbytes += n; } if (s[1] == '%') { /* Note that this code ignores one trailing percent escape - this is however okay as the args parser must have detected this already. */ rc = outfnc (outfncarg, s, 1); if (rc) return rc; *nbytes += 1; s += 2; format = s; continue; } /* Save the next start. */ s += arg->length; format = s; assert (argidx < argspecs_len); argidx++; /* Apply indirect field width and precision values. */ if (arg->width == STAR_FIELD_VALUE) { assert (valuetable[arg->width_pos-1].vt == VALTYPE_INT); arg->width = valuetable[arg->width_pos-1].value.a_int; if (arg->width < 0) { arg->width = -arg->width; arg->flags |= FLAG_LEFT_JUST; } } if (arg->precision == STAR_FIELD_VALUE) { assert (valuetable[arg->precision_pos-1].vt == VALTYPE_INT); arg->precision = valuetable[arg->precision_pos-1].value.a_int; if (arg->precision < 0) arg->precision = NO_FIELD_VALUE; } if (arg->arg_pos == -1 && arg->conspec == CONSPEC_STRERROR) value.a_string = strerror (myerrno); else { assert (arg->vt == valuetable[arg->arg_pos-1].vt); value = valuetable[arg->arg_pos-1].value; } switch (arg->conspec) { case CONSPEC_UNKNOWN: assert (!"bug"); break; case CONSPEC_DECIMAL: case CONSPEC_UNSIGNED: case CONSPEC_OCTAL: case CONSPEC_HEX: case CONSPEC_HEX_UP: rc = pr_integer (outfnc, outfncarg, arg, value, nbytes); break; case CONSPEC_FLOAT: case CONSPEC_FLOAT_UP: case CONSPEC_EXP: case CONSPEC_EXP_UP: case CONSPEC_F_OR_G: case CONSPEC_F_OR_G_UP: case CONSPEC_HEX_EXP: case CONSPEC_HEX_EXP_UP: rc = pr_float (outfnc, outfncarg, arg, value, nbytes); break; case CONSPEC_CHAR: rc = pr_char (outfnc, outfncarg, arg, value, nbytes); break; case CONSPEC_STRING: case CONSPEC_STRERROR: rc = pr_string (outfnc, outfncarg, arg, value, nbytes); break; case CONSPEC_POINTER: rc = pr_pointer (outfnc, outfncarg, arg, value, nbytes); break; case CONSPEC_BYTES_SO_FAR: rc = pr_bytes_so_far (outfnc, outfncarg, arg, value, nbytes); break; } if (rc) return rc; arg++; } /* Print out any trailing stuff. */ n = s - format; rc = n? outfnc (outfncarg, format, n) : 0; if (!rc) *nbytes += n; return rc; } /* The versatile printf formatting routine. It expects a callback function OUTFNC and an opaque argument OUTFNCARG used for actual output of the formatted stuff. FORMAT is the format specification and VAARGS a variable argumemt list matching the arguments of FORMAT. */ int estream_format (estream_printf_out_t outfnc, void *outfncarg, const char *format, va_list vaargs) { /* Buffer to hold the argspecs and a pointer to it.*/ struct argspec_s argspecs_buffer[DEFAULT_MAX_ARGSPECS]; argspec_t argspecs = argspecs_buffer; size_t argspecs_len; /* Number of specifications in ARGSPECS. */ /* Buffer to hold the description for the values. */ struct valueitem_s valuetable_buffer[DEFAULT_MAX_VALUES]; valueitem_t valuetable = valuetable_buffer; int rc; /* Return code. */ size_t argidx; /* Used to index the argspecs array. */ size_t validx; /* Used to index the valuetable. */ int max_pos;/* Highest argument position. */ size_t nbytes = 0; /* Keep track of the number of bytes passed to the output function. */ int myerrno = errno; /* Save the errno for use with "%m". */ /* Parse the arguments to come up with descriptive list. We can't do this on the fly because we need to support positional arguments. */ rc = parse_format (format, &argspecs, DIM(argspecs_buffer), &argspecs_len); if (rc) goto leave; /* Check that all ARG_POS fields are set. */ for (argidx=0,max_pos=0; argidx < argspecs_len; argidx++) { if (argspecs[argidx].arg_pos != -1 && argspecs[argidx].arg_pos > max_pos) max_pos = argspecs[argidx].arg_pos; if (argspecs[argidx].width_pos > max_pos) max_pos = argspecs[argidx].width_pos; if (argspecs[argidx].precision_pos > max_pos) max_pos = argspecs[argidx].precision_pos; } if (!max_pos) { /* Fill in all the positions. */ for (argidx=0; argidx < argspecs_len; argidx++) { if (argspecs[argidx].width == STAR_FIELD_VALUE) argspecs[argidx].width_pos = ++max_pos; if (argspecs[argidx].precision == STAR_FIELD_VALUE) argspecs[argidx].precision_pos = ++max_pos; if (argspecs[argidx].arg_pos != -1 ) argspecs[argidx].arg_pos = ++max_pos; } } else { /* Check that they are all filled. More test are done later. */ for (argidx=0; argidx < argspecs_len; argidx++) { if (!argspecs[argidx].arg_pos || (argspecs[argidx].width == STAR_FIELD_VALUE && !argspecs[argidx].width_pos) || (argspecs[argidx].precision == STAR_FIELD_VALUE && !argspecs[argidx].precision_pos)) goto leave_einval; } } /* Check that there is no overflow in max_pos and that it has a reasonable length. There may never be more elements than the number of characters in FORMAT. */ if (max_pos < 0 || max_pos >= strlen (format)) goto leave_einval; #ifdef DEBUG dump_argspecs (argspecs, argspecs_len); #endif /* Allocate a table to hold the values. If it is small enough we use a stack allocated buffer. */ if (max_pos > DIM(valuetable_buffer)) { valuetable = calloc (max_pos, sizeof *valuetable); if (!valuetable) goto leave_error; } else { for (validx=0; validx < DIM(valuetable_buffer); validx++) valuetable[validx].vt = VALTYPE_UNSUPPORTED; } for (argidx=0; argidx < argspecs_len; argidx++) { if (argspecs[argidx].arg_pos != - 1) { validx = argspecs[argidx].arg_pos - 1; if (valuetable[validx].vt) goto leave_einval; /* Already defined. */ valuetable[validx].vt = argspecs[argidx].vt; } if (argspecs[argidx].width == STAR_FIELD_VALUE) { validx = argspecs[argidx].width_pos - 1; if (valuetable[validx].vt) goto leave_einval; /* Already defined. */ valuetable[validx].vt = VALTYPE_INT; } if (argspecs[argidx].precision == STAR_FIELD_VALUE) { validx = argspecs[argidx].precision_pos - 1; if (valuetable[validx].vt) goto leave_einval; /* Already defined. */ valuetable[validx].vt = VALTYPE_INT; } } /* Read all the arguments. This will error out for unsupported types and for not given positional arguments. */ rc = read_values (valuetable, max_pos, vaargs); if (rc) goto leave_einval; /* for (validx=0; validx < max_pos; validx++) */ /* fprintf (stderr, "%2d: vt=%d\n", validx, valuetable[validx].vt); */ /* Everything has been collected, go ahead with the formatting. */ rc = do_format (outfnc, outfncarg, format, argspecs, argspecs_len, valuetable, myerrno, &nbytes); goto leave; leave_einval: _set_errno (EINVAL); leave_error: rc = -1; leave: if (valuetable != valuetable_buffer) free (valuetable); if (argspecs != argspecs_buffer) free (argspecs); return rc; } /* A simple output handler utilizing stdio. */ static int plain_stdio_out (void *outfncarg, const char *buf, size_t buflen) { FILE *fp = (FILE*)outfncarg; if ( fwrite (buf, buflen, 1, fp) != 1 ) return -1; return 0; } /* A replacement for printf. */ int estream_printf (const char *format, ...) { int rc; va_list arg_ptr; va_start (arg_ptr, format); rc = estream_format (plain_stdio_out, stderr, format, arg_ptr); va_end (arg_ptr); return rc; } /* A replacement for fprintf. */ int estream_fprintf (FILE *fp, const char *format, ...) { int rc; va_list arg_ptr; va_start (arg_ptr, format); rc = estream_format (plain_stdio_out, fp, format, arg_ptr); va_end (arg_ptr); return rc; } /* A replacement for vfprintf. */ int estream_vfprintf (FILE *fp, const char *format, va_list arg_ptr) { return estream_format (plain_stdio_out, fp, format, arg_ptr); } /* Communication object used between estream_snprintf and fixed_buffer_out. */ struct fixed_buffer_parm_s { size_t size; /* Size of the buffer. */ size_t count; /* Number of bytes requested for output. */ size_t used; /* Used size of the buffer. */ char *buffer; /* Provided buffer. */ }; /* A simple malloced buffer output handler. */ static int fixed_buffer_out (void *outfncarg, const char *buf, size_t buflen) { struct fixed_buffer_parm_s *parm = outfncarg; parm->count += buflen; if (!parm->buffer) ; else if (parm->used + buflen < parm->size) { /* Handle the common case that everything fits into the buffer separately. */ memcpy (parm->buffer + parm->used, buf, buflen); parm->used += buflen; } else { /* The slow version of above. */ for ( ;buflen && parm->used < parm->size; buflen--) parm->buffer[parm->used++] = *buf++; } return 0; } /* A replacement for vsnprintf. */ int estream_vsnprintf (char *buf, size_t bufsize, const char *format, va_list arg_ptr) { struct fixed_buffer_parm_s parm; int rc; parm.size = bufsize; parm.count = 0; parm.used = 0; parm.buffer = bufsize?buf:NULL; rc = estream_format (fixed_buffer_out, &parm, format, arg_ptr); if (!rc) rc = fixed_buffer_out (&parm, "", 1); /* Print terminating Nul. */ if (rc == -1) return -1; if (bufsize && buf && parm.size && parm.count >= parm.size) buf[parm.size-1] = 0; parm.count--; /* Do not count the trailing nul. */ return (int)parm.count; /* Return number of bytes which would have been written. */ } /* A replacement for snprintf. */ int estream_snprintf (char *buf, size_t bufsize, const char *format, ...) { int rc; va_list arg_ptr; va_start (arg_ptr, format); rc = estream_vsnprintf (buf, bufsize, format, arg_ptr); va_end (arg_ptr); return rc; } /* Communication object used between estream_asprintf and dynamic_buffer_out. */ struct dynamic_buffer_parm_s { int error_flag; /* Internal helper. */ size_t alloced; /* Allocated size of the buffer. */ size_t used; /* Used size of the buffer. */ char *buffer; /* Malloced buffer. */ }; /* A simple malloced buffer output handler. */ static int dynamic_buffer_out (void *outfncarg, const char *buf, size_t buflen) { struct dynamic_buffer_parm_s *parm = outfncarg; if (parm->error_flag) { /* Just in case some formatting routine did not checked for an error. */ _set_errno (parm->error_flag); return -1; } if (parm->used + buflen >= parm->alloced) { char *p; parm->alloced += buflen + 512; - p = realloc (parm->buffer, parm->alloced); + p = my_printf_realloc (parm->buffer, parm->alloced); if (!p) { parm->error_flag = errno ? errno : ENOMEM; /* Wipe out what we already accumulated. This is useful in case sensitive data is formated. */ memset (parm->buffer, 0, parm->used); return -1; } parm->buffer = p; } memcpy (parm->buffer + parm->used, buf, buflen); parm->used += buflen; return 0; } /* A replacement for vasprintf. As with the BSD of vasprintf version -1 will be returned on error and NULL stored at BUFP. On success the number of bytes printed will be returned. */ int estream_vasprintf (char **bufp, const char *format, va_list arg_ptr) { struct dynamic_buffer_parm_s parm; int rc; parm.error_flag = 0; parm.alloced = 512; parm.used = 0; - parm.buffer = my_printf_malloc (parm.alloced); + parm.buffer = my_printf_realloc (NULL, parm.alloced); if (!parm.buffer) { *bufp = NULL; return -1; } rc = estream_format (dynamic_buffer_out, &parm, format, arg_ptr); if (!rc) rc = dynamic_buffer_out (&parm, "", 1); /* Print terminating Nul. */ /* Fixme: Should we shrink the resulting buffer? */ if (rc != -1 && parm.error_flag) { rc = -1; _set_errno (parm.error_flag); } if (rc == -1) { memset (parm.buffer, 0, parm.used); - my_printf_free (parm.buffer); + if (parm.buffer) + my_printf_realloc (parm.buffer, 0); *bufp = NULL; return -1; } assert (parm.used); /* We have at least the terminating Nul. */ *bufp = parm.buffer; return parm.used - 1; /* Do not include that Nul. */ } /* A replacement for asprintf. As with the BSD of asprintf version -1 will be returned on error and NULL stored at BUFP. On success the number of bytes printed will be returned. */ int estream_asprintf (char **bufp, const char *format, ...) { int rc; va_list arg_ptr; va_start (arg_ptr, format); rc = estream_vasprintf (bufp, format, arg_ptr); va_end (arg_ptr); return rc; } diff --git a/common/estream-printf.h b/common/estream-printf.h index 9b6b83810..1aaad7812 100644 --- a/common/estream-printf.h +++ b/common/estream-printf.h @@ -1,144 +1,145 @@ /* estream-printf.h - Versatile mostly C-99 compliant printf formatting. - * Copyright (C) 2007, 2010 g10 Code GmbH + * Copyright (C) 2007, 2010, 2012 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 * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Libestream; if not, see <http://www.gnu.org/licenses/>. * * ALTERNATIVELY, Libestream may be distributed under the terms of the * following license, in which case the provisions of this license are * required INSTEAD OF the GNU General Public License. If you wish to * allow use of your version of this file only under the terms of the * GNU General Public License, and not to allow others to use your * version of this file under the terms of the following license, * indicate your decision by deleting this paragraph and the license * below. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, and the entire permission notice in its entirety, * including the disclaimer of warranties. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef ESTREAM_PRINTF_H #define ESTREAM_PRINTF_H #include <stdarg.h> #include <stdio.h> /* To use this file with libraries the following macro is useful: #define _ESTREAM_EXT_SYM_PREFIX _foo_ This prefixes all external symbols with "_foo_". For the implementation of the code (estream-printf.c) the following macros may be used to tune the implementation for certain systems: - #define _ESTREAM_PRINTF_MALLOC foo_malloc - #define _ESTREAM_PRINTF_FREE foo_free + #define _ESTREAM_PRINTF_REALLOC foo_realloc - Make estream_asprintf and estream_vasprintf use foo_malloc and - foo_free instead of the standard malloc and free functions to - allocate the memory returned to the caller. + Make estream_asprintf and estream_vasprintf use foo_realloc + instead of the standard realloc to allocate memory returned to + the caller. Note that foo_realloc needs to be C-90 compliant: + foo_realloc (NULL,n) is the same as a call to malloc(n) and + foo_realloc (a, 0) is the same as a call to free (a). #define _ESTREAM_PRINTF_EXTRA_INCLUDE "foo.h" This includes the file "foo.h" which may provide prototypes for the custom memory allocation functions. */ #ifdef _ESTREAM_EXT_SYM_PREFIX #ifndef _ESTREAM_PREFIX #define _ESTREAM_PREFIX1(x,y) x ## y #define _ESTREAM_PREFIX2(x,y) _ESTREAM_PREFIX1(x,y) #define _ESTREAM_PREFIX(x) _ESTREAM_PREFIX2(_ESTREAM_EXT_SYM_PREFIX,x) #endif /*_ESTREAM_PREFIX*/ #define estream_printf_out_t _ESTREAM_PREFIX(estream_printf_out_t) #define estream_format _ESTREAM_PREFIX(estream_format) #define estream_printf _ESTREAM_PREFIX(estream_printf) #define estream_fprintf _ESTREAM_PREFIX(estream_fprintf) #define estream_vfprintf _ESTREAM_PREFIX(estream_vfprintf) #define estream_snprintf _ESTREAM_PREFIX(estream_snprintf) #define estream_vsnprintf _ESTREAM_PREFIX(estream_vsnprintf) #define estream_asprintf _ESTREAM_PREFIX(estream_asprintf) #define estream_vasprintf _ESTREAM_PREFIX(estream_vasprintf) #endif /*_ESTREAM_EXT_SYM_PREFIX*/ #ifndef _ESTREAM_GCC_A_PRINTF #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ) # define _ESTREAM_GCC_A_PRINTF( f, a ) __attribute__ ((format (printf,f,a))) #else # define _ESTREAM_GCC_A_PRINTF( f, a ) #endif #endif /*_ESTREAM_GCC_A_PRINTF*/ #ifdef __cplusplus extern "C" { #if 0 } #endif #endif typedef int (*estream_printf_out_t) (void *outfncarg, const char *buf, size_t buflen); int estream_format (estream_printf_out_t outfnc, void *outfncarg, const char *format, va_list vaargs) _ESTREAM_GCC_A_PRINTF(3,0); int estream_printf (const char *format, ...) _ESTREAM_GCC_A_PRINTF(1,2); int estream_fprintf (FILE *fp, const char *format, ... ) _ESTREAM_GCC_A_PRINTF(2,3); int estream_vfprintf (FILE *fp, const char *format, va_list arg_ptr) _ESTREAM_GCC_A_PRINTF(2,0); int estream_snprintf (char *buf, size_t bufsize, const char *format, ...) _ESTREAM_GCC_A_PRINTF(3,4); int estream_vsnprintf (char *buf,size_t bufsize, const char *format, va_list arg_ptr) _ESTREAM_GCC_A_PRINTF(3,0); int estream_asprintf (char **bufp, const char *format, ...) _ESTREAM_GCC_A_PRINTF(2,3); int estream_vasprintf (char **bufp, const char *format, va_list arg_ptr) _ESTREAM_GCC_A_PRINTF(2,0); #ifdef __cplusplus } #endif #endif /*ESTREAM_PRINTF_H*/ diff --git a/common/xasprintf.c b/common/xasprintf.c index f16410dbd..a403c7b7c 100644 --- a/common/xasprintf.c +++ b/common/xasprintf.c @@ -1,61 +1,61 @@ /* xasprintf.c * Copyright (C) 2003, 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 3 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, see <http://www.gnu.org/licenses/>. */ #include <config.h> #include <stdlib.h> #include <errno.h> #include "util.h" #include "iobuf.h" -#if !defined(_ESTREAM_PRINTF_MALLOC) || !defined(_ESTREAM_PRINTF_FREE) -#error Need to define ESTREAM_PRINTF_MALLOC and _FREE +#if !defined(_ESTREAM_PRINTF_REALLOC) +#error Need to define _ESTREAM_PRINTF_REALLOC #endif /* Same as asprintf but return an allocated buffer suitable to be freed using xfree. This function simply dies on memory failure, thus no extra check is required. */ char * xasprintf (const char *fmt, ...) { va_list ap; char *buf; va_start (ap, fmt); if (estream_vasprintf (&buf, fmt, ap) < 0) log_fatal ("estream_asprintf failed: %s\n", strerror (errno)); va_end (ap); return buf; } /* Same as above but return NULL on memory failure. */ char * xtryasprintf (const char *fmt, ...) { int rc; va_list ap; char *buf; va_start (ap, fmt); rc = estream_vasprintf (&buf, fmt, ap); va_end (ap); if (rc < 0) return NULL; return buf; } diff --git a/configure.ac b/configure.ac index 9dd555ea7..ab847af09 100644 --- a/configure.ac +++ b/configure.ac @@ -1,1739 +1,1738 @@ # configure.ac - for GnuPG 2.1 # Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, # 2008, 2009, 2010, 2011 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 3 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, see <http://www.gnu.org/licenses/>. # Process this file with autoconf to produce a configure script. AC_PREREQ(2.61) min_automake_version="1.10" # Remember to change the version number immediately *after* a release. # Set my_issvn to "yes" for non-released code. Remember to run an # "svn up" and "autogen.sh" right before creating a distribution. m4_define([my_version], [2.1.0]) m4_define([my_issvn], [yes]) m4_define([svn_revision], m4_esyscmd([printf "%d" $(svn info 2>/dev/null \ | sed -n '/^Revision:/ s/[^0-9]//gp'|head -1)])) m4_define([git_revision], m4_esyscmd([git branch -v 2>/dev/null \ | awk '/^\* / {printf "%s",$3}'])) m4_define([my_full_version], [my_version[]m4_if(my_issvn,[yes], [m4_if(git_revision,[],[-svn[]svn_revision],[-git[]git_revision])])]) AC_INIT([gnupg],[my_full_version], [http://bugs.gnupg.org]) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. development_version=no NEED_GPG_ERROR_VERSION=1.10 NEED_LIBGCRYPT_API=1 NEED_LIBGCRYPT_VERSION=1.5.0 NEED_LIBASSUAN_API=2 NEED_LIBASSUAN_VERSION=2.0.3 NEED_KSBA_API=1 NEED_KSBA_VERSION=1.2.0 PACKAGE=$PACKAGE_NAME PACKAGE_GT=${PACKAGE_NAME}2 VERSION=$PACKAGE_VERSION AC_CONFIG_AUX_DIR(scripts) AC_CONFIG_SRCDIR(sm/gpgsm.c) AM_CONFIG_HEADER(config.h) AM_INIT_AUTOMAKE($PACKAGE, $VERSION) AC_CANONICAL_HOST AB_INIT AC_GNU_SOURCE # Some status variables. have_gpg_error=no have_libgcrypt=no have_libassuan=no have_ksba=no have_pth=no have_libusb=no have_adns=no use_zip=yes use_bzip2=yes use_exec=yes disable_keyserver_path=no use_ccid_driver=yes use_standard_socket=yes dirmngr_auto_start=no try_ks_ldap=no GNUPG_BUILD_PROGRAM(gpg, yes) GNUPG_BUILD_PROGRAM(gpgsm, yes) GNUPG_BUILD_PROGRAM(agent, yes) GNUPG_BUILD_PROGRAM(scdaemon, yes) GNUPG_BUILD_PROGRAM(g13, yes) GNUPG_BUILD_PROGRAM(dirmngr, yes) GNUPG_BUILD_PROGRAM(tools, yes) GNUPG_BUILD_PROGRAM(doc, yes) GNUPG_BUILD_PROGRAM(symcryptrun, no) GNUPG_BUILD_PROGRAM(gpgtar, no) AC_SUBST(PACKAGE) AC_SUBST(PACKAGE_GT) AC_SUBST(VERSION) AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of this package]) AC_DEFINE_UNQUOTED(PACKAGE_GT, "$PACKAGE_GT", [Name of this package for gettext]) AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version of this package]) AC_DEFINE_UNQUOTED(PACKAGE_BUGREPORT, "$PACKAGE_BUGREPORT", [Bug report address]) AC_DEFINE_UNQUOTED(NEED_LIBGCRYPT_VERSION, "$NEED_LIBGCRYPT_VERSION", [Required version of Libgcrypt]) AC_DEFINE_UNQUOTED(NEED_KSBA_VERSION, "$NEED_KSBA_VERSION", [Required version of Libksba]) # The default is to use the modules from this package and the few # other packages in a standard place; i.e where this package gets # installed. With these options it is possible to override these # ${prefix} depended values with fixed paths, which can't be replaced # at make time. See also am/cmacros.am and the defaults in AH_BOTTOM. AC_ARG_WITH(agent-pgm, [ --with-agent-pgm=PATH Use PATH as the default for the agent)], GNUPG_AGENT_PGM="$withval", GNUPG_AGENT_PGM="" ) AC_SUBST(GNUPG_AGENT_PGM) AM_CONDITIONAL(GNUPG_AGENT_PGM, test -n "$GNUPG_AGENT_PGM") show_gnupg_agent_pgm="(default)" test -n "$GNUPG_AGENT_PGM" && show_gnupg_agent_pgm="$GNUPG_AGENT_PGM" AC_ARG_WITH(pinentry-pgm, [ --with-pinentry-pgm=PATH Use PATH as the default for the pinentry)], GNUPG_PINENTRY_PGM="$withval", GNUPG_PINENTRY_PGM="" ) AC_SUBST(GNUPG_PINENTRY_PGM) AM_CONDITIONAL(GNUPG_PINENTRY_PGM, test -n "$GNUPG_PINENTRY_PGM") show_gnupg_pinentry_pgm="(default)" test -n "$GNUPG_PINENTRY_PGM" && show_gnupg_pinentry_pgm="$GNUPG_PINENTRY_PGM" AC_ARG_WITH(scdaemon-pgm, [ --with-scdaemon-pgm=PATH Use PATH as the default for the scdaemon)], GNUPG_SCDAEMON_PGM="$withval", GNUPG_SCDAEMON_PGM="" ) AC_SUBST(GNUPG_SCDAEMON_PGM) AM_CONDITIONAL(GNUPG_SCDAEMON_PGM, test -n "$GNUPG_SCDAEMON_PGM") show_gnupg_scdaemon_pgm="(default)" test -n "$GNUPG_SCDAEMON_PGM" && show_gnupg_scdaemon_pgm="$GNUPG_SCDAEMON_PGM" AC_ARG_WITH(dirmngr-pgm, [ --with-dirmngr-pgm=PATH Use PATH as the default for the dirmngr)], GNUPG_DIRMNGR_PGM="$withval", GNUPG_DIRMNGR_PGM="" ) AC_SUBST(GNUPG_DIRMNGR_PGM) AM_CONDITIONAL(GNUPG_DIRMNGR_PGM, test -n "$GNUPG_DIRMNGR_PGM") show_gnupg_dirmngr_pgm="(default)" test -n "$GNUPG_DIRMNGR_PGM" && show_gnupg_dirmngr_pgm="$GNUPG_DIRMNGR_PGM" AC_ARG_WITH(protect-tool-pgm, [ --with-protect-tool-pgm=PATH Use PATH as the default for the protect-tool)], GNUPG_PROTECT_TOOL_PGM="$withval", GNUPG_PROTECT_TOOL_PGM="" ) AC_SUBST(GNUPG_PROTECT_TOOL_PGM) AM_CONDITIONAL(GNUPG_PROTECT_TOOL_PGM, test -n "$GNUPG_PROTECT_TOOL_PGM") show_gnupg_protect_tool_pgm="(default)" test -n "$GNUPG_PROTECT_TOOL_PGM" \ && show_gnupg_protect_tool_pgm="$GNUPG_PROTECT_TOOL_PGM" AC_ARG_WITH(dirmngr-ldap-pgm, [ --with-dirmngr-ldap-pgm=PATH Use PATH as the default for the dirmnge ldap wrapper)], GNUPG_DIRMNGR_LDAP_PGM="$withval", GNUPG_DIRMNGR_LDAP_PGM="" ) AC_SUBST(GNUPG_DIRMNGR_LDAP_PGM) AM_CONDITIONAL(GNUPG_DIRMNGR_LDAP_PGM, test -n "$GNUPG_DIRMNGR_LDAP_PGM") show_gnupg_dirmngr_ldap_pgm="(default)" test -n "$GNUPG_DIRMNGR_LDAP_PGM" \ && show_gnupg_dirmngr_ldap_pgm="$GNUPG_DIRMNGR_LDAP_PGM" # # On some platforms gpg2 is usually installed as gpg without using a # symlink. For correct operation of gpgconf it needs to know the # installed name of gpg. This option sets "gpg2"'s installed name to # just "gpg". Note that it might be required to rename gpg2 to gpg # manually after the build process. # AC_ARG_ENABLE(gpg2-is-gpg, AC_HELP_STRING([--enable-gpg2-is-gpg],[Set installed name of gpg2 to gpg]), gpg2_is_gpg=$enableval) if test "$gpg2_is_gpg" = "yes"; then name_of_installed_gpg=gpg else name_of_installed_gpg=gpg2 fi AC_DEFINE_UNQUOTED(NAME_OF_INSTALLED_GPG, "$name_of_installed_gpg", [The name of the installed GPG tool]) # Some folks want to use only the agent from this packet. Make it # easier for them by providing the configure option # --enable-only-agent. AC_ARG_ENABLE(agent-only, AC_HELP_STRING([--enable-agent-only],[build only the gpg-agent]), build_agent_only=$enableval) # SELinux support includes tracking of sensitive files to avoid # leaking their contents through processing these files by gpg itself AC_MSG_CHECKING([whether SELinux support is requested]) AC_ARG_ENABLE(selinux-support, AC_HELP_STRING([--enable-selinux-support], [enable SELinux support]), selinux_support=$enableval, selinux_support=no) AC_MSG_RESULT($selinux_support) # Allow disabling of zip support. # This is in general not a good idea because according to rfc4880 OpenPGP # implementations SHOULD support ZLIB. AC_MSG_CHECKING([whether to enable the ZIP and ZLIB compression algorithm]) AC_ARG_ENABLE(zip, AC_HELP_STRING([--disable-zip], [disable the ZIP and ZLIB compression algorithm]), use_zip=$enableval) AC_MSG_RESULT($use_zip) # Allow disabling of bzib2 support. # It is defined only after we confirm the library is available later AC_MSG_CHECKING([whether to enable the BZIP2 compression algorithm]) AC_ARG_ENABLE(bzip2, AC_HELP_STRING([--disable-bzip2],[disable the BZIP2 compression algorithm]), use_bzip2=$enableval) AC_MSG_RESULT($use_bzip2) # Configure option to allow or disallow execution of external # programs, like a photo viewer. AC_MSG_CHECKING([whether to enable external program execution]) AC_ARG_ENABLE(exec, AC_HELP_STRING([--disable-exec],[disable all external program execution]), use_exec=$enableval) AC_MSG_RESULT($use_exec) if test "$use_exec" = no ; then AC_DEFINE(NO_EXEC,1,[Define to disable all external program execution]) fi if test "$use_exec" = yes ; then AC_MSG_CHECKING([whether to enable photo ID viewing]) AC_ARG_ENABLE(photo-viewers, [ --disable-photo-viewers disable photo ID viewers], [if test "$enableval" = no ; then AC_DEFINE(DISABLE_PHOTO_VIEWER,1,[define to disable photo viewing]) fi],enableval=yes) gnupg_cv_enable_photo_viewers=$enableval AC_MSG_RESULT($enableval) if test "$gnupg_cv_enable_photo_viewers" = yes ; then AC_MSG_CHECKING([whether to use a fixed photo ID viewer]) AC_ARG_WITH(photo-viewer, [ --with-photo-viewer=FIXED_VIEWER set a fixed photo ID viewer], [if test "$withval" = yes ; then withval=no elif test "$withval" != no ; then AC_DEFINE_UNQUOTED(FIXED_PHOTO_VIEWER,"$withval", [if set, restrict photo-viewer to this]) fi],withval=no) AC_MSG_RESULT($withval) fi AC_MSG_CHECKING([whether to enable external keyserver helpers]) AC_ARG_ENABLE(keyserver-helpers, [ --disable-keyserver-helpers disable all external keyserver support], [if test "$enableval" = no ; then AC_DEFINE(DISABLE_KEYSERVER_HELPERS,1, [define to disable keyserver helpers]) fi],enableval=yes) gnupg_cv_enable_keyserver_helpers=$enableval AC_MSG_RESULT($enableval) if test "$gnupg_cv_enable_keyserver_helpers" = yes ; then # LDAP is defined only after we confirm the library is available later AC_MSG_CHECKING([whether LDAP keyserver support is requested]) AC_ARG_ENABLE(ldap, AC_HELP_STRING([--disable-ldap],[disable LDAP keyserver interface only]), try_ks_ldap=$enableval, try_ks_ldap=yes) AC_MSG_RESULT($try_ks_ldap) AC_MSG_CHECKING([whether HKP keyserver support is requested]) AC_ARG_ENABLE(hkp, AC_HELP_STRING([--disable-hkp],[disable HKP keyserver interface only]), try_hkp=$enableval, try_hkp=yes) AC_MSG_RESULT($try_hkp) AC_MSG_CHECKING([whether finger key fetching support is requested]) AC_ARG_ENABLE(finger, AC_HELP_STRING([--disable-finger], [disable finger key fetching interface only]), try_finger=$enableval, try_finger=yes) AC_MSG_RESULT($try_finger) AC_MSG_CHECKING([whether generic object key fetching support is requested]) AC_ARG_ENABLE(generic, AC_HELP_STRING([--disable-generic], [disable generic object key fetching interface only]), try_generic=$enableval, try_generic=yes) AC_MSG_RESULT($try_generic) AC_MSG_CHECKING([whether email keyserver support is requested]) AC_ARG_ENABLE(mailto, AC_HELP_STRING([--enable-mailto], [enable email keyserver interface only]), try_mailto=$enableval, try_mailto=no) AC_MSG_RESULT($try_mailto) fi AC_MSG_CHECKING([whether keyserver exec-path is enabled]) AC_ARG_ENABLE(keyserver-path, AC_HELP_STRING([--disable-keyserver-path], [disable the exec-path option for keyserver helpers]), [if test "$enableval" = no ; then disable_keyserver_path=yes fi],enableval=yes) AC_MSG_RESULT($enableval) fi # # Check for the key/uid cache size. This can't be zero, but can be # pretty small on embedded systems. This is used for the gpg part. # AC_MSG_CHECKING([for the size of the key and uid cache]) AC_ARG_ENABLE(key-cache, AC_HELP_STRING([--enable-key-cache=SIZE], [Set key cache to SIZE (default 4096)]),,enableval=4096) if test "$enableval" = "no"; then enableval=5 elif test "$enableval" = "yes" || test "$enableval" = ""; then enableval=4096 fi changequote(,)dnl key_cache_size=`echo "$enableval" | sed 's/[A-Za-z]//g'` changequote([,])dnl if test "$enableval" != "$key_cache_size" || test "$key_cache_size" -lt 5; then AC_MSG_ERROR([invalid key-cache size]) fi AC_MSG_RESULT($key_cache_size) AC_DEFINE_UNQUOTED(PK_UID_CACHE_SIZE,$key_cache_size, [Size of the key and UID caches]) # # Check whether we want to use Linux capabilities # AC_MSG_CHECKING([whether use of capabilities is requested]) AC_ARG_WITH(capabilities, [ --with-capabilities use linux capabilities [default=no]], [use_capabilities="$withval"],[use_capabilities=no]) AC_MSG_RESULT($use_capabilities) # # Allow disabling of internal CCID support. # It is defined only after we confirm the library is available later # AC_MSG_CHECKING([whether to enable the internal CCID driver]) AC_ARG_ENABLE(ccid-driver, AC_HELP_STRING([--disable-ccid-driver], [disable the internal CCID driver]), use_ccid_driver=$enableval) AC_MSG_RESULT($use_ccid_driver) # # Dirmngr is nowadays a system service and thus it usually does no # make sense to start it as needed. However on some systems this is # possible; this option enable the feature. # AC_MSG_CHECKING([whether to auto start dirmngr]) AC_ARG_ENABLE(dirmngr-auto-start, AC_HELP_STRING([--enable-dirmngr-auto-start], [enable auto starting of the dirmngr]), dirmngr_auto_start=$enableval) AC_MSG_RESULT($dirmngr_auto_start) if test "$dirmngr_auto_start" = yes ; then AC_DEFINE(USE_DIRMNGR_AUTO_START,1, [Define to enable auto starting of the dirmngr]) fi # # To avoid double inclusion of config.h which might happen at some # places, we add the usual double inclusion protection at the top of # config.h. # AH_TOP([ #ifndef GNUPG_CONFIG_H_INCLUDED #define GNUPG_CONFIG_H_INCLUDED ]) # # Stuff which goes at the bottom of config.h. # AH_BOTTOM([ /* This is the major version number of GnuPG so that source included files can test for this. Note, that we use 2 here even for GnuPG 1.9.x. */ #define GNUPG_MAJOR_VERSION 2 /* Now to separate file name parts. Please note that the string version must not contain more than one character because the code assumes strlen()==1 */ #ifdef HAVE_DOSISH_SYSTEM #define DIRSEP_C '\\' #define DIRSEP_S "\\" #define EXTSEP_C '.' #define EXTSEP_S "." #define PATHSEP_C ';' #define PATHSEP_S ";" #define EXEEXT_S ".exe" #else #define DIRSEP_C '/' #define DIRSEP_S "/" #define EXTSEP_C '.' #define EXTSEP_S "." #define PATHSEP_C ':' #define PATHSEP_S ":" #define EXEEXT_S "" #endif /* This is the same as VERSION, but should be overridden if the platform cannot handle things like dots '.' in filenames. Set SAFE_VERSION_DOT and SAFE_VERSION_DASH to whatever SAFE_VERSION uses for dots and dashes. */ #define SAFE_VERSION VERSION #define SAFE_VERSION_DOT '.' #define SAFE_VERSION_DASH '-' /* Some global constants. */ #ifdef HAVE_DOSISH_SYSTEM # ifdef HAVE_DRIVE_LETTERS # define GNUPG_DEFAULT_HOMEDIR "c:/gnupg" # else # define GNUPG_DEFAULT_HOMEDIR "/gnupg" # endif #elif defined(__VMS) #define GNUPG_DEFAULT_HOMEDIR "/SYS$LOGIN/gnupg" #else #define GNUPG_DEFAULT_HOMEDIR "~/.gnupg" #endif #define GNUPG_PRIVATE_KEYS_DIR "private-keys-v1.d" /* For some systems (DOS currently), we hardcode the path here. For POSIX systems the values are constructed by the Makefiles, so that the values may be overridden by the make invocations; this is to comply with the GNU coding standards. Note that these values are only defaults. */ #ifdef HAVE_DOSISH_SYSTEM # ifdef HAVE_DRIVE_LETTERS # define GNUPG_BINDIR "c:\\gnupg" # define GNUPG_LIBEXECDIR "c:\\gnupg" # define GNUPG_LIBDIR "c:\\gnupg" # define GNUPG_DATADIR "c:\\gnupg" # define GNUPG_SYSCONFDIR "c:\\gnupg" # else # define GNUPG_BINDIR "\\gnupg" # define GNUPG_LIBEXECDIR "\\gnupg" # define GNUPG_LIBDIR "\\gnupg" # define GNUPG_DATADIR "\\gnupg" # define GNUPG_SYSCONFDIR "\\gnupg" # endif #endif /* Derive some other constants. */ #if !(defined(HAVE_FORK) && defined(HAVE_PIPE) && defined(HAVE_WAITPID)) #define EXEC_TEMPFILE_ONLY #endif /* We didn't define endianness above, so get it from OS macros. This is intended for making fat binary builds on OS X. */ #if !defined(BIG_ENDIAN_HOST) && !defined(LITTLE_ENDIAN_HOST) #if defined(__BIG_ENDIAN__) #define BIG_ENDIAN_HOST 1 #elif defined(__LITTLE_ENDIAN__) #define LITTLE_ENDIAN_HOST 1 #else #error "No endianness found" #endif #endif /* Hack used for W32: ldap.m4 also tests for the ASCII version of ldap_start_tls_s because that is the actual symbol used in the library. winldap.h redefines it to our commonly used value, thus we define our usual macro here. */ #ifdef HAVE_LDAP_START_TLS_SA # ifndef HAVE_LDAP_START_TLS_S # define HAVE_LDAP_START_TLS_S 1 # endif #endif /* Tell libgcrypt not to use its own libgpg-error implementation. */ #define USE_LIBGPG_ERROR 1 /* We use jnlib, so tell other modules about it. */ #define HAVE_JNLIB_LOGGING 1 /* Our HTTP code is used in estream mode. */ #define HTTP_USE_ESTREAM 1 /* Under W32 we do an explicit socket initialization, thus we need to avoid the on-demand initialization which would also install an atexit handler. */ #define HTTP_NO_WSASTARTUP /* We always include support for the OpenPGP card. */ #define ENABLE_CARD_SUPPORT 1 /* We explicitly need to disable PTH's soft mapping as Debian currently enables it by default for no reason. */ #define PTH_SYSCALL_SOFT 0 /* We want to use the libgcrypt provided memory allocation for asprintf. */ -#define _ESTREAM_PRINTF_MALLOC gcry_malloc -#define _ESTREAM_PRINTF_FREE gcry_free +#define _ESTREAM_PRINTF_REALLOC gcry_realloc #define _ESTREAM_PRINTF_EXTRA_INCLUDE "../common/util.h" /* Under Windows we use the gettext code from libgpg-error. */ #define GPG_ERR_ENABLE_GETTEXT_MACROS /* Under WindowsCE we use the strerror replacement from libgpg-error. */ #define GPG_ERR_ENABLE_ERRNO_MACROS #endif /*GNUPG_CONFIG_H_INCLUDED*/ ]) AM_MAINTAINER_MODE # Checks for programs. AC_MSG_NOTICE([checking for programs]) AC_PROG_MAKE_SET AM_SANITY_CHECK missing_dir=`cd $ac_aux_dir && pwd` AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir) AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir) AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) AC_PROG_AWK AC_PROG_CC AC_PROG_CPP AM_PROG_CC_C_O if test "x$ac_cv_prog_cc_c89" = "xno" ; then AC_MSG_ERROR([[No C-89 compiler found]]) fi AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_RANLIB AC_CHECK_TOOL(AR, ar, :) AC_PATH_PROG(PERL,"perl") AC_CHECK_TOOL(WINDRES, windres, :) AC_ISC_POSIX gl_EARLY AC_SYS_LARGEFILE GNUPG_CHECK_USTAR # We need to compile and run a program on the build machine. A # comment in libgpg-error says that the AC_PROG_CC_FOR_BUILD macro in # the AC archive is broken for autoconf 2.57. Given that there is no # newer version of that macro, we assume that it is also broken for # autoconf 2.61 and thus we use a simple but usually sufficient # approach. AC_MSG_CHECKING(for cc for build) if test "$cross_compiling" = "yes"; then CC_FOR_BUILD="${CC_FOR_BUILD-cc}" else CC_FOR_BUILD="${CC_FOR_BUILD-$CC}" fi AC_MSG_RESULT($CC_FOR_BUILD) AC_ARG_VAR(CC_FOR_BUILD,[build system C compiler]) try_gettext=yes have_dosish_system=no have_w32_system=no have_w32ce_system=no use_simple_gettext=no use_ldapwrapper=yes mmap_needed=yes case "${host}" in *-mingw32*) # special stuff for Windoze NT ac_cv_have_dev_random=no AC_DEFINE(USE_ONLY_8DOT3,1, [Set this to limit filenames to the 8.3 format]) AC_DEFINE(USE_SIMPLE_GETTEXT,1, [Because the Unix gettext has too much overhead on MingW32 systems and these systems lack Posix functions, we use a simplified version of gettext]) disable_keyserver_path=yes have_dosish_system=yes have_w32_system=yes use_ldapwrapper=no # Fixme: Do this only for CE. case "${host}" in *-mingw32ce*) have_w32ce_system=yes ;; *) AC_DEFINE(HAVE_DRIVE_LETTERS,1, [Defined if the OS supports drive letters.]) ;; esac try_gettext="no" use_simple_gettext=yes mmap_needed=no ;; i?86-emx-os2 | i?86-*-os2*emx ) # OS/2 with the EMX environment ac_cv_have_dev_random=no AC_DEFINE(HAVE_DRIVE_LETTERS) have_dosish_system=yes try_gettext="no" ;; i?86-*-msdosdjgpp*) # DOS with the DJGPP environment ac_cv_have_dev_random=no AC_DEFINE(HAVE_DRIVE_LETTERS) have_dosish_system=yes try_gettext="no" ;; *-*-freebsd*) # FreeBSD CPPFLAGS="$CPPFLAGS -I/usr/local/include" LDFLAGS="$LDFLAGS -L/usr/local/lib" ;; *-*-hpux*) if test -z "$GCC" ; then CFLAGS="$CFLAGS -Ae -D_HPUX_SOURCE" fi ;; *-dec-osf4*) if test -z "$GCC" ; then # Suppress all warnings # to get rid of the unsigned/signed char mismatch warnings. CFLAGS="$CFLAGS -w" fi ;; *-dec-osf5*) if test -z "$GCC" ; then # Use the newer compiler `-msg_disable ptrmismatch1' to # get rid of the unsigned/signed char mismatch warnings. # Using this may hide other pointer mismatch warnings, but # it at least lets other warning classes through CFLAGS="$CFLAGS -msg_disable ptrmismatch1" fi ;; m68k-atari-mint) ;; *) ;; esac if test "$have_dosish_system" = yes; then AC_DEFINE(HAVE_DOSISH_SYSTEM,1, [Defined if we run on some of the PCDOS like systems (DOS, Windoze. OS/2) with special properties like no file modes, case insensitive file names and preferred use of backslashes as directory name separators.]) fi AM_CONDITIONAL(HAVE_DOSISH_SYSTEM, test "$have_dosish_system" = yes) AM_CONDITIONAL(USE_SIMPLE_GETTEXT, test x"$use_simple_gettext" = xyes) if test "$have_w32_system" = yes; then AC_DEFINE(HAVE_W32_SYSTEM,1, [Defined if we run on a W32 API based system]) if test "$have_w32ce_system" = yes; then AC_DEFINE(HAVE_W32CE_SYSTEM,1,[Defined if we run on WindowsCE]) fi fi AM_CONDITIONAL(HAVE_W32_SYSTEM, test "$have_w32_system" = yes) AM_CONDITIONAL(HAVE_W32CE_SYSTEM, test "$have_w32ce_system" = yes) if test "$use_ldapwrapper" = yes; then AC_DEFINE(USE_LDAPWRAPPER,1, [Build dirmngr with LDAP wrapper process]) fi AM_CONDITIONAL(USE_LDAPWRAPPER, test "$use_ldapwrapper" = yes) if test "$disable_keyserver_path" = yes; then AC_DEFINE(DISABLE_KEYSERVER_PATH,1, [Defined to disable exec-path for keyserver helpers]) fi # # Allows enabling the use of a standard socket by default This is # gpg-agent's option --[no-]use-standard-socket. For Windows we force # the use of this. # AC_MSG_CHECKING([whether to use a standard socket by default]) AC_ARG_ENABLE(standard-socket, AC_HELP_STRING([--disable-standard-socket], [don't use a standard socket by default]), use_standard_socket=$enableval) tmp="" if test "$use_standard_socket" != yes; then if test "$have_w32_system" = yes; then use_standard_socket=yes tmp=" (forced)" fi fi AC_MSG_RESULT($use_standard_socket$tmp) if test "$use_standard_socket" = yes; then AC_DEFINE(USE_STANDARD_SOCKET,1, [Use the standard socket for the agent by default]) fi # (These need to go after AC_PROG_CC so that $EXEEXT is defined) AC_DEFINE_UNQUOTED(EXEEXT,"$EXEEXT",[The executable file extension, if any]) if test x"$try_hkp" = xyes ; then AC_SUBST(GPGKEYS_HKP,"gpg2keys_hkp$EXEEXT") fi if test x"$try_finger" = xyes ; then AC_SUBST(GPGKEYS_FINGER,"gpg2keys_finger$EXEEXT") fi # # Checks for libraries. # AC_MSG_NOTICE([checking for libraries]) # # libgpg-error is a library with error codes shared between GnuPG # related projects. # AM_PATH_GPG_ERROR("$NEED_GPG_ERROR_VERSION", have_gpg_error=yes,have_gpg_error=no) # # Libgcrypt is our generic crypto library # AM_PATH_LIBGCRYPT("$NEED_LIBGCRYPT_API:$NEED_LIBGCRYPT_VERSION", have_libgcrypt=yes,have_libgcrypt=no) # # libassuan is used for IPC # AM_PATH_LIBASSUAN("$NEED_LIBASSUAN_API:$NEED_LIBASSUAN_VERSION", have_libassuan=yes,have_libassuan=no) if test "$have_libassuan" = "yes"; then AC_DEFINE_UNQUOTED(GNUPG_LIBASSUAN_VERSION, "$libassuan_version", [version of the libassuan library]) fi # # libksba is our X.509 support library # AM_PATH_KSBA("$NEED_KSBA_API:$NEED_KSBA_VERSION",have_ksba=yes,have_ksba=no) # # libusb allows us to use the integrated CCID smartcard reader driver. # # FiXME: Use GNUPG_CHECK_LIBUSB and modify to use separate AC_SUBSTs. if test "$use_ccid_driver" = yes ; then AC_CHECK_LIB(usb, usb_bulk_write, [ LIBUSB_LIBS="$LIBUSB_LIBS -lusb" AC_DEFINE(HAVE_LIBUSB,1, [defined if libusb is available]) have_libusb=yes ]) AC_CHECK_FUNCS(usb_create_match) fi AC_SUBST(LIBUSB_LIBS) # # Check wether it is necessary to link against libdl. # gnupg_dlopen_save_libs="$LIBS" LIBS="" AC_SEARCH_LIBS(dlopen, c dl,,,) DL_LIBS=$LIBS AC_SUBST(DL_LIBS) LIBS="$gnupg_dlopen_save_libs" # Checks for g13 AC_PATH_PROG(ENCFS, encfs, /usr/bin/encfs) AC_DEFINE_UNQUOTED(ENCFS, "${ENCFS}", [defines the filename of the encfs program]) AC_PATH_PROG(FUSERMOUNT, fusermount, /usr/bin/fusermount) AC_DEFINE_UNQUOTED(FUSERMOUNT, "${FUSERMOUNT}", [defines the filename of the fusermount program]) # Checks for dirmngr # # Checks for symcryptrun: # # libutil has openpty() and login_tty(). AC_CHECK_LIB(util, openpty, [ LIBUTIL_LIBS="$LIBUTIL_LIBS -lutil" AC_DEFINE(HAVE_LIBUTIL,1, [defined if libutil is available]) ]) AC_SUBST(LIBUTIL_LIBS) # shred is used to clean temporary plain text files. AC_PATH_PROG(SHRED, shred, /usr/bin/shred) AC_DEFINE_UNQUOTED(SHRED, "${SHRED}", [defines the filename of the shred program]) # # Check whether the GNU Pth library is available # Note, that we include a Pth emulation for W32. # if test "$have_w32_system" = yes; then GNUPG_PATH_PTH([2.0.4]) else GNUPG_PATH_PTH fi if test "$have_pth" = "yes"; then AC_DEFINE(USE_GNU_PTH, 1, [Defined if the GNU Portable Thread Library should be used]) else AC_MSG_WARN([[ *** *** To support concurrent access to the gpg-agent and the SCdaemon *** we need the support of the GNU Portable Threads Library. *** Download it from ftp://ftp.gnu.org/gnu/pth/ *** On a Debian GNU/Linux system you might want to try *** apt-get install libpth-dev ***]]) fi AC_MSG_NOTICE([checking for networking options]) # # Must check for network library requirements before doing link tests # for ldap, for example. If ldap libs are static (or dynamic and without # ELF runtime link paths), then link will fail and LDAP support won't # be detected. # AC_CHECK_FUNC(gethostbyname, , AC_CHECK_LIB(nsl, gethostbyname, [NETLIBS="-lnsl $NETLIBS"])) AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt, [NETLIBS="-lsocket $NETLIBS"])) # # Check for ADNS. # _cppflags="${CPPFLAGS}" _ldflags="${LDFLAGS}" AC_ARG_WITH(adns, AC_HELP_STRING([--with-adns=DIR], [look for the adns library in DIR]), [if test -d "$withval"; then CPPFLAGS="${CPPFLAGS} -I$withval/include" LDFLAGS="${LDFLAGS} -L$withval/lib" fi]) if test "$with_adns" != "no"; then AC_CHECK_HEADERS(adns.h, AC_CHECK_LIB(adns, adns_init, [have_adns=yes], [CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}]), [CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}]) fi if test "$have_adns" = "yes"; then ADNSLIBS="-ladns" fi AC_SUBST(ADNSLIBS) # Newer adns versions feature a free function to be used under W32. AC_CHECK_FUNCS(adns_free) # # Now try for the resolver functions so we can use DNS for SRV, PA and CERT. # if test x"$try_hkp" = xyes || test x"$try_http" = xyes ; then AC_ARG_ENABLE(dns-srv, AC_HELP_STRING([--disable-dns-srv], [disable the use of DNS SRV in HKP and HTTP]), use_dns_srv=$enableval,use_dns_srv=yes) fi AC_ARG_ENABLE(dns-pka, AC_HELP_STRING([--disable-dns-pka], [disable the use of PKA records in DNS]), use_dns_pka=$enableval,use_dns_pka=yes) AC_ARG_ENABLE(dns-cert, AC_HELP_STRING([--disable-dns-cert], [disable the use of CERT records in DNS]), use_dns_cert=$enableval,use_dns_cert=yes) if test x"$use_dns_pka" = xyes || test x"$use_dns_srv" = xyes \ || test x"$use_dns_cert" = xyes; then _dns_save_libs=$LIBS LIBS="" # the double underscore thing is a glibc-ism? AC_SEARCH_LIBS(res_query,resolv bind,, AC_SEARCH_LIBS(__res_query,resolv bind,,have_resolver=no)) AC_SEARCH_LIBS(dn_expand,resolv bind,, AC_SEARCH_LIBS(__dn_expand,resolv bind,,have_resolver=no)) AC_SEARCH_LIBS(dn_skipname,resolv bind,, AC_SEARCH_LIBS(__dn_skipname,resolv bind,,have_resolver=no)) if test x"$have_resolver" != xno ; then # Make sure that the BIND 4 resolver interface is workable before # enabling any code that calls it. At some point I'll rewrite the # code to use the BIND 8 resolver API. # We might also want to use adns instead. Problem with ADNS is that # it does not support v6. AC_MSG_CHECKING([whether the resolver is usable]) AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h> #include <netinet/in.h> #include <arpa/nameser.h> #include <resolv.h>]], [[unsigned char answer[PACKETSZ]; res_query("foo.bar",C_IN,T_A,answer,PACKETSZ); dn_skipname(0,0); dn_expand(0,0,0,0,0); ]])],have_resolver=yes,have_resolver=no) AC_MSG_RESULT($have_resolver) # This is Apple-specific and somewhat bizarre as they changed the # define in bind 8 for some reason. if test x"$have_resolver" != xyes ; then AC_MSG_CHECKING( [whether I can make the resolver usable with BIND_8_COMPAT]) AC_LINK_IFELSE([AC_LANG_PROGRAM([[#define BIND_8_COMPAT #include <sys/types.h> #include <netinet/in.h> #include <arpa/nameser.h> #include <resolv.h>]], [[unsigned char answer[PACKETSZ]; res_query("foo.bar",C_IN,T_A,answer,PACKETSZ); dn_skipname(0,0); dn_expand(0,0,0,0,0); ]])],[have_resolver=yes ; need_compat=yes]) AC_MSG_RESULT($have_resolver) fi fi if test x"$have_resolver" = xyes ; then DNSLIBS=$LIBS if test x"$use_dns_srv" = xyes ; then AC_DEFINE(USE_DNS_SRV,1,[define to use DNS SRV]) fi if test x"$use_dns_pka" = xyes ; then AC_DEFINE(USE_DNS_PKA,1,[define to use our experimental DNS PKA]) fi if test x"$use_dns_cert" = xyes ; then AC_DEFINE(USE_DNS_CERT,1,[define to use DNS CERT]) fi if test x"$need_compat" = xyes ; then AC_DEFINE(BIND_8_COMPAT,1,[an Apple OSXism]) fi else # If we have no resolver library but ADNS (e.g. under W32) enable the # code parts which can be used with ADNS. if test x"$have_adns" = xyes ; then DNSLIBS="$ADNSLIBS" AC_DEFINE(USE_ADNS,1,[Use ADNS as resolver library.]) if test x"$use_dns_srv" = xyes ; then AC_DEFINE(USE_DNS_SRV,1) fi if test x"$use_dns_pka" = xyes ; then AC_DEFINE(USE_DNS_PKA,1) fi if test x"$use_dns_cert" = xyes ; then AC_DEFINE(USE_DNS_CERT,1,[define to use DNS CERT]) fi else use_dns_srv=no use_dns_pka=no use_dns_cert=no fi fi LIBS=$_dns_save_libs fi AC_SUBST(DNSLIBS) AM_CONDITIONAL(USE_DNS_SRV, test x"$use_dns_srv" = xyes) # # Check for LDAP # if test "$try_ks_ldap" = yes || test "$build_dirmngr" = "yes" ; then GNUPG_CHECK_LDAP($NETLIBS) fi # # Check for curl. We fake the curl API if libcurl isn't installed. # We require 7.10 or later as we use curl_version_info(). # LIBCURL_CHECK_CONFIG([yes],[7.10],,[fake_curl=yes]) AM_CONDITIONAL(FAKE_CURL,test x"$fake_curl" = xyes) # Generic, for us, means curl if test x"$try_generic" = xyes ; then AC_SUBST(GPGKEYS_CURL,"gpg2keys_curl$EXEEXT") fi # # Check for sendmail # # This isn't necessarily sendmail itself, but anything that gives a # sendmail-ish interface to the outside world. That includes Exim, # Postfix, etc. Basically, anything that can handle "sendmail -t". if test "$try_mailto" = yes ; then AC_ARG_WITH(mailprog, AC_HELP_STRING([--with-mailprog=NAME], [use "NAME -t" for mail transport]), ,with_mailprog=yes) if test x"$with_mailprog" = xyes ; then AC_PATH_PROG(SENDMAIL,sendmail,,$PATH:/usr/sbin:/usr/libexec:/usr/lib) if test "$ac_cv_path_SENDMAIL" ; then GPGKEYS_MAILTO="gpg2keys_mailto" fi elif test x"$with_mailprog" != xno ; then AC_MSG_CHECKING([for a mail transport program]) AC_SUBST(SENDMAIL,$with_mailprog) AC_MSG_RESULT($with_mailprog) GPGKEYS_MAILTO="gpg2keys_mailto" fi fi AC_SUBST(GPGKEYS_MAILTO) # # Construct a printable name of the OS # case "${host}" in *-mingw32ce*) PRINTABLE_OS_NAME="W32CE" ;; *-mingw32*) PRINTABLE_OS_NAME="MingW32" ;; *-*-cygwin*) PRINTABLE_OS_NAME="Cygwin" ;; i?86-emx-os2 | i?86-*-os2*emx ) PRINTABLE_OS_NAME="OS/2" ;; i?86-*-msdosdjgpp*) PRINTABLE_OS_NAME="MSDOS/DJGPP" try_dynload=no ;; *-linux*) PRINTABLE_OS_NAME="GNU/Linux" ;; *) PRINTABLE_OS_NAME=`uname -s || echo "Unknown"` ;; esac AC_DEFINE_UNQUOTED(PRINTABLE_OS_NAME, "$PRINTABLE_OS_NAME", [A human readable text with the name of the OS]) # # Checking for iconv # AM_ICONV # # Check for gettext # # This is "GNU gnupg" - The project-id script from gettext # needs this string # AC_MSG_NOTICE([checking for gettext]) AM_PO_SUBDIRS AM_GNU_GETTEXT_VERSION([0.17]) if test "$try_gettext" = yes; then AM_GNU_GETTEXT([external],[need-ngettext]) # gettext requires some extra checks. These really should be part of # the basic AM_GNU_GETTEXT macro. TODO: move other gettext-specific # function checks to here. AC_CHECK_FUNCS(strchr) else USE_NLS=no USE_INCLUDED_LIBINTL=no BUILD_INCLUDED_LIBINTL=no POSUB=po AC_SUBST(USE_NLS) AC_SUBST(USE_INCLUDED_LIBINTL) AC_SUBST(BUILD_INCLUDED_LIBINTL) AC_SUBST(POSUB) fi # We use HAVE_LANGINFO_CODESET in a couple of places. AM_LANGINFO_CODESET # Checks required for our use locales gt_LC_MESSAGES # # SELinux support # if test "$selinux_support" = yes ; then AC_DEFINE(ENABLE_SELINUX_HACKS,1,[Define to enable SELinux support]) fi # # Checks for header files. # AC_MSG_NOTICE([checking for header files]) AC_HEADER_STDC AC_CHECK_HEADERS([string.h unistd.h langinfo.h termio.h locale.h getopt.h \ pty.h utmp.h pwd.h inttypes.h signal.h]) AC_HEADER_TIME # # Checks for typedefs, structures, and compiler characteristics. # AC_MSG_NOTICE([checking for system characteristics]) AC_C_CONST AC_C_INLINE AC_C_VOLATILE AC_TYPE_SIZE_T AC_TYPE_MODE_T AC_TYPE_SIGNAL AC_DECL_SYS_SIGLIST gl_HEADER_SYS_SOCKET gl_TYPE_SOCKLEN_T AC_ARG_ENABLE(endian-check, AC_HELP_STRING([--disable-endian-check], [disable the endian check and trust the OS provided macros]), endiancheck=$enableval,endiancheck=yes) if test x"$endiancheck" = xyes ; then GNUPG_CHECK_ENDIAN fi # fixme: we should get rid of the byte type GNUPG_CHECK_TYPEDEF(byte, HAVE_BYTE_TYPEDEF) GNUPG_CHECK_TYPEDEF(ushort, HAVE_USHORT_TYPEDEF) GNUPG_CHECK_TYPEDEF(ulong, HAVE_ULONG_TYPEDEF) GNUPG_CHECK_TYPEDEF(u16, HAVE_U16_TYPEDEF) GNUPG_CHECK_TYPEDEF(u32, HAVE_U32_TYPEDEF) AC_CHECK_SIZEOF(unsigned short) AC_CHECK_SIZEOF(unsigned int) AC_CHECK_SIZEOF(unsigned long) AC_CHECK_SIZEOF(unsigned long long) AC_HEADER_TIME AC_CHECK_SIZEOF(time_t,,[[ #include <stdio.h> #if TIME_WITH_SYS_TIME # include <sys/time.h> # include <time.h> #else # if HAVE_SYS_TIME_H # include <sys/time.h> # else # include <time.h> # endif #endif ]]) GNUPG_TIME_T_UNSIGNED # Ensure that we have UINT64_C before we bother to check for uint64_t # Fixme: really needed in gnupg? I think it is only useful in libcgrypt. AC_CACHE_CHECK([for UINT64_C],[gnupg_cv_uint64_c_works], AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <inttypes.h>]], [[uint64_t foo=UINT64_C(42);]])], gnupg_cv_uint64_c_works=yes,gnupg_cv_uint64_c_works=no)) if test "$gnupg_cv_uint64_c_works" = "yes" ; then AC_CHECK_SIZEOF(uint64_t) fi if test "$ac_cv_sizeof_unsigned_short" = "0" \ || test "$ac_cv_sizeof_unsigned_int" = "0" \ || test "$ac_cv_sizeof_unsigned_long" = "0"; then AC_MSG_WARN([Hmmm, something is wrong with the sizes - using defaults]); fi # # Checks for library functions. # AC_MSG_NOTICE([checking for library functions]) AC_CHECK_DECLS(getpagesize) AC_FUNC_FSEEKO AC_FUNC_VPRINTF AC_FUNC_FORK AC_CHECK_FUNCS([strerror strlwr tcgetattr mmap canonicalize_file_name]) AC_CHECK_FUNCS([strcasecmp strncasecmp ctermid times gmtime_r strtoull]) AC_CHECK_FUNCS([unsetenv fcntl ftruncate canonicalize_file_name]) AC_CHECK_FUNCS([gettimeofday getrusage getrlimit setrlimit clock_gettime]) AC_CHECK_FUNCS([atexit raise getpagesize strftime nl_langinfo setlocale]) AC_CHECK_FUNCS([waitpid wait4 sigaction sigprocmask pipe getaddrinfo]) AC_CHECK_FUNCS([ttyname rand ftello fsync stat lstat]) AC_CHECK_TYPES([struct sigaction, sigset_t],,,[#include <signal.h>]) # Dirmngr requires mmap on Unix systems. if test $ac_cv_func_mmap != yes -a $mmap_needed = yes; then AC_MSG_ERROR([[Sorry, the current implemenation requires mmap.]]) fi # # These are needed by the jnlib parts in common. # Note: We already checked pwd.h. AC_CHECK_HEADERS([signal.h]) AC_CHECK_FUNCS([memicmp stpcpy strsep strlwr strtoul memmove stricmp strtol \ memrchr isascii timegm getrusage setrlimit stat setlocale \ flockfile funlockfile fopencookie funopen getpwnam getpwuid \ getenv inet_pton]) # end jnlib checks. # # gnulib checks # gl_SOURCE_BASE([gl]) gl_M4_BASE([gl/m4]) gl_MODULES([setenv mkdtemp xsize strpbrk]) gl_INIT # # W32 specific test # GNUPG_FUNC_MKDIR_TAKES_ONE_ARG # # Sanity check regex. Tests adapted from mutt. # AC_MSG_CHECKING([whether regular expression support is requested]) AC_ARG_ENABLE(regex, AC_HELP_STRING([--disable-regex], [do not handle regular expressions in trust signatures]), use_regex=$enableval, use_regex=yes) AC_MSG_RESULT($use_regex) if test "$use_regex" = yes ; then _cppflags="${CPPFLAGS}" _ldflags="${LDFLAGS}" AC_ARG_WITH(regex, AC_HELP_STRING([--with-regex=DIR],[look for regex in DIR]), [ if test -d "$withval" ; then CPPFLAGS="${CPPFLAGS} -I$withval/include" LDFLAGS="${LDFLAGS} -L$withval/lib" fi ],withval="") # Does the system have regex functions at all? AC_SEARCH_LIBS([regcomp], [regex]) AC_CHECK_FUNC(regcomp, gnupg_cv_have_regex=yes, gnupg_cv_have_regex=no) if test $gnupg_cv_have_regex = no; then use_regex=no else if test x"$cross_compiling" = xyes; then AC_MSG_WARN([cross compiling; assuming regexp libray is not broken]) else AC_CACHE_CHECK([whether your system's regexp library is broken], [gnupg_cv_regex_broken], AC_TRY_RUN([ #include <unistd.h> #include <regex.h> main() { regex_t blah ; regmatch_t p; p.rm_eo = p.rm_eo; return regcomp(&blah, "foo.*bar", REG_NOSUB) || regexec (&blah, "foobar", 0, NULL, 0); }], gnupg_cv_regex_broken=no, gnupg_cv_regex_broken=yes, gnupg_cv_regex_broken=yes)) if test $gnupg_cv_regex_broken = yes; then AC_MSG_WARN([your regex is broken - disabling regex use]) use_regex=no fi fi fi CPPFLAGS="${_cppflags}" LDFLAGS="${_ldflags}" fi if test "$use_regex" != yes ; then AC_DEFINE(DISABLE_REGEX,1, [Define to disable regular expression support]) fi AM_CONDITIONAL(DISABLE_REGEX, test x"$use_regex" != xyes) # # Do we have zlib? Must do it here because Solaris failed # when compiling a conftest (due to the "-lz" from LIBS). # Note that we combine zlib and bzlib2 in ZLIBS. # if test "$use_zip" = yes ; then _cppflags="${CPPFLAGS}" _ldflags="${LDFLAGS}" AC_ARG_WITH(zlib, [ --with-zlib=DIR use libz in DIR],[ if test -d "$withval"; then CPPFLAGS="${CPPFLAGS} -I$withval/include" LDFLAGS="${LDFLAGS} -L$withval/lib" fi ]) AC_CHECK_HEADER(zlib.h, AC_CHECK_LIB(z, deflateInit2_, ZLIBS="-lz", CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}), CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}) AC_DEFINE(HAVE_ZIP,1, [Defined if ZIP and ZLIB are supported]) fi # # Check whether we can support bzip2 # if test "$use_bzip2" = yes ; then _cppflags="${CPPFLAGS}" _ldflags="${LDFLAGS}" AC_ARG_WITH(bzip2, AC_HELP_STRING([--with-bzip2=DIR],[look for bzip2 in DIR]), [ if test -d "$withval" ; then CPPFLAGS="${CPPFLAGS} -I$withval/include" LDFLAGS="${LDFLAGS} -L$withval/lib" fi ],withval="") # Checking alongside stdio.h as an early version of bzip2 (1.0) # required stdio.h to be included before bzlib.h, and Solaris 9 is # woefully out of date. if test "$withval" != no ; then AC_CHECK_HEADER(bzlib.h, AC_CHECK_LIB(bz2,BZ2_bzCompressInit, [ have_bz2=yes ZLIBS="$ZLIBS -lbz2" AC_DEFINE(HAVE_BZIP2,1, [Defined if the bz2 compression library is available]) ], CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}), CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags},[#include <stdio.h>]) fi fi AM_CONDITIONAL(ENABLE_BZIP2_SUPPORT,test x"$have_bz2" = "xyes") AC_SUBST(ZLIBS) # Check for readline support GNUPG_CHECK_READLINE # # Allow users to append something to the version string without # flagging it as development version. The user version parts is # considered everything after a dash. # if test "$development_version" != yes; then changequote(,)dnl tmp_pat='[a-zA-Z]' changequote([,])dnl if echo "$VERSION" | sed 's/-.*//' | grep "$tmp_pat" >/dev/null ; then development_version=yes fi fi if test "$development_version" = yes; then AC_DEFINE(IS_DEVELOPMENT_VERSION,1, [Defined if this is not a regular release]) fi AM_CONDITIONAL(CROSS_COMPILING, test x$cross_compiling = xyes) GNUPG_CHECK_GNUMAKE # Add some extra libs here so that previous tests don't fail for # mysterious reasons - the final link step should bail out. # W32SOCKLIBS is also defined so that if can be used for tools not # requiring any network stuff but linking to code in libcommon which # tracks in winsock stuff (e.g. init_common_subsystems). if test "$have_w32_system" = yes; then if test "$have_w32ce_system" = yes; then W32SOCKLIBS="-lws2" else W32SOCKLIBS="-lws2_32" fi NETLIBS="${NETLIBS} ${W32SOCKLIBS}" fi AC_SUBST(NETLIBS) AC_SUBST(W32SOCKLIBS) # # Setup gcc specific options # AC_MSG_NOTICE([checking for cc features]) if test "$GCC" = yes; then # Note that it is okay to use CFLAGS here because this are just # warning options and the user should have a chance of overriding # them. if test "$USE_MAINTAINER_MODE" = "yes"; then CFLAGS="$CFLAGS -O3 -Wall -Wcast-align -Wshadow -Wstrict-prototypes" CFLAGS="$CFLAGS -Wformat -Wno-format-y2k -Wformat-security" AC_MSG_CHECKING([if gcc supports -Wno-missing-field-initializers]) _gcc_cflags_save=$CFLAGS CFLAGS="-Wno-missing-field-initializers" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],_gcc_wopt=yes,_gcc_wopt=no) AC_MSG_RESULT($_gcc_wopt) CFLAGS=$_gcc_cflags_save; if test x"$_gcc_wopt" = xyes ; then CFLAGS="$CFLAGS -W -Wno-sign-compare -Wno-missing-field-initializers" fi AC_MSG_CHECKING([if gcc supports -Wdeclaration-after-statement]) _gcc_cflags_save=$CFLAGS CFLAGS="-Wdeclaration-after-statement" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],_gcc_wopt=yes,_gcc_wopt=no) AC_MSG_RESULT($_gcc_wopt) CFLAGS=$_gcc_cflags_save; if test x"$_gcc_wopt" = xyes ; then CFLAGS="$CFLAGS -Wdeclaration-after-statement" fi else CFLAGS="$CFLAGS -Wall" fi AC_MSG_CHECKING([if gcc supports -Wno-pointer-sign]) _gcc_cflags_save=$CFLAGS CFLAGS="-Wno-pointer-sign" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],_gcc_psign=yes,_gcc_psign=no) AC_MSG_RESULT($_gcc_psign) CFLAGS=$_gcc_cflags_save; if test x"$_gcc_psign" = xyes ; then CFLAGS="$CFLAGS -Wno-pointer-sign" fi AC_MSG_CHECKING([if gcc supports -Wpointer-arith]) _gcc_cflags_save=$CFLAGS CFLAGS="-Wpointer-arith" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],_gcc_psign=yes,_gcc_psign=no) AC_MSG_RESULT($_gcc_psign) CFLAGS=$_gcc_cflags_save; if test x"$_gcc_psign" = xyes ; then CFLAGS="$CFLAGS -Wpointer-arith" fi fi # # This is handy for debugging so the compiler doesn't rearrange # things and eliminate variables. # AC_ARG_ENABLE(optimization, AC_HELP_STRING([--disable-optimization], [disable compiler optimization]), [if test $enableval = no ; then CFLAGS=`echo $CFLAGS | sed s/-O[[1-9]]\ /-O0\ /g` fi]) # # Prepare building of estream # estream_INIT # # Decide what to build # if test "$have_adns" = "yes"; then AC_SUBST(GPGKEYS_KDNS, "gpg2keys_kdns$EXEEXT") fi missing_pth=no if test $have_ksba = no; then build_gpgsm=no build_scdaemon=no fi build_agent_threaded="" if test "$build_agent" = "yes"; then if test $have_pth = no; then build_agent_threaded="(not multi-threaded)" missing_pth=yes fi fi build_scdaemon_extra="" if test "$build_scdaemon" = "yes"; then tmp="" if test $have_pth = no; then build_scdaemon_extra="not multi-threaded" tmp=", " missing_pth=yes fi if test $have_libusb = no; then build_scdaemon_extra="${tmp}without internal CCID driver" tmp=", " fi if test -n "$build_scdaemon_extra"; then build_scdaemon_extra="(${build_scdaemon_extra})" fi fi if test "$build_agent_only" = "yes" ; then build_gpg=no build_gpgsm=no build_scdaemon=no build_tools=no build_doc=no fi # # Set variables for use by th automake makefile. # AM_CONDITIONAL(BUILD_GPG, test "$build_gpg" = "yes") AM_CONDITIONAL(BUILD_GPGSM, test "$build_gpgsm" = "yes") AM_CONDITIONAL(BUILD_AGENT, test "$build_agent" = "yes") AM_CONDITIONAL(BUILD_SCDAEMON, test "$build_scdaemon" = "yes") AM_CONDITIONAL(BUILD_G13, test "$build_g13" = "yes") AM_CONDITIONAL(BUILD_DIRMNGR, test "$build_dirmngr" = "yes") AM_CONDITIONAL(BUILD_TOOLS, test "$build_tools" = "yes") AM_CONDITIONAL(BUILD_DOC, test "$build_doc" = "yes") AM_CONDITIONAL(BUILD_SYMCRYPTRUN, test "$build_symcryptrun" = "yes") AM_CONDITIONAL(BUILD_GPGTAR, test "$build_gpgtar" = "yes") AM_CONDITIONAL(RUN_GPG_TESTS, test x$cross_compiling = xno -a "$build_gpg" = yes ) # # Set some defines for use gpgconf. # if test "$build_gpg" = yes ; then AC_DEFINE(BUILD_WITH_GPG,1,[Defined if GPG is to be build]) fi if test "$build_gpgsm" = yes ; then AC_DEFINE(BUILD_WITH_GPGSM,1,[Defined if GPGSM is to be build]) fi if test "$build_agent" = yes ; then AC_DEFINE(BUILD_WITH_AGENT,1,[Defined if GPG-AGENT is to be build]) fi if test "$build_scdaemon" = yes ; then AC_DEFINE(BUILD_WITH_SCDAEMON,1,[Defined if SCDAEMON is to be build]) fi if test "$build_dirmngr" = yes ; then AC_DEFINE(BUILD_WITH_DIRMNGR,1,[Defined if SCDAEMON is to be build]) fi if test "$build_g13" = yes ; then AC_DEFINE(BUILD_WITH_G13,1,[Defined if G13 is to be build]) fi # # Print errors here so that they are visible all # together and the user can acquire them all together. # die=no if test "$have_gpg_error" = "no"; then die=yes AC_MSG_NOTICE([[ *** *** You need libgpg-error to build this program. ** This library is for example available at *** ftp://ftp.gnupg.org/gcrypt/libgpg-error *** (at least version $NEED_GPG_ERROR_VERSION is required.) ***]]) fi if test "$have_libgcrypt" = "no"; then die=yes AC_MSG_NOTICE([[ *** *** You need libgcrypt to build this program. ** This library is for example available at *** ftp://ftp.gnupg.org/gcrypt/alpha/libgcrypt/ *** (at least version $NEED_LIBGCRYPT_VERSION using API $NEED_LIBGCRYPT_API is required.) ***]]) dnl elif test "$gnupg_cv_gcry_kdf_derive" = no; then dnl die=yes dnl AC_MSG_NOTICE([[ dnl *** dnl *** Libgcrypt 1.5.0 has not yet been released and thus the API dnl *** is a bit in a flux. Your version misses the function dnl *** gcry_kdf_derive dnl *** You need to install a newer Libgcrypt version. dnl #***]]) fi if test "$have_libassuan" = "no"; then die=yes AC_MSG_NOTICE([[ *** *** You need libassuan to build this program. *** This library is for example available at *** ftp://ftp.gnupg.org/gcrypt/libassuan/ *** (at least version $NEED_LIBASSUAN_VERSION (API $NEED_LIBASSUAN_API) is required). ***]]) fi if test "$have_ksba" = "no"; then AC_MSG_NOTICE([[ *** *** You need libksba to build this program. *** This library is for example available at *** ftp://ftp.gnupg.org/gcrypt/libksba/ *** (at least version $NEED_KSBA_VERSION using API $NEED_KSBA_API is required). ***]]) fi if test "$gnupg_have_ldap" = "no"; then die=yes AC_MSG_NOTICE([[ *** *** You need a LDAP library to build this program. *** Check out *** http://www.openldap.org *** for a suitable implementation. ***]]) if test "$have_w32ce_system" = yes; then AC_MSG_NOTICE([[ *** Note that CeGCC might be broken, a package fixing this is: *** http://files.kolab.org/local/windows-ce/ *** source/wldap32_0.1-mingw32ce.orig.tar.gz *** binary/wldap32-ce-arm-dev_0.1-1_all.deb ***]]) fi fi if test "$missing_pth" = "yes"; then AC_MSG_NOTICE([[ *** *** It is now required to build with support for the *** GNU Portable Threads Library (Pth). Please install this *** library first. The library is for example available at *** ftp://ftp.gnu.org/gnu/pth/ *** On a Debian GNU/Linux system you can install it using *** apt-get install libpth-dev *** To build GnuPG for Windows you need to use the W32PTH *** package; available at: *** ftp://ftp.g10code.com/g10code/w32pth/ ***]]) die=yes fi if test "$die" = "yes"; then AC_MSG_ERROR([[ *** *** Required libraries not found. Please consult the above messages *** and install them before running configure again. ***]]) fi AC_CONFIG_FILES([ m4/Makefile Makefile po/Makefile.in gl/Makefile include/Makefile common/Makefile kbx/Makefile g10/Makefile sm/Makefile agent/Makefile scd/Makefile g13/Makefile dirmngr/Makefile tools/gpg-zip tools/Makefile doc/Makefile tests/Makefile tests/openpgp/Makefile tests/pkits/Makefile ]) #keyserver/Makefile #keyserver/gpg2keys_mailto #keyserver/gpg2keys_test AC_OUTPUT echo " GnuPG v${VERSION} has been configured as follows: Platform: $PRINTABLE_OS_NAME ($host) OpenPGP: $build_gpg S/MIME: $build_gpgsm Agent: $build_agent $build_agent_threaded Smartcard: $build_scdaemon $build_scdaemon_extra G13: $build_g13 Dirmngr: $build_dirmngr Gpgtar: $build_gpgtar Protect tool: $show_gnupg_protect_tool_pgm LDAP wrapper: $show_gnupg_dirmngr_ldap_pgm Default agent: $show_gnupg_agent_pgm Default pinentry: $show_gnupg_pinentry_pgm Default scdaemon: $show_gnupg_scdaemon_pgm Default dirmngr: $show_gnupg_dirmngr_pgm Use standard socket: $use_standard_socket Dirmngr auto start: $dirmngr_auto_start " if test x"$use_regex" != xyes ; then echo " Warning: No regular expression support available. OpenPGP trust signatures won't work. gpg-check-pattern will not be build. " fi