diff options
Diffstat (limited to 'comm/third_party/libgpg-error/src')
111 files changed, 36397 insertions, 0 deletions
diff --git a/comm/third_party/libgpg-error/src/Makefile.am b/comm/third_party/libgpg-error/src/Makefile.am new file mode 100644 index 0000000000..fc3acc3f60 --- /dev/null +++ b/comm/third_party/libgpg-error/src/Makefile.am @@ -0,0 +1,367 @@ +# Makefile.am for libgpg-error. +# Copyright (C) 2003, 2004, 2014 g10 Code GmbH +# +# This file is part of libgpg-error. +# +# libgpg-error is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of the +# License, or (at your option) any later version. +# +# libgpg-error is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <https://www.gnu.org/licenses/>. +# SPDX-License-Identifier: LGPL-2.1+ + + +# +# We distribute the generated sources err-sources.h and err-codes.h, +# because they are needed to build the po directory, and they don't +# depend on the configuration anyway. +# + +if HAVE_W32CE_SYSTEM +gpg_extra_headers = gpg-extra/errno.h +extra_cppflags = -idirafter gpg-extra +else +gpg_extra_headers = +extra_cppflags = +endif + +localedir = $(datadir)/locale + +bin_PROGRAMS = gpg-error + +if HAVE_W32_SYSTEM +noinst_PROGRAMS = gen-w32-lock-obj +else +noinst_PROGRAMS = gen-posix-lock-obj +endif + +# Distributed lock object definitions for cross compilation. +lock_obj_pub = \ + syscfg/lock-obj-pub.aarch64-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.aarch64-unknown-linux-gnu_ilp32.h \ + syscfg/lock-obj-pub.aarch64-apple-darwin.h \ + syscfg/lock-obj-pub.alpha-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.arm-unknown-linux-androideabi.h \ + syscfg/lock-obj-pub.arm-unknown-linux-gnueabi.h \ + syscfg/lock-obj-pub.arm-apple-darwin.h \ + syscfg/lock-obj-pub.hppa-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.i386-apple-darwin.h \ + syscfg/lock-obj-pub.i686-unknown-gnu.h \ + syscfg/lock-obj-pub.i686-unknown-kfreebsd-gnu.h \ + syscfg/lock-obj-pub.i686-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.m68k-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.mips-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.mips64el-unknown-linux-gnuabi64.h \ + syscfg/lock-obj-pub.mips64-unknown-linux-gnuabi64.h \ + syscfg/lock-obj-pub.mipsel-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.nios2-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.or1k-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.powerpc-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.powerpc64-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.powerpc64le-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.powerpc-unknown-linux-gnuspe.h \ + syscfg/lock-obj-pub.riscv64-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.riscv32-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.s390x-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.sh3-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.sh4-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.sparc-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.sparc64-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.x86_64-apple-darwin.h \ + syscfg/lock-obj-pub.x86_64-unknown-kfreebsd-gnu.h \ + syscfg/lock-obj-pub.x86_64-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.x86_64-unknown-linux-gnux32.h \ + syscfg/lock-obj-pub.x86_64-unknown-linux-musl.h \ + syscfg/lock-obj-pub.tilegx-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.ia64-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.mingw32.h + + +lib_LTLIBRARIES = libgpg-error.la +nodist_include_HEADERS = gpg-error.h gpgrt.h +dist_bin_SCRIPTS = gpgrt-config +bin_SCRIPTS = gpg-error-config +m4datadir = $(datadir)/aclocal +m4data_DATA = gpg-error.m4 gpgrt.m4 + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = gpg-error.pc + +EXTRA_DIST = mkstrtable.awk err-sources.h.in err-codes.h.in \ + mkerrnos.awk errnos.in README \ + mkerrcodes.awk mkerrcodes1.awk mkerrcodes2.awk mkerrcodes.c \ + mkheader.c gpg-error.h.in mkw32errmap.c w32-add.h w32ce-add.h \ + err-sources.h err-codes.h gpg-error-config.in gpg-error.m4 gpgrt.m4 \ + gpg-error.vers gpg-error.def.in \ + versioninfo.rc.in gpg-error.w32-manifest.in \ + gpg-error-config-test.sh gpg-error.pc.in \ + gen-lock-obj.sh $(lock_obj_pub) + +BUILT_SOURCES = $(srcdir)/err-sources.h $(srcdir)/err-codes.h \ + code-to-errno.h code-from-errno.h \ + err-sources-sym.h err-codes-sym.h errnos-sym.h gpg-error.h gpgrt.h \ + gpg-error.def mkw32errmap.map.c + +tmp_files = _mkerrcodes.h _gpg-error.def.h mkw32errmap.tab.h mkw32errmap.map.c + +CLEANFILES = code-to-errno.h code-from-errno.h \ + gpg-error.h gpgrt.h \ + mkerrcodes$(EXEEXT_FOR_BUILD) mkerrcodes.h gpg-error.def mkw32errmap.tab.h \ + mkw32errmap.map.c err-sources-sym.h err-codes-sym.h errnos-sym.h \ + gpg-extra/errno.h mkheader$(EXEEXT_FOR_BUILD) \ + gpg-error-config gpg-error-config-test.log \ + $(tmp_files) lock-obj-pub.native.h + +MAINTAINERCLEANFILES = $(srcdir)/err-sources.h $(srcdir)/err-codes.h + +TESTS = gpg-error-config-test.sh + +# +# {{{ Begin Windows part +# +if HAVE_W32_SYSTEM +arch_sources = w32-gettext.c w32-lock.c w32-lock-obj.h w32-thread.c \ + w32-iconv.c w32-estream.c w32-reg.c spawn-w32.c +RCCOMPILE = $(RC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + -DLOCALEDIR=\"$(localedir)\" $(AM_CPPFLAGS) $(CPPFLAGS) +LTRCCOMPILE = $(LIBTOOL) --mode=compile --tag=RC $(RCCOMPILE) + +SUFFIXES = .rc .lo + +.rc.lo: + $(LTRCCOMPILE) -i "$<" -o "$@" + +gpg_error_res = versioninfo.lo +export_symbols = -export-symbols gpg-error.def +# i686-w64-mingw32.gcc version 4.9.1 takes the long long helper +# functions from libgcc_s_sjlj-1.dll and not from a static libgcc. As +# a plain C program we do not use exception handler and thus there is +# no need to use this DLL. Thus we force gcc to link that statically. +extra_ltoptions = -XCClinker -static-libgcc + +versioninfo.lo : gpg-error.w32-manifest + +install-def-file: gpg-error.def + -$(INSTALL) -d $(DESTDIR)$(libdir) + $(INSTALL) gpg-error.def $(DESTDIR)$(libdir)/gpg-error.def + +uninstall-def-file: + -rm $(DESTDIR)$(libdir)/gpg-error.def + +libgpg_error_la_DEPENDENCIES = $(gpg_error_res) gpg-error.def +intllibs = + +# +# }}} End Windows part +# +else +# +# {{{ Begin Unix part +# +arch_sources = posix-lock.c posix-lock-obj.h posix-thread.c spawn-posix.c +gpg_error_res = +export_symbols = +extra_ltoptions = + +install-def-file: +uninstall-def-file: + +intllibs = @LTLIBINTL@ + +endif +# +# }}} End Unix part +# + +socklibs = @GPG_ERROR_CONFIG_LIBS_PRIVATE@ + +if HAVE_LD_VERSION_SCRIPT + libgpg_error_vers_opt = -Wl,--version-script=$(srcdir)/gpg-error.vers +else + libgpg_error_vers_opt = +endif + +libgpg_error_la_LDFLAGS = \ + -no-undefined $(export_symbols) $(libgpg_error_vers_opt) \ + $(extra_ltoptions) -version-info \ + @LIBGPG_ERROR_LT_CURRENT@:@LIBGPG_ERROR_LT_REVISION@:@LIBGPG_ERROR_LT_AGE@ + +libgpg_error_la_SOURCES = gettext.h $(arch_sources) \ + gpgrt-int.h protos.h init.c init.h version.c lock.h thread.h \ + estream.c estream-printf.c estream-printf.h \ + strsource.c strerror.c code-to-errno.c code-from-errno.c \ + visibility.c visibility.h \ + sysutils.c \ + stringutils.c \ + syscall-clamp.c \ + logging.c \ + b64dec.c b64enc.c \ + argparse.c + + +nodist_libgpg_error_la_SOURCES = gpg-error.h + +# libgpg_error_la_DEPENDENCIES = \ +# $(srcdir)/gpg-error.vers + +# Note that RCCOMPILE needs the same defines as ..._la_CPPFLAGS but +# without the extra_cppflags because they may include am -idirafter +# which is not supported by the RC compiler. +libgpg_error_la_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" $(extra_cppflags) +libgpg_error_la_LIBADD = $(gpg_error_res) $(intllibs) $(socklibs) $(LIBTHREAD) + +gpg_error_SOURCES = strsource-sym.c strerror-sym.c gpg-error.c +gpg_error_CPPFLAGS = -DPKGDATADIR=\"$(pkgdatadir)\" \ + -DLOCALEDIR=\"$(localedir)\" $(extra_cppflags) +gpg_error_LDADD = libgpg-error.la $(LTLIBINTL) + +# We build err-sources.h and err-codes.h in the source directory. +# This is needed because gettext does only look into the source +# directory to find the files listed in po/POTFILE.in. To make these +# rules work we also need to depend on Makefile.am and not on the +# generated files Makefile.in or Makefile. +$(srcdir)/err-sources.h: Makefile.am mkstrtable.awk err-sources.h.in + $(AWK) -f $(srcdir)/mkstrtable.awk -v textidx=3 \ + $(srcdir)/err-sources.h.in >$@ + +err-sources-sym.h: Makefile mkstrtable.awk err-sources.h.in + $(AWK) -f $(srcdir)/mkstrtable.awk -v textidx=2 -v nogettext=1 \ + $(srcdir)/err-sources.h.in >$@ + +$(srcdir)/err-codes.h: Makefile.am mkstrtable.awk err-codes.h.in + $(AWK) -f $(srcdir)/mkstrtable.awk -v textidx=3 \ + $(srcdir)/err-codes.h.in >$@ + +err-codes-sym.h: Makefile mkstrtable.awk err-codes.h.in + $(AWK) -f $(srcdir)/mkstrtable.awk -v textidx=2 -v nogettext=1 \ + $(srcdir)/err-codes.h.in >$@ + +code-to-errno.h: Makefile mkerrnos.awk errnos.in + $(AWK) -f $(srcdir)/mkerrnos.awk $(srcdir)/errnos.in >$@ + +# It is correct to use $(CPP). We want the host's idea of the error codes. +mkerrcodes.h: Makefile mkerrcodes.awk $(gpg_extra_headers) + $(AWK) -f $(srcdir)/mkerrcodes1.awk $(srcdir)/errnos.in >_$@ + $(CPP) $(CPPFLAGS) $(extra_cppflags) -P _$@ | grep GPG_ERR_ | \ + $(AWK) -f $(srcdir)/mkerrcodes.awk >$@ + -rm _$@ + +if HAVE_W32CE_SYSTEM +# It is correct to use $(CPP). We want the host's idea of the error codes. +mkw32errmap.tab.h: Makefile mkw32errmap.c + $(CPP) -DRESOLVE_MACROS $(srcdir)/mkw32errmap.c | \ + grep '{&mkw32errmap_marker' >$@ +mkw32errmap.map.c: mkw32errmap$(EXEEXT_FOR_BUILD) + ./mkw32errmap$(EXEEXT_FOR_BUILD) --map > $@ +gpg-extra/errno.h: mkw32errmap$(EXEEXT_FOR_BUILD) + -$(MKDIR_P) gpg-extra + ./mkw32errmap$(EXEEXT_FOR_BUILD) > $@ +else +mkw32errmap.map.c: + echo "/*dummy*/" > $@ +endif + +# We use CC proper for preprocessing thus we have to convince it that +# the data is really to be preprocessed. +gpg-error.def: Makefile gpg-error.def.in + cat $(srcdir)/gpg-error.def.in >_$@.h + $(CPP) $(DEFAULT_INCLUDES) $(INCLUDES) $(extra_cppflags) _$@.h | \ + grep -v '^#' >$@ + -rm _$@.h + +# It is correct to use $(CC_FOR_BUILD) here. We want to run the +# program at build time. +mkerrcodes$(EXEEXT_FOR_BUILD): mkerrcodes.c mkerrcodes.h Makefile + $(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) \ + $(CPPFLAGS_FOR_BUILD) -I. -I$(srcdir) -o $@ $(srcdir)/mkerrcodes.c + +if HAVE_W32CE_SYSTEM +# It is correct to use $(CC_FOR_BUILD) here. We want to run the +# program at build time. +mkw32errmap$(EXEEXT_FOR_BUILD): mkw32errmap.c mkw32errmap.tab.h Makefile + $(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) \ + $(CPPFLAGS_FOR_BUILD) -I. -I$(srcdir) -o $@ $(srcdir)/mkw32errmap.c +endif + +code-from-errno.h: mkerrcodes$(EXEEXT_FOR_BUILD) Makefile + ./mkerrcodes$(EXEEXT_FOR_BUILD) | $(AWK) -f $(srcdir)/mkerrcodes2.awk >$@ + +errnos-sym.h: Makefile mkstrtable.awk errnos.in + $(AWK) -f $(srcdir)/mkstrtable.awk -v textidx=2 -v nogettext=1 \ + -v prefix=GPG_ERR_ -v pkg_namespace=errnos_ \ + $(srcdir)/errnos.in >$@ + + +mkheader$(EXEEXT_FOR_BUILD): mkheader.c Makefile + $(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) \ + $(CPPFLAGS_FOR_BUILD) -g -I. -I$(srcdir) -o $@ $(srcdir)/mkheader.c + +parts_of_gpg_error_h = \ + gpg-error.h.in \ + err-sources.h.in \ + err-codes.h.in \ + errnos.in \ + w32-add.h \ + w32ce-add.h \ + $(lock_obj_pub) + +# If we are cross-compiling or building on Windows we better make sure +# that no stale native lock include file will be found by mkheader. +if FORCE_USE_SYSCFG +pre_mkheader_cmds = if test -f lock-obj-pub.native.h; \ + then rm lock-obj-pub.native.h; fi +mkheader_opts = --cross +else +if HAVE_GENERATED_LOCK_OBJ_H +# lock-obj-pub.native.h is generated at configure time +pre_mkheader_cmds = : +mkheader_opts = +parts_of_gpg_error_h += ./lock-obj-pub.native.h +else +pre_mkheader_cmds = : +mkheader_opts = +parts_of_gpg_error_h += ./lock-obj-pub.native.h + +./lock-obj-pub.native.h: Makefile gen-posix-lock-obj$(EXEEXT) posix-lock-obj.h + ./gen-posix-lock-obj >$@ +endif +endif + +# We also depend on versioninfo.rc because that is build by +# config.status and thus has up-to-date version numbers. +gpg-error.h: Makefile mkheader$(EXEEXT_FOR_BUILD) $(parts_of_gpg_error_h) \ + versioninfo.rc ../config.h + $(pre_mkheader_cmds) + ./mkheader$(EXEEXT_FOR_BUILD) $(mkheader_opts) \ + $(host_triplet) $(srcdir)/gpg-error.h.in \ + ../config.h $(PACKAGE_VERSION) $(VERSION_NUMBER) >$@ + +gpgrt.h: gpg-error.h + cp gpg-error.h gpgrt.h + +gpg-error-config: gpgrt-config gpg-error-config-old + @echo $(ECHO_N) "Confirm gpg-error-config works... $(ECHO_C)" + @if ./gpg-error-config-test.sh --old-new; then \ + echo "good"; \ + else \ + echo "no"; \ + echo "*** Please report to <https://bugs.gnupg.org> with gpg-error-config-test.log"; \ + exit 1; \ + fi + cp gpg-error-config-old $@ + +install-data-local: +if HAVE_W32CE_SYSTEM + -$(MKDIR_P) "$(DESTDIR)$(includedir)/gpg-extra" + $(INSTALL_DATA) gpg-extra/errno.h \ + "$(DESTDIR)$(includedir)/gpg-extra/errno.h" +else + : +endif diff --git a/comm/third_party/libgpg-error/src/Makefile.in b/comm/third_party/libgpg-error/src/Makefile.in new file mode 100644 index 0000000000..cf5cf8d98a --- /dev/null +++ b/comm/third_party/libgpg-error/src/Makefile.in @@ -0,0 +1,1784 @@ +# Makefile.in generated by automake 1.16.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2018 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am for libgpg-error. +# Copyright (C) 2003, 2004, 2014 g10 Code GmbH +# +# This file is part of libgpg-error. +# +# libgpg-error is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of the +# License, or (at your option) any later version. +# +# libgpg-error is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <https://www.gnu.org/licenses/>. +# SPDX-License-Identifier: LGPL-2.1+ + +# +# We distribute the generated sources err-sources.h and err-codes.h, +# because they are needed to build the po directory, and they don't +# depend on the configuration anyway. +# + + + + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +bin_PROGRAMS = gpg-error$(EXEEXT) +@HAVE_W32_SYSTEM_FALSE@noinst_PROGRAMS = gen-posix-lock-obj$(EXEEXT) +@HAVE_W32_SYSTEM_TRUE@noinst_PROGRAMS = gen-w32-lock-obj$(EXEEXT) +@HAVE_W32_SYSTEM_FALSE@libgpg_error_la_DEPENDENCIES = \ +@HAVE_W32_SYSTEM_FALSE@ $(am__DEPENDENCIES_1) \ +@HAVE_W32_SYSTEM_FALSE@ $(am__DEPENDENCIES_2) \ +@HAVE_W32_SYSTEM_FALSE@ $(am__DEPENDENCIES_2) \ +@HAVE_W32_SYSTEM_FALSE@ $(am__DEPENDENCIES_2) +@FORCE_USE_SYSCFG_FALSE@@HAVE_GENERATED_LOCK_OBJ_H_TRUE@am__append_1 = ./lock-obj-pub.native.h +@FORCE_USE_SYSCFG_FALSE@@HAVE_GENERATED_LOCK_OBJ_H_FALSE@am__append_2 = ./lock-obj-pub.native.h +subdir = src +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/autobuild.m4 \ + $(top_srcdir)/m4/ax_cc_for_build.m4 \ + $(top_srcdir)/m4/estream.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gnupg-misc.m4 $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/lock.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/readline.m4 $(top_srcdir)/m4/threadlib.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(dist_bin_SCRIPTS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = versioninfo.rc gpg-error.w32-manifest \ + gpg-error.pc gpg-error-config-old gpgrt-config \ + gpg-error-config-test.sh +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libdir)" \ + "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)" \ + "$(DESTDIR)$(m4datadir)" "$(DESTDIR)$(pkgconfigdir)" \ + "$(DESTDIR)$(includedir)" +PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +LTLIBRARIES = $(lib_LTLIBRARIES) +@HAVE_W32_SYSTEM_TRUE@am__DEPENDENCIES_1 = versioninfo.lo +am__DEPENDENCIES_2 = +am__libgpg_error_la_SOURCES_DIST = gettext.h posix-lock.c \ + posix-lock-obj.h posix-thread.c spawn-posix.c w32-gettext.c \ + w32-lock.c w32-lock-obj.h w32-thread.c w32-iconv.c \ + w32-estream.c w32-reg.c spawn-w32.c gpgrt-int.h protos.h \ + init.c init.h version.c lock.h thread.h estream.c \ + estream-printf.c estream-printf.h strsource.c strerror.c \ + code-to-errno.c code-from-errno.c visibility.c visibility.h \ + sysutils.c stringutils.c syscall-clamp.c logging.c b64dec.c \ + b64enc.c argparse.c +@HAVE_W32_SYSTEM_FALSE@am__objects_1 = libgpg_error_la-posix-lock.lo \ +@HAVE_W32_SYSTEM_FALSE@ libgpg_error_la-posix-thread.lo \ +@HAVE_W32_SYSTEM_FALSE@ libgpg_error_la-spawn-posix.lo +@HAVE_W32_SYSTEM_TRUE@am__objects_1 = libgpg_error_la-w32-gettext.lo \ +@HAVE_W32_SYSTEM_TRUE@ libgpg_error_la-w32-lock.lo \ +@HAVE_W32_SYSTEM_TRUE@ libgpg_error_la-w32-thread.lo \ +@HAVE_W32_SYSTEM_TRUE@ libgpg_error_la-w32-iconv.lo \ +@HAVE_W32_SYSTEM_TRUE@ libgpg_error_la-w32-estream.lo \ +@HAVE_W32_SYSTEM_TRUE@ libgpg_error_la-w32-reg.lo \ +@HAVE_W32_SYSTEM_TRUE@ libgpg_error_la-spawn-w32.lo +am_libgpg_error_la_OBJECTS = $(am__objects_1) libgpg_error_la-init.lo \ + libgpg_error_la-version.lo libgpg_error_la-estream.lo \ + libgpg_error_la-estream-printf.lo libgpg_error_la-strsource.lo \ + libgpg_error_la-strerror.lo libgpg_error_la-code-to-errno.lo \ + libgpg_error_la-code-from-errno.lo \ + libgpg_error_la-visibility.lo libgpg_error_la-sysutils.lo \ + libgpg_error_la-stringutils.lo \ + libgpg_error_la-syscall-clamp.lo libgpg_error_la-logging.lo \ + libgpg_error_la-b64dec.lo libgpg_error_la-b64enc.lo \ + libgpg_error_la-argparse.lo +nodist_libgpg_error_la_OBJECTS = +libgpg_error_la_OBJECTS = $(am_libgpg_error_la_OBJECTS) \ + $(nodist_libgpg_error_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libgpg_error_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libgpg_error_la_LDFLAGS) $(LDFLAGS) \ + -o $@ +gen_posix_lock_obj_SOURCES = gen-posix-lock-obj.c +gen_posix_lock_obj_OBJECTS = gen-posix-lock-obj.$(OBJEXT) +gen_posix_lock_obj_LDADD = $(LDADD) +gen_w32_lock_obj_SOURCES = gen-w32-lock-obj.c +gen_w32_lock_obj_OBJECTS = gen-w32-lock-obj.$(OBJEXT) +gen_w32_lock_obj_LDADD = $(LDADD) +am_gpg_error_OBJECTS = gpg_error-strsource-sym.$(OBJEXT) \ + gpg_error-strerror-sym.$(OBJEXT) gpg_error-gpg-error.$(OBJEXT) +gpg_error_OBJECTS = $(am_gpg_error_OBJECTS) +gpg_error_DEPENDENCIES = libgpg-error.la $(am__DEPENDENCIES_2) +SCRIPTS = $(bin_SCRIPTS) $(dist_bin_SCRIPTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/gen-posix-lock-obj.Po \ + ./$(DEPDIR)/gen-w32-lock-obj.Po \ + ./$(DEPDIR)/gpg_error-gpg-error.Po \ + ./$(DEPDIR)/gpg_error-strerror-sym.Po \ + ./$(DEPDIR)/gpg_error-strsource-sym.Po \ + ./$(DEPDIR)/libgpg_error_la-argparse.Plo \ + ./$(DEPDIR)/libgpg_error_la-b64dec.Plo \ + ./$(DEPDIR)/libgpg_error_la-b64enc.Plo \ + ./$(DEPDIR)/libgpg_error_la-code-from-errno.Plo \ + ./$(DEPDIR)/libgpg_error_la-code-to-errno.Plo \ + ./$(DEPDIR)/libgpg_error_la-estream-printf.Plo \ + ./$(DEPDIR)/libgpg_error_la-estream.Plo \ + ./$(DEPDIR)/libgpg_error_la-init.Plo \ + ./$(DEPDIR)/libgpg_error_la-logging.Plo \ + ./$(DEPDIR)/libgpg_error_la-posix-lock.Plo \ + ./$(DEPDIR)/libgpg_error_la-posix-thread.Plo \ + ./$(DEPDIR)/libgpg_error_la-spawn-posix.Plo \ + ./$(DEPDIR)/libgpg_error_la-spawn-w32.Plo \ + ./$(DEPDIR)/libgpg_error_la-strerror.Plo \ + ./$(DEPDIR)/libgpg_error_la-stringutils.Plo \ + ./$(DEPDIR)/libgpg_error_la-strsource.Plo \ + ./$(DEPDIR)/libgpg_error_la-syscall-clamp.Plo \ + ./$(DEPDIR)/libgpg_error_la-sysutils.Plo \ + ./$(DEPDIR)/libgpg_error_la-version.Plo \ + ./$(DEPDIR)/libgpg_error_la-visibility.Plo \ + ./$(DEPDIR)/libgpg_error_la-w32-estream.Plo \ + ./$(DEPDIR)/libgpg_error_la-w32-gettext.Plo \ + ./$(DEPDIR)/libgpg_error_la-w32-iconv.Plo \ + ./$(DEPDIR)/libgpg_error_la-w32-lock.Plo \ + ./$(DEPDIR)/libgpg_error_la-w32-reg.Plo \ + ./$(DEPDIR)/libgpg_error_la-w32-thread.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libgpg_error_la_SOURCES) $(nodist_libgpg_error_la_SOURCES) \ + gen-posix-lock-obj.c gen-w32-lock-obj.c $(gpg_error_SOURCES) +DIST_SOURCES = $(am__libgpg_error_la_SOURCES_DIST) \ + gen-posix-lock-obj.c gen-w32-lock-obj.c $(gpg_error_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(m4data_DATA) $(pkgconfig_DATA) +HEADERS = $(nodist_include_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red='[0;31m'; \ + grn='[0;32m'; \ + lgn='[1;32m'; \ + blu='[1;34m'; \ + mgn='[0;35m'; \ + brg='[1m'; \ + std='[m'; \ + fi; \ +} +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(srcdir)/gpg-error-config-test.sh.in \ + $(srcdir)/gpg-error-config.in $(srcdir)/gpg-error.pc.in \ + $(srcdir)/gpg-error.w32-manifest.in $(srcdir)/gpgrt-config.in \ + $(srcdir)/versioninfo.rc.in $(top_srcdir)/build-aux/depcomp \ + README +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_FILEVERSION = @BUILD_FILEVERSION@ +BUILD_REVISION = @BUILD_REVISION@ +BUILD_TIMESTAMP = @BUILD_TIMESTAMP@ +BUILD_VERSION = @BUILD_VERSION@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +EXEEXT_FOR_BUILD = @EXEEXT_FOR_BUILD@ +FGREP = @FGREP@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GPG_ERROR_CONFIG_CFLAGS = @GPG_ERROR_CONFIG_CFLAGS@ +GPG_ERROR_CONFIG_HOST = @GPG_ERROR_CONFIG_HOST@ +GPG_ERROR_CONFIG_LIBS = @GPG_ERROR_CONFIG_LIBS@ +GPG_ERROR_CONFIG_LIBS_PRIVATE = @GPG_ERROR_CONFIG_LIBS_PRIVATE@ +GPG_ERROR_CONFIG_MT_CFLAGS = @GPG_ERROR_CONFIG_MT_CFLAGS@ +GPG_ERROR_CONFIG_MT_LIBS = @GPG_ERROR_CONFIG_MT_LIBS@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALLSHELLPATH = @INSTALLSHELLPATH@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LD = @LD@ +LDADD_FOR_TESTS_KLUDGE = @LDADD_FOR_TESTS_KLUDGE@ +LDFLAGS = @LDFLAGS@ +LIBGPG_ERROR_LT_AGE = @LIBGPG_ERROR_LT_AGE@ +LIBGPG_ERROR_LT_CURRENT = @LIBGPG_ERROR_LT_CURRENT@ +LIBGPG_ERROR_LT_REVISION = @LIBGPG_ERROR_LT_REVISION@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBMULTITHREAD = @LIBMULTITHREAD@ +LIBOBJS = @LIBOBJS@ +LIBREADLINE = @LIBREADLINE@ +LIBS = @LIBS@ +LIBTHREAD = @LIBTHREAD@ +LIBTOOL = @LIBTOOL@ +LIB_NETWORK = @LIB_NETWORK@ +LIB_SCHED_YIELD = @LIB_SCHED_YIELD@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBMULTITHREAD = @LTLIBMULTITHREAD@ +LTLIBOBJS = @LTLIBOBJS@ +LTLIBTHREAD = @LTLIBTHREAD@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +RC = @RC@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +VERSION_NUMBER = @VERSION_NUMBER@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = $(datadir)/locale +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +@HAVE_W32CE_SYSTEM_FALSE@gpg_extra_headers = +@HAVE_W32CE_SYSTEM_TRUE@gpg_extra_headers = gpg-extra/errno.h +@HAVE_W32CE_SYSTEM_FALSE@extra_cppflags = +@HAVE_W32CE_SYSTEM_TRUE@extra_cppflags = -idirafter gpg-extra + +# Distributed lock object definitions for cross compilation. +lock_obj_pub = \ + syscfg/lock-obj-pub.aarch64-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.aarch64-unknown-linux-gnu_ilp32.h \ + syscfg/lock-obj-pub.aarch64-apple-darwin.h \ + syscfg/lock-obj-pub.alpha-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.arm-unknown-linux-androideabi.h \ + syscfg/lock-obj-pub.arm-unknown-linux-gnueabi.h \ + syscfg/lock-obj-pub.arm-apple-darwin.h \ + syscfg/lock-obj-pub.hppa-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.i386-apple-darwin.h \ + syscfg/lock-obj-pub.i686-unknown-gnu.h \ + syscfg/lock-obj-pub.i686-unknown-kfreebsd-gnu.h \ + syscfg/lock-obj-pub.i686-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.m68k-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.mips-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.mips64el-unknown-linux-gnuabi64.h \ + syscfg/lock-obj-pub.mips64-unknown-linux-gnuabi64.h \ + syscfg/lock-obj-pub.mipsel-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.nios2-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.or1k-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.powerpc-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.powerpc64-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.powerpc64le-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.powerpc-unknown-linux-gnuspe.h \ + syscfg/lock-obj-pub.riscv64-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.riscv32-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.s390x-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.sh3-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.sh4-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.sparc-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.sparc64-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.x86_64-apple-darwin.h \ + syscfg/lock-obj-pub.x86_64-unknown-kfreebsd-gnu.h \ + syscfg/lock-obj-pub.x86_64-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.x86_64-unknown-linux-gnux32.h \ + syscfg/lock-obj-pub.x86_64-unknown-linux-musl.h \ + syscfg/lock-obj-pub.tilegx-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.ia64-unknown-linux-gnu.h \ + syscfg/lock-obj-pub.mingw32.h + +lib_LTLIBRARIES = libgpg-error.la +nodist_include_HEADERS = gpg-error.h gpgrt.h +dist_bin_SCRIPTS = gpgrt-config +bin_SCRIPTS = gpg-error-config +m4datadir = $(datadir)/aclocal +m4data_DATA = gpg-error.m4 gpgrt.m4 +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = gpg-error.pc +EXTRA_DIST = mkstrtable.awk err-sources.h.in err-codes.h.in \ + mkerrnos.awk errnos.in README \ + mkerrcodes.awk mkerrcodes1.awk mkerrcodes2.awk mkerrcodes.c \ + mkheader.c gpg-error.h.in mkw32errmap.c w32-add.h w32ce-add.h \ + err-sources.h err-codes.h gpg-error-config.in gpg-error.m4 gpgrt.m4 \ + gpg-error.vers gpg-error.def.in \ + versioninfo.rc.in gpg-error.w32-manifest.in \ + gpg-error-config-test.sh gpg-error.pc.in \ + gen-lock-obj.sh $(lock_obj_pub) + +BUILT_SOURCES = $(srcdir)/err-sources.h $(srcdir)/err-codes.h \ + code-to-errno.h code-from-errno.h \ + err-sources-sym.h err-codes-sym.h errnos-sym.h gpg-error.h gpgrt.h \ + gpg-error.def mkw32errmap.map.c + +tmp_files = _mkerrcodes.h _gpg-error.def.h mkw32errmap.tab.h mkw32errmap.map.c +CLEANFILES = code-to-errno.h code-from-errno.h \ + gpg-error.h gpgrt.h \ + mkerrcodes$(EXEEXT_FOR_BUILD) mkerrcodes.h gpg-error.def mkw32errmap.tab.h \ + mkw32errmap.map.c err-sources-sym.h err-codes-sym.h errnos-sym.h \ + gpg-extra/errno.h mkheader$(EXEEXT_FOR_BUILD) \ + gpg-error-config gpg-error-config-test.log \ + $(tmp_files) lock-obj-pub.native.h + +MAINTAINERCLEANFILES = $(srcdir)/err-sources.h $(srcdir)/err-codes.h +TESTS = gpg-error-config-test.sh + +# +# }}} End Windows part +# +# +# {{{ Begin Unix part +# +@HAVE_W32_SYSTEM_FALSE@arch_sources = posix-lock.c posix-lock-obj.h posix-thread.c spawn-posix.c + +# +# {{{ Begin Windows part +# +@HAVE_W32_SYSTEM_TRUE@arch_sources = w32-gettext.c w32-lock.c w32-lock-obj.h w32-thread.c \ +@HAVE_W32_SYSTEM_TRUE@ w32-iconv.c w32-estream.c w32-reg.c spawn-w32.c + +@HAVE_W32_SYSTEM_TRUE@RCCOMPILE = $(RC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ +@HAVE_W32_SYSTEM_TRUE@ -DLOCALEDIR=\"$(localedir)\" $(AM_CPPFLAGS) $(CPPFLAGS) + +@HAVE_W32_SYSTEM_TRUE@LTRCCOMPILE = $(LIBTOOL) --mode=compile --tag=RC $(RCCOMPILE) +@HAVE_W32_SYSTEM_TRUE@SUFFIXES = .rc .lo +@HAVE_W32_SYSTEM_FALSE@gpg_error_res = +@HAVE_W32_SYSTEM_TRUE@gpg_error_res = versioninfo.lo +@HAVE_W32_SYSTEM_FALSE@export_symbols = +@HAVE_W32_SYSTEM_TRUE@export_symbols = -export-symbols gpg-error.def +@HAVE_W32_SYSTEM_FALSE@extra_ltoptions = +# i686-w64-mingw32.gcc version 4.9.1 takes the long long helper +# functions from libgcc_s_sjlj-1.dll and not from a static libgcc. As +# a plain C program we do not use exception handler and thus there is +# no need to use this DLL. Thus we force gcc to link that statically. +@HAVE_W32_SYSTEM_TRUE@extra_ltoptions = -XCClinker -static-libgcc +@HAVE_W32_SYSTEM_TRUE@libgpg_error_la_DEPENDENCIES = $(gpg_error_res) gpg-error.def +@HAVE_W32_SYSTEM_FALSE@intllibs = @LTLIBINTL@ +@HAVE_W32_SYSTEM_TRUE@intllibs = + +# +# }}} End Unix part +# +socklibs = @GPG_ERROR_CONFIG_LIBS_PRIVATE@ +@HAVE_LD_VERSION_SCRIPT_FALSE@libgpg_error_vers_opt = +@HAVE_LD_VERSION_SCRIPT_TRUE@libgpg_error_vers_opt = -Wl,--version-script=$(srcdir)/gpg-error.vers +libgpg_error_la_LDFLAGS = \ + -no-undefined $(export_symbols) $(libgpg_error_vers_opt) \ + $(extra_ltoptions) -version-info \ + @LIBGPG_ERROR_LT_CURRENT@:@LIBGPG_ERROR_LT_REVISION@:@LIBGPG_ERROR_LT_AGE@ + +libgpg_error_la_SOURCES = gettext.h $(arch_sources) \ + gpgrt-int.h protos.h init.c init.h version.c lock.h thread.h \ + estream.c estream-printf.c estream-printf.h \ + strsource.c strerror.c code-to-errno.c code-from-errno.c \ + visibility.c visibility.h \ + sysutils.c \ + stringutils.c \ + syscall-clamp.c \ + logging.c \ + b64dec.c b64enc.c \ + argparse.c + +nodist_libgpg_error_la_SOURCES = gpg-error.h + +# libgpg_error_la_DEPENDENCIES = \ +# $(srcdir)/gpg-error.vers + +# Note that RCCOMPILE needs the same defines as ..._la_CPPFLAGS but +# without the extra_cppflags because they may include am -idirafter +# which is not supported by the RC compiler. +libgpg_error_la_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" $(extra_cppflags) +libgpg_error_la_LIBADD = $(gpg_error_res) $(intllibs) $(socklibs) $(LIBTHREAD) +gpg_error_SOURCES = strsource-sym.c strerror-sym.c gpg-error.c +gpg_error_CPPFLAGS = -DPKGDATADIR=\"$(pkgdatadir)\" \ + -DLOCALEDIR=\"$(localedir)\" $(extra_cppflags) + +gpg_error_LDADD = libgpg-error.la $(LTLIBINTL) +parts_of_gpg_error_h = gpg-error.h.in err-sources.h.in err-codes.h.in \ + errnos.in w32-add.h w32ce-add.h $(lock_obj_pub) \ + $(am__append_1) $(am__append_2) +@FORCE_USE_SYSCFG_FALSE@@HAVE_GENERATED_LOCK_OBJ_H_FALSE@pre_mkheader_cmds = : +# lock-obj-pub.native.h is generated at configure time +@FORCE_USE_SYSCFG_FALSE@@HAVE_GENERATED_LOCK_OBJ_H_TRUE@pre_mkheader_cmds = : + +# If we are cross-compiling or building on Windows we better make sure +# that no stale native lock include file will be found by mkheader. +@FORCE_USE_SYSCFG_TRUE@pre_mkheader_cmds = if test -f lock-obj-pub.native.h; \ +@FORCE_USE_SYSCFG_TRUE@ then rm lock-obj-pub.native.h; fi + +@FORCE_USE_SYSCFG_FALSE@@HAVE_GENERATED_LOCK_OBJ_H_FALSE@mkheader_opts = +@FORCE_USE_SYSCFG_FALSE@@HAVE_GENERATED_LOCK_OBJ_H_TRUE@mkheader_opts = +@FORCE_USE_SYSCFG_TRUE@mkheader_opts = --cross +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .rc .lo .c .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +versioninfo.rc: $(top_builddir)/config.status $(srcdir)/versioninfo.rc.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +gpg-error.w32-manifest: $(top_builddir)/config.status $(srcdir)/gpg-error.w32-manifest.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +gpg-error.pc: $(top_builddir)/config.status $(srcdir)/gpg-error.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +gpg-error-config-old: $(top_builddir)/config.status $(srcdir)/gpg-error-config.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +gpgrt-config: $(top_builddir)/config.status $(srcdir)/gpgrt-config.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +gpg-error-config-test.sh: $(top_builddir)/config.status $(srcdir)/gpg-error-config-test.sh.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libgpg-error.la: $(libgpg_error_la_OBJECTS) $(libgpg_error_la_DEPENDENCIES) $(EXTRA_libgpg_error_la_DEPENDENCIES) + $(AM_V_CCLD)$(libgpg_error_la_LINK) -rpath $(libdir) $(libgpg_error_la_OBJECTS) $(libgpg_error_la_LIBADD) $(LIBS) + +gen-posix-lock-obj$(EXEEXT): $(gen_posix_lock_obj_OBJECTS) $(gen_posix_lock_obj_DEPENDENCIES) $(EXTRA_gen_posix_lock_obj_DEPENDENCIES) + @rm -f gen-posix-lock-obj$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gen_posix_lock_obj_OBJECTS) $(gen_posix_lock_obj_LDADD) $(LIBS) + +gen-w32-lock-obj$(EXEEXT): $(gen_w32_lock_obj_OBJECTS) $(gen_w32_lock_obj_DEPENDENCIES) $(EXTRA_gen_w32_lock_obj_DEPENDENCIES) + @rm -f gen-w32-lock-obj$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gen_w32_lock_obj_OBJECTS) $(gen_w32_lock_obj_LDADD) $(LIBS) + +gpg-error$(EXEEXT): $(gpg_error_OBJECTS) $(gpg_error_DEPENDENCIES) $(EXTRA_gpg_error_DEPENDENCIES) + @rm -f gpg-error$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gpg_error_OBJECTS) $(gpg_error_LDADD) $(LIBS) +install-binSCRIPTS: $(bin_SCRIPTS) + @$(NORMAL_INSTALL) + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n' \ + -e 'h;s|.*|.|' \ + -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) { files[d] = files[d] " " $$1; \ + if (++n[d] == $(am__install_max)) { \ + print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ + else { print "f", d "/" $$4, $$1 } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binSCRIPTS: + @$(NORMAL_UNINSTALL) + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 's,.*/,,;$(transform)'`; \ + dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) +install-dist_binSCRIPTS: $(dist_bin_SCRIPTS) + @$(NORMAL_INSTALL) + @list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n' \ + -e 'h;s|.*|.|' \ + -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) { files[d] = files[d] " " $$1; \ + if (++n[d] == $(am__install_max)) { \ + print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ + else { print "f", d "/" $$4, $$1 } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-dist_binSCRIPTS: + @$(NORMAL_UNINSTALL) + @list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 's,.*/,,;$(transform)'`; \ + dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen-posix-lock-obj.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen-w32-lock-obj.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpg_error-gpg-error.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpg_error-strerror-sym.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpg_error-strsource-sym.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgpg_error_la-argparse.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgpg_error_la-b64dec.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgpg_error_la-b64enc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgpg_error_la-code-from-errno.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgpg_error_la-code-to-errno.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgpg_error_la-estream-printf.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgpg_error_la-estream.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgpg_error_la-init.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgpg_error_la-logging.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgpg_error_la-posix-lock.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgpg_error_la-posix-thread.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgpg_error_la-spawn-posix.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgpg_error_la-spawn-w32.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgpg_error_la-strerror.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgpg_error_la-stringutils.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgpg_error_la-strsource.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgpg_error_la-syscall-clamp.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgpg_error_la-sysutils.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgpg_error_la-version.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgpg_error_la-visibility.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgpg_error_la-w32-estream.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgpg_error_la-w32-gettext.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgpg_error_la-w32-iconv.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgpg_error_la-w32-lock.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgpg_error_la-w32-reg.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgpg_error_la-w32-thread.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +libgpg_error_la-posix-lock.lo: posix-lock.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgpg_error_la-posix-lock.lo -MD -MP -MF $(DEPDIR)/libgpg_error_la-posix-lock.Tpo -c -o libgpg_error_la-posix-lock.lo `test -f 'posix-lock.c' || echo '$(srcdir)/'`posix-lock.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgpg_error_la-posix-lock.Tpo $(DEPDIR)/libgpg_error_la-posix-lock.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='posix-lock.c' object='libgpg_error_la-posix-lock.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgpg_error_la-posix-lock.lo `test -f 'posix-lock.c' || echo '$(srcdir)/'`posix-lock.c + +libgpg_error_la-posix-thread.lo: posix-thread.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgpg_error_la-posix-thread.lo -MD -MP -MF $(DEPDIR)/libgpg_error_la-posix-thread.Tpo -c -o libgpg_error_la-posix-thread.lo `test -f 'posix-thread.c' || echo '$(srcdir)/'`posix-thread.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgpg_error_la-posix-thread.Tpo $(DEPDIR)/libgpg_error_la-posix-thread.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='posix-thread.c' object='libgpg_error_la-posix-thread.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgpg_error_la-posix-thread.lo `test -f 'posix-thread.c' || echo '$(srcdir)/'`posix-thread.c + +libgpg_error_la-spawn-posix.lo: spawn-posix.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgpg_error_la-spawn-posix.lo -MD -MP -MF $(DEPDIR)/libgpg_error_la-spawn-posix.Tpo -c -o libgpg_error_la-spawn-posix.lo `test -f 'spawn-posix.c' || echo '$(srcdir)/'`spawn-posix.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgpg_error_la-spawn-posix.Tpo $(DEPDIR)/libgpg_error_la-spawn-posix.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spawn-posix.c' object='libgpg_error_la-spawn-posix.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgpg_error_la-spawn-posix.lo `test -f 'spawn-posix.c' || echo '$(srcdir)/'`spawn-posix.c + +libgpg_error_la-w32-gettext.lo: w32-gettext.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgpg_error_la-w32-gettext.lo -MD -MP -MF $(DEPDIR)/libgpg_error_la-w32-gettext.Tpo -c -o libgpg_error_la-w32-gettext.lo `test -f 'w32-gettext.c' || echo '$(srcdir)/'`w32-gettext.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgpg_error_la-w32-gettext.Tpo $(DEPDIR)/libgpg_error_la-w32-gettext.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='w32-gettext.c' object='libgpg_error_la-w32-gettext.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgpg_error_la-w32-gettext.lo `test -f 'w32-gettext.c' || echo '$(srcdir)/'`w32-gettext.c + +libgpg_error_la-w32-lock.lo: w32-lock.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgpg_error_la-w32-lock.lo -MD -MP -MF $(DEPDIR)/libgpg_error_la-w32-lock.Tpo -c -o libgpg_error_la-w32-lock.lo `test -f 'w32-lock.c' || echo '$(srcdir)/'`w32-lock.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgpg_error_la-w32-lock.Tpo $(DEPDIR)/libgpg_error_la-w32-lock.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='w32-lock.c' object='libgpg_error_la-w32-lock.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgpg_error_la-w32-lock.lo `test -f 'w32-lock.c' || echo '$(srcdir)/'`w32-lock.c + +libgpg_error_la-w32-thread.lo: w32-thread.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgpg_error_la-w32-thread.lo -MD -MP -MF $(DEPDIR)/libgpg_error_la-w32-thread.Tpo -c -o libgpg_error_la-w32-thread.lo `test -f 'w32-thread.c' || echo '$(srcdir)/'`w32-thread.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgpg_error_la-w32-thread.Tpo $(DEPDIR)/libgpg_error_la-w32-thread.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='w32-thread.c' object='libgpg_error_la-w32-thread.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgpg_error_la-w32-thread.lo `test -f 'w32-thread.c' || echo '$(srcdir)/'`w32-thread.c + +libgpg_error_la-w32-iconv.lo: w32-iconv.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgpg_error_la-w32-iconv.lo -MD -MP -MF $(DEPDIR)/libgpg_error_la-w32-iconv.Tpo -c -o libgpg_error_la-w32-iconv.lo `test -f 'w32-iconv.c' || echo '$(srcdir)/'`w32-iconv.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgpg_error_la-w32-iconv.Tpo $(DEPDIR)/libgpg_error_la-w32-iconv.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='w32-iconv.c' object='libgpg_error_la-w32-iconv.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgpg_error_la-w32-iconv.lo `test -f 'w32-iconv.c' || echo '$(srcdir)/'`w32-iconv.c + +libgpg_error_la-w32-estream.lo: w32-estream.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgpg_error_la-w32-estream.lo -MD -MP -MF $(DEPDIR)/libgpg_error_la-w32-estream.Tpo -c -o libgpg_error_la-w32-estream.lo `test -f 'w32-estream.c' || echo '$(srcdir)/'`w32-estream.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgpg_error_la-w32-estream.Tpo $(DEPDIR)/libgpg_error_la-w32-estream.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='w32-estream.c' object='libgpg_error_la-w32-estream.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgpg_error_la-w32-estream.lo `test -f 'w32-estream.c' || echo '$(srcdir)/'`w32-estream.c + +libgpg_error_la-w32-reg.lo: w32-reg.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgpg_error_la-w32-reg.lo -MD -MP -MF $(DEPDIR)/libgpg_error_la-w32-reg.Tpo -c -o libgpg_error_la-w32-reg.lo `test -f 'w32-reg.c' || echo '$(srcdir)/'`w32-reg.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgpg_error_la-w32-reg.Tpo $(DEPDIR)/libgpg_error_la-w32-reg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='w32-reg.c' object='libgpg_error_la-w32-reg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgpg_error_la-w32-reg.lo `test -f 'w32-reg.c' || echo '$(srcdir)/'`w32-reg.c + +libgpg_error_la-spawn-w32.lo: spawn-w32.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgpg_error_la-spawn-w32.lo -MD -MP -MF $(DEPDIR)/libgpg_error_la-spawn-w32.Tpo -c -o libgpg_error_la-spawn-w32.lo `test -f 'spawn-w32.c' || echo '$(srcdir)/'`spawn-w32.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgpg_error_la-spawn-w32.Tpo $(DEPDIR)/libgpg_error_la-spawn-w32.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spawn-w32.c' object='libgpg_error_la-spawn-w32.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgpg_error_la-spawn-w32.lo `test -f 'spawn-w32.c' || echo '$(srcdir)/'`spawn-w32.c + +libgpg_error_la-init.lo: init.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgpg_error_la-init.lo -MD -MP -MF $(DEPDIR)/libgpg_error_la-init.Tpo -c -o libgpg_error_la-init.lo `test -f 'init.c' || echo '$(srcdir)/'`init.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgpg_error_la-init.Tpo $(DEPDIR)/libgpg_error_la-init.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='init.c' object='libgpg_error_la-init.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgpg_error_la-init.lo `test -f 'init.c' || echo '$(srcdir)/'`init.c + +libgpg_error_la-version.lo: version.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgpg_error_la-version.lo -MD -MP -MF $(DEPDIR)/libgpg_error_la-version.Tpo -c -o libgpg_error_la-version.lo `test -f 'version.c' || echo '$(srcdir)/'`version.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgpg_error_la-version.Tpo $(DEPDIR)/libgpg_error_la-version.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='version.c' object='libgpg_error_la-version.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgpg_error_la-version.lo `test -f 'version.c' || echo '$(srcdir)/'`version.c + +libgpg_error_la-estream.lo: estream.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgpg_error_la-estream.lo -MD -MP -MF $(DEPDIR)/libgpg_error_la-estream.Tpo -c -o libgpg_error_la-estream.lo `test -f 'estream.c' || echo '$(srcdir)/'`estream.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgpg_error_la-estream.Tpo $(DEPDIR)/libgpg_error_la-estream.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='estream.c' object='libgpg_error_la-estream.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgpg_error_la-estream.lo `test -f 'estream.c' || echo '$(srcdir)/'`estream.c + +libgpg_error_la-estream-printf.lo: estream-printf.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgpg_error_la-estream-printf.lo -MD -MP -MF $(DEPDIR)/libgpg_error_la-estream-printf.Tpo -c -o libgpg_error_la-estream-printf.lo `test -f 'estream-printf.c' || echo '$(srcdir)/'`estream-printf.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgpg_error_la-estream-printf.Tpo $(DEPDIR)/libgpg_error_la-estream-printf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='estream-printf.c' object='libgpg_error_la-estream-printf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgpg_error_la-estream-printf.lo `test -f 'estream-printf.c' || echo '$(srcdir)/'`estream-printf.c + +libgpg_error_la-strsource.lo: strsource.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgpg_error_la-strsource.lo -MD -MP -MF $(DEPDIR)/libgpg_error_la-strsource.Tpo -c -o libgpg_error_la-strsource.lo `test -f 'strsource.c' || echo '$(srcdir)/'`strsource.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgpg_error_la-strsource.Tpo $(DEPDIR)/libgpg_error_la-strsource.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strsource.c' object='libgpg_error_la-strsource.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgpg_error_la-strsource.lo `test -f 'strsource.c' || echo '$(srcdir)/'`strsource.c + +libgpg_error_la-strerror.lo: strerror.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgpg_error_la-strerror.lo -MD -MP -MF $(DEPDIR)/libgpg_error_la-strerror.Tpo -c -o libgpg_error_la-strerror.lo `test -f 'strerror.c' || echo '$(srcdir)/'`strerror.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgpg_error_la-strerror.Tpo $(DEPDIR)/libgpg_error_la-strerror.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strerror.c' object='libgpg_error_la-strerror.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgpg_error_la-strerror.lo `test -f 'strerror.c' || echo '$(srcdir)/'`strerror.c + +libgpg_error_la-code-to-errno.lo: code-to-errno.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgpg_error_la-code-to-errno.lo -MD -MP -MF $(DEPDIR)/libgpg_error_la-code-to-errno.Tpo -c -o libgpg_error_la-code-to-errno.lo `test -f 'code-to-errno.c' || echo '$(srcdir)/'`code-to-errno.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgpg_error_la-code-to-errno.Tpo $(DEPDIR)/libgpg_error_la-code-to-errno.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='code-to-errno.c' object='libgpg_error_la-code-to-errno.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgpg_error_la-code-to-errno.lo `test -f 'code-to-errno.c' || echo '$(srcdir)/'`code-to-errno.c + +libgpg_error_la-code-from-errno.lo: code-from-errno.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgpg_error_la-code-from-errno.lo -MD -MP -MF $(DEPDIR)/libgpg_error_la-code-from-errno.Tpo -c -o libgpg_error_la-code-from-errno.lo `test -f 'code-from-errno.c' || echo '$(srcdir)/'`code-from-errno.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgpg_error_la-code-from-errno.Tpo $(DEPDIR)/libgpg_error_la-code-from-errno.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='code-from-errno.c' object='libgpg_error_la-code-from-errno.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgpg_error_la-code-from-errno.lo `test -f 'code-from-errno.c' || echo '$(srcdir)/'`code-from-errno.c + +libgpg_error_la-visibility.lo: visibility.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgpg_error_la-visibility.lo -MD -MP -MF $(DEPDIR)/libgpg_error_la-visibility.Tpo -c -o libgpg_error_la-visibility.lo `test -f 'visibility.c' || echo '$(srcdir)/'`visibility.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgpg_error_la-visibility.Tpo $(DEPDIR)/libgpg_error_la-visibility.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='visibility.c' object='libgpg_error_la-visibility.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgpg_error_la-visibility.lo `test -f 'visibility.c' || echo '$(srcdir)/'`visibility.c + +libgpg_error_la-sysutils.lo: sysutils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgpg_error_la-sysutils.lo -MD -MP -MF $(DEPDIR)/libgpg_error_la-sysutils.Tpo -c -o libgpg_error_la-sysutils.lo `test -f 'sysutils.c' || echo '$(srcdir)/'`sysutils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgpg_error_la-sysutils.Tpo $(DEPDIR)/libgpg_error_la-sysutils.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sysutils.c' object='libgpg_error_la-sysutils.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgpg_error_la-sysutils.lo `test -f 'sysutils.c' || echo '$(srcdir)/'`sysutils.c + +libgpg_error_la-stringutils.lo: stringutils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgpg_error_la-stringutils.lo -MD -MP -MF $(DEPDIR)/libgpg_error_la-stringutils.Tpo -c -o libgpg_error_la-stringutils.lo `test -f 'stringutils.c' || echo '$(srcdir)/'`stringutils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgpg_error_la-stringutils.Tpo $(DEPDIR)/libgpg_error_la-stringutils.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='stringutils.c' object='libgpg_error_la-stringutils.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgpg_error_la-stringutils.lo `test -f 'stringutils.c' || echo '$(srcdir)/'`stringutils.c + +libgpg_error_la-syscall-clamp.lo: syscall-clamp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgpg_error_la-syscall-clamp.lo -MD -MP -MF $(DEPDIR)/libgpg_error_la-syscall-clamp.Tpo -c -o libgpg_error_la-syscall-clamp.lo `test -f 'syscall-clamp.c' || echo '$(srcdir)/'`syscall-clamp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgpg_error_la-syscall-clamp.Tpo $(DEPDIR)/libgpg_error_la-syscall-clamp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='syscall-clamp.c' object='libgpg_error_la-syscall-clamp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgpg_error_la-syscall-clamp.lo `test -f 'syscall-clamp.c' || echo '$(srcdir)/'`syscall-clamp.c + +libgpg_error_la-logging.lo: logging.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgpg_error_la-logging.lo -MD -MP -MF $(DEPDIR)/libgpg_error_la-logging.Tpo -c -o libgpg_error_la-logging.lo `test -f 'logging.c' || echo '$(srcdir)/'`logging.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgpg_error_la-logging.Tpo $(DEPDIR)/libgpg_error_la-logging.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='logging.c' object='libgpg_error_la-logging.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgpg_error_la-logging.lo `test -f 'logging.c' || echo '$(srcdir)/'`logging.c + +libgpg_error_la-b64dec.lo: b64dec.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgpg_error_la-b64dec.lo -MD -MP -MF $(DEPDIR)/libgpg_error_la-b64dec.Tpo -c -o libgpg_error_la-b64dec.lo `test -f 'b64dec.c' || echo '$(srcdir)/'`b64dec.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgpg_error_la-b64dec.Tpo $(DEPDIR)/libgpg_error_la-b64dec.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='b64dec.c' object='libgpg_error_la-b64dec.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgpg_error_la-b64dec.lo `test -f 'b64dec.c' || echo '$(srcdir)/'`b64dec.c + +libgpg_error_la-b64enc.lo: b64enc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgpg_error_la-b64enc.lo -MD -MP -MF $(DEPDIR)/libgpg_error_la-b64enc.Tpo -c -o libgpg_error_la-b64enc.lo `test -f 'b64enc.c' || echo '$(srcdir)/'`b64enc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgpg_error_la-b64enc.Tpo $(DEPDIR)/libgpg_error_la-b64enc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='b64enc.c' object='libgpg_error_la-b64enc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgpg_error_la-b64enc.lo `test -f 'b64enc.c' || echo '$(srcdir)/'`b64enc.c + +libgpg_error_la-argparse.lo: argparse.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgpg_error_la-argparse.lo -MD -MP -MF $(DEPDIR)/libgpg_error_la-argparse.Tpo -c -o libgpg_error_la-argparse.lo `test -f 'argparse.c' || echo '$(srcdir)/'`argparse.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgpg_error_la-argparse.Tpo $(DEPDIR)/libgpg_error_la-argparse.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='argparse.c' object='libgpg_error_la-argparse.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgpg_error_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgpg_error_la-argparse.lo `test -f 'argparse.c' || echo '$(srcdir)/'`argparse.c + +gpg_error-strsource-sym.o: strsource-sym.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gpg_error_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gpg_error-strsource-sym.o -MD -MP -MF $(DEPDIR)/gpg_error-strsource-sym.Tpo -c -o gpg_error-strsource-sym.o `test -f 'strsource-sym.c' || echo '$(srcdir)/'`strsource-sym.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gpg_error-strsource-sym.Tpo $(DEPDIR)/gpg_error-strsource-sym.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strsource-sym.c' object='gpg_error-strsource-sym.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gpg_error_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gpg_error-strsource-sym.o `test -f 'strsource-sym.c' || echo '$(srcdir)/'`strsource-sym.c + +gpg_error-strsource-sym.obj: strsource-sym.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gpg_error_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gpg_error-strsource-sym.obj -MD -MP -MF $(DEPDIR)/gpg_error-strsource-sym.Tpo -c -o gpg_error-strsource-sym.obj `if test -f 'strsource-sym.c'; then $(CYGPATH_W) 'strsource-sym.c'; else $(CYGPATH_W) '$(srcdir)/strsource-sym.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gpg_error-strsource-sym.Tpo $(DEPDIR)/gpg_error-strsource-sym.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strsource-sym.c' object='gpg_error-strsource-sym.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gpg_error_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gpg_error-strsource-sym.obj `if test -f 'strsource-sym.c'; then $(CYGPATH_W) 'strsource-sym.c'; else $(CYGPATH_W) '$(srcdir)/strsource-sym.c'; fi` + +gpg_error-strerror-sym.o: strerror-sym.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gpg_error_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gpg_error-strerror-sym.o -MD -MP -MF $(DEPDIR)/gpg_error-strerror-sym.Tpo -c -o gpg_error-strerror-sym.o `test -f 'strerror-sym.c' || echo '$(srcdir)/'`strerror-sym.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gpg_error-strerror-sym.Tpo $(DEPDIR)/gpg_error-strerror-sym.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strerror-sym.c' object='gpg_error-strerror-sym.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gpg_error_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gpg_error-strerror-sym.o `test -f 'strerror-sym.c' || echo '$(srcdir)/'`strerror-sym.c + +gpg_error-strerror-sym.obj: strerror-sym.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gpg_error_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gpg_error-strerror-sym.obj -MD -MP -MF $(DEPDIR)/gpg_error-strerror-sym.Tpo -c -o gpg_error-strerror-sym.obj `if test -f 'strerror-sym.c'; then $(CYGPATH_W) 'strerror-sym.c'; else $(CYGPATH_W) '$(srcdir)/strerror-sym.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gpg_error-strerror-sym.Tpo $(DEPDIR)/gpg_error-strerror-sym.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strerror-sym.c' object='gpg_error-strerror-sym.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gpg_error_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gpg_error-strerror-sym.obj `if test -f 'strerror-sym.c'; then $(CYGPATH_W) 'strerror-sym.c'; else $(CYGPATH_W) '$(srcdir)/strerror-sym.c'; fi` + +gpg_error-gpg-error.o: gpg-error.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gpg_error_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gpg_error-gpg-error.o -MD -MP -MF $(DEPDIR)/gpg_error-gpg-error.Tpo -c -o gpg_error-gpg-error.o `test -f 'gpg-error.c' || echo '$(srcdir)/'`gpg-error.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gpg_error-gpg-error.Tpo $(DEPDIR)/gpg_error-gpg-error.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gpg-error.c' object='gpg_error-gpg-error.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gpg_error_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gpg_error-gpg-error.o `test -f 'gpg-error.c' || echo '$(srcdir)/'`gpg-error.c + +gpg_error-gpg-error.obj: gpg-error.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gpg_error_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gpg_error-gpg-error.obj -MD -MP -MF $(DEPDIR)/gpg_error-gpg-error.Tpo -c -o gpg_error-gpg-error.obj `if test -f 'gpg-error.c'; then $(CYGPATH_W) 'gpg-error.c'; else $(CYGPATH_W) '$(srcdir)/gpg-error.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gpg_error-gpg-error.Tpo $(DEPDIR)/gpg_error-gpg-error.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gpg-error.c' object='gpg_error-gpg-error.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gpg_error_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gpg_error-gpg-error.obj `if test -f 'gpg-error.c'; then $(CYGPATH_W) 'gpg-error.c'; else $(CYGPATH_W) '$(srcdir)/gpg-error.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-m4dataDATA: $(m4data_DATA) + @$(NORMAL_INSTALL) + @list='$(m4data_DATA)'; test -n "$(m4datadir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(m4datadir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(m4datadir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(m4datadir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(m4datadir)" || exit $$?; \ + done + +uninstall-m4dataDATA: + @$(NORMAL_UNINSTALL) + @list='$(m4data_DATA)'; test -n "$(m4datadir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(m4datadir)'; $(am__uninstall_files_from_dir) +install-pkgconfigDATA: $(pkgconfig_DATA) + @$(NORMAL_INSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ + done + +uninstall-pkgconfigDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) +install-nodist_includeHEADERS: $(nodist_include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(nodist_include_HEADERS)'; test -n "$(includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \ + done + +uninstall-nodist_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nodist_include_HEADERS)'; test -n "$(includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + fi; \ + echo "$${col}$$dashes$${std}"; \ + echo "$${col}$$banner$${std}"; \ + test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ + test -z "$$report" || echo "$${col}$$report$${std}"; \ + echo "$${col}$$dashes$${std}"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(PROGRAMS) $(LTLIBRARIES) $(SCRIPTS) $(DATA) \ + $(HEADERS) +install-binPROGRAMS: install-libLTLIBRARIES + +installdirs: + for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(m4datadir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \ + clean-libtool clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/gen-posix-lock-obj.Po + -rm -f ./$(DEPDIR)/gen-w32-lock-obj.Po + -rm -f ./$(DEPDIR)/gpg_error-gpg-error.Po + -rm -f ./$(DEPDIR)/gpg_error-strerror-sym.Po + -rm -f ./$(DEPDIR)/gpg_error-strsource-sym.Po + -rm -f ./$(DEPDIR)/libgpg_error_la-argparse.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-b64dec.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-b64enc.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-code-from-errno.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-code-to-errno.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-estream-printf.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-estream.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-init.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-logging.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-posix-lock.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-posix-thread.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-spawn-posix.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-spawn-w32.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-strerror.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-stringutils.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-strsource.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-syscall-clamp.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-sysutils.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-version.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-visibility.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-w32-estream.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-w32-gettext.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-w32-iconv.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-w32-lock.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-w32-reg.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-w32-thread.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-data-local install-m4dataDATA \ + install-nodist_includeHEADERS install-pkgconfigDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS install-binSCRIPTS \ + install-dist_binSCRIPTS install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/gen-posix-lock-obj.Po + -rm -f ./$(DEPDIR)/gen-w32-lock-obj.Po + -rm -f ./$(DEPDIR)/gpg_error-gpg-error.Po + -rm -f ./$(DEPDIR)/gpg_error-strerror-sym.Po + -rm -f ./$(DEPDIR)/gpg_error-strsource-sym.Po + -rm -f ./$(DEPDIR)/libgpg_error_la-argparse.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-b64dec.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-b64enc.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-code-from-errno.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-code-to-errno.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-estream-printf.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-estream.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-init.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-logging.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-posix-lock.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-posix-thread.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-spawn-posix.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-spawn-w32.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-strerror.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-stringutils.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-strsource.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-syscall-clamp.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-sysutils.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-version.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-visibility.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-w32-estream.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-w32-gettext.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-w32-iconv.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-w32-lock.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-w32-reg.Plo + -rm -f ./$(DEPDIR)/libgpg_error_la-w32-thread.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS \ + uninstall-dist_binSCRIPTS uninstall-libLTLIBRARIES \ + uninstall-m4dataDATA uninstall-nodist_includeHEADERS \ + uninstall-pkgconfigDATA + +.MAKE: all check check-am install install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \ + check-am clean clean-binPROGRAMS clean-generic \ + clean-libLTLIBRARIES clean-libtool clean-noinstPROGRAMS \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-binPROGRAMS install-binSCRIPTS install-data \ + install-data-am install-data-local install-dist_binSCRIPTS \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-libLTLIBRARIES install-m4dataDATA install-man \ + install-nodist_includeHEADERS install-pdf install-pdf-am \ + install-pkgconfigDATA install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-binPROGRAMS \ + uninstall-binSCRIPTS uninstall-dist_binSCRIPTS \ + uninstall-libLTLIBRARIES uninstall-m4dataDATA \ + uninstall-nodist_includeHEADERS uninstall-pkgconfigDATA + +.PRECIOUS: Makefile + + +@HAVE_W32_SYSTEM_TRUE@.rc.lo: +@HAVE_W32_SYSTEM_TRUE@ $(LTRCCOMPILE) -i "$<" -o "$@" + +@HAVE_W32_SYSTEM_TRUE@versioninfo.lo : gpg-error.w32-manifest + +@HAVE_W32_SYSTEM_TRUE@install-def-file: gpg-error.def +@HAVE_W32_SYSTEM_TRUE@ -$(INSTALL) -d $(DESTDIR)$(libdir) +@HAVE_W32_SYSTEM_TRUE@ $(INSTALL) gpg-error.def $(DESTDIR)$(libdir)/gpg-error.def + +@HAVE_W32_SYSTEM_TRUE@uninstall-def-file: +@HAVE_W32_SYSTEM_TRUE@ -rm $(DESTDIR)$(libdir)/gpg-error.def + +@HAVE_W32_SYSTEM_FALSE@install-def-file: +@HAVE_W32_SYSTEM_FALSE@uninstall-def-file: + +# We build err-sources.h and err-codes.h in the source directory. +# This is needed because gettext does only look into the source +# directory to find the files listed in po/POTFILE.in. To make these +# rules work we also need to depend on Makefile.am and not on the +# generated files Makefile.in or Makefile. +$(srcdir)/err-sources.h: Makefile.am mkstrtable.awk err-sources.h.in + $(AWK) -f $(srcdir)/mkstrtable.awk -v textidx=3 \ + $(srcdir)/err-sources.h.in >$@ + +err-sources-sym.h: Makefile mkstrtable.awk err-sources.h.in + $(AWK) -f $(srcdir)/mkstrtable.awk -v textidx=2 -v nogettext=1 \ + $(srcdir)/err-sources.h.in >$@ + +$(srcdir)/err-codes.h: Makefile.am mkstrtable.awk err-codes.h.in + $(AWK) -f $(srcdir)/mkstrtable.awk -v textidx=3 \ + $(srcdir)/err-codes.h.in >$@ + +err-codes-sym.h: Makefile mkstrtable.awk err-codes.h.in + $(AWK) -f $(srcdir)/mkstrtable.awk -v textidx=2 -v nogettext=1 \ + $(srcdir)/err-codes.h.in >$@ + +code-to-errno.h: Makefile mkerrnos.awk errnos.in + $(AWK) -f $(srcdir)/mkerrnos.awk $(srcdir)/errnos.in >$@ + +# It is correct to use $(CPP). We want the host's idea of the error codes. +mkerrcodes.h: Makefile mkerrcodes.awk $(gpg_extra_headers) + $(AWK) -f $(srcdir)/mkerrcodes1.awk $(srcdir)/errnos.in >_$@ + $(CPP) $(CPPFLAGS) $(extra_cppflags) -P _$@ | grep GPG_ERR_ | \ + $(AWK) -f $(srcdir)/mkerrcodes.awk >$@ + -rm _$@ + +# It is correct to use $(CPP). We want the host's idea of the error codes. +@HAVE_W32CE_SYSTEM_TRUE@mkw32errmap.tab.h: Makefile mkw32errmap.c +@HAVE_W32CE_SYSTEM_TRUE@ $(CPP) -DRESOLVE_MACROS $(srcdir)/mkw32errmap.c | \ +@HAVE_W32CE_SYSTEM_TRUE@ grep '{&mkw32errmap_marker' >$@ +@HAVE_W32CE_SYSTEM_TRUE@mkw32errmap.map.c: mkw32errmap$(EXEEXT_FOR_BUILD) +@HAVE_W32CE_SYSTEM_TRUE@ ./mkw32errmap$(EXEEXT_FOR_BUILD) --map > $@ +@HAVE_W32CE_SYSTEM_TRUE@gpg-extra/errno.h: mkw32errmap$(EXEEXT_FOR_BUILD) +@HAVE_W32CE_SYSTEM_TRUE@ -$(MKDIR_P) gpg-extra +@HAVE_W32CE_SYSTEM_TRUE@ ./mkw32errmap$(EXEEXT_FOR_BUILD) > $@ +@HAVE_W32CE_SYSTEM_FALSE@mkw32errmap.map.c: +@HAVE_W32CE_SYSTEM_FALSE@ echo "/*dummy*/" > $@ + +# We use CC proper for preprocessing thus we have to convince it that +# the data is really to be preprocessed. +gpg-error.def: Makefile gpg-error.def.in + cat $(srcdir)/gpg-error.def.in >_$@.h + $(CPP) $(DEFAULT_INCLUDES) $(INCLUDES) $(extra_cppflags) _$@.h | \ + grep -v '^#' >$@ + -rm _$@.h + +# It is correct to use $(CC_FOR_BUILD) here. We want to run the +# program at build time. +mkerrcodes$(EXEEXT_FOR_BUILD): mkerrcodes.c mkerrcodes.h Makefile + $(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) \ + $(CPPFLAGS_FOR_BUILD) -I. -I$(srcdir) -o $@ $(srcdir)/mkerrcodes.c + +# It is correct to use $(CC_FOR_BUILD) here. We want to run the +# program at build time. +@HAVE_W32CE_SYSTEM_TRUE@mkw32errmap$(EXEEXT_FOR_BUILD): mkw32errmap.c mkw32errmap.tab.h Makefile +@HAVE_W32CE_SYSTEM_TRUE@ $(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) \ +@HAVE_W32CE_SYSTEM_TRUE@ $(CPPFLAGS_FOR_BUILD) -I. -I$(srcdir) -o $@ $(srcdir)/mkw32errmap.c + +code-from-errno.h: mkerrcodes$(EXEEXT_FOR_BUILD) Makefile + ./mkerrcodes$(EXEEXT_FOR_BUILD) | $(AWK) -f $(srcdir)/mkerrcodes2.awk >$@ + +errnos-sym.h: Makefile mkstrtable.awk errnos.in + $(AWK) -f $(srcdir)/mkstrtable.awk -v textidx=2 -v nogettext=1 \ + -v prefix=GPG_ERR_ -v pkg_namespace=errnos_ \ + $(srcdir)/errnos.in >$@ + +mkheader$(EXEEXT_FOR_BUILD): mkheader.c Makefile + $(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) \ + $(CPPFLAGS_FOR_BUILD) -g -I. -I$(srcdir) -o $@ $(srcdir)/mkheader.c + +@FORCE_USE_SYSCFG_FALSE@@HAVE_GENERATED_LOCK_OBJ_H_FALSE@./lock-obj-pub.native.h: Makefile gen-posix-lock-obj$(EXEEXT) posix-lock-obj.h +@FORCE_USE_SYSCFG_FALSE@@HAVE_GENERATED_LOCK_OBJ_H_FALSE@ ./gen-posix-lock-obj >$@ + +# We also depend on versioninfo.rc because that is build by +# config.status and thus has up-to-date version numbers. +gpg-error.h: Makefile mkheader$(EXEEXT_FOR_BUILD) $(parts_of_gpg_error_h) \ + versioninfo.rc ../config.h + $(pre_mkheader_cmds) + ./mkheader$(EXEEXT_FOR_BUILD) $(mkheader_opts) \ + $(host_triplet) $(srcdir)/gpg-error.h.in \ + ../config.h $(PACKAGE_VERSION) $(VERSION_NUMBER) >$@ + +gpgrt.h: gpg-error.h + cp gpg-error.h gpgrt.h + +gpg-error-config: gpgrt-config gpg-error-config-old + @echo $(ECHO_N) "Confirm gpg-error-config works... $(ECHO_C)" + @if ./gpg-error-config-test.sh --old-new; then \ + echo "good"; \ + else \ + echo "no"; \ + echo "*** Please report to <https://bugs.gnupg.org> with gpg-error-config-test.log"; \ + exit 1; \ + fi + cp gpg-error-config-old $@ + +install-data-local: +@HAVE_W32CE_SYSTEM_TRUE@ -$(MKDIR_P) "$(DESTDIR)$(includedir)/gpg-extra" +@HAVE_W32CE_SYSTEM_TRUE@ $(INSTALL_DATA) gpg-extra/errno.h \ +@HAVE_W32CE_SYSTEM_TRUE@ "$(DESTDIR)$(includedir)/gpg-extra/errno.h" +@HAVE_W32CE_SYSTEM_FALSE@ : + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/comm/third_party/libgpg-error/src/README b/comm/third_party/libgpg-error/src/README new file mode 100644 index 0000000000..c415983598 --- /dev/null +++ b/comm/third_party/libgpg-error/src/README @@ -0,0 +1,47 @@ +Notes on the source code +======================== + +The mechanism to generate the system error codes is delicate and +fragile, but it's the best I could come up with that supports +cross-compilation and dynamic self-configuration. Here is how it +works: + +1. Generate list of supported system error codes. + +mkerrcodes1.awk generates a list of supported system error codes from +errnos.in. Each entry in the list is protected with #ifdef/#endif, +and contains a GPG_ERR_* marker. The list is stored in "_mkerrcodes.h". + +2. The HOST cpp is run on _mkerrcodes.h. This evaluates the known +system error macros to something (may be a number, maybe a constant +expression as on the GNU/Hurd), suppressing the unknown ones. The +output is piped into step 3. + +3. The cpp output is filtered with grep for only those lines which +contain a GPG_ERR_* marker. The output is piped into step 4. + +4. The filtered output is processed by mkerrcodes.awk, which produces +a table of constant expressions plus GPG_ERR_* code string symbols in +a format suitable for the C program mkerrcodes.c. At this point we +are crossing our fingers that the constant expressions produced by the +system do not contain GPG_ERR_* markers. The output is stored in +mkerrcodes.h. + +5. The file mkerrcodes.h is included by mkerrcodes.c, which is +compiled to a binary executable on the BUILD system. At this point we +are crossing our fingers that the constant expressions produced by the +system do not depend on the build platform anymore. The output is +post-processed by mkerrcodes2.awk and stored in "code-from-errno.h", +which is subsequently used in the library. + +-- Marcus + + Copyright 2006 g10 Code GmbH + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/comm/third_party/libgpg-error/src/argparse.c b/comm/third_party/libgpg-error/src/argparse.c new file mode 100644 index 0000000000..cb5c58ce4c --- /dev/null +++ b/comm/third_party/libgpg-error/src/argparse.c @@ -0,0 +1,2852 @@ +/* argparse.c - Argument Parser for option handling + * Copyright (C) 1997-2001, 2006-2008, 2013-2017 Werner Koch + * Copyright (C) 1998-2001, 2006-2008, 2012 Free Software Foundation, Inc. + * Copyright (C) 2015-2020 g10 Code GmbH + * + * This file is part of Libgpg-error. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, see <https://www.gnu.org/licenses/>. + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * This file was originally a part of GnuPG. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <stdarg.h> +#include <limits.h> +#include <errno.h> +#include <unistd.h> +#include <time.h> + +#include "gpgrt-int.h" + +#ifdef HAVE_W32_SYSTEM +# define PATHSEP_C ';' +# define DIRSEP_C '\\' +#else +# define PATHSEP_C ':' +# define DIRSEP_C '/' +#endif + + +/* The malloced configuration directories or NULL. */ +static struct +{ + char *user; + char *sys; +} confdir; + + +/* Hidden argparse flag used to mark the object as initialized. */ +#define ARGPARSE_FLAG__INITIALIZED (1u << ((8*SIZEOF_INT)-1)) + +/* Special short options which are auto-inserterd. Must fit into an + * unsigned short. */ +#define ARGPARSE_SHORTOPT_HELP 32768 +#define ARGPARSE_SHORTOPT_VERSION 32769 +#define ARGPARSE_SHORTOPT_WARRANTY 32770 +#define ARGPARSE_SHORTOPT_DUMP_OPTIONS 32771 +#define ARGPARSE_SHORTOPT_DUMP_OPTTBL 32772 + + +/* The states for the gpgrt_argparser machinery. */ +enum argparser_states + { + STATE_init = 0, + STATE_open_sys, + STATE_open_user, + STATE_open_cmdline, + STATE_read_sys, + STATE_read_user, + STATE_read_cmdline, + STATE_finished + }; + + +/* An internal object used to store the user provided option table and + * some meta information. */ +typedef struct +{ + unsigned short short_opt; + unsigned short ordinal; /* (for --help) */ + unsigned int flags; + const char *long_opt; /* Points into the user provided table. */ + const char *description; /* Points into the user provided table. */ + unsigned int forced:1; /* Forced to use the sysconf value. */ + unsigned int ignore:1; /* Ignore this option everywhere but in + * the sysconf file. */ + unsigned int explicit_ignore:1; /* Ignore was explicitly set. */ +} opttable_t; + + +/* Internal object of the public gpgrt_argparse_t object. */ +struct _gpgrt_argparse_internal_s +{ + int idx; /* Note that this is saved and restored in _gpgrt_argparser. */ + int inarg; /* (index into args) */ + unsigned int verbose:1; /* Print diagnostics. */ + unsigned int stopped:1; /* Option processing has stopped. */ + unsigned int in_sysconf:1; /* Processing global config file. */ + unsigned int mark_forced:1; /* Mark options as forced. */ + unsigned int mark_ignore:1; /* Mark options as to be ignored. */ + unsigned int explicit_ignore:1; /* Option has explicitly been set + * to ignore or unignore. */ + unsigned int ignore_all_seen:1; /* [ignore-all] has been seen. */ + unsigned int user_seen:1; /* A [user] has been seen. */ + unsigned int user_wildcard:1; /* A [user *] has been seen. */ + unsigned int user_any_active:1; /* Any user section was active. */ + unsigned int user_active:1; /* User section active. */ + unsigned int explicit_confopt:1; /* A conffile option has been given. */ + char *explicit_conffile; /* Malloced name of an explicit + * conffile. */ + char *username; /* Malloced current user name. */ + unsigned int opt_flags; /* Current option flags. */ + enum argparser_states state; /* State of the gpgrt_argparser. */ + const char *last; + void *aliases; + const void *cur_alias; + void *iio_list; + estream_t conffp; + char *confname; + opttable_t *opts; /* Malloced option table. */ + unsigned int nopts; /* Number of items in OPTS. */ +}; + + +typedef struct alias_def_s *ALIAS_DEF; +struct alias_def_s { + ALIAS_DEF next; + char *name; /* malloced buffer with name, \0, value */ + const char *value; /* ptr into name */ +}; + + +/* Object to store the names for the --ignore-invalid-option option. + This is a simple linked list. */ +typedef struct iio_item_def_s *IIO_ITEM_DEF; +struct iio_item_def_s +{ + IIO_ITEM_DEF next; + char name[1]; /* String with the long option name. */ +}; + + +/* The almost always needed user handler for strusage. */ +static const char *(*strusage_handler)( int ) = NULL; +/* Optional handler to write strings. See _gpgrt_set_usage_outfnc. */ +static int (*custom_outfnc) (int, const char *); +/* Optional handler to map strings. See _gpgrt_set_fixed_string_mapper. */ +static const char *(*fixed_string_mapper)(const char*); + +static int set_opt_arg (gpgrt_argparse_t *arg, unsigned int flags, char *s); +static void show_help (opttable_t *opts, unsigned int nopts,unsigned int flags); +static void show_version (void); +static void dump_option_table (gpgrt_argparse_t *arg); +static int writestrings (int is_error, const char *string, + ...) GPGRT_ATTR_SENTINEL(0); +static int arg_parse (gpgrt_argparse_t *arg, gpgrt_opt_t *opts, int no_init); + + + + + +/* Return true if the native charset is utf-8. */ +static int +is_native_utf8 (void) +{ + static char result; + + if (!result) + { + const char *p = _gpgrt_strusage (8); + if (!p || !*p || !strcmp (p, "utf-8")) + result = 1; + result |= 128; + } + + return (result & 1); +} + + +static char * +trim_spaces (char *str) +{ + char *string, *p, *mark; + + string = str; + /* Find first non space character. */ + for (p=string; *p && isspace (*(unsigned char*)p) ; p++) + ; + /* Move characters. */ + for ((mark = NULL); (*string = *p); string++, p++) + if (isspace (*(unsigned char*)p)) + { + if (!mark) + mark = string; + } + else + mark = NULL; + if (mark) + *mark = '\0' ; /* Remove trailing spaces. */ + + return str ; +} + + +static const char * +map_fixed_string (const char *string) +{ + return fixed_string_mapper? fixed_string_mapper (string) : string; +} + + +/* Write STRING and all following const char * arguments either to + stdout or, if IS_ERROR is set, to stderr. The list of strings must + be terminated by a NULL. */ +static int +writestrings (int is_error, const char *string, ...) +{ + va_list arg_ptr; + const char *s; + int count = 0; + + if (string) + { + s = string; + va_start (arg_ptr, string); + do + { + if (custom_outfnc) + custom_outfnc (is_error? 2:1, s); + else + _gpgrt_fputs (s, is_error? es_stderr : es_stdout); + count += strlen (s); + } + while ((s = va_arg (arg_ptr, const char *))); + va_end (arg_ptr); + } + return count; +} + + +static void +flushstrings (int is_error) +{ + if (custom_outfnc) + custom_outfnc (is_error? 2:1, NULL); + else + _gpgrt_fflush (is_error? es_stderr : es_stdout); +} + + +static void +deinitialize (gpgrt_argparse_t *arg) +{ + if (arg->internal) + { + xfree (arg->internal->username); + xfree (arg->internal->explicit_conffile); + xfree (arg->internal->opts); + xfree (arg->internal); + arg->internal = NULL; + } + + arg->flags &= ARGPARSE_FLAG__INITIALIZED; + arg->lineno = 0; + arg->err = 0; +} + +/* Our own exit handler to clean up used memory. */ +static void +my_exit (gpgrt_argparse_t *arg, int code) +{ + deinitialize (arg); + exit (code); +} + + +static gpg_err_code_t +initialize (gpgrt_argparse_t *arg, gpgrt_opt_t *opts, estream_t fp) +{ + /* We use a dedicated flag to detect whether *ARG has been + * initialized. This is because the old version of that struct, as + * used in GnuPG, had no requirement to zero out all fields of the + * object and existing code still sets only argc,argv and flags. */ + if (!(arg->flags & ARGPARSE_FLAG__INITIALIZED) + || (arg->flags & ARGPARSE_FLAG_RESET) + || !arg->internal) + { + /* Allocate internal data. */ + if (!(arg->flags & ARGPARSE_FLAG__INITIALIZED) || !arg->internal) + { + arg->internal = xtrymalloc (sizeof *arg->internal); + if (!arg->internal) + return _gpg_err_code_from_syserror (); + arg->flags |= ARGPARSE_FLAG__INITIALIZED; /* Mark as initialized. */ + } + else if (arg->internal->opts) + xfree (arg->internal->opts); + arg->internal->opts = NULL; + arg->internal->nopts = 0; + + /* Initialize this instance. */ + arg->internal->idx = 0; + arg->internal->last = NULL; + arg->internal->inarg = 0; + arg->internal->stopped = 0; + arg->internal->in_sysconf = 0; + arg->internal->user_seen = 0; + arg->internal->user_wildcard = 0; + arg->internal->user_any_active = 0; + arg->internal->user_active = 0; + arg->internal->username = NULL; + arg->internal->mark_forced = 0; + arg->internal->mark_ignore = 0; + arg->internal->explicit_ignore = 0; + arg->internal->ignore_all_seen = 0; + arg->internal->explicit_confopt = 0; + arg->internal->explicit_conffile = NULL; + arg->internal->opt_flags = 0; + arg->internal->state = STATE_init; + arg->internal->aliases = NULL; + arg->internal->cur_alias = NULL; + arg->internal->iio_list = NULL; + arg->internal->conffp = NULL; + arg->internal->confname = NULL; + + /* Clear the copy of the option list. */ + /* Clear the error indicator. */ + arg->err = 0; + + /* Usually an option file will be parsed from the start. + * However, we do not open the stream and thus we have no way to + * know the current lineno. Using this flag we can allow the + * user to provide a lineno which we don't reset. */ + if (fp || arg->internal->conffp || !(arg->flags & ARGPARSE_FLAG_NOLINENO)) + arg->lineno = 0; + + /* Need to clear the reset request. */ + arg->flags &= ~ARGPARSE_FLAG_RESET; + + /* Check initial args. */ + if ( *arg->argc < 0 ) + _gpgrt_log_bug ("invalid argument passed to gpgrt_argparse\n"); + + } + + /* Create an array with pointers to the provided list of options. + * Keeping a copy is useful to sort that array and thus do a binary + * search and to allow for extra space at the end to insert the + * hidden options. An ARGPARSE_FLAG_RESET can be used to reinit + * this array. */ + if (!arg->internal->opts) + { + int seen_help = 0; + int seen_version = 0; + int seen_warranty = 0; + int seen_dump_options = 0; + int seen_dump_option_table = 0; + int i; + + for (i=0; opts[i].short_opt; i++) + { + if (opts[i].long_opt) + { + if (!strcmp(opts[i].long_opt, "help")) + seen_help = 1; + else if (!strcmp(opts[i].long_opt, "version")) + seen_version = 1; + else if (!strcmp(opts[i].long_opt, "warranty")) + seen_warranty = 1; + else if (!strcmp(opts[i].long_opt, "dump-options")) + seen_dump_options = 1; + else if (!strcmp(opts[i].long_opt, "dump-option-table")) + seen_dump_option_table = 1; + } + } + i += 5; /* The number of the above internal options. */ + i++; /* End of list marker. */ + arg->internal->opts = xtrycalloc (i, sizeof *arg->internal->opts); + if (!arg->internal->opts) + return _gpg_err_code_from_syserror (); + for(i=0; opts[i].short_opt; i++) + { + arg->internal->opts[i].short_opt = opts[i].short_opt; + arg->internal->opts[i].flags = opts[i].flags; + arg->internal->opts[i].long_opt = opts[i].long_opt; + arg->internal->opts[i].description = opts[i].description; + arg->internal->opts[i].ordinal = i; + } + + if (!seen_help) + { + arg->internal->opts[i].short_opt = ARGPARSE_SHORTOPT_HELP; + arg->internal->opts[i].flags = ARGPARSE_TYPE_NONE; + arg->internal->opts[i].long_opt = "help"; + arg->internal->opts[i].description = "@"; + arg->internal->opts[i].ordinal = i; + i++; + } + if (!seen_version) + { + arg->internal->opts[i].short_opt = ARGPARSE_SHORTOPT_VERSION; + arg->internal->opts[i].flags = ARGPARSE_TYPE_NONE; + arg->internal->opts[i].long_opt = "version"; + arg->internal->opts[i].description = "@"; + arg->internal->opts[i].ordinal = i; + i++; + } + + if (!seen_warranty) + { + arg->internal->opts[i].short_opt = ARGPARSE_SHORTOPT_WARRANTY; + arg->internal->opts[i].flags = ARGPARSE_TYPE_NONE; + arg->internal->opts[i].long_opt = "warranty"; + arg->internal->opts[i].description = "@"; + arg->internal->opts[i].ordinal = i; + i++; + } + + if (!seen_dump_option_table) + { + arg->internal->opts[i].short_opt = ARGPARSE_SHORTOPT_DUMP_OPTTBL; + arg->internal->opts[i].flags = ARGPARSE_TYPE_NONE; + arg->internal->opts[i].long_opt = "dump-option-table"; + arg->internal->opts[i].description = "@"; + arg->internal->opts[i].ordinal = i; + i++; + } + + if (!seen_dump_options) + { + arg->internal->opts[i].short_opt = ARGPARSE_SHORTOPT_DUMP_OPTIONS; + arg->internal->opts[i].flags = ARGPARSE_TYPE_NONE; + arg->internal->opts[i].long_opt = "dump-options"; + arg->internal->opts[i].description = "@"; + arg->internal->opts[i].ordinal = i; + i++; + } + /* Take care: When adding new options remember to increase the + * size of the array. */ + + arg->internal->opts[i].short_opt = 0; + + /* Note that we do not count the end marker but keep it in the + * table anyway as an extra item. */ + arg->internal->nopts = i; + } + + if (arg->err) + { + /* Last option was erroneous. */ + const char *s; + + if (!fp && arg->internal->conffp) + fp = arg->internal->conffp; + + if (fp) + { + if ( arg->r_opt == ARGPARSE_UNEXPECTED_ARG ) + s = _("argument not expected"); + else if ( arg->r_opt == ARGPARSE_READ_ERROR ) + s = _("read error"); + else if ( arg->r_opt == ARGPARSE_KEYWORD_TOO_LONG ) + s = _("keyword too long"); + else if ( arg->r_opt == ARGPARSE_MISSING_ARG ) + s = _("missing argument"); + else if ( arg->r_opt == ARGPARSE_INVALID_ARG ) + s = _("invalid argument"); + else if ( arg->r_opt == ARGPARSE_INVALID_COMMAND ) + s = _("invalid command"); + else if ( arg->r_opt == ARGPARSE_INVALID_ALIAS ) + s = _("invalid alias definition"); + else if ( arg->r_opt == ARGPARSE_PERMISSION_ERROR ) + s = _("permission error"); + else if ( arg->r_opt == ARGPARSE_OUT_OF_CORE ) + s = _("out of core"); + else if ( arg->r_opt == ARGPARSE_NO_CONFFILE ) + s = NULL; /* Error has already been printed. */ + else if ( arg->r_opt == ARGPARSE_INVALID_META ) + s = _("invalid meta command"); + else if ( arg->r_opt == ARGPARSE_UNKNOWN_META ) + s = _("unknown meta command"); + else if ( arg->r_opt == ARGPARSE_UNEXPECTED_META ) + s = _("unexpected meta command"); + else + s = _("invalid option"); + if (s) + _gpgrt_log_error ("%s:%u: %s\n", + _gpgrt_fname_get (fp), arg->lineno, s); + } + else + { + s = arg->internal->last? arg->internal->last:"[??]"; + + if ( arg->r_opt == ARGPARSE_MISSING_ARG ) + _gpgrt_log_error (_("missing argument for option \"%.50s\"\n"), s); + else if ( arg->r_opt == ARGPARSE_INVALID_ARG ) + _gpgrt_log_error (_("invalid argument for option \"%.50s\"\n"), s); + else if ( arg->r_opt == ARGPARSE_UNEXPECTED_ARG ) + _gpgrt_log_error (_("option \"%.50s\" does not expect " + "an argument\n"), s); + else if ( arg->r_opt == ARGPARSE_INVALID_COMMAND ) + _gpgrt_log_error (_("invalid command \"%.50s\"\n"), s); + else if ( arg->r_opt == ARGPARSE_AMBIGUOUS_OPTION ) + _gpgrt_log_error (_("option \"%.50s\" is ambiguous\n"), s); + else if ( arg->r_opt == ARGPARSE_AMBIGUOUS_COMMAND ) + _gpgrt_log_error (_("command \"%.50s\" is ambiguous\n"),s ); + else if ( arg->r_opt == ARGPARSE_OUT_OF_CORE ) + _gpgrt_log_error ("%s\n", _("out of core")); + else if ( arg->r_opt == ARGPARSE_PERMISSION_ERROR ) + _gpgrt_log_error ("%s\n", _("permission error")); + else if ( arg->r_opt == ARGPARSE_NO_CONFFILE) + ; /* Error has already been printed. */ + else if ( arg->r_opt == ARGPARSE_INVALID_META ) + _gpgrt_log_error ("%s\n", _("invalid meta command")); + else if ( arg->r_opt == ARGPARSE_UNKNOWN_META ) + _gpgrt_log_error ("%s\n", _("unknown meta command")); + else if ( arg->r_opt == ARGPARSE_UNEXPECTED_META ) + _gpgrt_log_error ("%s\n",_("unexpected meta command")); + else + _gpgrt_log_error (_("invalid option \"%.50s\"\n"), s); + } + if (arg->err != ARGPARSE_PRINT_WARNING) + my_exit (arg, 2); + arg->err = 0; + } + + /* Zero out the return value union. */ + arg->r.ret_str = NULL; + arg->r.ret_long = 0; + + return 0; +} + + +static void +store_alias( gpgrt_argparse_t *arg, char *name, char *value ) +{ + /* TODO: replace this dummy function with a rea one + * and fix the probelms IRIX has with (ALIAS_DEV)arg.. + * used as lvalue + */ + (void)arg; + (void)name; + (void)value; +#if 0 + ALIAS_DEF a = xmalloc( sizeof *a ); + a->name = name; + a->value = value; + a->next = (ALIAS_DEF)arg->internal->aliases; + (ALIAS_DEF)arg->internal->aliases = a; +#endif +} + + +/* Return true if KEYWORD is in the ignore-invalid-option list. */ +static int +ignore_invalid_option_p (gpgrt_argparse_t *arg, const char *keyword) +{ + IIO_ITEM_DEF item = arg->internal->iio_list; + + for (; item; item = item->next) + if (!strcmp (item->name, keyword)) + return 1; + return 0; +} + + +/* Add the keywords up to the next LF to the list of to be ignored + options. After returning FP will either be at EOF or the next + character read wll be the first of a new line. The function + returns 0 on success or true on malloc failure. */ +static int +ignore_invalid_option_add (gpgrt_argparse_t *arg, estream_t fp) +{ + IIO_ITEM_DEF item; + int c; + char name[100]; + int namelen = 0; + int ready = 0; + enum { skipWS, collectNAME, skipNAME, addNAME} state = skipWS; + + while (!ready) + { + c = _gpgrt_fgetc (fp); + if (c == '\n') + ready = 1; + else if (c == EOF) + { + c = '\n'; + ready = 1; + } + again: + switch (state) + { + case skipWS: + if (!isascii (c) || !isspace(c)) + { + namelen = 0; + state = collectNAME; + goto again; + } + break; + + case collectNAME: + if (isspace (c)) + { + state = addNAME; + goto again; + } + else if (namelen < DIM(name)-1) + name[namelen++] = c; + else /* Too long. */ + state = skipNAME; + break; + + case skipNAME: + if (isspace (c)) + { + state = skipWS; + goto again; + } + break; + + case addNAME: + name[namelen] = 0; + if (!ignore_invalid_option_p (arg, name)) + { + item = xtrymalloc (sizeof *item + namelen); + if (!item) + return 1; + strcpy (item->name, name); + item->next = (IIO_ITEM_DEF)arg->internal->iio_list; + arg->internal->iio_list = item; + } + state = skipWS; + goto again; + } + } + return 0; +} + + +/* Clear the entire ignore-invalid-option list. */ +static void +ignore_invalid_option_clear (gpgrt_argparse_t *arg) +{ + IIO_ITEM_DEF item, tmpitem; + + for (item = arg->internal->iio_list; item; item = tmpitem) + { + tmpitem = item->next; + xfree (item); + } + arg->internal->iio_list = NULL; +} + + +/* Make sure the username field is filled. Return 0 on success. */ +static int +assure_username (gpgrt_argparse_t *arg) +{ + if (!arg->internal->username) + { + arg->internal->username = _gpgrt_getusername (); + if (!arg->internal->username) + { + _gpgrt_log_error ("%s:%u: error getting current user's name: %s\n", + arg->internal->confname, arg->lineno, + _gpg_strerror (gpg_error_from_syserror ())); + /* Not necessary the correct error code but given that we + * either have a malloc error or some internal system error, + * it is the best we can do. */ + return ARGPARSE_PERMISSION_ERROR; + } + } + return 0; +} + + +/* Implementation of the "user" command. ARG is the context. ARGS is + * a non-empty string which this function is allowed to modify. */ +static int +handle_meta_user (gpgrt_argparse_t *arg, unsigned int alternate, char *args) +{ + int rc; + + (void)alternate; + + rc = assure_username (arg); + if (rc) + return rc; + + arg->internal->user_seen = 1; + if (*args == '*' && !args[1]) + { + arg->internal->user_wildcard = 1; + arg->internal->user_active = !arg->internal->user_any_active; + } + else if (arg->internal->user_wildcard) + { + /* All other user statements are ignored after a wildcard. */ + arg->internal->user_active = 0; + } + else if (!strcasecmp (args, arg->internal->username)) + { + arg->internal->user_any_active = 1; + arg->internal->user_active = 1; + } + else + { + arg->internal->user_active = 0; + } + + return 0; +} + + +/* Implementation of the "force" command. ARG is the context. A + * value of 0 for ALTERNATE is "force", a value of 1 requests an + * unforce". ARGS is the empty string and not used. */ +static int +handle_meta_force (gpgrt_argparse_t *arg, unsigned int alternate, char *args) +{ + (void)args; + + arg->internal->mark_forced = alternate? 0 : 1; + + return 0; +} + + +/* Implementation of the "ignore" command. ARG is the context. A + * value of 0 for ALTERNATE is a plain "ignore", a value of 1 request + * an "unignore, a value of 2 requests an "ignore-all". ARGS is the + * empty string and not used. */ +static int +handle_meta_ignore (gpgrt_argparse_t *arg, unsigned int alternate, char *args) +{ + (void)args; + + if (!alternate) + { + arg->internal->mark_ignore = 1; + arg->internal->explicit_ignore = 1; + } + else if (alternate == 1) + { + arg->internal->mark_ignore = 0; + arg->internal->explicit_ignore = 1; + } + else + arg->internal->ignore_all_seen = 1; + + return 0; +} + + +/* Implementation of the "echo" command. ARG is the context. If + * ALTERNATE is true the filename is not printed. ARGS is the string + * to log. */ +static int +handle_meta_echo (gpgrt_argparse_t *arg, unsigned int alternate, char *args) +{ + int rc = 0; + char *p, *pend; + + if (alternate) + _gpgrt_log_info ("%s", ""); + else + _gpgrt_log_info ("%s:%u: ", arg->internal->confname, arg->lineno); + + while (*args) + { + p = strchr (args, '$'); + if (!p) + { + _gpgrt_log_printf ("%s", args); + break; + } + *p = 0; + _gpgrt_log_printf ("%s", args); + if (p[1] == '$') + { + _gpgrt_log_printf ("$"); + args = p+2; + continue; + } + if (p[1] != '{') + { + _gpgrt_log_printf ("$"); + args = p+1; + continue; + } + pend = strchr (p+2, '}'); + if (!pend) /* No closing brace. */ + { + _gpgrt_log_printf ("$"); + args = p+1; + continue; + } + p += 2; + *pend = 0; + args = pend+1; + if (!strcmp (p, "user")) + { + rc = assure_username (arg); + if (rc) + goto leave; + _gpgrt_log_printf ("%s", arg->internal->username); + } + else if (!strcmp (p, "file")) + _gpgrt_log_printf ("%s", arg->internal->confname); + else if (!strcmp (p, "line")) + _gpgrt_log_printf ("%u", arg->lineno); + else if (!strcmp (p, "epoch")) + _gpgrt_log_printf ("%lu", (unsigned long)time (NULL)); + } + + leave: + _gpgrt_log_printf ("\n"); + return rc; +} + + +/* Implementation of the "verbose" command. ARG is the context. If + * ALTERNATE is true the verbosity is disabled. ARGS is not used. */ +static int +handle_meta_verbose (gpgrt_argparse_t *arg, unsigned int alternate, char *args) +{ + (void)args; + + if (alternate) + arg->internal->verbose = 0; + else + arg->internal->verbose = 1; + return 0; +} + +/* Handle a meta command. KEYWORD has the content inside the brackets + * with leading and trailing spaces removed. The function may modify + * KEYWORD. On success 0 is returned, on error an ARGPARSE_ error + * code is returned. */ +static int +handle_metacmd (gpgrt_argparse_t *arg, char *keyword) +{ + static struct { + const char *name; /* Name of the command. */ + unsigned short alternate; /* Use alternate version of the command. */ + unsigned short needarg:1; /* Command requires an argument. */ + unsigned short always:1; /* Command allowed in all conf files. */ + unsigned short noskip:1; /* Even done in non-active [user] mode. */ + int (*func)(gpgrt_argparse_t *arg, + unsigned int alternate, char *args); /*handler*/ + } cmds[] = + {{ "user", 0, 1, 0, 1, handle_meta_user }, + { "force", 0, 0, 0, 0, handle_meta_force }, + { "+force", 0, 0, 0, 0, handle_meta_force }, + { "-force", 1, 0, 0, 0, handle_meta_force }, + { "ignore", 0, 0, 0, 0, handle_meta_ignore }, + { "+ignore", 0, 0, 0, 0, handle_meta_ignore }, + { "-ignore", 1, 0, 0, 0, handle_meta_ignore }, + { "ignore-all", 2, 0, 0, 0, handle_meta_ignore }, + { "+ignore-all", 2, 0, 0, 0, handle_meta_ignore }, + { "verbose", 0, 0, 1, 1, handle_meta_verbose }, + { "+verbose", 0, 0, 1, 1, handle_meta_verbose }, + { "-verbose", 1, 0, 1, 1, handle_meta_verbose }, + { "echo", 0, 1, 1, 1, handle_meta_echo }, + { "-echo", 1, 1, 1, 1, handle_meta_echo }, + { "info", 0, 1, 1, 0, handle_meta_echo }, + { "-info", 1, 1, 1, 0, handle_meta_echo } + }; + char *rest; + int i; + + for (rest = keyword; *rest && !(isascii (*rest) && isspace (*rest)); rest++) + ; + if (*rest) + { + *rest++ = 0; + trim_spaces (rest); + } + + for (i=0; i < DIM (cmds); i++) + if (!strcmp (cmds[i].name, keyword)) + break; + if (!(i < DIM (cmds))) + return ARGPARSE_UNKNOWN_META; + if (cmds[i].needarg && !*rest) + return ARGPARSE_MISSING_ARG; + if (!cmds[i].needarg && *rest) + return ARGPARSE_UNEXPECTED_ARG; + if (!arg->internal->in_sysconf && !cmds[i].always) + return ARGPARSE_UNEXPECTED_META; + + if (!cmds[i].noskip + && arg->internal->in_sysconf + && arg->internal->user_seen + && !arg->internal->user_active) + return 0; /* Skip this meta command. */ + + return cmds[i].func (arg, cmds[i].alternate, rest); +} + + +/* Helper for _gpgrt_argparse. */ +static void +prepare_arg_return (gpgrt_argparse_t *arg, opttable_t *opts, + int idx, int in_alias, int set_ignore) +{ + /* No argument found at the end of the line. */ + if (in_alias) + arg->r_opt = ARGPARSE_MISSING_ARG; + else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK)) + arg->r_type = ARGPARSE_TYPE_NONE; /* Does not take an arg. */ + else if ((opts[idx].flags & ARGPARSE_OPT_OPTIONAL)) + arg->r_type = ARGPARSE_TYPE_NONE; /* No optional argument. */ + else if (!(opts[idx].ignore && !opts[idx].forced) && !set_ignore) + arg->r_opt = ARGPARSE_MISSING_ARG; + + /* If the caller wants us to return the attributes or + * ignored options, or these flags in. */ + if ((arg->flags & ARGPARSE_FLAG_WITHATTR)) + { + if (opts[idx].ignore) + arg->r_type |= ARGPARSE_ATTR_IGNORE; + if (opts[idx].forced) + arg->r_type |= ARGPARSE_ATTR_FORCE; + if (set_ignore) + arg->r_type |= ARGPARSE_OPT_IGNORE; + } +} + +/**************** + * Get options from a file. + * Lines starting with '#' are comment lines. + * Syntax is simply a keyword and the argument. + * Valid keywords are all keywords from the long_opt list without + * the leading dashes. The special keywords "help", "warranty" and "version" + * are not valid here. + * The special keyword "alias" may be used to store alias definitions, + * which are later expanded like long options. + * The option + * ignore-invalid-option OPTIONNAMEs + * is recognized and updates a list of option which should be ignored if they + * are not defined. + * Caller must free returned strings. + * If called with FP set to NULL command line args are parse instead. + * + * Q: Should we allow the syntax + * keyword = value + * and accept for boolean options a value of 1/0, yes/no or true/false? + * Note: Abbreviation of options is here not allowed. + */ +int +_gpgrt_argparse (estream_t fp, gpgrt_argparse_t *arg, gpgrt_opt_t *opts_orig) +{ + enum { Ainit, + Acomment, /* In a comment line. */ + Acopykeyword, /* Collecting a keyword. */ + Awaitarg, /* Wait for an argument. */ + Acopyarg, /* Copy the argument. */ + Akeyword_eol, /* Got keyword at end of line. */ + Akeyword_spc, /* Got keyword at space. */ + Acopymetacmd, /* Copy a meta command. */ + Askipmetacmd, /* Skip spaces after metacmd. */ + Askipmetacmd2,/* Skip comment after metacmd. */ + Ametacmd, /* Process the metacmd. */ + Askipandleave /* Skip the rest of the line and then leave. */ + } state; + opttable_t *opts; + unsigned int nopts; + int i, c; + int idx = 0; + char keyword[100]; + char *buffer = NULL; + size_t buflen = 0; + int in_alias=0; + int set_ignore = 0; + int unread_buf[3]; /* We use an int so that we can store EOF. */ + int unread_buf_count = 0; + + if (arg && !opts_orig) + { + deinitialize (arg); + return 0; + } + + if (!fp) /* Divert to arg_parse() in this case. */ + return arg_parse (arg, opts_orig, 0); + + if (initialize (arg, opts_orig, fp)) + return (arg->r_opt = ARGPARSE_OUT_OF_CORE); + + opts = arg->internal->opts; + nopts = arg->internal->nopts; + + /* If the LINENO is zero we assume that we are at the start of a + * file and we skip over a possible Byte Order Mark. */ + if (!arg->lineno) + { + unread_buf[0] = _gpgrt_fgetc (fp); + unread_buf[1] = _gpgrt_fgetc (fp); + unread_buf[2] = _gpgrt_fgetc (fp); + if (unread_buf[0] != 0xef + || unread_buf[1] != 0xbb + || unread_buf[2] != 0xbf) + unread_buf_count = 3; + } + + arg->internal->opt_flags = 0; + + /* Find the next keyword. */ + state = Ainit; + i = 0; + for (;;) + { + nextstate: + /* Before scanning the next char handle the keyword seen states. */ + if (state == Akeyword_eol || state == Akeyword_spc) + { + /* We are either at the end of a line or right after a + * keyword. In the latter case we need to find the keyword + * so that we can decide whether an argument is required. */ + + /* Check the keyword. */ + for (idx=0; idx < nopts; idx++ ) + { + if (opts[idx].long_opt && !strcmp (opts[idx].long_opt, keyword)) + break; + } + arg->r_opt = opts[idx].short_opt; + if (!(idx < nopts)) + { + /* The option (keyword) is not known - check for + * internal keywords before returning an error. */ + if (state == Akeyword_spc && !strcmp (keyword, "alias")) + { + in_alias = 1; + state = Awaitarg; + } + else if (!strcmp (keyword, "ignore-invalid-option")) + { + /* We might have keywords as argument - add them to + * the list of ignored keywords. Note that we + * ignore empty argument lists and thus do not to + * call the function in the Akeyword_eol state. */ + if (state == Akeyword_spc) + { + if (ignore_invalid_option_add (arg, fp)) + { + arg->r_opt = ARGPARSE_OUT_OF_CORE; + goto leave; + } + arg->lineno++; + } + state = Ainit; + i = 0; + } + else if (ignore_invalid_option_p (arg, keyword)) + { + /* This invalid option is already in the iio list. */ + state = state == Akeyword_eol? Ainit : Acomment; + i = 0; + } + else + { + arg->r_opt = ((opts[idx].flags & ARGPARSE_OPT_COMMAND) + ? ARGPARSE_INVALID_COMMAND + : ARGPARSE_INVALID_OPTION); + if (state == Akeyword_spc) + state = Askipandleave; + else + goto leave; + } + } + else if (state != Akeyword_spc + && arg->internal->in_sysconf + && arg->internal->user_seen + && !arg->internal->user_active) + { + /* We are in a [user] meta command and it is not active. + * Skip the command. */ + state = state == Akeyword_eol? Ainit : Acomment; + i = 0; + } + else if (state != Akeyword_spc + && (opts[idx].flags & ARGPARSE_OPT_IGNORE)) + { + /* Known option is configured to be ignored. Start from + * scratch (new line) or process like a comment. */ + state = state == Akeyword_eol? Ainit : Acomment; + i = 0; + } + else /* Known option */ + { + set_ignore = 0; + + if (arg->internal->in_sysconf) + { + /* Set the current forced and ignored attributes. */ + if (arg->internal->mark_forced) + opts[idx].forced = 1; + if (arg->internal->mark_ignore) + opts[idx].ignore = 1; + if (arg->internal->explicit_ignore) + opts[idx].explicit_ignore = 1; + + if (opts[idx].ignore && !opts[idx].forced) + { + if (arg->internal->verbose) + _gpgrt_log_info ("%s:%u: ignoring option \"--%s\"\n", + arg->internal->confname, + arg->lineno, + opts[idx].long_opt); + if ((arg->flags & ARGPARSE_FLAG_WITHATTR)) + set_ignore = 1; + else + { + state = state == Akeyword_eol? Ainit : Acomment; + i = 0; + goto nextstate; /* Ignore this one. */ + } + } + } + else /* Non-sysconf file */ + { /* Act upon the forced and ignored attributes. */ + if (opts[idx].ignore || opts[idx].forced) + { + if (arg->internal->verbose) + _gpgrt_log_info ("%s:%u: ignoring option \"--%s\"" + " due to attributes:%s%s\n", + arg->internal->confname, + arg->lineno, + opts[idx].long_opt, + opts[idx].forced? " forced":"", + opts[idx].ignore? " ignore":""); + if ((arg->flags & ARGPARSE_FLAG_WITHATTR)) + set_ignore = 1; + else + { + state = state == Akeyword_eol? Ainit : Acomment; + i = 0; + goto nextstate; /* Ignore this one. */ + } + } + } + + if (state == Akeyword_spc) + { + /* If we shall ignore but not set the option we skip + * the argument. Otherwise we would need to use a + * made-up but not used args in the conf file. */ + if (set_ignore || (opts[idx].ignore && !opts[idx].forced)) + { + prepare_arg_return (arg, opts, idx, 0, set_ignore); + set_ignore = 0; + state = Askipandleave; + } + else + state = Awaitarg; + } + else + { + prepare_arg_return (arg, opts, idx, 0, set_ignore); + set_ignore = 0; + goto leave; + } + + } + } /* (end state Akeyword_eol/Akeyword_spc) */ + else if (state == Ametacmd) + { + /* We are at the end of a line. */ + gpgrt_assert (*keyword == '['); + trim_spaces (keyword+1); + if (!keyword[1]) + { + arg->r_opt = ARGPARSE_INVALID_META; /* Empty. */ + goto leave; + } + c = handle_metacmd (arg, keyword+1); + if (c) + { + arg->r_opt = c; /* Return error. */ + goto leave; + } + state = Ainit; + i = 0; + } + + /* Get the next character from the line. */ + if (unread_buf_count) + c = unread_buf[3 - unread_buf_count--]; + else + c = _gpgrt_fgetc (fp); + + if (c == '\n' || c== EOF ) + { /* Handle end of line. */ + if ( c != EOF ) + arg->lineno++; + if (state == Askipandleave) + goto leave; + else if (state == Acopykeyword) + { + keyword[i] = 0; + state = Akeyword_eol; + goto nextstate; + } + else if (state == Acopymetacmd) + { + arg->r_opt = ARGPARSE_INVALID_META; /* "]" missing */ + goto leave; + } + else if (state == Askipmetacmd || state == Askipmetacmd2) + { + state = Ametacmd; + goto nextstate; + } + else if (state == Awaitarg) + { + /* No argument found at the end of the line. */ + prepare_arg_return (arg, opts, idx, in_alias, set_ignore); + set_ignore = 0; + goto leave; + } + else if (state == Acopyarg) + { + /* Has an argument at the end of a line. */ + if (in_alias) + { + if (!buffer) + arg->r_opt = ARGPARSE_UNEXPECTED_ARG; + else + { + char *p; + + buffer[i] = 0; + p = strpbrk (buffer, " \t"); + if (p) + { + *p++ = 0; + trim_spaces (p); + } + if (!p || !*p) + { + xfree (buffer); + arg->r_opt = ARGPARSE_INVALID_ALIAS; + } + else + { + store_alias (arg, buffer, p); + } + } + } + else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK)) + arg->r_opt = ARGPARSE_UNEXPECTED_ARG; + else + { + char *p; + + if (!buffer) + { + keyword[i] = 0; + buffer = xtrystrdup (keyword); + if (!buffer) + arg->r_opt = ARGPARSE_OUT_OF_CORE; + } + else + buffer[i] = 0; + + if (buffer) + { + trim_spaces (buffer); + p = buffer; + if (*p == '"') + { + /* Remove quotes. */ + p++; + if (*p && p[strlen(p)-1] == '\"' ) + p[strlen(p)-1] = 0; + } + if (!set_opt_arg (arg, opts[idx].flags, p)) + xfree (buffer); + else + gpgrt_annotate_leaked_object (buffer); + } + } + goto leave; + } + else if (c == EOF) + { + ignore_invalid_option_clear (arg); + if (_gpgrt_ferror (fp)) + arg->r_opt = ARGPARSE_READ_ERROR; + else + arg->r_opt = 0; /* EOF. */ + goto leave; + } + state = Ainit; + i = 0; + } /* (end handle end of line) */ + else if (state == Askipandleave) + ; /* Skip. */ + else if (state == Ainit && isascii (c) && isspace(c)) + ; /* Skip leading white space. */ + else if (state == Ainit && c == '#' ) + state = Acomment; /* Start of a comment. */ + else if (state == Acomment || state == Askipmetacmd2) + ; /* Skip comments. */ + else if (state == Askipmetacmd) + { + if (c == '#') + state = Askipmetacmd2; + else if (!(isascii (c) && isspace(c))) + { + arg->r_opt = ARGPARSE_INVALID_META; + state = Askipandleave; + } + } + else if (state == Acopykeyword && isascii (c) && isspace(c)) + { + keyword[i] = 0; + state = Akeyword_spc; + goto nextstate; + } + else if (state == Acopymetacmd && c == ']') + { + keyword[i] = 0; + state = Askipmetacmd; + goto nextstate; + } + else if (state == Awaitarg) + { + /* Skip leading spaces of the argument. */ + if (!isascii (c) || !isspace(c)) + { + i = 0; + keyword[i++] = c; + state = Acopyarg; + } + } + else if (state == Acopyarg) + { + /* Collect the argument. */ + if (buffer) + { + if (i < buflen-1) + buffer[i++] = c; + else + { + char *tmp; + size_t tmplen = buflen + 50; + + tmp = xtryrealloc (buffer, tmplen); + if (tmp) + { + buflen = tmplen; + buffer = tmp; + buffer[i++] = c; + } + else + { + xfree (buffer); + arg->r_opt = ARGPARSE_OUT_OF_CORE; + goto leave; + } + } + } + else if (i < DIM(keyword)-1) + keyword[i++] = c; + else + { + size_t tmplen = DIM(keyword) + 50; + buffer = xtrymalloc (tmplen); + if (buffer) + { + buflen = tmplen; + memcpy(buffer, keyword, i); + buffer[i++] = c; + } + else + { + arg->r_opt = ARGPARSE_OUT_OF_CORE; + goto leave; + } + } + } + else if (i >= DIM(keyword)-1) + { + arg->r_opt = ARGPARSE_KEYWORD_TOO_LONG; + state = Askipandleave; /* Skip rest of line and leave. */ + } + else if (!i) + { + state = c == '[' ? Acopymetacmd : Acopykeyword; + keyword[i++] = c; + } + else + { + keyword[i++] = c; + } + } + + leave: + return arg->r_opt; +} + + +/* Return true if the list of options OPTS has any option marked with + * ARGPARSE_OPT_CONFFILE. */ +static int +any_opt_conffile (opttable_t *opts, unsigned int nopts) +{ + int i; + + for (i=0; i < nopts; i++ ) + if ((opts[i].flags & ARGPARSE_OPT_CONFFILE)) + return 1; + return 0; +} + + +/* Return true if FNAME is an absoluete filename. */ +static int +is_absfname (const char *fname) +{ + const char *s; + +#ifdef HAVE_W32_SYSTEM + s = strchr (fname, ':'); + if (s) + s++; + else + s = fname; +#else + s = fname; +#endif + + return (*s == '/' +#ifdef HAVE_W32_SYSTEM + || *s == DIRSEP_C +#endif + ); +} + + +/* If FNAME specifies two files of the form + * NAME1:/NAME2 (Unix) + * or + * NAME1;[x:]/NAME2 (Windows) + * return a pointer to the delimiter or NULL if there is none. + */ +static const char * +is_twopartfname (const char *fname) +{ + const char *s; + + if ((s = strchr (fname, PATHSEP_C)) && is_absfname (s+1) && s != fname) + return s; + return NULL; +} + + +/* Try to use a version-ed config file name. A version-ed config file + * name is one which has the packages version number appended. For + * example if the standard config file name is "foo.conf" and the + * version of the foo program is 1.2.3-beta1 the following config + * files are tried in order until one is readable: + * + * foo.conf-1.2.3-beta1 + * foo.conf-1.2.3 + * foo.conf-1.2 + * foo.conf-1 + * foo.conf + * + * The argument CONFIGNAME should already be expanded. On success a + * newly allocated file name is returned. On error NULL is returned. + */ +static char * +try_versioned_conffile (const char *configname) +{ + const char *version = _gpgrt_strusage (13); + char *name; + char *dash, *endp; + + if (!version || !*version) + return NULL; /* No program version known. */ + + name = _gpgrt_strconcat (configname, "-", version, NULL); + if (!name) + return NULL; /* Oops: Out of core - ignore. */ + dash = name + strlen (configname); + + endp = dash + strlen (dash) - 1; + while (endp > dash) + { + if (!_gpgrt_access (name, R_OK)) + { + return name; + } + for (; endp > dash; endp--) + { + if (*endp == '-' || *endp == '.') + { + *endp = 0; + break; + } + } + } + + _gpgrt_free (name); + return NULL; +} + + +/* This function is called after a sysconf file has been read. */ +static void +finish_read_sys (gpgrt_argparse_t *arg) +{ + opttable_t *opts = arg->internal->opts; + unsigned int nopts = arg->internal->nopts; + int i; + + if (arg->internal->ignore_all_seen) + { + /* [ignore-all] was used: Set all options which have not + * explictly been set as ignore or not ignore to ignore. */ + for (i = 0; i < nopts; i++) + { + if (!opts[i].explicit_ignore) + opts[i].ignore = 1; + } + } + + /* Reset all flags which pertain only to sysconf files. */ + arg->internal->in_sysconf = 0; + arg->internal->user_active = 0; + arg->internal->mark_forced = 0; + arg->internal->mark_ignore = 0; + arg->internal->explicit_ignore = 0; + arg->internal->ignore_all_seen = 0; +} + + +/* The full arg parser which handles option files and command line + * arguments. The behaviour depends on the combinations of CONFNAME + * and the ARGPARSE_FLAG_xxx values: + * + * | CONFNAME | SYS | USER | Action | + * |----------+-----+------+--------------------| + * | NULL | - | - | cmdline | + * | string | 0 | 1 | user, cmdline | + * | string | 1 | 0 | sys, cmdline | + * | string | 1 | 1 | sys, user, cmdline | + * + * Note that if an option has been flagged with ARGPARSE_OPT_CONFFILE + * and a type of ARGPARSE_TYPE_STRING that option is not returned but + * the specified configuration file is processed directly; if + * ARGPARSE_TYPE_NONE is used no user configuration files are + * processed and from the system configuration files only those which + * are immutable are processed. The string values for CONFNAME shall + * not include a directory part because that is taken from the values + * set by gpgrt_set_confdir. However, if CONFNAME is a twopart + * filename delimited by a colon (semicolon on Windows) with the + * second part being an absolute filename, the first part is used for + * the SYS file and the the entire second part for the USER file. + */ +int +_gpgrt_argparser (gpgrt_argparse_t *arg, gpgrt_opt_t *opts, + const char *confname) +{ + /* First check whether releasing the resources has been requested. */ + if (arg && !opts) + { + deinitialize (arg); + return 0; + } + + /* Make sure that the internal data object is ready and also print + * warnings or errors from the last iteration. */ + if (initialize (arg, opts, NULL)) + return (arg->r_opt = ARGPARSE_OUT_OF_CORE); + + next_state: + switch (arg->internal->state) + { + case STATE_init: + if (arg->argc && arg->argv && *arg->argc + && any_opt_conffile (arg->internal->opts, arg->internal->nopts)) + { + /* The list of option allow for conf files + * (e.g. gpg's "--option FILE" and "--no-options") + * Now check whether one was really given on the command + * line. Note that we don't need to run this code if no + * argument array was provided. */ + int save_argc = *arg->argc; + char **save_argv = *arg->argv; + unsigned int save_flags = arg->flags; + int save_idx = arg->internal->idx; + int any_no_conffile = 0; + + arg->flags = (ARGPARSE_FLAG_KEEP | ARGPARSE_FLAG_NOVERSION + | ARGPARSE_FLAG__INITIALIZED); + while (arg_parse (arg, opts, 1)) + { + if ((arg->internal->opt_flags & ARGPARSE_OPT_CONFFILE)) + { + arg->internal->explicit_confopt = 1; + if ((arg->r_type & ARGPARSE_TYPE_MASK) == ARGPARSE_TYPE_STRING + && !arg->internal->explicit_conffile) + { + /* Store the first conffile name. All further + * conf file options are not handled. */ + arg->internal->explicit_conffile + = xtrystrdup (arg->r.ret_str); + if (!arg->internal->explicit_conffile) + return (arg->r_opt = ARGPARSE_OUT_OF_CORE); + + } + else if ((arg->r_type & ARGPARSE_TYPE_MASK) + == ARGPARSE_TYPE_NONE) + any_no_conffile = 1; + } + } + if (any_no_conffile) + { + /* A NoConffile option overrides any other conf file option. */ + xfree (arg->internal->explicit_conffile); + arg->internal->explicit_conffile = NULL; + } + /* Restore parser. */ + *arg->argc = save_argc; + *arg->argv = save_argv; + arg->flags = save_flags; + arg->internal->idx = save_idx; + } + + if (confname && *confname) + { + if ((arg->flags & ARGPARSE_FLAG_SYS)) + arg->internal->state = STATE_open_sys; + else if ((arg->flags & ARGPARSE_FLAG_USER)) + arg->internal->state = STATE_open_user; + else + return (arg->r_opt = ARGPARSE_INVALID_ARG); + } + else + arg->internal->state = STATE_open_cmdline; + goto next_state; + + case STATE_open_sys: + { + /* If it is a two part name take the first part. */ + const char *s; + char *tmpname = NULL; + + if ((s = is_twopartfname (confname))) + { + tmpname = xtrymalloc (s - confname + 1); + if (!tmpname) + return (arg->r_opt = ARGPARSE_OUT_OF_CORE); + memcpy (tmpname, confname, s-confname); + tmpname[s-confname] = 0; + s = tmpname; + } + else + s = confname; + xfree (arg->internal->confname); + arg->internal->confname = _gpgrt_fnameconcat + (confdir.sys? confdir.sys : "/etc", s, NULL); + _gpgrt_free (tmpname); + if (!arg->internal->confname) + return (arg->r_opt = ARGPARSE_OUT_OF_CORE); + } + arg->lineno = 0; + arg->internal->idx = 0; + arg->internal->verbose = 0; + arg->internal->stopped = 0; + arg->internal->inarg = 0; + _gpgrt_fclose (arg->internal->conffp); + arg->internal->conffp = _gpgrt_fopen (arg->internal->confname, "r"); + if (!arg->internal->conffp) + { + if ((arg->flags & ARGPARSE_FLAG_VERBOSE) || arg->internal->verbose) + _gpgrt_log_info (_("Note: no default option file '%s'\n"), + arg->internal->confname); + if ((arg->flags & ARGPARSE_FLAG_USER)) + arg->internal->state = STATE_open_user; + else + arg->internal->state = STATE_open_cmdline; + goto next_state; + } + + if ((arg->flags & ARGPARSE_FLAG_VERBOSE) || arg->internal->verbose) + _gpgrt_log_info (_("reading options from '%s'\n"), + arg->internal->confname); + arg->internal->state = STATE_read_sys; + arg->internal->in_sysconf = 1; + arg->r.ret_str = xtrystrdup (arg->internal->confname); + if (!arg->r.ret_str) + arg->r_opt = ARGPARSE_OUT_OF_CORE; + else + { + gpgrt_annotate_leaked_object (arg->r.ret_str); + arg->r_opt = ARGPARSE_CONFFILE; + arg->r_type = ARGPARSE_TYPE_STRING; + } + break; + + case STATE_open_user: + if (arg->internal->explicit_confopt + && arg->internal->explicit_conffile) + { + /* An explict option to use a specific configuration file + * has been given - use that one. */ + xfree (arg->internal->confname); + arg->internal->confname + = xtrystrdup (arg->internal->explicit_conffile); + if (!arg->internal->confname) + return (arg->r_opt = ARGPARSE_OUT_OF_CORE); + } + else if (arg->internal->explicit_confopt) + { + /* An explict option not to use a configuration file has + * been given - leap direct to command line reading. */ + arg->internal->state = STATE_open_cmdline; + goto next_state; + } + else + { + /* Use the standard configure file. If it is a two part + * name take the second part. If it is the standard name + * and ARGPARSE_FLAG_USERVERS is set try versioned config + * files. */ + const char *s; + char *nconf; + + xfree (arg->internal->confname); + if ((s = is_twopartfname (confname))) + { + arg->internal->confname = _gpgrt_fnameconcat (s + 1, NULL); + if (!arg->internal->confname) + return (arg->r_opt = ARGPARSE_OUT_OF_CORE); + } + else + { + arg->internal->confname = _gpgrt_fnameconcat + (confdir.user? confdir.user : "~/.config", confname, NULL); + if (!arg->internal->confname) + return (arg->r_opt = ARGPARSE_OUT_OF_CORE); + if ((arg->flags & ARGPARSE_FLAG_USERVERS) + && (nconf = try_versioned_conffile (arg->internal->confname))) + { + xfree (arg->internal->confname); + arg->internal->confname = nconf; + } + } + } + arg->lineno = 0; + arg->internal->idx = 0; + arg->internal->verbose = 0; + arg->internal->stopped = 0; + arg->internal->inarg = 0; + arg->internal->in_sysconf = 0; + _gpgrt_fclose (arg->internal->conffp); + arg->internal->conffp = _gpgrt_fopen (arg->internal->confname, "r"); + if (!arg->internal->conffp) + { + arg->internal->state = STATE_open_cmdline; + if (arg->internal->explicit_confopt) + { + _gpgrt_log_error (_("option file '%s': %s\n"), + arg->internal->confname, strerror (errno)); + return (arg->r_opt = ARGPARSE_NO_CONFFILE); + } + else + { + if ((arg->flags & ARGPARSE_FLAG_VERBOSE) + || arg->internal->verbose) + _gpgrt_log_info (_("Note: no default option file '%s'\n"), + arg->internal->confname); + goto next_state; + } + } + + if ((arg->flags & ARGPARSE_FLAG_VERBOSE) || arg->internal->verbose) + _gpgrt_log_info (_("reading options from '%s'\n"), + arg->internal->confname); + arg->internal->state = STATE_read_user; + arg->r.ret_str = xtrystrdup (arg->internal->confname); + if (!arg->r.ret_str) + arg->r_opt = ARGPARSE_OUT_OF_CORE; + else + { + gpgrt_annotate_leaked_object (arg->r.ret_str); + arg->r_opt = ARGPARSE_CONFFILE; + arg->r_type = ARGPARSE_TYPE_STRING; + } + break; + + case STATE_open_cmdline: + _gpgrt_fclose (arg->internal->conffp); + arg->internal->conffp = NULL; + xfree (arg->internal->confname); + arg->internal->confname = NULL; + arg->internal->idx = 0; + arg->internal->verbose = 0; + arg->internal->stopped = 0; + arg->internal->inarg = 0; + arg->internal->in_sysconf = 0; + if (!arg->argc || !arg->argv || !*arg->argv) + { + /* No or empty argument vector - don't bother to parse things. */ + arg->internal->state = STATE_finished; + goto next_state; + } + arg->r_opt = ARGPARSE_CONFFILE; + arg->r_type = ARGPARSE_TYPE_NONE; + arg->r.ret_str = NULL; + arg->internal->state = STATE_read_cmdline; + break; + + case STATE_read_sys: + arg->r_opt = _gpgrt_argparse (arg->internal->conffp, arg, opts); + if (!arg->r_opt) + { + finish_read_sys (arg); + arg->internal->state = STATE_open_user; + goto next_state; + } + if ((arg->internal->opt_flags & ARGPARSE_OPT_CONFFILE)) + goto next_state; /* Already handled - again. */ + break; + + case STATE_read_user: + arg->r_opt = _gpgrt_argparse (arg->internal->conffp, arg, opts); + if (!arg->r_opt) + { + arg->internal->state = STATE_open_cmdline; + goto next_state; + } + if ((arg->internal->opt_flags & ARGPARSE_OPT_CONFFILE)) + goto next_state; /* Already handled - again. */ + break; + + case STATE_read_cmdline: + arg->r_opt = arg_parse (arg, opts, 1); + if (!arg->r_opt) + { + arg->internal->state = STATE_finished; + goto next_state; + } + if ((arg->internal->opt_flags & ARGPARSE_OPT_CONFFILE)) + goto next_state; /* Already handled - again. */ + break; + + case STATE_finished: + arg->r_opt = 0; + break; + } + + return arg->r_opt; +} + + +/* Given the list of options in ARG and a keyword, return the index of + * the long option matching KEYWORD. On error -1 is returned for not + * found or -2 for ambigious keyword. */ +static int +find_long_option (gpgrt_argparse_t *arg, const char *keyword) +{ + int i; + size_t n; + opttable_t *opts = arg->internal->opts; + unsigned int nopts = arg->internal->nopts; + + /* Would be better if we can do a binary search, but it is not + * possible to reorder our option table because we would mess up our + * help strings. What we can do is: Build an option lookup table + * when this function is first invoked. The latter has already been + * done. */ + if (!*keyword) + return -1; + for (i=0; i < nopts; i++ ) + if (opts[i].long_opt && !strcmp (opts[i].long_opt, keyword)) + return i; +#if 0 + { + ALIAS_DEF a; + /* see whether it is an alias */ + for (a = args->internal->aliases; a; a = a->next) + { + if (!strcmp( a->name, keyword)) + { + /* todo: must parse the alias here */ + args->internal->cur_alias = a; + return -3; /* alias available */ + } + } + } +#endif + /* Not found. See whether it is an abbreviation. Aliases may not + * be abbreviated, though. */ + n = strlen (keyword); + for (i=0; i < nopts; i++) + { + if (opts[i].long_opt && !strncmp (opts[i].long_opt, keyword, n)) + { + int j; + for (j=i+1; j < nopts; j++) + { + if (opts[j].long_opt + && !strncmp (opts[j].long_opt, keyword, n) + && !(opts[j].short_opt == opts[i].short_opt + && opts[j].flags == opts[i].flags ) ) + return -2; /* Abbreviation is ambiguous. */ + } + return i; + } + } + return -1; /* Not found. */ +} + + +/* The option parser for command line options. */ +static int +arg_parse (gpgrt_argparse_t *arg, gpgrt_opt_t *opts_orig, int no_init) +{ + int idx; + opttable_t *opts; + unsigned int nopts; + int argc; + char **argv; + char *s, *s2; + int i; + + if (no_init) + ; + else if (initialize (arg, opts_orig, NULL)) + return (arg->r_opt = ARGPARSE_OUT_OF_CORE); + + opts = arg->internal->opts; + nopts = arg->internal->nopts; + argc = *arg->argc; + argv = *arg->argv; + idx = arg->internal->idx; + + if (!idx && argc && !(arg->flags & ARGPARSE_FLAG_ARG0)) + { + /* Skip the first argument. */ + argc--; argv++; idx++; + } + + next_one: + if (!argc || (s = *argv) == NULL) + { + /* No more args. */ + arg->r_opt = 0; + goto leave; /* Ready. */ + } + + arg->internal->last = s; + arg->internal->opt_flags = 0; + + if (arg->internal->stopped && (arg->flags & ARGPARSE_FLAG_ALL)) + { + arg->r_opt = ARGPARSE_IS_ARG; /* Not an option but an argument. */ + arg->r_type = ARGPARSE_TYPE_STRING; + arg->r.ret_str = s; + argc--; argv++; idx++; /* set to next one */ + } + else if (arg->internal->stopped) + { + arg->r_opt = 0; + goto leave; /* Ready. */ + } + else if ( *s == '-' && s[1] == '-' ) + { + /* Long option. */ + char *argpos; + + arg->internal->inarg = 0; + if (!s[2] && !(arg->flags & ARGPARSE_FLAG_NOSTOP)) + { + /* Stop option processing. */ + arg->internal->stopped = 1; + arg->flags |= ARGPARSE_FLAG_STOP_SEEN; + argc--; argv++; idx++; + goto next_one; + } + + argpos = strchr( s+2, '=' ); + if ( argpos ) + *argpos = 0; + i = find_long_option (arg, s+2); + if ( argpos ) + *argpos = '='; + + if (i > 0 && opts[i].short_opt == ARGPARSE_SHORTOPT_HELP) + { + show_help (opts, nopts, arg->flags); + my_exit (arg, 0); + } + else if (i > 0 && opts[i].short_opt == ARGPARSE_SHORTOPT_VERSION) + { + if (!(arg->flags & ARGPARSE_FLAG_NOVERSION)) + { + show_version (); + my_exit (arg, 0); + } + } + else if (i > 0 && opts[i].short_opt == ARGPARSE_SHORTOPT_WARRANTY) + { + writestrings (0, _gpgrt_strusage (16), "\n", NULL); + my_exit (arg, 0); + } + else if (i > 0 && opts[i].short_opt == ARGPARSE_SHORTOPT_DUMP_OPTTBL) + dump_option_table (arg); + else if (i > 0 && opts[i].short_opt == ARGPARSE_SHORTOPT_DUMP_OPTIONS) + { + for (i=0; i < nopts; i++ ) + { + if (opts[i].long_opt && !(opts[i].flags & ARGPARSE_OPT_IGNORE)) + writestrings (0, "--", opts[i].long_opt, "\n", NULL); + } + my_exit (arg, 0); + } + + if ( i == -2 ) + arg->r_opt = ARGPARSE_AMBIGUOUS_OPTION; + else if ( i == -1 ) + { + arg->r_opt = ARGPARSE_INVALID_OPTION; + arg->r.ret_str = s+2; + } + else + arg->r_opt = opts[i].short_opt; + + if ( i < 0 ) + ; + else if ( (opts[i].flags & ARGPARSE_TYPE_MASK) ) + { + if ( argpos ) + { + s2 = argpos+1; + if ( !*s2 ) + s2 = NULL; + } + else + s2 = argv[1]; + + if ( !s2 && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) ) + { + arg->r_type = ARGPARSE_TYPE_NONE; /* Argument is optional. */ + } + else if ( !s2 ) + { + arg->r_opt = ARGPARSE_MISSING_ARG; + } + else if ( !argpos && *s2 == '-' + && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) ) + { + /* The argument is optional and the next seems to be an + option. We do not check this possible option but + assume no argument */ + arg->r_type = ARGPARSE_TYPE_NONE; + } + else + { + set_opt_arg (arg, opts[i].flags, s2); + if ( !argpos ) + { + argc--; argv++; idx++; /* Skip one. */ + } + } + } + else + { + /* Does not take an argument. */ + if ( argpos ) + arg->r_type = ARGPARSE_UNEXPECTED_ARG; + else + { + arg->internal->opt_flags = opts[i].flags; + arg->r_type = ARGPARSE_TYPE_NONE; + } + } + argc--; argv++; idx++; /* Set to next one. */ + } + else if ( (*s == '-' && s[1]) || arg->internal->inarg ) + { + /* Short option. */ + int dash_kludge = 0; + + i = 0; + if ( !arg->internal->inarg ) + { + arg->internal->inarg++; + if ( (arg->flags & ARGPARSE_FLAG_ONEDASH) ) + { + for (i=0; i < nopts; i++ ) + if ( opts[i].long_opt && !strcmp (opts[i].long_opt, s+1)) + { + dash_kludge = 1; + break; + } + } + } + s += arg->internal->inarg; + + if (!dash_kludge ) + { + for (i=0; i < nopts; i++ ) + if ( opts[i].short_opt == *s ) + break; + } + + if ( !opts[i].short_opt && ( *s == 'h' || *s == '?' ) ) + { + show_help (opts, nopts, arg->flags); + my_exit (arg, 0); + } + + arg->r_opt = opts[i].short_opt; + if (!opts[i].short_opt ) + { + arg->r_opt = (opts[i].flags & ARGPARSE_OPT_COMMAND)? + ARGPARSE_INVALID_COMMAND:ARGPARSE_INVALID_OPTION; + arg->internal->inarg++; /* Point to the next arg. */ + arg->r.ret_str = s; + } + else if ( (opts[i].flags & ARGPARSE_TYPE_MASK) ) + { + if ( s[1] && !dash_kludge ) + { + s2 = s+1; + set_opt_arg (arg, opts[i].flags, s2); + } + else + { + s2 = argv[1]; + if ( !s2 && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) ) + { + arg->r_type = ARGPARSE_TYPE_NONE; + arg->internal->opt_flags = opts[i].flags; + } + else if ( !s2 ) + { + arg->r_opt = ARGPARSE_MISSING_ARG; + } + else if ( *s2 == '-' && s2[1] + && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) ) + { + /* The argument is optional and the next seems to + be an option. We do not check this possible + option but assume no argument. */ + arg->r_type = ARGPARSE_TYPE_NONE; + arg->internal->opt_flags = opts[i].flags; + } + else + { + set_opt_arg (arg, opts[i].flags, s2); + argc--; argv++; idx++; /* Skip one. */ + } + } + s = "x"; /* This is so that !s[1] yields false. */ + } + else + { + /* Does not take an argument. */ + arg->r_type = ARGPARSE_TYPE_NONE; + arg->internal->opt_flags = opts[i].flags; + arg->internal->inarg++; /* Point to the next arg. */ + } + if ( !s[1] || dash_kludge ) + { + /* No more concatenated short options. */ + arg->internal->inarg = 0; + argc--; argv++; idx++; + } + } + else if ( arg->flags & ARGPARSE_FLAG_MIXED ) + { + arg->r_opt = ARGPARSE_IS_ARG; + arg->r_type = ARGPARSE_TYPE_STRING; + arg->r.ret_str = s; + argc--; argv++; idx++; /* Set to next one. */ + } + else + { + arg->internal->stopped = 1; /* Stop option processing. */ + goto next_one; + } + + if (arg->r_opt > 0 && i >= 0 && i < nopts + && ((opts[i].ignore && opts[i].explicit_ignore) || opts[i].forced)) + { + + if ((arg->flags & ARGPARSE_FLAG_WITHATTR)) + { + if (opts[i].ignore) + arg->r_type |= ARGPARSE_ATTR_IGNORE; + if (opts[i].forced) + arg->r_type |= ARGPARSE_ATTR_FORCE; + arg->r_type |= ARGPARSE_OPT_IGNORE; + } + else + { + _gpgrt_log_info (_("Note: ignoring option \"--%s\"" + " due to global config\n"), + opts[i].long_opt); + goto next_one; /* Skip ignored/forced option. */ + } + } + + leave: + *arg->argc = argc; + *arg->argv = argv; + arg->internal->idx = idx; + return arg->r_opt; +} + + +/* Returns: -1 on error, 0 for an integer type and 1 for a non integer + type argument. */ +static int +set_opt_arg (gpgrt_argparse_t *arg, unsigned flags, char *s) +{ + int base = (flags & ARGPARSE_OPT_PREFIX)? 0 : 10; + long l; + + arg->internal->opt_flags = flags; + switch ( (arg->r_type = (flags & ARGPARSE_TYPE_MASK)) ) + { + case ARGPARSE_TYPE_LONG: + case ARGPARSE_TYPE_INT: + errno = 0; + l = strtol (s, NULL, base); + if ((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE) + { + arg->r_opt = ARGPARSE_INVALID_ARG; + return -1; + } + if (arg->r_type == ARGPARSE_TYPE_LONG) + arg->r.ret_long = l; + else if ( (l < 0 && l < INT_MIN) || l > INT_MAX ) + { + arg->r_opt = ARGPARSE_INVALID_ARG; + return -1; + } + else + arg->r.ret_int = (int)l; + return 0; + + case ARGPARSE_TYPE_ULONG: + while (isascii (*s) && isspace(*s)) + s++; + if (*s == '-') + { + arg->r.ret_ulong = 0; + arg->r_opt = ARGPARSE_INVALID_ARG; + return -1; + } + errno = 0; + arg->r.ret_ulong = strtoul (s, NULL, base); + if (arg->r.ret_ulong == ULONG_MAX && errno == ERANGE) + { + arg->r_opt = ARGPARSE_INVALID_ARG; + return -1; + } + return 0; + + case ARGPARSE_TYPE_STRING: + default: + arg->r.ret_str = s; + return 1; + } +} + + +/* Return the length of the option O. This needs to consider the + * description as well as the option name. */ +static size_t +long_opt_strlen (opttable_t *o) +{ + size_t n = strlen (o->long_opt); + + if ( o->description && *o->description == '|' ) + { + const char *s; + int is_utf8 = is_native_utf8 (); + + s=o->description+1; + if ( *s != '=' ) + n++; + /* For a (mostly) correct length calculation we exclude + * continuation bytes (10xxxxxx) if we are on a native utf8 + * terminal. */ + for (; *s && *s != '|'; s++ ) + if ( is_utf8 && (*s&0xc0) != 0x80 ) + n++; + } + return n; +} + + + +/* Qsort compare for show_help. */ +static int +cmp_ordtbl (const void *a_v, const void *b_v) +{ + const unsigned short *a = a_v; + const unsigned short *b = b_v; + + return *a - *b; +} + + +/**************** + * Print formatted help. The description string has some special + * meanings: + * - A description string which is "@" suppresses help output for + * this option + * - a description which starts with a '@' and is followed by + * any other characters is printed as is; this may be used for examples + * and such. This is a legacy methiod, moder codes uses the flags + * ARGPARSE_OPT_VERBATIM or ARGPARSE_OPT_HEADER. + * - A description which starts with a '|' outputs the string between this + * bar and the next one as arguments of the long option. + */ +static void +show_help (opttable_t *opts, unsigned int nopts, unsigned int flags) +{ + const char *s; + char tmp[2]; + unsigned int *ordtbl = NULL; + + show_version (); + writestrings (0, "\n", NULL); + s = _gpgrt_strusage (42); + if (s && *s == '1') + { + s = _gpgrt_strusage (40); + writestrings (1, s, NULL); + if (*s && s[strlen(s)] != '\n') + writestrings (1, "\n", NULL); + } + s = _gpgrt_strusage(41); + writestrings (0, s, "\n", NULL); + if ( nopts ) + { + /* Auto format the option description. */ + int i,j,indent; + const char *last_header = NULL; + + ordtbl = xtrycalloc (nopts, sizeof *ordtbl); + if (!ordtbl) + { + writestrings (1, "\nOoops: Out of memory whilst printing the help.\n", + NULL); + goto leave; + } + + /* Get max. length of long options. */ + for (i=indent=0; i < nopts; i++ ) + { + if ( opts[i].long_opt ) + if ( !opts[i].description || *opts[i].description != '@' ) + if ( (j=long_opt_strlen(opts+i)) > indent && j < 35 ) + indent = j; + ordtbl[i] = opts[i].ordinal; + } + + qsort (ordtbl, nopts, sizeof *ordtbl, cmp_ordtbl); + + /* The first option needs to have a description; if not do not + * print the help at all. */ + if (!opts[ordtbl[0]].description) + goto leave; + + /* Example: " -v, --verbose Viele Sachen ausgeben" */ + indent += 10; + if ( *opts[ordtbl[0]].description != '@' + && !(opts[ordtbl[0]].flags + & (ARGPARSE_OPT_VERBATIM|ARGPARSE_OPT_HEADER))) + writestrings (0, "Options:", "\n", NULL); + for (i=0; i < nopts; i++ ) + { + s = map_fixed_string (_( opts[ordtbl[i]].description )); + if ( s && *s== '@' && !s[1] ) /* Hide this line. */ + continue; + if ( s && (opts[ordtbl[i]].flags & ARGPARSE_OPT_HEADER)) + { + /* We delay printing until we have found one real output + * line. This avoids having a header above an empty + * section. */ + last_header = s; + continue; + } + if (last_header) + { + if (*last_header) + writestrings (0, "\n", last_header, ":\n", NULL); + last_header = NULL; + } + if ( s && (opts[ordtbl[i]].flags & ARGPARSE_OPT_VERBATIM)) + { + writestrings (0, s, NULL); + continue; + } + if ( s && *s == '@' ) /* Unindented legacy comment only line. */ + { + for (s++; *s; s++ ) + { + if ( *s == '\n' ) + { + if( s[1] ) + writestrings (0, "\n", NULL); + } + else + { + tmp[0] = *s; + tmp[1] = 0; + writestrings (0, tmp, NULL); + } + } + writestrings (0, "\n", NULL); + continue; + } + + j = 3; + if ( opts[ordtbl[i]].short_opt < 256 ) + { + tmp[0] = opts[ordtbl[i]].short_opt; + tmp[1] = 0; + writestrings (0, " -", tmp, NULL ); + if ( !opts[ordtbl[i]].long_opt ) + { + if (s && *s == '|' ) + { + writestrings (0, " ", NULL); j++; + for (s++ ; *s && *s != '|'; s++, j++ ) + { + tmp[0] = *s; + tmp[1] = 0; + writestrings (0, tmp, NULL); + } + if ( *s ) + s++; + } + } + } + else + writestrings (0, " ", NULL); + if ( opts[ordtbl[i]].long_opt ) + { + tmp[0] = opts[ordtbl[i]].short_opt < 256?',':' '; + tmp[1] = 0; + j += writestrings (0, tmp, " --", opts[ordtbl[i]].long_opt, NULL); + if (s && *s == '|' ) + { + if ( *++s != '=' ) + { + writestrings (0, " ", NULL); + j++; + } + for ( ; *s && *s != '|'; s++, j++ ) + { + tmp[0] = *s; + tmp[1] = 0; + writestrings (0, tmp, NULL); + } + if ( *s ) + s++; + } + writestrings (0, " ", NULL); + j += 3; + } + for (;j < indent; j++ ) + writestrings (0, " ", NULL); + if ( s ) + { + if ( *s && j > indent ) + { + writestrings (0, "\n", NULL); + for (j=0;j < indent; j++ ) + writestrings (0, " ", NULL); + } + for (; *s; s++ ) + { + if ( *s == '\n' ) + { + if ( s[1] ) + { + writestrings (0, "\n", NULL); + for (j=0; j < indent; j++ ) + writestrings (0, " ", NULL); + } + } + else + { + tmp[0] = *s; + tmp[1] = 0; + writestrings (0, tmp, NULL); + } + } + } + writestrings (0, "\n", NULL); + } + if ( (flags & ARGPARSE_FLAG_ONEDASH) ) + writestrings (0, "\n(A single dash may be used " + "instead of the double ones)\n", NULL); + } + if ( (s=_gpgrt_strusage(19)) ) + { + writestrings (0, "\n", NULL); + writestrings (0, s, NULL); + } + + leave: + flushstrings (0); + xfree (ordtbl); +} + + +static void +show_version () +{ + const char *s; + int i; + + /* Version line. */ + writestrings (0, _gpgrt_strusage (11), NULL); + if ((s=_gpgrt_strusage (12))) + writestrings (0, " (", s, ")", NULL); + writestrings (0, " ", _gpgrt_strusage (13), "\n", NULL); + /* Additional version lines. */ + for (i=20; i < 30; i++) + if ((s=_gpgrt_strusage (i))) + writestrings (0, s, "\n", NULL); + /* Copyright string. */ + if ((s=_gpgrt_strusage (14))) + writestrings (0, s, "\n", NULL); + /* Licence string. */ + if( (s=_gpgrt_strusage (10)) ) + writestrings (0, s, "\n", NULL); + /* Copying conditions. */ + if ( (s=_gpgrt_strusage(15)) ) + writestrings (0, s, NULL); + /* Thanks. */ + if ((s=_gpgrt_strusage(18))) + writestrings (0, s, NULL); + /* Additional program info. */ + for (i=30; i < 40; i++ ) + if ( (s=_gpgrt_strusage (i)) ) + writestrings (0, s, NULL); + flushstrings (0); +} + + +/* Print the table of options with flags etc. */ +static void +dump_option_table (gpgrt_argparse_t *arg) +{ + opttable_t *opts; + unsigned int nopts; + const char *s; + char tmp[50]; + unsigned int *ordtbl = NULL; + int i; + + opts = arg->internal->opts; + nopts = arg->internal->nopts; + if (!nopts) + return; + + ordtbl = xtrycalloc (nopts, sizeof *ordtbl); + if (!ordtbl) + { + writestrings (1, "\nOoops: Out of memory whilst dumping the table.\n", + NULL); + flushstrings (1); + my_exit (arg, 2); + } + for (i=0; i < nopts; i++ ) + ordtbl[i] = opts[i].ordinal; + qsort (ordtbl, nopts, sizeof *ordtbl, cmp_ordtbl); + for (i=0; i < nopts; i++ ) + { + if (!opts[ordtbl[i]].long_opt) + continue; + writestrings (0, opts[ordtbl[i]].long_opt, ":", NULL); + snprintf (tmp, sizeof tmp, "%u:%u:", + opts[ordtbl[i]].short_opt, + opts[ordtbl[i]].flags); + writestrings (0, tmp, NULL); + s = opts[ordtbl[i]].description; + if (s) + { + for (; *s; s++) + { + if (*s == '%' || *s == ':' || *s == '\n') + snprintf (tmp, sizeof tmp, "%%%02X", *s); + else + { + tmp[0] = *s; + tmp[1] = 0; + } + writestrings (0, tmp, NULL); + } + } + writestrings (0, ":\n", NULL); + } + + flushstrings (0); + xfree (ordtbl); + my_exit (arg, 0); +} + + +void +_gpgrt_usage (int level) +{ + const char *p; + + if (!level) + { + writestrings (1, _gpgrt_strusage(11), " ", _gpgrt_strusage(13), "; ", + _gpgrt_strusage (14), "\n", NULL); + flushstrings (1); + } + else if (level == 1) + { + p = _gpgrt_strusage (40); + writestrings (1, p, NULL); + if (*p && p[strlen(p)] != '\n') + writestrings (1, "\n", NULL); + exit (2); + } + else if (level == 2) + { + p = _gpgrt_strusage (42); + if (p && *p == '1') + { + p = _gpgrt_strusage (40); + writestrings (1, p, NULL); + if (*p && p[strlen(p)] != '\n') + writestrings (1, "\n", NULL); + } + writestrings (0, _gpgrt_strusage(41), "\n", NULL); + exit (0); + } +} + +/* Level + * 0: Print copyright string to stderr + * 1: Print a short usage hint to stderr and terminate + * 2: Print a long usage hint to stdout and terminate + * 8: Return NULL for UTF-8 or string with the native charset. + * 9: Return the SPDX License tag. + * 10: Return license info string + * 11: Return the name of the program + * 12: Return optional name of package which includes this program. + * 13: version string + * 14: copyright string + * 15: Short copying conditions (with LFs) + * 16: Long copying conditions (with LFs) + * 17: Optional printable OS name + * 18: Optional thanks list (with LFs) + * 19: Bug report info + *20..29: Additional lib version strings. + *30..39: Additional program info (with LFs) + * 40: short usage note (with LF) + * 41: long usage note (with LF) + * 42: Flag string: + * First char is '1': + * The short usage notes needs to be printed + * before the long usage note. + * 95: Application flag string + * First character is '1': + * On Windows enable argument globbing + */ +const char * +_gpgrt_strusage (int level) +{ + const char *p = strusage_handler? strusage_handler(level) : NULL; + const char *tmp; + + if ( p ) + return map_fixed_string (p); + + switch ( level ) + { + + case 8: break; /* Default to utf-8. */ + case 9: + p = "GPL-3.0-or-later"; /* Suggested license. */ + break; + + case 10: + tmp = _gpgrt_strusage (9); + if (tmp && !strcmp (tmp, "GPL-2.0-or-later")) + p = ("License GNU GPL-2.0-or-later <https://gnu.org/licenses/>"); + else if (tmp && !strcmp (tmp, "LGPL-2.1-or-later")) + p = ("License GNU LGPL-2.1-or-later <https://gnu.org/licenses/>"); + else /* Default to GPLv3+. */ + p = ("License GNU GPL-3.0-or-later <https://gnu.org/licenses/gpl.html>"); + break; + case 11: p = "foo"; break; + case 13: p = "0.0"; break; + case 14: p = "Copyright (C) YEAR NAME"; break; + case 15: p = +"This is free software: you are free to change and redistribute it.\n" +"There is NO WARRANTY, to the extent permitted by law.\n"; + break; + case 16: + tmp = _gpgrt_strusage (9); + if (tmp && !strcmp (tmp, "GPL-2.0-or-later")) + p = +"This is free software; you can redistribute it and/or modify\n" +"it under the terms of the GNU General Public License as published by\n" +"the Free Software Foundation; either version 2 of the License, or\n" +"(at your option) any later version.\n\n" +"It is distributed in the hope that it will be useful,\n" +"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" +"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" +"GNU General Public License for more details.\n\n" +"You should have received a copy of the GNU General Public License\n" +"along with this software. If not, see <https://gnu.org/licenses/>.\n"; + else if (tmp && !strcmp (tmp, "LGPL-2.1-or-later")) + p = +"This is free software; you can redistribute it and/or modify\n" +"it under the terms of the GNU Lesser General Public License as\n" +"published by the Free Software Foundation; either version 2.1 of\n" +"the License, or (at your option) any later version.\n\n" +"It is distributed in the hope that it will be useful,\n" +"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" +"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" +"GNU Lesser General Public License for more details.\n\n" +"You should have received a copy of the GNU Lesser General Public License\n" +"along with this software. If not, see <https://gnu.org/licenses/>.\n"; + else /* Default */ + p = +"This is free software; you can redistribute it and/or modify\n" +"it under the terms of the GNU General Public License as published by\n" +"the Free Software Foundation; either version 3 of the License, or\n" +"(at your option) any later version.\n\n" +"It is distributed in the hope that it will be useful,\n" +"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" +"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" +"GNU General Public License for more details.\n\n" +"You should have received a copy of the GNU General Public License\n" +"along with this software. If not, see <https://gnu.org/licenses/>.\n"; + break; + case 40: /* short and long usage */ + case 41: p = ""; break; + } + + return p; +} + + +/* Set the usage handler. This function is basically a constructor. */ +void +_gpgrt_set_strusage (const char *(*f)(int) ) +{ + strusage_handler = f; +} + + +/* Set a function to write strings which is then used instead of + * estream. The first arg of that function is MODE and the second the + * STRING to write. A mode of 1 is used for writing to stdout and a + * mode of 2 to write to stderr. Other modes are reserved and should + * not output anything. A NULL for STRING requests a flush. */ +void +_gpgrt_set_usage_outfnc (int (*f)(int, const char *)) +{ + custom_outfnc = f; +} + + +/* Register function F as a string mapper which takes a string as + * argument, replaces known "@FOO@" style macros and returns a new + * fixed string. Warning: The input STRING must have been allocated + * statically. */ +void +_gpgrt_set_fixed_string_mapper (const char *(*f)(const char*)) +{ + fixed_string_mapper = f; +} + + +/* Register a configuration directory for use by the argparse + * functions. The defined values for WHAT are: + * + * GPGRT_CONFDIR_SYS The systems's configuration dir. + * The default is /etc + * + * GPGRT_CONFDIR_USER The user's configuration directory. + * The default is $HOME. + * + * A trailing slash is ignored; to have the function lookup + * configuration files in the current directory, use ".". There is no + * error return; more configuraion values may be added in future + * revisions of this library. + */ +void +_gpgrt_set_confdir (int what, const char *name) +{ + char *buf, *p; + + if (what == GPGRT_CONFDIR_SYS) + { + _gpgrt_free (confdir.sys); + buf = confdir.sys = _gpgrt_strdup (name); + } + else if (what == GPGRT_CONFDIR_USER) + { + _gpgrt_free (confdir.user); + buf = confdir.user = _gpgrt_strdup (name); + } + else + return; + + if (!buf) + _gpgrt_log_fatal ("out of core in %s\n", __func__); +#ifdef HAVE_W32_SYSTEM + for (p=buf; *p; p++) + if (*p == '\\') + *p = '/'; +#endif + /* Strip trailing slashes unless buf is "/" or any other single char + * string. */ + if (*buf) + { + for (p=buf + strlen (buf)-1; p > buf; p--) + if (*p == '/') + *p = 0; + else + break; + } +} diff --git a/comm/third_party/libgpg-error/src/b64dec.c b/comm/third_party/libgpg-error/src/b64dec.c new file mode 100644 index 0000000000..868d985685 --- /dev/null +++ b/comm/third_party/libgpg-error/src/b64dec.c @@ -0,0 +1,279 @@ +/* b64dec.c - Simple Base64 decoder. + * Copyright (C) 2008, 2011 Free Software Foundation, Inc. + * Copyright (C) 2008, 2011, 2016 g10 Code GmbH + * + * This file is part of Libgpg-error. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, see <https://www.gnu.org/licenses/>. + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * This file was originally a part of GnuPG. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "gpgrt-int.h" + + +/* The reverse base-64 list used for base-64 decoding. */ +static unsigned char const asctobin[128] = + { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, + 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, + 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff + }; + +enum decoder_states + { + s_init, s_idle, s_lfseen, s_beginseen, s_waitheader, s_waitblank, s_begin, + s_b64_0, s_b64_1, s_b64_2, s_b64_3, + s_waitendtitle, s_waitend + }; + + + +/* Allocate and initialize the context for the base64 decoder. If + TITLE is NULL a plain base64 decoding is done. If it is the empty + string the decoder will skip everything until a "-----BEGIN " line + has been seen, decoding ends at a "----END " line. */ +gpgrt_b64state_t +_gpgrt_b64dec_start (const char *title) +{ + gpgrt_b64state_t state; + char *t = NULL; + + if (title) + { + t = xtrystrdup (title); + if (!t) + return NULL; + } + + state = xtrycalloc (1, sizeof (struct _gpgrt_b64state)); + if (!state) + { + xfree (t); + return NULL; + } + + if (t) + { + state->title = t; + state->idx = s_init; + } + else + state->idx = s_b64_0; + + state->using_decoder = 1; + + return state; +} + + +/* Do in-place decoding of base-64 data of LENGTH in BUFFER. Stores the + new length of the buffer at R_NBYTES. */ +gpg_err_code_t +_gpgrt_b64dec_proc (gpgrt_b64state_t state, void *buffer, size_t length, + size_t *r_nbytes) +{ + enum decoder_states ds = state->idx; + unsigned char val = state->radbuf[0]; + int pos = state->quad_count; + char *d, *s; + + if (state->lasterr) + return state->lasterr; + + if (state->stop_seen) + { + *r_nbytes = 0; + state->lasterr = GPG_ERR_EOF; + xfree (state->title); + state->title = NULL; + return state->lasterr; + } + + for (s=d=buffer; length && !state->stop_seen; length--, s++) + { + again: + switch (ds) + { + case s_idle: + if (*s == '\n') + { + ds = s_lfseen; + pos = 0; + } + break; + case s_init: + ds = s_lfseen; + /* Fall through */ + case s_lfseen: + if (*s != "-----BEGIN "[pos]) + { + ds = s_idle; + goto again; + } + else if (pos == 10) + { + pos = 0; + ds = s_beginseen; + } + else + pos++; + break; + case s_beginseen: + if (*s != "PGP "[pos]) + ds = s_begin; /* Not a PGP armor. */ + else if (pos == 3) + ds = s_waitheader; + else + pos++; + break; + case s_waitheader: + if (*s == '\n') + ds = s_waitblank; + break; + case s_waitblank: + if (*s == '\n') + ds = s_b64_0; /* blank line found. */ + else if (*s == ' ' || *s == '\r' || *s == '\t') + ; /* Ignore spaces. */ + else + { + /* Armor header line. Note that we don't care that our + * FSM accepts a header prefixed with spaces. */ + ds = s_waitheader; /* Wait for next header. */ + } + break; + case s_begin: + if (*s == '\n') + ds = s_b64_0; + break; + case s_b64_0: + case s_b64_1: + case s_b64_2: + case s_b64_3: + { + int c; + + if (*s == '-' && state->title) + { + /* Not a valid Base64 character: assume end + header. */ + ds = s_waitend; + } + else if (*s == '=') + { + /* Pad character: stop */ + if (ds == s_b64_1) + *d++ = val; + ds = state->title? s_waitendtitle : s_waitend; + } + else if (*s == '\n' || *s == ' ' || *s == '\r' || *s == '\t') + ; /* Skip white spaces. */ + else if ( (*s & 0x80) + || (c = asctobin[*(unsigned char *)s]) == 255) + { + /* Skip invalid encodings. */ + state->invalid_encoding = 1; + } + else if (ds == s_b64_0) + { + val = c << 2; + ds = s_b64_1; + } + else if (ds == s_b64_1) + { + val |= (c>>4)&3; + *d++ = val; + val = (c<<4)&0xf0; + ds = s_b64_2; + } + else if (ds == s_b64_2) + { + val |= (c>>2)&15; + *d++ = val; + val = (c<<6)&0xc0; + ds = s_b64_3; + } + else + { + val |= c&0x3f; + *d++ = val; + ds = s_b64_0; + } + } + break; + case s_waitendtitle: + if (*s == '-') + ds = s_waitend; + break; + case s_waitend: + if ( *s == '\n') + state->stop_seen = 1; + break; + default: + gpgrt_assert (!"invalid state"); + } + } + + + state->idx = ds; + state->radbuf[0] = val; + state->quad_count = pos; + *r_nbytes = (d -(char*) buffer); + return 0; +} + + +/* Return an error code in case an encoding error has been found + during decoding. */ +gpg_err_code_t +_gpgrt_b64dec_finish (gpgrt_b64state_t state) +{ + gpg_error_t err; + + if (!state) + return 0; /* Already released. */ + + if (!state->using_decoder) + err = GPG_ERR_CONFLICT; /* State was allocated for the encoder. */ + else if (state->lasterr) + err = state->lasterr; + else + { + xfree (state->title); + err = state->invalid_encoding? GPG_ERR_BAD_DATA : 0; + } + xfree (state); + + return err; +} diff --git a/comm/third_party/libgpg-error/src/b64enc.c b/comm/third_party/libgpg-error/src/b64enc.c new file mode 100644 index 0000000000..571f4ec792 --- /dev/null +++ b/comm/third_party/libgpg-error/src/b64enc.c @@ -0,0 +1,386 @@ +/* b64enc.c - Simple Base64 encoder. + * Copyright (C) 2001, 2003, 2004, 2008, 2010, + * 2011 Free Software Foundation, Inc. + * Copyright (C) 2001, 2003, 2004, 2008, 2010, + * 2011, 2018 g10 Code GmbH + * + * This file is part of Libgpg-error. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, see <https://www.gnu.org/licenses/>. + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * This file was originally a part of GnuPG. + */ + +#include <config.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include "gpgrt-int.h" + + +#define B64ENC_DID_HEADER 1 +#define B64ENC_DID_TRAILER 2 +#define B64ENC_NO_LINEFEEDS 16 +#define B64ENC_USE_PGPCRC 32 + +/* The base-64 character list */ +static unsigned char const bintoasc[64] = ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"); + +/* Stuff required to create the OpenPGP CRC. This crc_table has been + created using this code: + + #include <stdio.h> + #include <stdint.h> + + #define CRCPOLY 0x864CFB + + int + main (void) + { + int i, j; + uint32_t t; + uint32_t crc_table[256]; + + crc_table[0] = 0; + for (i=j=0; j < 128; j++ ) + { + t = crc_table[j]; + if ( (t & 0x00800000) ) + { + t <<= 1; + crc_table[i++] = t ^ CRCPOLY; + crc_table[i++] = t; + } + else + { + t <<= 1; + crc_table[i++] = t; + crc_table[i++] = t ^ CRCPOLY; + } + } + + puts ("static const u32 crc_table[256] = {"); + for (i=j=0; i < 256; i++) + { + printf ("%s 0x%08lx", j? "":" ", (unsigned long)crc_table[i]); + if (i != 255) + { + putchar (','); + if ( ++j > 5) + { + j = 0; + putchar ('\n'); + } + } + } + puts ("\n};"); + return 0; + } +*/ +#define CRCINIT 0xB704CE +static const uint32_t crc_table[256] = { + 0x00000000, 0x00864cfb, 0x018ad50d, 0x010c99f6, 0x0393e6e1, 0x0315aa1a, + 0x021933ec, 0x029f7f17, 0x07a18139, 0x0727cdc2, 0x062b5434, 0x06ad18cf, + 0x043267d8, 0x04b42b23, 0x05b8b2d5, 0x053efe2e, 0x0fc54e89, 0x0f430272, + 0x0e4f9b84, 0x0ec9d77f, 0x0c56a868, 0x0cd0e493, 0x0ddc7d65, 0x0d5a319e, + 0x0864cfb0, 0x08e2834b, 0x09ee1abd, 0x09685646, 0x0bf72951, 0x0b7165aa, + 0x0a7dfc5c, 0x0afbb0a7, 0x1f0cd1e9, 0x1f8a9d12, 0x1e8604e4, 0x1e00481f, + 0x1c9f3708, 0x1c197bf3, 0x1d15e205, 0x1d93aefe, 0x18ad50d0, 0x182b1c2b, + 0x192785dd, 0x19a1c926, 0x1b3eb631, 0x1bb8faca, 0x1ab4633c, 0x1a322fc7, + 0x10c99f60, 0x104fd39b, 0x11434a6d, 0x11c50696, 0x135a7981, 0x13dc357a, + 0x12d0ac8c, 0x1256e077, 0x17681e59, 0x17ee52a2, 0x16e2cb54, 0x166487af, + 0x14fbf8b8, 0x147db443, 0x15712db5, 0x15f7614e, 0x3e19a3d2, 0x3e9fef29, + 0x3f9376df, 0x3f153a24, 0x3d8a4533, 0x3d0c09c8, 0x3c00903e, 0x3c86dcc5, + 0x39b822eb, 0x393e6e10, 0x3832f7e6, 0x38b4bb1d, 0x3a2bc40a, 0x3aad88f1, + 0x3ba11107, 0x3b275dfc, 0x31dced5b, 0x315aa1a0, 0x30563856, 0x30d074ad, + 0x324f0bba, 0x32c94741, 0x33c5deb7, 0x3343924c, 0x367d6c62, 0x36fb2099, + 0x37f7b96f, 0x3771f594, 0x35ee8a83, 0x3568c678, 0x34645f8e, 0x34e21375, + 0x2115723b, 0x21933ec0, 0x209fa736, 0x2019ebcd, 0x228694da, 0x2200d821, + 0x230c41d7, 0x238a0d2c, 0x26b4f302, 0x2632bff9, 0x273e260f, 0x27b86af4, + 0x252715e3, 0x25a15918, 0x24adc0ee, 0x242b8c15, 0x2ed03cb2, 0x2e567049, + 0x2f5ae9bf, 0x2fdca544, 0x2d43da53, 0x2dc596a8, 0x2cc90f5e, 0x2c4f43a5, + 0x2971bd8b, 0x29f7f170, 0x28fb6886, 0x287d247d, 0x2ae25b6a, 0x2a641791, + 0x2b688e67, 0x2beec29c, 0x7c3347a4, 0x7cb50b5f, 0x7db992a9, 0x7d3fde52, + 0x7fa0a145, 0x7f26edbe, 0x7e2a7448, 0x7eac38b3, 0x7b92c69d, 0x7b148a66, + 0x7a181390, 0x7a9e5f6b, 0x7801207c, 0x78876c87, 0x798bf571, 0x790db98a, + 0x73f6092d, 0x737045d6, 0x727cdc20, 0x72fa90db, 0x7065efcc, 0x70e3a337, + 0x71ef3ac1, 0x7169763a, 0x74578814, 0x74d1c4ef, 0x75dd5d19, 0x755b11e2, + 0x77c46ef5, 0x7742220e, 0x764ebbf8, 0x76c8f703, 0x633f964d, 0x63b9dab6, + 0x62b54340, 0x62330fbb, 0x60ac70ac, 0x602a3c57, 0x6126a5a1, 0x61a0e95a, + 0x649e1774, 0x64185b8f, 0x6514c279, 0x65928e82, 0x670df195, 0x678bbd6e, + 0x66872498, 0x66016863, 0x6cfad8c4, 0x6c7c943f, 0x6d700dc9, 0x6df64132, + 0x6f693e25, 0x6fef72de, 0x6ee3eb28, 0x6e65a7d3, 0x6b5b59fd, 0x6bdd1506, + 0x6ad18cf0, 0x6a57c00b, 0x68c8bf1c, 0x684ef3e7, 0x69426a11, 0x69c426ea, + 0x422ae476, 0x42aca88d, 0x43a0317b, 0x43267d80, 0x41b90297, 0x413f4e6c, + 0x4033d79a, 0x40b59b61, 0x458b654f, 0x450d29b4, 0x4401b042, 0x4487fcb9, + 0x461883ae, 0x469ecf55, 0x479256a3, 0x47141a58, 0x4defaaff, 0x4d69e604, + 0x4c657ff2, 0x4ce33309, 0x4e7c4c1e, 0x4efa00e5, 0x4ff69913, 0x4f70d5e8, + 0x4a4e2bc6, 0x4ac8673d, 0x4bc4fecb, 0x4b42b230, 0x49ddcd27, 0x495b81dc, + 0x4857182a, 0x48d154d1, 0x5d26359f, 0x5da07964, 0x5cace092, 0x5c2aac69, + 0x5eb5d37e, 0x5e339f85, 0x5f3f0673, 0x5fb94a88, 0x5a87b4a6, 0x5a01f85d, + 0x5b0d61ab, 0x5b8b2d50, 0x59145247, 0x59921ebc, 0x589e874a, 0x5818cbb1, + 0x52e37b16, 0x526537ed, 0x5369ae1b, 0x53efe2e0, 0x51709df7, 0x51f6d10c, + 0x50fa48fa, 0x507c0401, 0x5542fa2f, 0x55c4b6d4, 0x54c82f22, 0x544e63d9, + 0x56d11cce, 0x56575035, 0x575bc9c3, 0x57dd8538 +}; + + +/* Prepare for Base-64 writing to STREAM. If TITLE is not NULL and + * not an empty string, that string will be used as the title for the + * armor lines, with TITLE being an empty string, we don't write the + * header lines and furthermore even don't write any linefeeds. If + * TITLE starts with "PGP " the OpenPGP CRC checksum will be written + * as well. With TITLE being NULL, we merely don't write header but + * make sure that lines are not too long. Note, that we don't write + * anything unless at least one byte is written using b64enc_write. + * On success an enoder object is returned which needs to be released + * using _gpgrt_b64dec_finish. On error NULL is returned an ERRNO is + * set. + */ +gpgrt_b64state_t +_gpgrt_b64enc_start (estream_t stream, const char *title) +{ + gpgrt_b64state_t state; + + state = xtrycalloc (1, sizeof *state); + if (!state) + return NULL; + + state->stream = stream; + if (title && !*title) + state->flags |= B64ENC_NO_LINEFEEDS; + else if (title) + { + if (!strncmp (title, "PGP ", 4)) + { + state->flags |= B64ENC_USE_PGPCRC; + state->crc = CRCINIT; + } + state->title = xtrystrdup (title); + if (!state->title) + { + xfree (state); + return NULL; + } + } + + return state; +} + + +/* Write NBYTES from BUFFER to the Base 64 stream identified by STATE. + * With BUFFER and NBYTES being 0, merely do a fflush on the stream. + */ +gpg_err_code_t +_gpgrt_b64enc_write (gpgrt_b64state_t state, const void *buffer, size_t nbytes) +{ + unsigned char radbuf[4]; + int idx, quad_count; + const unsigned char *p; + + if (state->lasterr) + return state->lasterr; + + if (!nbytes) + { + if (buffer) + if (_gpgrt_fflush (state->stream)) + goto write_error; + return 0; + } + + if (!(state->flags & B64ENC_DID_HEADER)) + { + if (state->title) + { + if ( _gpgrt_fputs ("-----BEGIN ", state->stream) == EOF + || _gpgrt_fputs (state->title, state->stream) == EOF + || _gpgrt_fputs ("-----\n", state->stream) == EOF) + goto write_error; + if ( (state->flags & B64ENC_USE_PGPCRC) + && _gpgrt_fputs ("\n", state->stream) == EOF) + goto write_error; + } + + state->flags |= B64ENC_DID_HEADER; + } + + idx = state->idx; + quad_count = state->quad_count; + gpgrt_assert (idx < 4); + memcpy (radbuf, state->radbuf, idx); + + if ( (state->flags & B64ENC_USE_PGPCRC) ) + { + size_t n; + uint32_t crc = state->crc; + + for (p=buffer, n=nbytes; n; p++, n-- ) + crc = ((uint32_t)crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ *p]; + state->crc = (crc & 0x00ffffff); + } + + for (p=buffer; nbytes; p++, nbytes--) + { + radbuf[idx++] = *p; + if (idx > 2) + { + char tmp[4]; + + tmp[0] = bintoasc[(*radbuf >> 2) & 077]; + tmp[1] = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077]; + tmp[2] = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077]; + tmp[3] = bintoasc[radbuf[2]&077]; + for (idx=0; idx < 4; idx++) + _gpgrt_fputc (tmp[idx], state->stream); + idx = 0; + if (_gpgrt_ferror (state->stream)) + goto write_error; + + if (++quad_count >= (64/4)) + { + quad_count = 0; + if (!(state->flags & B64ENC_NO_LINEFEEDS) + && _gpgrt_fputs ("\n", state->stream) == EOF) + goto write_error; + } + } + } + memcpy (state->radbuf, radbuf, idx); + state->idx = idx; + state->quad_count = quad_count; + return 0; + + write_error: + state->lasterr = _gpg_err_code_from_syserror (); + if (state->title) + { + xfree (state->title); + state->title = NULL; + } + return state->lasterr; +} + + +gpg_err_code_t +_gpgrt_b64enc_finish (gpgrt_b64state_t state) +{ + gpg_err_code_t err = 0; + unsigned char radbuf[4]; + int idx, quad_count; + char tmp[4]; + + if (!state) + return 0; /* Already released. */ + + if (state->using_decoder) + { + err = GPG_ERR_CONFLICT; /* State was created for the decoder. */ + goto cleanup; + } + + if (state->lasterr) + { + err = state->lasterr; + goto cleanup; + } + + if (!(state->flags & B64ENC_DID_HEADER)) + goto cleanup; + + /* Flush the base64 encoding */ + idx = state->idx; + quad_count = state->quad_count; + gpgrt_assert (idx < 4); + memcpy (radbuf, state->radbuf, idx); + + if (idx) + { + tmp[0] = bintoasc[(*radbuf>>2)&077]; + if (idx == 1) + { + tmp[1] = bintoasc[((*radbuf << 4) & 060) & 077]; + tmp[2] = '='; + tmp[3] = '='; + } + else + { + tmp[1] = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077]; + tmp[2] = bintoasc[((radbuf[1] << 2) & 074) & 077]; + tmp[3] = '='; + } + for (idx=0; idx < 4; idx++) + _gpgrt_fputc (tmp[idx], state->stream); + if (_gpgrt_ferror (state->stream)) + goto write_error; + + if (++quad_count >= (64/4)) + { + quad_count = 0; + if (!(state->flags & B64ENC_NO_LINEFEEDS) + && _gpgrt_fputs ("\n", state->stream) == EOF) + goto write_error; + } + } + + /* Finish the last line and write the trailer. */ + if (quad_count + && !(state->flags & B64ENC_NO_LINEFEEDS) + && _gpgrt_fputs ("\n", state->stream) == EOF) + goto write_error; + + if ( (state->flags & B64ENC_USE_PGPCRC) ) + { + /* Write the CRC. */ + _gpgrt_fputs ("=", state->stream); + radbuf[0] = state->crc >>16; + radbuf[1] = state->crc >> 8; + radbuf[2] = state->crc; + tmp[0] = bintoasc[(*radbuf>>2)&077]; + tmp[1] = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077]; + tmp[2] = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077]; + tmp[3] = bintoasc[radbuf[2]&077]; + for (idx=0; idx < 4; idx++) + _gpgrt_fputc (tmp[idx], state->stream); + if (_gpgrt_ferror (state->stream)) + goto write_error; + + if (!(state->flags & B64ENC_NO_LINEFEEDS) + && _gpgrt_fputs ("\n", state->stream) == EOF) + goto write_error; + } + + if (state->title) + { + if ( _gpgrt_fputs ("-----END ", state->stream) == EOF + || _gpgrt_fputs (state->title, state->stream) == EOF + || _gpgrt_fputs ("-----\n", state->stream) == EOF) + goto write_error; + } + + cleanup: + xfree (state->title); + xfree (state); + return err; + + write_error: + err = gpg_error_from_syserror (); + goto cleanup; +} diff --git a/comm/third_party/libgpg-error/src/code-from-errno.c b/comm/third_party/libgpg-error/src/code-from-errno.c new file mode 100644 index 0000000000..6064270594 --- /dev/null +++ b/comm/third_party/libgpg-error/src/code-from-errno.c @@ -0,0 +1,69 @@ +/* code-from-errno.c - Mapping errnos to error codes. + Copyright (C) 2003 g10 Code GmbH + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with libgpg-error; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#include <errno.h> + +#include <gpg-error.h> + +#include "code-from-errno.h" + +/* Retrieve the error code for the system error ERR. This returns + GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped (report + this). */ +gpg_err_code_t +_gpg_err_code_from_errno (int err) +{ + int idx; + + if (!err) + return GPG_ERR_NO_ERROR; + + idx = errno_to_idx (err); + + if (idx < 0) + return GPG_ERR_UNKNOWN_ERRNO; + + return GPG_ERR_SYSTEM_ERROR | err_code_from_index[idx]; +} + + +/* Retrieve the error code directly from the ERRNO variable. This + returns GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped + (report this) and GPG_ERR_MISSING_ERRNO if ERRNO has the value 0. */ +gpg_err_code_t +_gpg_err_code_from_syserror (void) +{ + int err = errno; + int idx; + + if (!err) + return GPG_ERR_MISSING_ERRNO; + + idx = errno_to_idx (err); + + if (idx < 0) + return GPG_ERR_UNKNOWN_ERRNO; + + return GPG_ERR_SYSTEM_ERROR | err_code_from_index[idx]; +} diff --git a/comm/third_party/libgpg-error/src/code-to-errno.c b/comm/third_party/libgpg-error/src/code-to-errno.c new file mode 100644 index 0000000000..6ba6d8788d --- /dev/null +++ b/comm/third_party/libgpg-error/src/code-to-errno.c @@ -0,0 +1,42 @@ +/* code-to-errno.c - Mapping error codes to errnos. + Copyright (C) 2003 g10 Code GmbH + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with libgpg-error; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gpg-error.h> + +#include "code-to-errno.h" + +/* Retrieve the system error for the error code CODE. This returns 0 + if CODE is not a system error code. */ +int +_gpg_err_code_to_errno (gpg_err_code_t code) +{ + if (!(code & GPG_ERR_SYSTEM_ERROR)) + return 0; + code &= ~GPG_ERR_SYSTEM_ERROR; + + if (code < sizeof (err_code_to_errno) / sizeof (err_code_to_errno[0])) + return err_code_to_errno[code]; + else + return 0; +} diff --git a/comm/third_party/libgpg-error/src/err-codes.h b/comm/third_party/libgpg-error/src/err-codes.h new file mode 100644 index 0000000000..c4786c91c8 --- /dev/null +++ b/comm/third_party/libgpg-error/src/err-codes.h @@ -0,0 +1,936 @@ +/* Output of mkstrtable.awk. DO NOT EDIT. */ + +/* err-codes.h - List of error codes and their description. + Copyright (C) 2003, 2004 g10 Code GmbH + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with libgpg-error; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + + +/* The purpose of this complex string table is to produce + optimal code with a minimum of relocations. */ + +static const char msgstr[] = + gettext_noop ("Success") "\0" + gettext_noop ("General error") "\0" + gettext_noop ("Unknown packet") "\0" + gettext_noop ("Unknown version in packet") "\0" + gettext_noop ("Invalid public key algorithm") "\0" + gettext_noop ("Invalid digest algorithm") "\0" + gettext_noop ("Bad public key") "\0" + gettext_noop ("Bad secret key") "\0" + gettext_noop ("Bad signature") "\0" + gettext_noop ("No public key") "\0" + gettext_noop ("Checksum error") "\0" + gettext_noop ("Bad passphrase") "\0" + gettext_noop ("Invalid cipher algorithm") "\0" + gettext_noop ("Cannot open keyring") "\0" + gettext_noop ("Invalid packet") "\0" + gettext_noop ("Invalid armor") "\0" + gettext_noop ("No user ID") "\0" + gettext_noop ("No secret key") "\0" + gettext_noop ("Wrong secret key used") "\0" + gettext_noop ("Bad session key") "\0" + gettext_noop ("Unknown compression algorithm") "\0" + gettext_noop ("Number is not prime") "\0" + gettext_noop ("Invalid encoding method") "\0" + gettext_noop ("Invalid encryption scheme") "\0" + gettext_noop ("Invalid signature scheme") "\0" + gettext_noop ("Invalid attribute") "\0" + gettext_noop ("No value") "\0" + gettext_noop ("Not found") "\0" + gettext_noop ("Value not found") "\0" + gettext_noop ("Syntax error") "\0" + gettext_noop ("Bad MPI value") "\0" + gettext_noop ("Invalid passphrase") "\0" + gettext_noop ("Invalid signature class") "\0" + gettext_noop ("Resources exhausted") "\0" + gettext_noop ("Invalid keyring") "\0" + gettext_noop ("Trust DB error") "\0" + gettext_noop ("Bad certificate") "\0" + gettext_noop ("Invalid user ID") "\0" + gettext_noop ("Unexpected error") "\0" + gettext_noop ("Time conflict") "\0" + gettext_noop ("Keyserver error") "\0" + gettext_noop ("Wrong public key algorithm") "\0" + gettext_noop ("Tribute to D. A.") "\0" + gettext_noop ("Weak encryption key") "\0" + gettext_noop ("Invalid key length") "\0" + gettext_noop ("Invalid argument") "\0" + gettext_noop ("Syntax error in URI") "\0" + gettext_noop ("Invalid URI") "\0" + gettext_noop ("Network error") "\0" + gettext_noop ("Unknown host") "\0" + gettext_noop ("Selftest failed") "\0" + gettext_noop ("Data not encrypted") "\0" + gettext_noop ("Data not processed") "\0" + gettext_noop ("Unusable public key") "\0" + gettext_noop ("Unusable secret key") "\0" + gettext_noop ("Invalid value") "\0" + gettext_noop ("Bad certificate chain") "\0" + gettext_noop ("Missing certificate") "\0" + gettext_noop ("No data") "\0" + gettext_noop ("Bug") "\0" + gettext_noop ("Not supported") "\0" + gettext_noop ("Invalid operation code") "\0" + gettext_noop ("Timeout") "\0" + gettext_noop ("Internal error") "\0" + gettext_noop ("EOF (gcrypt)") "\0" + gettext_noop ("Invalid object") "\0" + gettext_noop ("Provided object is too short") "\0" + gettext_noop ("Provided object is too large") "\0" + gettext_noop ("Missing item in object") "\0" + gettext_noop ("Not implemented") "\0" + gettext_noop ("Conflicting use") "\0" + gettext_noop ("Invalid cipher mode") "\0" + gettext_noop ("Invalid flag") "\0" + gettext_noop ("Invalid handle") "\0" + gettext_noop ("Result truncated") "\0" + gettext_noop ("Incomplete line") "\0" + gettext_noop ("Invalid response") "\0" + gettext_noop ("No agent running") "\0" + gettext_noop ("Agent error") "\0" + gettext_noop ("Invalid data") "\0" + gettext_noop ("Unspecific Assuan server fault") "\0" + gettext_noop ("General Assuan error") "\0" + gettext_noop ("Invalid session key") "\0" + gettext_noop ("Invalid S-expression") "\0" + gettext_noop ("Unsupported algorithm") "\0" + gettext_noop ("No pinentry") "\0" + gettext_noop ("pinentry error") "\0" + gettext_noop ("Bad PIN") "\0" + gettext_noop ("Invalid name") "\0" + gettext_noop ("Bad data") "\0" + gettext_noop ("Invalid parameter") "\0" + gettext_noop ("Wrong card") "\0" + gettext_noop ("No dirmngr") "\0" + gettext_noop ("dirmngr error") "\0" + gettext_noop ("Certificate revoked") "\0" + gettext_noop ("No CRL known") "\0" + gettext_noop ("CRL too old") "\0" + gettext_noop ("Line too long") "\0" + gettext_noop ("Not trusted") "\0" + gettext_noop ("Operation cancelled") "\0" + gettext_noop ("Bad CA certificate") "\0" + gettext_noop ("Certificate expired") "\0" + gettext_noop ("Certificate too young") "\0" + gettext_noop ("Unsupported certificate") "\0" + gettext_noop ("Unknown S-expression") "\0" + gettext_noop ("Unsupported protection") "\0" + gettext_noop ("Corrupted protection") "\0" + gettext_noop ("Ambiguous name") "\0" + gettext_noop ("Card error") "\0" + gettext_noop ("Card reset required") "\0" + gettext_noop ("Card removed") "\0" + gettext_noop ("Invalid card") "\0" + gettext_noop ("Card not present") "\0" + gettext_noop ("No PKCS15 application") "\0" + gettext_noop ("Not confirmed") "\0" + gettext_noop ("Configuration error") "\0" + gettext_noop ("No policy match") "\0" + gettext_noop ("Invalid index") "\0" + gettext_noop ("Invalid ID") "\0" + gettext_noop ("No SmartCard daemon") "\0" + gettext_noop ("SmartCard daemon error") "\0" + gettext_noop ("Unsupported protocol") "\0" + gettext_noop ("Bad PIN method") "\0" + gettext_noop ("Card not initialized") "\0" + gettext_noop ("Unsupported operation") "\0" + gettext_noop ("Wrong key usage") "\0" + gettext_noop ("Nothing found") "\0" + gettext_noop ("Wrong blob type") "\0" + gettext_noop ("Missing value") "\0" + gettext_noop ("Hardware problem") "\0" + gettext_noop ("PIN blocked") "\0" + gettext_noop ("Conditions of use not satisfied") "\0" + gettext_noop ("PINs are not synced") "\0" + gettext_noop ("Invalid CRL") "\0" + gettext_noop ("BER error") "\0" + gettext_noop ("Invalid BER") "\0" + gettext_noop ("Element not found") "\0" + gettext_noop ("Identifier not found") "\0" + gettext_noop ("Invalid tag") "\0" + gettext_noop ("Invalid length") "\0" + gettext_noop ("Invalid key info") "\0" + gettext_noop ("Unexpected tag") "\0" + gettext_noop ("Not DER encoded") "\0" + gettext_noop ("No CMS object") "\0" + gettext_noop ("Invalid CMS object") "\0" + gettext_noop ("Unknown CMS object") "\0" + gettext_noop ("Unsupported CMS object") "\0" + gettext_noop ("Unsupported encoding") "\0" + gettext_noop ("Unsupported CMS version") "\0" + gettext_noop ("Unknown algorithm") "\0" + gettext_noop ("Invalid crypto engine") "\0" + gettext_noop ("Public key not trusted") "\0" + gettext_noop ("Decryption failed") "\0" + gettext_noop ("Key expired") "\0" + gettext_noop ("Signature expired") "\0" + gettext_noop ("Encoding problem") "\0" + gettext_noop ("Invalid state") "\0" + gettext_noop ("Duplicated value") "\0" + gettext_noop ("Missing action") "\0" + gettext_noop ("ASN.1 module not found") "\0" + gettext_noop ("Invalid OID string") "\0" + gettext_noop ("Invalid time") "\0" + gettext_noop ("Invalid CRL object") "\0" + gettext_noop ("Unsupported CRL version") "\0" + gettext_noop ("Invalid certificate object") "\0" + gettext_noop ("Unknown name") "\0" + gettext_noop ("A locale function failed") "\0" + gettext_noop ("Not locked") "\0" + gettext_noop ("Protocol violation") "\0" + gettext_noop ("Invalid MAC") "\0" + gettext_noop ("Invalid request") "\0" + gettext_noop ("Unknown extension") "\0" + gettext_noop ("Unknown critical extension") "\0" + gettext_noop ("Locked") "\0" + gettext_noop ("Unknown option") "\0" + gettext_noop ("Unknown command") "\0" + gettext_noop ("Not operational") "\0" + gettext_noop ("No passphrase given") "\0" + gettext_noop ("No PIN given") "\0" + gettext_noop ("Not enabled") "\0" + gettext_noop ("No crypto engine") "\0" + gettext_noop ("Missing key") "\0" + gettext_noop ("Too many objects") "\0" + gettext_noop ("Limit reached") "\0" + gettext_noop ("Not initialized") "\0" + gettext_noop ("Missing issuer certificate") "\0" + gettext_noop ("No keyserver available") "\0" + gettext_noop ("Invalid elliptic curve") "\0" + gettext_noop ("Unknown elliptic curve") "\0" + gettext_noop ("Duplicated key") "\0" + gettext_noop ("Ambiguous result") "\0" + gettext_noop ("No crypto context") "\0" + gettext_noop ("Wrong crypto context") "\0" + gettext_noop ("Bad crypto context") "\0" + gettext_noop ("Conflict in the crypto context") "\0" + gettext_noop ("Broken public key") "\0" + gettext_noop ("Broken secret key") "\0" + gettext_noop ("Invalid MAC algorithm") "\0" + gettext_noop ("Operation fully cancelled") "\0" + gettext_noop ("Operation not yet finished") "\0" + gettext_noop ("Buffer too short") "\0" + gettext_noop ("Invalid length specifier in S-expression") "\0" + gettext_noop ("String too long in S-expression") "\0" + gettext_noop ("Unmatched parentheses in S-expression") "\0" + gettext_noop ("S-expression not canonical") "\0" + gettext_noop ("Bad character in S-expression") "\0" + gettext_noop ("Bad quotation in S-expression") "\0" + gettext_noop ("Zero prefix in S-expression") "\0" + gettext_noop ("Nested display hints in S-expression") "\0" + gettext_noop ("Unmatched display hints") "\0" + gettext_noop ("Unexpected reserved punctuation in S-expression") "\0" + gettext_noop ("Bad hexadecimal character in S-expression") "\0" + gettext_noop ("Odd hexadecimal numbers in S-expression") "\0" + gettext_noop ("Bad octal character in S-expression") "\0" + gettext_noop ("All subkeys are expired or revoked") "\0" + gettext_noop ("Database is corrupted") "\0" + gettext_noop ("Server indicated a failure") "\0" + gettext_noop ("No name") "\0" + gettext_noop ("No key") "\0" + gettext_noop ("Legacy key") "\0" + gettext_noop ("Request too short") "\0" + gettext_noop ("Request too long") "\0" + gettext_noop ("Object is in termination state") "\0" + gettext_noop ("No certificate chain") "\0" + gettext_noop ("Certificate is too large") "\0" + gettext_noop ("Invalid record") "\0" + gettext_noop ("The MAC does not verify") "\0" + gettext_noop ("Unexpected message") "\0" + gettext_noop ("Compression or decompression failed") "\0" + gettext_noop ("A counter would wrap") "\0" + gettext_noop ("Fatal alert message received") "\0" + gettext_noop ("No cipher algorithm") "\0" + gettext_noop ("Missing client certificate") "\0" + gettext_noop ("Close notification received") "\0" + gettext_noop ("Ticket expired") "\0" + gettext_noop ("Bad ticket") "\0" + gettext_noop ("Unknown identity") "\0" + gettext_noop ("Bad certificate message in handshake") "\0" + gettext_noop ("Bad certificate request message in handshake") "\0" + gettext_noop ("Bad certificate verify message in handshake") "\0" + gettext_noop ("Bad change cipher message in handshake") "\0" + gettext_noop ("Bad client hello message in handshake") "\0" + gettext_noop ("Bad server hello message in handshake") "\0" + gettext_noop ("Bad server hello done message in handshake") "\0" + gettext_noop ("Bad finished message in handshake") "\0" + gettext_noop ("Bad server key exchange message in handshake") "\0" + gettext_noop ("Bad client key exchange message in handshake") "\0" + gettext_noop ("Bogus string") "\0" + gettext_noop ("Forbidden") "\0" + gettext_noop ("Key disabled") "\0" + gettext_noop ("Not possible with a card based key") "\0" + gettext_noop ("Invalid lock object") "\0" + gettext_noop ("True") "\0" + gettext_noop ("False") "\0" + gettext_noop ("General IPC error") "\0" + gettext_noop ("IPC accept call failed") "\0" + gettext_noop ("IPC connect call failed") "\0" + gettext_noop ("Invalid IPC response") "\0" + gettext_noop ("Invalid value passed to IPC") "\0" + gettext_noop ("Incomplete line passed to IPC") "\0" + gettext_noop ("Line passed to IPC too long") "\0" + gettext_noop ("Nested IPC commands") "\0" + gettext_noop ("No data callback in IPC") "\0" + gettext_noop ("No inquire callback in IPC") "\0" + gettext_noop ("Not an IPC server") "\0" + gettext_noop ("Not an IPC client") "\0" + gettext_noop ("Problem starting IPC server") "\0" + gettext_noop ("IPC read error") "\0" + gettext_noop ("IPC write error") "\0" + gettext_noop ("Too much data for IPC layer") "\0" + gettext_noop ("Unexpected IPC command") "\0" + gettext_noop ("Unknown IPC command") "\0" + gettext_noop ("IPC syntax error") "\0" + gettext_noop ("IPC call has been cancelled") "\0" + gettext_noop ("No input source for IPC") "\0" + gettext_noop ("No output source for IPC") "\0" + gettext_noop ("IPC parameter error") "\0" + gettext_noop ("Unknown IPC inquire") "\0" + gettext_noop ("Crypto engine too old") "\0" + gettext_noop ("Screen or window too small") "\0" + gettext_noop ("Screen or window too large") "\0" + gettext_noop ("Required environment variable not set") "\0" + gettext_noop ("User ID already exists") "\0" + gettext_noop ("Name already exists") "\0" + gettext_noop ("Duplicated name") "\0" + gettext_noop ("Object is too young") "\0" + gettext_noop ("Object is too old") "\0" + gettext_noop ("Unknown flag") "\0" + gettext_noop ("Invalid execution order") "\0" + gettext_noop ("Already fetched") "\0" + gettext_noop ("Try again later") "\0" + gettext_noop ("Wrong name") "\0" + gettext_noop ("Not authenticated") "\0" + gettext_noop ("Bad authentication") "\0" + gettext_noop ("No Keybox daemon running") "\0" + gettext_noop ("Keybox daemon error") "\0" + gettext_noop ("Service is not running") "\0" + gettext_noop ("Service error") "\0" + gettext_noop ("System bug detected") "\0" + gettext_noop ("Unknown DNS error") "\0" + gettext_noop ("Invalid DNS section") "\0" + gettext_noop ("Invalid textual address form") "\0" + gettext_noop ("Missing DNS query packet") "\0" + gettext_noop ("Missing DNS answer packet") "\0" + gettext_noop ("Connection closed in DNS") "\0" + gettext_noop ("Verification failed in DNS") "\0" + gettext_noop ("DNS Timeout") "\0" + gettext_noop ("General LDAP error") "\0" + gettext_noop ("General LDAP attribute error") "\0" + gettext_noop ("General LDAP name error") "\0" + gettext_noop ("General LDAP security error") "\0" + gettext_noop ("General LDAP service error") "\0" + gettext_noop ("General LDAP update error") "\0" + gettext_noop ("Experimental LDAP error code") "\0" + gettext_noop ("Private LDAP error code") "\0" + gettext_noop ("Other general LDAP error") "\0" + gettext_noop ("LDAP connecting failed (X)") "\0" + gettext_noop ("LDAP referral limit exceeded") "\0" + gettext_noop ("LDAP client loop") "\0" + gettext_noop ("No LDAP results returned") "\0" + gettext_noop ("LDAP control not found") "\0" + gettext_noop ("Not supported by LDAP") "\0" + gettext_noop ("LDAP connect error") "\0" + gettext_noop ("Out of memory in LDAP") "\0" + gettext_noop ("Bad parameter to an LDAP routine") "\0" + gettext_noop ("User cancelled LDAP operation") "\0" + gettext_noop ("Bad LDAP search filter") "\0" + gettext_noop ("Unknown LDAP authentication method") "\0" + gettext_noop ("Timeout in LDAP") "\0" + gettext_noop ("LDAP decoding error") "\0" + gettext_noop ("LDAP encoding error") "\0" + gettext_noop ("LDAP local error") "\0" + gettext_noop ("Cannot contact LDAP server") "\0" + gettext_noop ("LDAP success") "\0" + gettext_noop ("LDAP operations error") "\0" + gettext_noop ("LDAP protocol error") "\0" + gettext_noop ("Time limit exceeded in LDAP") "\0" + gettext_noop ("Size limit exceeded in LDAP") "\0" + gettext_noop ("LDAP compare false") "\0" + gettext_noop ("LDAP compare true") "\0" + gettext_noop ("LDAP authentication method not supported") "\0" + gettext_noop ("Strong(er) LDAP authentication required") "\0" + gettext_noop ("Partial LDAP results+referral received") "\0" + gettext_noop ("LDAP referral") "\0" + gettext_noop ("Administrative LDAP limit exceeded") "\0" + gettext_noop ("Critical LDAP extension is unavailable") "\0" + gettext_noop ("Confidentiality required by LDAP") "\0" + gettext_noop ("LDAP SASL bind in progress") "\0" + gettext_noop ("No such LDAP attribute") "\0" + gettext_noop ("Undefined LDAP attribute type") "\0" + gettext_noop ("Inappropriate matching in LDAP") "\0" + gettext_noop ("Constraint violation in LDAP") "\0" + gettext_noop ("LDAP type or value exists") "\0" + gettext_noop ("Invalid syntax in LDAP") "\0" + gettext_noop ("No such LDAP object") "\0" + gettext_noop ("LDAP alias problem") "\0" + gettext_noop ("Invalid DN syntax in LDAP") "\0" + gettext_noop ("LDAP entry is a leaf") "\0" + gettext_noop ("LDAP alias dereferencing problem") "\0" + gettext_noop ("LDAP proxy authorization failure (X)") "\0" + gettext_noop ("Inappropriate LDAP authentication") "\0" + gettext_noop ("Invalid LDAP credentials") "\0" + gettext_noop ("Insufficient access for LDAP") "\0" + gettext_noop ("LDAP server is busy") "\0" + gettext_noop ("LDAP server is unavailable") "\0" + gettext_noop ("LDAP server is unwilling to perform") "\0" + gettext_noop ("Loop detected by LDAP") "\0" + gettext_noop ("LDAP naming violation") "\0" + gettext_noop ("LDAP object class violation") "\0" + gettext_noop ("LDAP operation not allowed on non-leaf") "\0" + gettext_noop ("LDAP operation not allowed on RDN") "\0" + gettext_noop ("Already exists (LDAP)") "\0" + gettext_noop ("Cannot modify LDAP object class") "\0" + gettext_noop ("LDAP results too large") "\0" + gettext_noop ("LDAP operation affects multiple DSAs") "\0" + gettext_noop ("Virtual LDAP list view error") "\0" + gettext_noop ("Other LDAP error") "\0" + gettext_noop ("Resources exhausted in LCUP") "\0" + gettext_noop ("Security violation in LCUP") "\0" + gettext_noop ("Invalid data in LCUP") "\0" + gettext_noop ("Unsupported scheme in LCUP") "\0" + gettext_noop ("Reload required in LCUP") "\0" + gettext_noop ("LDAP cancelled") "\0" + gettext_noop ("No LDAP operation to cancel") "\0" + gettext_noop ("Too late to cancel LDAP") "\0" + gettext_noop ("Cannot cancel LDAP") "\0" + gettext_noop ("LDAP assertion failed") "\0" + gettext_noop ("Proxied authorization denied by LDAP") "\0" + gettext_noop ("User defined error code 1") "\0" + gettext_noop ("User defined error code 2") "\0" + gettext_noop ("User defined error code 3") "\0" + gettext_noop ("User defined error code 4") "\0" + gettext_noop ("User defined error code 5") "\0" + gettext_noop ("User defined error code 6") "\0" + gettext_noop ("User defined error code 7") "\0" + gettext_noop ("User defined error code 8") "\0" + gettext_noop ("User defined error code 9") "\0" + gettext_noop ("User defined error code 10") "\0" + gettext_noop ("User defined error code 11") "\0" + gettext_noop ("User defined error code 12") "\0" + gettext_noop ("User defined error code 13") "\0" + gettext_noop ("User defined error code 14") "\0" + gettext_noop ("User defined error code 15") "\0" + gettext_noop ("User defined error code 16") "\0" + gettext_noop ("SQL success") "\0" + gettext_noop ("SQL error") "\0" + gettext_noop ("Internal logic error in SQL library") "\0" + gettext_noop ("Access permission denied (SQL)") "\0" + gettext_noop ("SQL abort was requested") "\0" + gettext_noop ("SQL database file is locked") "\0" + gettext_noop ("An SQL table in the database is locked") "\0" + gettext_noop ("SQL library ran out of core") "\0" + gettext_noop ("Attempt to write a readonly SQL database") "\0" + gettext_noop ("SQL operation terminated by interrupt") "\0" + gettext_noop ("I/O error during SQL operation") "\0" + gettext_noop ("SQL database disk image is malformed") "\0" + gettext_noop ("Unknown opcode in SQL file control") "\0" + gettext_noop ("Insertion failed because SQL database is full") "\0" + gettext_noop ("Unable to open the SQL database file") "\0" + gettext_noop ("SQL database lock protocol error") "\0" + gettext_noop ("(internal SQL code: empty)") "\0" + gettext_noop ("SQL database schema changed") "\0" + gettext_noop ("String or blob exceeds size limit (SQL)") "\0" + gettext_noop ("SQL abort due to constraint violation") "\0" + gettext_noop ("Data type mismatch (SQL)") "\0" + gettext_noop ("SQL library used incorrectly") "\0" + gettext_noop ("SQL library uses unsupported OS features") "\0" + gettext_noop ("Authorization denied (SQL)") "\0" + gettext_noop ("(unused SQL code: format)") "\0" + gettext_noop ("SQL bind parameter out of range") "\0" + gettext_noop ("File opened that is not an SQL database file") "\0" + gettext_noop ("Notifications from SQL logger") "\0" + gettext_noop ("Warnings from SQL logger") "\0" + gettext_noop ("SQL has another row ready") "\0" + gettext_noop ("SQL has finished executing") "\0" + gettext_noop ("System error w/o errno") "\0" + gettext_noop ("Unknown system error") "\0" + gettext_noop ("End of file") "\0" + gettext_noop ("Unknown error code"); + +static const int msgidx[] = + { + 0, + 8, + 22, + 37, + 63, + 92, + 117, + 132, + 147, + 161, + 175, + 190, + 205, + 230, + 250, + 265, + 279, + 290, + 304, + 326, + 342, + 372, + 392, + 416, + 442, + 467, + 485, + 494, + 504, + 520, + 533, + 547, + 566, + 590, + 610, + 626, + 641, + 657, + 673, + 690, + 704, + 720, + 747, + 764, + 784, + 803, + 820, + 840, + 852, + 866, + 879, + 895, + 914, + 933, + 953, + 973, + 987, + 1009, + 1029, + 1037, + 1041, + 1055, + 1078, + 1086, + 1101, + 1114, + 1129, + 1158, + 1187, + 1210, + 1226, + 1242, + 1262, + 1275, + 1290, + 1307, + 1323, + 1340, + 1357, + 1369, + 1382, + 1413, + 1434, + 1454, + 1475, + 1497, + 1509, + 1524, + 1532, + 1545, + 1554, + 1572, + 1583, + 1594, + 1608, + 1628, + 1641, + 1653, + 1667, + 1679, + 1699, + 1718, + 1738, + 1760, + 1784, + 1805, + 1828, + 1849, + 1864, + 1875, + 1895, + 1908, + 1921, + 1938, + 1960, + 1974, + 1994, + 2010, + 2024, + 2035, + 2055, + 2078, + 2099, + 2114, + 2135, + 2157, + 2173, + 2187, + 2203, + 2217, + 2234, + 2246, + 2278, + 2298, + 2310, + 2320, + 2332, + 2350, + 2371, + 2383, + 2398, + 2415, + 2430, + 2446, + 2460, + 2479, + 2498, + 2521, + 2542, + 2566, + 2584, + 2606, + 2629, + 2647, + 2659, + 2677, + 2694, + 2708, + 2725, + 2740, + 2763, + 2782, + 2795, + 2814, + 2838, + 2865, + 2878, + 2903, + 2914, + 2933, + 2945, + 2961, + 2979, + 3006, + 3013, + 3028, + 3044, + 3060, + 3080, + 3093, + 3105, + 3122, + 3134, + 3151, + 3165, + 3181, + 3208, + 3231, + 3254, + 3277, + 3292, + 3309, + 3327, + 3348, + 3367, + 3398, + 3416, + 3434, + 3456, + 3482, + 3509, + 3526, + 3567, + 3599, + 3637, + 3664, + 3694, + 3724, + 3752, + 3789, + 3813, + 3861, + 3903, + 3943, + 3979, + 4014, + 4036, + 4063, + 4071, + 4078, + 4089, + 4107, + 4124, + 4155, + 4176, + 4201, + 4216, + 4240, + 4259, + 4295, + 4316, + 4345, + 4365, + 4392, + 4420, + 4435, + 4446, + 4463, + 4500, + 4545, + 4589, + 4628, + 4666, + 4704, + 4747, + 4781, + 4826, + 4871, + 4884, + 4894, + 4907, + 4942, + 4962, + 4967, + 4973, + 4991, + 5014, + 5038, + 5059, + 5087, + 5117, + 5145, + 5165, + 5189, + 5216, + 5234, + 5252, + 5280, + 5295, + 5311, + 5339, + 5362, + 5382, + 5399, + 5427, + 5451, + 5476, + 5496, + 5516, + 5538, + 5565, + 5592, + 5630, + 5653, + 5673, + 5689, + 5709, + 5727, + 5740, + 5764, + 5780, + 5796, + 5807, + 5825, + 5844, + 5869, + 5889, + 5912, + 5926, + 5946, + 5964, + 5984, + 6013, + 6038, + 6064, + 6089, + 6116, + 6128, + 6147, + 6176, + 6200, + 6228, + 6255, + 6281, + 6310, + 6334, + 6359, + 6386, + 6415, + 6432, + 6457, + 6480, + 6502, + 6521, + 6543, + 6576, + 6606, + 6629, + 6664, + 6680, + 6700, + 6720, + 6737, + 6764, + 6777, + 6799, + 6819, + 6847, + 6875, + 6894, + 6912, + 6953, + 6993, + 7032, + 7046, + 7081, + 7120, + 7153, + 7180, + 7203, + 7233, + 7264, + 7293, + 7319, + 7342, + 7362, + 7381, + 7407, + 7428, + 7461, + 7498, + 7532, + 7557, + 7586, + 7606, + 7633, + 7669, + 7691, + 7713, + 7741, + 7780, + 7814, + 7836, + 7868, + 7891, + 7928, + 7957, + 7974, + 8002, + 8029, + 8050, + 8077, + 8101, + 8116, + 8144, + 8168, + 8187, + 8209, + 8246, + 8272, + 8298, + 8324, + 8350, + 8376, + 8402, + 8428, + 8454, + 8480, + 8507, + 8534, + 8561, + 8588, + 8615, + 8642, + 8669, + 8681, + 8691, + 8727, + 8758, + 8782, + 8810, + 8849, + 8877, + 8918, + 8956, + 8987, + 9024, + 9059, + 9105, + 9142, + 9175, + 9202, + 9230, + 9270, + 9308, + 9333, + 9362, + 9403, + 9430, + 9456, + 9488, + 9533, + 9563, + 9588, + 9614, + 9641, + 9664, + 9685, + 9697 + }; + +static GPG_ERR_INLINE int +msgidxof (int code) +{ + return (0 ? 0 + : ((code >= 0) && (code <= 213)) ? (code - 0) + : ((code >= 217) && (code <= 271)) ? (code - 3) + : ((code >= 273) && (code <= 281)) ? (code - 4) + : ((code >= 300) && (code <= 319)) ? (code - 22) + : ((code >= 666) && (code <= 666)) ? (code - 368) + : ((code >= 711) && (code <= 718)) ? (code - 412) + : ((code >= 721) && (code <= 729)) ? (code - 414) + : ((code >= 750) && (code <= 752)) ? (code - 434) + : ((code >= 754) && (code <= 782)) ? (code - 435) + : ((code >= 784) && (code <= 789)) ? (code - 436) + : ((code >= 800) && (code <= 804)) ? (code - 446) + : ((code >= 815) && (code <= 822)) ? (code - 456) + : ((code >= 832) && (code <= 839)) ? (code - 465) + : ((code >= 844) && (code <= 844)) ? (code - 469) + : ((code >= 848) && (code <= 848)) ? (code - 472) + : ((code >= 881) && (code <= 891)) ? (code - 504) + : ((code >= 1024) && (code <= 1039)) ? (code - 636) + : ((code >= 1500) && (code <= 1528)) ? (code - 1096) + : ((code >= 1600) && (code <= 1601)) ? (code - 1167) + : ((code >= 16381) && (code <= 16383)) ? (code - 15946) + : 16384 - 15946); +} diff --git a/comm/third_party/libgpg-error/src/err-codes.h.in b/comm/third_party/libgpg-error/src/err-codes.h.in new file mode 100644 index 0000000000..c65775f72c --- /dev/null +++ b/comm/third_party/libgpg-error/src/err-codes.h.in @@ -0,0 +1,527 @@ +# err-codes.h.in - List of error codes and their description input file. +/* err-codes.h - List of error codes and their description. + Copyright (C) 2003, 2004 g10 Code GmbH + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with libgpg-error; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +# Everything up to the first line that starts with a number in the +# first column is copied into the output verbatim. Then, empty lines +# are ignored. Other lines must have an error code number, followed +# by one or more <tab> characters, followed by the error code symbol, +# followed by one or more <tab> characters, followed by the error +# message. Trailing whitespace is removed. The error codes should be +# sorted. The last line should not have a number, but only a <tab>, +# followed by a dummy field, followed by a <tab>, followed by a +# description for error codes that are not in the list. + +0 GPG_ERR_NO_ERROR Success +1 GPG_ERR_GENERAL General error +2 GPG_ERR_UNKNOWN_PACKET Unknown packet +3 GPG_ERR_UNKNOWN_VERSION Unknown version in packet +4 GPG_ERR_PUBKEY_ALGO Invalid public key algorithm +5 GPG_ERR_DIGEST_ALGO Invalid digest algorithm +6 GPG_ERR_BAD_PUBKEY Bad public key +7 GPG_ERR_BAD_SECKEY Bad secret key +8 GPG_ERR_BAD_SIGNATURE Bad signature +9 GPG_ERR_NO_PUBKEY No public key +10 GPG_ERR_CHECKSUM Checksum error +11 GPG_ERR_BAD_PASSPHRASE Bad passphrase +12 GPG_ERR_CIPHER_ALGO Invalid cipher algorithm +13 GPG_ERR_KEYRING_OPEN Cannot open keyring +14 GPG_ERR_INV_PACKET Invalid packet +15 GPG_ERR_INV_ARMOR Invalid armor +16 GPG_ERR_NO_USER_ID No user ID +17 GPG_ERR_NO_SECKEY No secret key +18 GPG_ERR_WRONG_SECKEY Wrong secret key used +19 GPG_ERR_BAD_KEY Bad session key +20 GPG_ERR_COMPR_ALGO Unknown compression algorithm +21 GPG_ERR_NO_PRIME Number is not prime +22 GPG_ERR_NO_ENCODING_METHOD Invalid encoding method +23 GPG_ERR_NO_ENCRYPTION_SCHEME Invalid encryption scheme +24 GPG_ERR_NO_SIGNATURE_SCHEME Invalid signature scheme +25 GPG_ERR_INV_ATTR Invalid attribute +26 GPG_ERR_NO_VALUE No value +27 GPG_ERR_NOT_FOUND Not found +28 GPG_ERR_VALUE_NOT_FOUND Value not found +29 GPG_ERR_SYNTAX Syntax error +30 GPG_ERR_BAD_MPI Bad MPI value +31 GPG_ERR_INV_PASSPHRASE Invalid passphrase +32 GPG_ERR_SIG_CLASS Invalid signature class +33 GPG_ERR_RESOURCE_LIMIT Resources exhausted +34 GPG_ERR_INV_KEYRING Invalid keyring +35 GPG_ERR_TRUSTDB Trust DB error +36 GPG_ERR_BAD_CERT Bad certificate +37 GPG_ERR_INV_USER_ID Invalid user ID +38 GPG_ERR_UNEXPECTED Unexpected error +39 GPG_ERR_TIME_CONFLICT Time conflict +40 GPG_ERR_KEYSERVER Keyserver error +41 GPG_ERR_WRONG_PUBKEY_ALGO Wrong public key algorithm +42 GPG_ERR_TRIBUTE_TO_D_A Tribute to D. A. +43 GPG_ERR_WEAK_KEY Weak encryption key +44 GPG_ERR_INV_KEYLEN Invalid key length +45 GPG_ERR_INV_ARG Invalid argument +46 GPG_ERR_BAD_URI Syntax error in URI +47 GPG_ERR_INV_URI Invalid URI +48 GPG_ERR_NETWORK Network error +49 GPG_ERR_UNKNOWN_HOST Unknown host +50 GPG_ERR_SELFTEST_FAILED Selftest failed +51 GPG_ERR_NOT_ENCRYPTED Data not encrypted +52 GPG_ERR_NOT_PROCESSED Data not processed +53 GPG_ERR_UNUSABLE_PUBKEY Unusable public key +54 GPG_ERR_UNUSABLE_SECKEY Unusable secret key +55 GPG_ERR_INV_VALUE Invalid value +56 GPG_ERR_BAD_CERT_CHAIN Bad certificate chain +57 GPG_ERR_MISSING_CERT Missing certificate +58 GPG_ERR_NO_DATA No data +59 GPG_ERR_BUG Bug +60 GPG_ERR_NOT_SUPPORTED Not supported +61 GPG_ERR_INV_OP Invalid operation code +62 GPG_ERR_TIMEOUT Timeout +63 GPG_ERR_INTERNAL Internal error +64 GPG_ERR_EOF_GCRYPT EOF (gcrypt) +65 GPG_ERR_INV_OBJ Invalid object +66 GPG_ERR_TOO_SHORT Provided object is too short +67 GPG_ERR_TOO_LARGE Provided object is too large +68 GPG_ERR_NO_OBJ Missing item in object +69 GPG_ERR_NOT_IMPLEMENTED Not implemented +70 GPG_ERR_CONFLICT Conflicting use +71 GPG_ERR_INV_CIPHER_MODE Invalid cipher mode +72 GPG_ERR_INV_FLAG Invalid flag +73 GPG_ERR_INV_HANDLE Invalid handle +74 GPG_ERR_TRUNCATED Result truncated +75 GPG_ERR_INCOMPLETE_LINE Incomplete line +76 GPG_ERR_INV_RESPONSE Invalid response +77 GPG_ERR_NO_AGENT No agent running +78 GPG_ERR_AGENT Agent error +79 GPG_ERR_INV_DATA Invalid data +80 GPG_ERR_ASSUAN_SERVER_FAULT Unspecific Assuan server fault +81 GPG_ERR_ASSUAN General Assuan error +82 GPG_ERR_INV_SESSION_KEY Invalid session key +83 GPG_ERR_INV_SEXP Invalid S-expression +84 GPG_ERR_UNSUPPORTED_ALGORITHM Unsupported algorithm +85 GPG_ERR_NO_PIN_ENTRY No pinentry +86 GPG_ERR_PIN_ENTRY pinentry error +87 GPG_ERR_BAD_PIN Bad PIN +88 GPG_ERR_INV_NAME Invalid name +89 GPG_ERR_BAD_DATA Bad data +90 GPG_ERR_INV_PARAMETER Invalid parameter +91 GPG_ERR_WRONG_CARD Wrong card +92 GPG_ERR_NO_DIRMNGR No dirmngr +93 GPG_ERR_DIRMNGR dirmngr error +94 GPG_ERR_CERT_REVOKED Certificate revoked +95 GPG_ERR_NO_CRL_KNOWN No CRL known +96 GPG_ERR_CRL_TOO_OLD CRL too old +97 GPG_ERR_LINE_TOO_LONG Line too long +98 GPG_ERR_NOT_TRUSTED Not trusted +99 GPG_ERR_CANCELED Operation cancelled +100 GPG_ERR_BAD_CA_CERT Bad CA certificate +101 GPG_ERR_CERT_EXPIRED Certificate expired +102 GPG_ERR_CERT_TOO_YOUNG Certificate too young +103 GPG_ERR_UNSUPPORTED_CERT Unsupported certificate +104 GPG_ERR_UNKNOWN_SEXP Unknown S-expression +105 GPG_ERR_UNSUPPORTED_PROTECTION Unsupported protection +106 GPG_ERR_CORRUPTED_PROTECTION Corrupted protection +107 GPG_ERR_AMBIGUOUS_NAME Ambiguous name +108 GPG_ERR_CARD Card error +109 GPG_ERR_CARD_RESET Card reset required +110 GPG_ERR_CARD_REMOVED Card removed +111 GPG_ERR_INV_CARD Invalid card +112 GPG_ERR_CARD_NOT_PRESENT Card not present +113 GPG_ERR_NO_PKCS15_APP No PKCS15 application +114 GPG_ERR_NOT_CONFIRMED Not confirmed +115 GPG_ERR_CONFIGURATION Configuration error +116 GPG_ERR_NO_POLICY_MATCH No policy match +117 GPG_ERR_INV_INDEX Invalid index +118 GPG_ERR_INV_ID Invalid ID +119 GPG_ERR_NO_SCDAEMON No SmartCard daemon +120 GPG_ERR_SCDAEMON SmartCard daemon error +121 GPG_ERR_UNSUPPORTED_PROTOCOL Unsupported protocol +122 GPG_ERR_BAD_PIN_METHOD Bad PIN method +123 GPG_ERR_CARD_NOT_INITIALIZED Card not initialized +124 GPG_ERR_UNSUPPORTED_OPERATION Unsupported operation +125 GPG_ERR_WRONG_KEY_USAGE Wrong key usage +126 GPG_ERR_NOTHING_FOUND Nothing found +127 GPG_ERR_WRONG_BLOB_TYPE Wrong blob type +128 GPG_ERR_MISSING_VALUE Missing value +129 GPG_ERR_HARDWARE Hardware problem +130 GPG_ERR_PIN_BLOCKED PIN blocked +131 GPG_ERR_USE_CONDITIONS Conditions of use not satisfied +132 GPG_ERR_PIN_NOT_SYNCED PINs are not synced +133 GPG_ERR_INV_CRL Invalid CRL +134 GPG_ERR_BAD_BER BER error +135 GPG_ERR_INV_BER Invalid BER +136 GPG_ERR_ELEMENT_NOT_FOUND Element not found +137 GPG_ERR_IDENTIFIER_NOT_FOUND Identifier not found +138 GPG_ERR_INV_TAG Invalid tag +139 GPG_ERR_INV_LENGTH Invalid length +140 GPG_ERR_INV_KEYINFO Invalid key info +141 GPG_ERR_UNEXPECTED_TAG Unexpected tag +142 GPG_ERR_NOT_DER_ENCODED Not DER encoded +143 GPG_ERR_NO_CMS_OBJ No CMS object +144 GPG_ERR_INV_CMS_OBJ Invalid CMS object +145 GPG_ERR_UNKNOWN_CMS_OBJ Unknown CMS object +146 GPG_ERR_UNSUPPORTED_CMS_OBJ Unsupported CMS object +147 GPG_ERR_UNSUPPORTED_ENCODING Unsupported encoding +148 GPG_ERR_UNSUPPORTED_CMS_VERSION Unsupported CMS version +149 GPG_ERR_UNKNOWN_ALGORITHM Unknown algorithm +150 GPG_ERR_INV_ENGINE Invalid crypto engine +151 GPG_ERR_PUBKEY_NOT_TRUSTED Public key not trusted +152 GPG_ERR_DECRYPT_FAILED Decryption failed +153 GPG_ERR_KEY_EXPIRED Key expired +154 GPG_ERR_SIG_EXPIRED Signature expired +155 GPG_ERR_ENCODING_PROBLEM Encoding problem +156 GPG_ERR_INV_STATE Invalid state +157 GPG_ERR_DUP_VALUE Duplicated value +158 GPG_ERR_MISSING_ACTION Missing action +159 GPG_ERR_MODULE_NOT_FOUND ASN.1 module not found +160 GPG_ERR_INV_OID_STRING Invalid OID string +161 GPG_ERR_INV_TIME Invalid time +162 GPG_ERR_INV_CRL_OBJ Invalid CRL object +163 GPG_ERR_UNSUPPORTED_CRL_VERSION Unsupported CRL version +164 GPG_ERR_INV_CERT_OBJ Invalid certificate object +165 GPG_ERR_UNKNOWN_NAME Unknown name +166 GPG_ERR_LOCALE_PROBLEM A locale function failed +167 GPG_ERR_NOT_LOCKED Not locked +168 GPG_ERR_PROTOCOL_VIOLATION Protocol violation +169 GPG_ERR_INV_MAC Invalid MAC +170 GPG_ERR_INV_REQUEST Invalid request +171 GPG_ERR_UNKNOWN_EXTN Unknown extension +172 GPG_ERR_UNKNOWN_CRIT_EXTN Unknown critical extension +173 GPG_ERR_LOCKED Locked +174 GPG_ERR_UNKNOWN_OPTION Unknown option +175 GPG_ERR_UNKNOWN_COMMAND Unknown command +176 GPG_ERR_NOT_OPERATIONAL Not operational +177 GPG_ERR_NO_PASSPHRASE No passphrase given +178 GPG_ERR_NO_PIN No PIN given +179 GPG_ERR_NOT_ENABLED Not enabled +180 GPG_ERR_NO_ENGINE No crypto engine +181 GPG_ERR_MISSING_KEY Missing key +182 GPG_ERR_TOO_MANY Too many objects +183 GPG_ERR_LIMIT_REACHED Limit reached +184 GPG_ERR_NOT_INITIALIZED Not initialized +185 GPG_ERR_MISSING_ISSUER_CERT Missing issuer certificate +186 GPG_ERR_NO_KEYSERVER No keyserver available +187 GPG_ERR_INV_CURVE Invalid elliptic curve +188 GPG_ERR_UNKNOWN_CURVE Unknown elliptic curve +189 GPG_ERR_DUP_KEY Duplicated key +190 GPG_ERR_AMBIGUOUS Ambiguous result +191 GPG_ERR_NO_CRYPT_CTX No crypto context +192 GPG_ERR_WRONG_CRYPT_CTX Wrong crypto context +193 GPG_ERR_BAD_CRYPT_CTX Bad crypto context +194 GPG_ERR_CRYPT_CTX_CONFLICT Conflict in the crypto context +195 GPG_ERR_BROKEN_PUBKEY Broken public key +196 GPG_ERR_BROKEN_SECKEY Broken secret key +197 GPG_ERR_MAC_ALGO Invalid MAC algorithm +198 GPG_ERR_FULLY_CANCELED Operation fully cancelled +199 GPG_ERR_UNFINISHED Operation not yet finished +200 GPG_ERR_BUFFER_TOO_SHORT Buffer too short + +# Error codes pertaining to S-expressions. + +201 GPG_ERR_SEXP_INV_LEN_SPEC Invalid length specifier in S-expression +202 GPG_ERR_SEXP_STRING_TOO_LONG String too long in S-expression +203 GPG_ERR_SEXP_UNMATCHED_PAREN Unmatched parentheses in S-expression +204 GPG_ERR_SEXP_NOT_CANONICAL S-expression not canonical +205 GPG_ERR_SEXP_BAD_CHARACTER Bad character in S-expression +206 GPG_ERR_SEXP_BAD_QUOTATION Bad quotation in S-expression +207 GPG_ERR_SEXP_ZERO_PREFIX Zero prefix in S-expression +208 GPG_ERR_SEXP_NESTED_DH Nested display hints in S-expression +209 GPG_ERR_SEXP_UNMATCHED_DH Unmatched display hints +210 GPG_ERR_SEXP_UNEXPECTED_PUNC Unexpected reserved punctuation in S-expression +211 GPG_ERR_SEXP_BAD_HEX_CHAR Bad hexadecimal character in S-expression +212 GPG_ERR_SEXP_ODD_HEX_NUMBERS Odd hexadecimal numbers in S-expression +213 GPG_ERR_SEXP_BAD_OCT_CHAR Bad octal character in S-expression + +# 214 to 216 are free to be used. +217 GPG_ERR_SUBKEYS_EXP_OR_REV All subkeys are expired or revoked +218 GPG_ERR_DB_CORRUPTED Database is corrupted +219 GPG_ERR_SERVER_FAILED Server indicated a failure +220 GPG_ERR_NO_NAME No name +221 GPG_ERR_NO_KEY No key +222 GPG_ERR_LEGACY_KEY Legacy key +223 GPG_ERR_REQUEST_TOO_SHORT Request too short +224 GPG_ERR_REQUEST_TOO_LONG Request too long +225 GPG_ERR_OBJ_TERM_STATE Object is in termination state +226 GPG_ERR_NO_CERT_CHAIN No certificate chain +227 GPG_ERR_CERT_TOO_LARGE Certificate is too large +228 GPG_ERR_INV_RECORD Invalid record +229 GPG_ERR_BAD_MAC The MAC does not verify +230 GPG_ERR_UNEXPECTED_MSG Unexpected message +231 GPG_ERR_COMPR_FAILED Compression or decompression failed +232 GPG_ERR_WOULD_WRAP A counter would wrap +233 GPG_ERR_FATAL_ALERT Fatal alert message received +234 GPG_ERR_NO_CIPHER No cipher algorithm +235 GPG_ERR_MISSING_CLIENT_CERT Missing client certificate +236 GPG_ERR_CLOSE_NOTIFY Close notification received +237 GPG_ERR_TICKET_EXPIRED Ticket expired +238 GPG_ERR_BAD_TICKET Bad ticket +239 GPG_ERR_UNKNOWN_IDENTITY Unknown identity +240 GPG_ERR_BAD_HS_CERT Bad certificate message in handshake +241 GPG_ERR_BAD_HS_CERT_REQ Bad certificate request message in handshake +242 GPG_ERR_BAD_HS_CERT_VER Bad certificate verify message in handshake +243 GPG_ERR_BAD_HS_CHANGE_CIPHER Bad change cipher message in handshake +244 GPG_ERR_BAD_HS_CLIENT_HELLO Bad client hello message in handshake +245 GPG_ERR_BAD_HS_SERVER_HELLO Bad server hello message in handshake +246 GPG_ERR_BAD_HS_SERVER_HELLO_DONE Bad server hello done message in handshake +247 GPG_ERR_BAD_HS_FINISHED Bad finished message in handshake +248 GPG_ERR_BAD_HS_SERVER_KEX Bad server key exchange message in handshake +249 GPG_ERR_BAD_HS_CLIENT_KEX Bad client key exchange message in handshake +250 GPG_ERR_BOGUS_STRING Bogus string +251 GPG_ERR_FORBIDDEN Forbidden +252 GPG_ERR_KEY_DISABLED Key disabled +253 GPG_ERR_KEY_ON_CARD Not possible with a card based key +254 GPG_ERR_INV_LOCK_OBJ Invalid lock object + +255 GPG_ERR_TRUE True +256 GPG_ERR_FALSE False + +# Error codes pertaining to the Assuan IPC interface +257 GPG_ERR_ASS_GENERAL General IPC error +258 GPG_ERR_ASS_ACCEPT_FAILED IPC accept call failed +259 GPG_ERR_ASS_CONNECT_FAILED IPC connect call failed +260 GPG_ERR_ASS_INV_RESPONSE Invalid IPC response +261 GPG_ERR_ASS_INV_VALUE Invalid value passed to IPC +262 GPG_ERR_ASS_INCOMPLETE_LINE Incomplete line passed to IPC +263 GPG_ERR_ASS_LINE_TOO_LONG Line passed to IPC too long +264 GPG_ERR_ASS_NESTED_COMMANDS Nested IPC commands +265 GPG_ERR_ASS_NO_DATA_CB No data callback in IPC +266 GPG_ERR_ASS_NO_INQUIRE_CB No inquire callback in IPC +267 GPG_ERR_ASS_NOT_A_SERVER Not an IPC server +268 GPG_ERR_ASS_NOT_A_CLIENT Not an IPC client +269 GPG_ERR_ASS_SERVER_START Problem starting IPC server +270 GPG_ERR_ASS_READ_ERROR IPC read error +271 GPG_ERR_ASS_WRITE_ERROR IPC write error +# reserved +273 GPG_ERR_ASS_TOO_MUCH_DATA Too much data for IPC layer +274 GPG_ERR_ASS_UNEXPECTED_CMD Unexpected IPC command +275 GPG_ERR_ASS_UNKNOWN_CMD Unknown IPC command +276 GPG_ERR_ASS_SYNTAX IPC syntax error +277 GPG_ERR_ASS_CANCELED IPC call has been cancelled +278 GPG_ERR_ASS_NO_INPUT No input source for IPC +279 GPG_ERR_ASS_NO_OUTPUT No output source for IPC +280 GPG_ERR_ASS_PARAMETER IPC parameter error +281 GPG_ERR_ASS_UNKNOWN_INQUIRE Unknown IPC inquire + +# 282 to 299 are reserved for future assuan codes. + +300 GPG_ERR_ENGINE_TOO_OLD Crypto engine too old +301 GPG_ERR_WINDOW_TOO_SMALL Screen or window too small +302 GPG_ERR_WINDOW_TOO_LARGE Screen or window too large +303 GPG_ERR_MISSING_ENVVAR Required environment variable not set +304 GPG_ERR_USER_ID_EXISTS User ID already exists +305 GPG_ERR_NAME_EXISTS Name already exists +306 GPG_ERR_DUP_NAME Duplicated name +307 GPG_ERR_TOO_YOUNG Object is too young +308 GPG_ERR_TOO_OLD Object is too old +309 GPG_ERR_UNKNOWN_FLAG Unknown flag +310 GPG_ERR_INV_ORDER Invalid execution order +311 GPG_ERR_ALREADY_FETCHED Already fetched +312 GPG_ERR_TRY_LATER Try again later +313 GPG_ERR_WRONG_NAME Wrong name +314 GPG_ERR_NO_AUTH Not authenticated +315 GPG_ERR_BAD_AUTH Bad authentication +316 GPG_ERR_NO_KEYBOXD No Keybox daemon running +317 GPG_ERR_KEYBOXD Keybox daemon error +318 GPG_ERR_NO_SERVICE Service is not running +319 GPG_ERR_SERVICE Service error +# This range is free for use. + +666 GPG_ERR_SYSTEM_BUG System bug detected + +# +# Mapping of some error codes from libdns and other DNS specific error codes +# +711 GPG_ERR_DNS_UNKNOWN Unknown DNS error +712 GPG_ERR_DNS_SECTION Invalid DNS section +713 GPG_ERR_DNS_ADDRESS Invalid textual address form +714 GPG_ERR_DNS_NO_QUERY Missing DNS query packet +715 GPG_ERR_DNS_NO_ANSWER Missing DNS answer packet +716 GPG_ERR_DNS_CLOSED Connection closed in DNS +717 GPG_ERR_DNS_VERIFY Verification failed in DNS +718 GPG_ERR_DNS_TIMEOUT DNS Timeout + +# +# Mapping of LDAP error codes +# +# The numbers reflect the OpenLDAP code with an offset of 768. +# Some error names are shortened +# +721 GPG_ERR_LDAP_GENERAL General LDAP error +722 GPG_ERR_LDAP_ATTR_GENERAL General LDAP attribute error +723 GPG_ERR_LDAP_NAME_GENERAL General LDAP name error +724 GPG_ERR_LDAP_SECURITY_GENERAL General LDAP security error +725 GPG_ERR_LDAP_SERVICE_GENERAL General LDAP service error +726 GPG_ERR_LDAP_UPDATE_GENERAL General LDAP update error +727 GPG_ERR_LDAP_E_GENERAL Experimental LDAP error code +728 GPG_ERR_LDAP_X_GENERAL Private LDAP error code +729 GPG_ERR_LDAP_OTHER_GENERAL Other general LDAP error +# 730 to 749 not used +750 GPG_ERR_LDAP_X_CONNECTING LDAP connecting failed (X) +751 GPG_ERR_LDAP_REFERRAL_LIMIT LDAP referral limit exceeded +752 GPG_ERR_LDAP_CLIENT_LOOP LDAP client loop +# 753 is an obsolete error code +754 GPG_ERR_LDAP_NO_RESULTS No LDAP results returned +755 GPG_ERR_LDAP_CONTROL_NOT_FOUND LDAP control not found +756 GPG_ERR_LDAP_NOT_SUPPORTED Not supported by LDAP +757 GPG_ERR_LDAP_CONNECT LDAP connect error +758 GPG_ERR_LDAP_NO_MEMORY Out of memory in LDAP +759 GPG_ERR_LDAP_PARAM Bad parameter to an LDAP routine +760 GPG_ERR_LDAP_USER_CANCELLED User cancelled LDAP operation +761 GPG_ERR_LDAP_FILTER Bad LDAP search filter +762 GPG_ERR_LDAP_AUTH_UNKNOWN Unknown LDAP authentication method +763 GPG_ERR_LDAP_TIMEOUT Timeout in LDAP +764 GPG_ERR_LDAP_DECODING LDAP decoding error +765 GPG_ERR_LDAP_ENCODING LDAP encoding error +766 GPG_ERR_LDAP_LOCAL LDAP local error +767 GPG_ERR_LDAP_SERVER_DOWN Cannot contact LDAP server +768 GPG_ERR_LDAP_SUCCESS LDAP success +769 GPG_ERR_LDAP_OPERATIONS LDAP operations error +770 GPG_ERR_LDAP_PROTOCOL LDAP protocol error +771 GPG_ERR_LDAP_TIMELIMIT Time limit exceeded in LDAP +772 GPG_ERR_LDAP_SIZELIMIT Size limit exceeded in LDAP +773 GPG_ERR_LDAP_COMPARE_FALSE LDAP compare false +774 GPG_ERR_LDAP_COMPARE_TRUE LDAP compare true +775 GPG_ERR_LDAP_UNSUPPORTED_AUTH LDAP authentication method not supported +776 GPG_ERR_LDAP_STRONG_AUTH_RQRD Strong(er) LDAP authentication required +777 GPG_ERR_LDAP_PARTIAL_RESULTS Partial LDAP results+referral received +778 GPG_ERR_LDAP_REFERRAL LDAP referral +779 GPG_ERR_LDAP_ADMINLIMIT Administrative LDAP limit exceeded +780 GPG_ERR_LDAP_UNAVAIL_CRIT_EXTN Critical LDAP extension is unavailable +781 GPG_ERR_LDAP_CONFIDENT_RQRD Confidentiality required by LDAP +782 GPG_ERR_LDAP_SASL_BIND_INPROG LDAP SASL bind in progress +# 783 not used +784 GPG_ERR_LDAP_NO_SUCH_ATTRIBUTE No such LDAP attribute +785 GPG_ERR_LDAP_UNDEFINED_TYPE Undefined LDAP attribute type +786 GPG_ERR_LDAP_BAD_MATCHING Inappropriate matching in LDAP +787 GPG_ERR_LDAP_CONST_VIOLATION Constraint violation in LDAP +788 GPG_ERR_LDAP_TYPE_VALUE_EXISTS LDAP type or value exists +789 GPG_ERR_LDAP_INV_SYNTAX Invalid syntax in LDAP +# 790 to 799 not used +800 GPG_ERR_LDAP_NO_SUCH_OBJ No such LDAP object +801 GPG_ERR_LDAP_ALIAS_PROBLEM LDAP alias problem +802 GPG_ERR_LDAP_INV_DN_SYNTAX Invalid DN syntax in LDAP +803 GPG_ERR_LDAP_IS_LEAF LDAP entry is a leaf +804 GPG_ERR_LDAP_ALIAS_DEREF LDAP alias dereferencing problem +# 805 to 814 not used +815 GPG_ERR_LDAP_X_PROXY_AUTH_FAIL LDAP proxy authorization failure (X) +816 GPG_ERR_LDAP_BAD_AUTH Inappropriate LDAP authentication +817 GPG_ERR_LDAP_INV_CREDENTIALS Invalid LDAP credentials +818 GPG_ERR_LDAP_INSUFFICIENT_ACC Insufficient access for LDAP +819 GPG_ERR_LDAP_BUSY LDAP server is busy +820 GPG_ERR_LDAP_UNAVAILABLE LDAP server is unavailable +821 GPG_ERR_LDAP_UNWILL_TO_PERFORM LDAP server is unwilling to perform +822 GPG_ERR_LDAP_LOOP_DETECT Loop detected by LDAP +# 823 to 831 not used +832 GPG_ERR_LDAP_NAMING_VIOLATION LDAP naming violation +833 GPG_ERR_LDAP_OBJ_CLS_VIOLATION LDAP object class violation +834 GPG_ERR_LDAP_NOT_ALLOW_NONLEAF LDAP operation not allowed on non-leaf +835 GPG_ERR_LDAP_NOT_ALLOW_ON_RDN LDAP operation not allowed on RDN +836 GPG_ERR_LDAP_ALREADY_EXISTS Already exists (LDAP) +837 GPG_ERR_LDAP_NO_OBJ_CLASS_MODS Cannot modify LDAP object class +838 GPG_ERR_LDAP_RESULTS_TOO_LARGE LDAP results too large +839 GPG_ERR_LDAP_AFFECTS_MULT_DSAS LDAP operation affects multiple DSAs +# 840 to 843 not used +844 GPG_ERR_LDAP_VLV Virtual LDAP list view error +# 845 to 847 not used +848 GPG_ERR_LDAP_OTHER Other LDAP error +# 849 to 880 not used +881 GPG_ERR_LDAP_CUP_RESOURCE_LIMIT Resources exhausted in LCUP +882 GPG_ERR_LDAP_CUP_SEC_VIOLATION Security violation in LCUP +883 GPG_ERR_LDAP_CUP_INV_DATA Invalid data in LCUP +884 GPG_ERR_LDAP_CUP_UNSUP_SCHEME Unsupported scheme in LCUP +885 GPG_ERR_LDAP_CUP_RELOAD Reload required in LCUP +886 GPG_ERR_LDAP_CANCELLED LDAP cancelled +887 GPG_ERR_LDAP_NO_SUCH_OPERATION No LDAP operation to cancel +888 GPG_ERR_LDAP_TOO_LATE Too late to cancel LDAP +889 GPG_ERR_LDAP_CANNOT_CANCEL Cannot cancel LDAP +890 GPG_ERR_LDAP_ASSERTION_FAILED LDAP assertion failed +891 GPG_ERR_LDAP_PROX_AUTH_DENIED Proxied authorization denied by LDAP + +# 892 to 950 are reserved for future LDAP codes. + +# 951 to 1023 are free to be used. + +# For free use by non-GnuPG components: +1024 GPG_ERR_USER_1 User defined error code 1 +1025 GPG_ERR_USER_2 User defined error code 2 +1026 GPG_ERR_USER_3 User defined error code 3 +1027 GPG_ERR_USER_4 User defined error code 4 +1028 GPG_ERR_USER_5 User defined error code 5 +1029 GPG_ERR_USER_6 User defined error code 6 +1030 GPG_ERR_USER_7 User defined error code 7 +1031 GPG_ERR_USER_8 User defined error code 8 +1032 GPG_ERR_USER_9 User defined error code 9 +1033 GPG_ERR_USER_10 User defined error code 10 +1034 GPG_ERR_USER_11 User defined error code 11 +1035 GPG_ERR_USER_12 User defined error code 12 +1036 GPG_ERR_USER_13 User defined error code 13 +1037 GPG_ERR_USER_14 User defined error code 14 +1038 GPG_ERR_USER_15 User defined error code 15 +1039 GPG_ERR_USER_16 User defined error code 16 + +# 1040 to 1499 are free to be used. + +# 1500 to 1755 are mapped SQLite primary error codes. +1500 GPG_ERR_SQL_OK SQL success +1501 GPG_ERR_SQL_ERROR SQL error +1502 GPG_ERR_SQL_INTERNAL Internal logic error in SQL library +1503 GPG_ERR_SQL_PERM Access permission denied (SQL) +1504 GPG_ERR_SQL_ABORT SQL abort was requested +1505 GPG_ERR_SQL_BUSY SQL database file is locked +1506 GPG_ERR_SQL_LOCKED An SQL table in the database is locked +1507 GPG_ERR_SQL_NOMEM SQL library ran out of core +1508 GPG_ERR_SQL_READONLY Attempt to write a readonly SQL database +1509 GPG_ERR_SQL_INTERRUPT SQL operation terminated by interrupt +1510 GPG_ERR_SQL_IOERR I/O error during SQL operation +1511 GPG_ERR_SQL_CORRUPT SQL database disk image is malformed +1512 GPG_ERR_SQL_NOTFOUND Unknown opcode in SQL file control +1513 GPG_ERR_SQL_FULL Insertion failed because SQL database is full +1514 GPG_ERR_SQL_CANTOPEN Unable to open the SQL database file +1515 GPG_ERR_SQL_PROTOCOL SQL database lock protocol error +1516 GPG_ERR_SQL_EMPTY (internal SQL code: empty) +1517 GPG_ERR_SQL_SCHEMA SQL database schema changed +1518 GPG_ERR_SQL_TOOBIG String or blob exceeds size limit (SQL) +1519 GPG_ERR_SQL_CONSTRAINT SQL abort due to constraint violation +1520 GPG_ERR_SQL_MISMATCH Data type mismatch (SQL) +1521 GPG_ERR_SQL_MISUSE SQL library used incorrectly +1522 GPG_ERR_SQL_NOLFS SQL library uses unsupported OS features +1523 GPG_ERR_SQL_AUTH Authorization denied (SQL) +1524 GPG_ERR_SQL_FORMAT (unused SQL code: format) +1525 GPG_ERR_SQL_RANGE SQL bind parameter out of range +1526 GPG_ERR_SQL_NOTADB File opened that is not an SQL database file +1527 GPG_ERR_SQL_NOTICE Notifications from SQL logger +1528 GPG_ERR_SQL_WARNING Warnings from SQL logger + +# 1529 to 1599 are reserved for newer SQLite primary error codes. + +1600 GPG_ERR_SQL_ROW SQL has another row ready +1601 GPG_ERR_SQL_DONE SQL has finished executing + +# 1602 to 1755 are reserved for newer SQLite primary error codes. + +# 1756 to 16380 are free to be used. + +16381 GPG_ERR_MISSING_ERRNO System error w/o errno +16382 GPG_ERR_UNKNOWN_ERRNO Unknown system error +16383 GPG_ERR_EOF End of file + +# 16384 - 32767 are reserved for future extensions. + +# GPG_SYSTEM_ERROR | (141 to 32767) are to be used for system errors. + + GPG_ERR_CODE_DIM Unknown error code diff --git a/comm/third_party/libgpg-error/src/err-sources.h b/comm/third_party/libgpg-error/src/err-sources.h new file mode 100644 index 0000000000..08be48da01 --- /dev/null +++ b/comm/third_party/libgpg-error/src/err-sources.h @@ -0,0 +1,88 @@ +/* Output of mkstrtable.awk. DO NOT EDIT. */ + +/* err-sources.h - List of error sources and their description. + Copyright (C) 2003, 2004 g10 Code GmbH + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with libgpg-error; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + + +/* The purpose of this complex string table is to produce + optimal code with a minimum of relocations. */ + +static const char msgstr[] = + gettext_noop ("Unspecified source") "\0" + gettext_noop ("gcrypt") "\0" + gettext_noop ("GnuPG") "\0" + gettext_noop ("GpgSM") "\0" + gettext_noop ("GPG Agent") "\0" + gettext_noop ("Pinentry") "\0" + gettext_noop ("SCD") "\0" + gettext_noop ("GPGME") "\0" + gettext_noop ("Keybox") "\0" + gettext_noop ("KSBA") "\0" + gettext_noop ("Dirmngr") "\0" + gettext_noop ("GSTI") "\0" + gettext_noop ("GPA") "\0" + gettext_noop ("Kleopatra") "\0" + gettext_noop ("G13") "\0" + gettext_noop ("Assuan") "\0" + gettext_noop ("TPM2d") "\0" + gettext_noop ("TLS") "\0" + gettext_noop ("Any source") "\0" + gettext_noop ("User defined source 1") "\0" + gettext_noop ("User defined source 2") "\0" + gettext_noop ("User defined source 3") "\0" + gettext_noop ("User defined source 4") "\0" + gettext_noop ("Unknown source"); + +static const int msgidx[] = + { + 0, + 19, + 26, + 32, + 38, + 48, + 57, + 61, + 67, + 74, + 79, + 87, + 92, + 96, + 106, + 110, + 117, + 123, + 127, + 138, + 160, + 182, + 204, + 226 + }; + +static GPG_ERR_INLINE int +msgidxof (int code) +{ + return (0 ? 0 + : ((code >= 0) && (code <= 17)) ? (code - 0) + : ((code >= 31) && (code <= 35)) ? (code - 13) + : 36 - 13); +} diff --git a/comm/third_party/libgpg-error/src/err-sources.h.in b/comm/third_party/libgpg-error/src/err-sources.h.in new file mode 100644 index 0000000000..f6e3f1de52 --- /dev/null +++ b/comm/third_party/libgpg-error/src/err-sources.h.in @@ -0,0 +1,61 @@ +# err-sources.h.in - List of error sources and their description input file. +/* err-sources.h - List of error sources and their description. + Copyright (C) 2003, 2004 g10 Code GmbH + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with libgpg-error; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +# Everything up to the first line that starts with a number in the +# first column is copied into the output verbatim. Then, empty lines +# are ignored. Other lines must have an error source number, followed +# by one or more <tab> characters, followed by the error source +# symbol, followed by one or more <tab> characters, followed by the +# error source name. Trailing whitespace is removed. The error +# sources should be sorted. The last line should not have a number, +# but only a <tab>, followed by a description for error sources that +# are not in the list. + +0 GPG_ERR_SOURCE_UNKNOWN Unspecified source +1 GPG_ERR_SOURCE_GCRYPT gcrypt +2 GPG_ERR_SOURCE_GPG GnuPG +3 GPG_ERR_SOURCE_GPGSM GpgSM +4 GPG_ERR_SOURCE_GPGAGENT GPG Agent +5 GPG_ERR_SOURCE_PINENTRY Pinentry +6 GPG_ERR_SOURCE_SCD SCD +7 GPG_ERR_SOURCE_GPGME GPGME +8 GPG_ERR_SOURCE_KEYBOX Keybox +9 GPG_ERR_SOURCE_KSBA KSBA +10 GPG_ERR_SOURCE_DIRMNGR Dirmngr +11 GPG_ERR_SOURCE_GSTI GSTI +12 GPG_ERR_SOURCE_GPA GPA +13 GPG_ERR_SOURCE_KLEO Kleopatra +14 GPG_ERR_SOURCE_G13 G13 +15 GPG_ERR_SOURCE_ASSUAN Assuan +16 GPG_ERR_SOURCE_TPM2D TPM2d +17 GPG_ERR_SOURCE_TLS TLS + +# 18 to 30 are free to be used. + +31 GPG_ERR_SOURCE_ANY Any source +32 GPG_ERR_SOURCE_USER_1 User defined source 1 +33 GPG_ERR_SOURCE_USER_2 User defined source 2 +34 GPG_ERR_SOURCE_USER_3 User defined source 3 +35 GPG_ERR_SOURCE_USER_4 User defined source 4 + +# 36 to 255 are free to be used. + + GPG_ERR_SOURCE_DIM Unknown source diff --git a/comm/third_party/libgpg-error/src/errnos.in b/comm/third_party/libgpg-error/src/errnos.in new file mode 100644 index 0000000000..018fb9ad57 --- /dev/null +++ b/comm/third_party/libgpg-error/src/errnos.in @@ -0,0 +1,172 @@ +# errnos.in - List of system error values input file. +/* errnos.in - List of system error values. + Copyright (C) 2003, 2004 g10 Code GmbH + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with libgpg-error; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +# Everything up to the first line that starts with a number in the +# first column is copied into the output verbatim. Then, empty lines +# are ignored. Other lines must have an error code number, followed +# by one or more <tab> characters, followed by the error name. +# +# IMPORTANT: For now, the numbering must be consecutive. Some of the +# scripts (notably mkerrnos.h) do not deal correctly with a numbering +# that is out of order or has gaps. + + +0 E2BIG +1 EACCES +2 EADDRINUSE +3 EADDRNOTAVAIL +4 EADV +5 EAFNOSUPPORT +6 EAGAIN +7 EALREADY +8 EAUTH +9 EBACKGROUND +10 EBADE +11 EBADF +12 EBADFD +13 EBADMSG +14 EBADR +15 EBADRPC +16 EBADRQC +17 EBADSLT +18 EBFONT +19 EBUSY +20 ECANCELED +21 ECHILD +22 ECHRNG +23 ECOMM +24 ECONNABORTED +25 ECONNREFUSED +26 ECONNRESET +27 ED +28 EDEADLK +29 EDEADLOCK +30 EDESTADDRREQ +31 EDIED +32 EDOM +33 EDOTDOT +34 EDQUOT +35 EEXIST +36 EFAULT +37 EFBIG +38 EFTYPE +39 EGRATUITOUS +40 EGREGIOUS +41 EHOSTDOWN +42 EHOSTUNREACH +43 EIDRM +44 EIEIO +45 EILSEQ +46 EINPROGRESS +47 EINTR +48 EINVAL +49 EIO +50 EISCONN +51 EISDIR +52 EISNAM +53 EL2HLT +54 EL2NSYNC +55 EL3HLT +56 EL3RST +57 ELIBACC +58 ELIBBAD +59 ELIBEXEC +60 ELIBMAX +61 ELIBSCN +62 ELNRNG +63 ELOOP +64 EMEDIUMTYPE +65 EMFILE +66 EMLINK +67 EMSGSIZE +68 EMULTIHOP +69 ENAMETOOLONG +70 ENAVAIL +71 ENEEDAUTH +72 ENETDOWN +73 ENETRESET +74 ENETUNREACH +75 ENFILE +76 ENOANO +77 ENOBUFS +78 ENOCSI +79 ENODATA +80 ENODEV +81 ENOENT +82 ENOEXEC +83 ENOLCK +84 ENOLINK +85 ENOMEDIUM +86 ENOMEM +87 ENOMSG +88 ENONET +89 ENOPKG +90 ENOPROTOOPT +91 ENOSPC +92 ENOSR +93 ENOSTR +94 ENOSYS +95 ENOTBLK +96 ENOTCONN +97 ENOTDIR +98 ENOTEMPTY +99 ENOTNAM +100 ENOTSOCK +101 ENOTSUP +102 ENOTTY +103 ENOTUNIQ +104 ENXIO +105 EOPNOTSUPP +106 EOVERFLOW +107 EPERM +108 EPFNOSUPPORT +109 EPIPE +110 EPROCLIM +111 EPROCUNAVAIL +112 EPROGMISMATCH +113 EPROGUNAVAIL +114 EPROTO +115 EPROTONOSUPPORT +116 EPROTOTYPE +117 ERANGE +118 EREMCHG +119 EREMOTE +120 EREMOTEIO +121 ERESTART +122 EROFS +123 ERPCMISMATCH +124 ESHUTDOWN +125 ESOCKTNOSUPPORT +126 ESPIPE +127 ESRCH +128 ESRMNT +129 ESTALE +130 ESTRPIPE +131 ETIME +132 ETIMEDOUT +133 ETOOMANYREFS +134 ETXTBSY +135 EUCLEAN +136 EUNATCH +137 EUSERS +138 EWOULDBLOCK +139 EXDEV +140 EXFULL diff --git a/comm/third_party/libgpg-error/src/estream-printf.c b/comm/third_party/libgpg-error/src/estream-printf.c new file mode 100644 index 0000000000..fe25657d1b --- /dev/null +++ b/comm/third_party/libgpg-error/src/estream-printf.c @@ -0,0 +1,1904 @@ +/* estream-printf.c - Versatile mostly C-99 compliant printf formatting + * Copyright (C) 2007, 2008, 2009, 2010, 2012, 2014 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 Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libestream is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libestream; if not, see <https://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_THOUSEP + + 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 + thousep 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> +#if defined(HAVE_INTMAX_T) || defined(HAVE_UINTMAX_T) +# ifdef HAVE_STDINT_H +# include <stdint.h> +# endif +#endif +#ifdef HAVE_LANGINFO_THOUSEP +#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 realloc function. */ +#if defined(_ESTREAM_PRINTF_REALLOC) +#define my_printf_realloc(a,b) _ESTREAM_PRINTF_REALLOC((a),(b)) +#else +#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 address 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_THOUSEP + nl_langinfo(THOUSEP); +#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, + gpgrt_string_filter_t sf, void *sfvalue, int string_no) +{ + int rc; + size_t n; + const char *string, *s; + + if (arg->vt != VALTYPE_STRING) + return -1; + if (sf) + string = sf (value.a_string, string_no, sfvalue); + else + string = value.a_string; + + if (!string) + string = "(null)"; + if (arg->precision >= 0) + { + /* Test for nul after N so that we can pass a non-nul terminated + string. */ + for (n=0,s=string; n < arg->precision && *s; 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) + goto leave; + } + + rc = outfnc (outfncarg, string, n); + if (rc) + goto leave; + *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) + goto leave; + } + + rc = 0; + + leave: + if (sf) /* Tell the filter to release resources. */ + sf (value.a_string, -1, sfvalue); + + return rc; +} + + +/* "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. + * STRING_FILTER is an optional function to filter string (%s) args; + * it is called with the original string and the count of already + * processed %s arguments. Its return value will be used instead of + * the original string. 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, + gpgrt_string_filter_t sf, void *sfvalue, + 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; + int string_no = 0; /* Number of processed "%s" args. */ + + 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; + + gpgrt_assert (argidx < argspecs_len); + argidx++; + + /* Apply indirect field width and precision values. */ + if (arg->width == STAR_FIELD_VALUE) + { + gpgrt_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) + { + gpgrt_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 + { + gpgrt_assert (arg->vt == valuetable[arg->arg_pos-1].vt); + value = valuetable[arg->arg_pos-1].value; + } + + switch (arg->conspec) + { + case CONSPEC_UNKNOWN: gpgrt_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: + rc = pr_string (outfnc, outfncarg, arg, value, nbytes, + sf, sfvalue, string_no++); + break; + case CONSPEC_STRERROR: + rc = pr_string (outfnc, outfncarg, arg, value, nbytes, + NULL, NULL, 0); + 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 +_gpgrt_estream_format (estream_printf_out_t outfnc, + void *outfncarg, + gpgrt_string_filter_t sf, void *sfvalue, + 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; + memset (&valuetable[validx].value, 0, + sizeof valuetable[validx].value); + } + } + 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, sf, sfvalue, 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 +_gpgrt_estream_printf (const char *format, ...) +{ + int rc; + va_list arg_ptr; + + va_start (arg_ptr, format); + rc = _gpgrt_estream_format (plain_stdio_out, stderr, NULL, NULL, + format, arg_ptr); + va_end (arg_ptr); + + return rc; +} + +/* A replacement for fprintf. */ +int +_gpgrt_estream_fprintf (FILE *fp, const char *format, ...) +{ + int rc; + va_list arg_ptr; + + va_start (arg_ptr, format); + rc = _gpgrt_estream_format (plain_stdio_out, fp, NULL, NULL, + format, arg_ptr); + va_end (arg_ptr); + + return rc; +} + +/* A replacement for vfprintf. */ +int +_gpgrt_estream_vfprintf (FILE *fp, const char *format, va_list arg_ptr) +{ + return _gpgrt_estream_format (plain_stdio_out, fp, NULL, NULL, + 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 +_gpgrt_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 = _gpgrt_estream_format (fixed_buffer_out, &parm, NULL, NULL, + 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 +_gpgrt_estream_snprintf (char *buf, size_t bufsize, const char *format, ...) +{ + int rc; + va_list arg_ptr; + + va_start (arg_ptr, format); + rc = _gpgrt_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 = 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 formatted. */ + 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 version of vasprintf + -1 will be returned on error and NULL stored at BUFP. On success + the number of bytes printed will be returned. */ +int +_gpgrt_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_realloc (NULL, parm.alloced); + if (!parm.buffer) + { + *bufp = NULL; + return -1; + } + + rc = _gpgrt_estream_format (dynamic_buffer_out, &parm, NULL, NULL, + 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); + if (parm.buffer) + my_printf_realloc (parm.buffer, 0); + *bufp = NULL; + return -1; + } + gpgrt_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 +_gpgrt_estream_asprintf (char **bufp, const char *format, ...) +{ + int rc; + va_list arg_ptr; + + va_start (arg_ptr, format); + rc = _gpgrt_estream_vasprintf (bufp, format, arg_ptr); + va_end (arg_ptr); + + return rc; +} + +/* A variant of asprintf. The function returns the allocated buffer + or NULL on error; ERRNO is set in the error case. The caller + should use es_free to release the buffer. This function actually + belongs into estream-printf but we put it here as a convenience + and because es_free is required anyway. */ +char * +_gpgrt_estream_bsprintf (const char *format, ...) +{ + int rc; + va_list ap; + char *buf; + + va_start (ap, format); + rc = _gpgrt_estream_vasprintf (&buf, format, ap); + va_end (ap); + if (rc < 0) + return NULL; + return buf; +} diff --git a/comm/third_party/libgpg-error/src/estream-printf.h b/comm/third_party/libgpg-error/src/estream-printf.h new file mode 100644 index 0000000000..69c70520f3 --- /dev/null +++ b/comm/third_party/libgpg-error/src/estream-printf.h @@ -0,0 +1,153 @@ +/* estream-printf.h - Versatile mostly C-99 compliant printf formatting. + * 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 Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libestream is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libestream; if not, see <https://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_REALLOC foo_realloc + + 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__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4 ) +# define _ESTREAM_GCC_A_PRINTF( f, a ) \ + __attribute__ ((format (__gnu_printf__,f,a))) +# elif __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 _gpgrt_estream_format (estream_printf_out_t outfnc, void *outfncarg, + char *(*string_filter)(const char *s,int n,void*st), + void *string_filter_state, + const char *format, va_list vaargs) + _ESTREAM_GCC_A_PRINTF(5,0); +int _gpgrt_estream_printf (const char *format, ...) + _ESTREAM_GCC_A_PRINTF(1,2); +int _gpgrt_estream_fprintf (FILE *fp, const char *format, ... ) + _ESTREAM_GCC_A_PRINTF(2,3); +int _gpgrt_estream_vfprintf (FILE *fp, const char *format, va_list arg_ptr) + _ESTREAM_GCC_A_PRINTF(2,0); +int _gpgrt_estream_snprintf (char *buf, size_t bufsize, const char *format, ...) + _ESTREAM_GCC_A_PRINTF(3,4); +int _gpgrt_estream_vsnprintf (char *buf,size_t bufsize, + const char *format, va_list arg_ptr) + _ESTREAM_GCC_A_PRINTF(3,0); +int _gpgrt_estream_asprintf (char **bufp, const char *format, ...) + _ESTREAM_GCC_A_PRINTF(2,3); +int _gpgrt_estream_vasprintf (char **bufp, const char *format, va_list arg_ptr) + _ESTREAM_GCC_A_PRINTF(2,0); +char *_gpgrt_estream_bsprintf (const char *format, ...) + _ESTREAM_GCC_A_PRINTF(1,2); + + +#ifdef __cplusplus +} +#endif +#endif /*ESTREAM_PRINTF_H*/ diff --git a/comm/third_party/libgpg-error/src/estream.c b/comm/third_party/libgpg-error/src/estream.c new file mode 100644 index 0000000000..f75e05210e --- /dev/null +++ b/comm/third_party/libgpg-error/src/estream.c @@ -0,0 +1,5414 @@ +/* estream.c - Extended Stream I/O Library + * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011, + * 2014, 2015, 2016, 2017 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 Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libestream is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libestream; if not, see <https://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. + */ + +#ifdef USE_ESTREAM_SUPPORT_H +# include <estream-support.h> +#endif + +#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 + +#ifdef HAVE_SYS_SELECT_H +# include <sys/select.h> +#endif +#ifdef HAVE_SYS_TIME_H +# include <sys/time.h> +#endif +#include <sys/types.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <stdarg.h> +#include <fcntl.h> +#include <errno.h> +#include <stddef.h> +#ifdef HAVE_W32_SYSTEM +# ifdef HAVE_WINSOCK2_H +# include <winsock2.h> +# endif +# include <windows.h> +#else +# ifdef HAVE_POLL_H +# include <poll.h> +# endif +#endif + +/* Enable tracing. The value is the module name to be printed. */ +/*#define ENABLE_TRACING "estream"*/ + +#include "gpgrt-int.h" +#include "estream-printf.h" +#include "thread.h" +#include "lock.h" + + +#ifndef O_BINARY +# define O_BINARY 0 +#endif +#ifndef HAVE_DOSISH_SYSTEM +# ifdef HAVE_W32_SYSTEM +# define HAVE_DOSISH_SYSTEM 1 +# endif +#endif + + +#ifdef HAVE_W32_SYSTEM +# ifndef S_IRGRP +# define S_IRGRP S_IRUSR +# endif +# ifndef S_IROTH +# define S_IROTH S_IRUSR +# endif +# ifndef S_IWGRP +# define S_IWGRP S_IWUSR +# endif +# ifndef S_IWOTH +# define S_IWOTH S_IWUSR +# endif +# ifndef S_IXGRP +# define S_IXGRP S_IXUSR +# endif +# ifndef S_IXOTH +# define S_IXOTH S_IXUSR +# endif +#endif + +#if !defined (EWOULDBLOCK) && defined (HAVE_W32_SYSTEM) +/* Compatibility with errno.h from mingw-2.0 */ +# define EWOULDBLOCK 140 +#endif + +#ifndef EAGAIN +# define EAGAIN EWOULDBLOCK +#endif + + +#ifdef HAVE_W32CE_SYSTEM +# define _set_errno(a) gpg_err_set_errno ((a)) +/* Setmode is missing in cegcc but available since CE 5.0. */ +int _setmode (int handle, int mode); +# define setmode(a,b) _setmode ((a),(b)) +#else +# define _set_errno(a) do { errno = (a); } while (0) +#endif + +#define IS_INVALID_FD(a) ((a) == -1) + +/* Calculate array dimension. */ +#ifndef DIM +#define DIM(array) (sizeof (array) / sizeof (*array)) +#endif + +/* A helper macro used to convert to a hex string. */ +#define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A')) + + +/* Generally used types. */ + +typedef void *(*func_realloc_t) (void *mem, size_t size); +typedef void (*func_free_t) (void *mem); + + + + +/* + * A linked list to hold active stream objects. + * Protected by ESTREAM_LIST_LOCK. + */ +struct estream_list_s +{ + struct estream_list_s *next; + estream_t stream; /* Entry is not used if NULL. */ +}; +typedef struct estream_list_s *estream_list_t; +static estream_list_t estream_list; + +/* + * File descriptors registered for use as the standard file handles. + * Protected by ESTREAM_LIST_LOCK. + */ +static int custom_std_fds[3]; +static unsigned char custom_std_fds_valid[3]; + +/* + * A lock object to protect ESTREAM LIST, CUSTOM_STD_FDS and + * CUSTOM_STD_FDS_VALID. Used by lock_list() and unlock_list(). + */ +GPGRT_LOCK_DEFINE (estream_list_lock); + + +/* + * Error code replacements. + */ +#ifndef EOPNOTSUPP +# define EOPNOTSUPP ENOSYS +#endif + + +/* Local prototypes. */ +static void fname_set_internal (estream_t stream, const char *fname, int quote); + + + + +/* + * Memory allocation wrappers used in this file. + */ +static void * +mem_alloc (size_t n) +{ + return _gpgrt_malloc (n); +} + +static void * +mem_realloc (void *p, size_t n) +{ + return _gpgrt_realloc (p, n); +} + +static void +mem_free (void *p) +{ + if (p) + _gpgrt_free (p); +} + + +/* + * A Windows helper function to map a W32 API error code to a standard + * system error code. That actually belong into sysutils but to allow + * standalone use of estream we keep it here. + */ +#ifdef HAVE_W32_SYSTEM +static int +map_w32_to_errno (DWORD w32_err) +{ + switch (w32_err) + { + case 0: + return 0; + + case ERROR_FILE_NOT_FOUND: + return ENOENT; + + case ERROR_PATH_NOT_FOUND: + return ENOENT; + + case ERROR_ACCESS_DENIED: + return EPERM; /* ReactOS uses EACCES ("Permission denied") and + * is likely right because they used an + * undocumented function to associate the error + * codes. However we have always used EPERM + * ("Operation not permitted", e.g. function is + * required to be called by root) and we better + * stick to that to avoid surprising bugs. */ + + case ERROR_INVALID_HANDLE: + return EBADF; + + case ERROR_INVALID_BLOCK: + return ENOMEM; + + case ERROR_NOT_ENOUGH_MEMORY: + return ENOMEM; + + case ERROR_NO_DATA: + return EPIPE; + + case ERROR_ALREADY_EXISTS: + return EEXIST; + + /* This mapping has been taken from reactOS. */ + case ERROR_TOO_MANY_OPEN_FILES: return EMFILE; + case ERROR_ARENA_TRASHED: return ENOMEM; + case ERROR_BAD_ENVIRONMENT: return E2BIG; + case ERROR_BAD_FORMAT: return ENOEXEC; + case ERROR_INVALID_DRIVE: return ENOENT; + case ERROR_CURRENT_DIRECTORY: return EACCES; + case ERROR_NOT_SAME_DEVICE: return EXDEV; + case ERROR_NO_MORE_FILES: return ENOENT; + case ERROR_WRITE_PROTECT: return EACCES; + case ERROR_BAD_UNIT: return EACCES; + case ERROR_NOT_READY: return EACCES; + case ERROR_BAD_COMMAND: return EACCES; + case ERROR_CRC: return EACCES; + case ERROR_BAD_LENGTH: return EACCES; + case ERROR_SEEK: return EACCES; + case ERROR_NOT_DOS_DISK: return EACCES; + case ERROR_SECTOR_NOT_FOUND: return EACCES; + case ERROR_OUT_OF_PAPER: return EACCES; + case ERROR_WRITE_FAULT: return EACCES; + case ERROR_READ_FAULT: return EACCES; + case ERROR_GEN_FAILURE: return EACCES; + case ERROR_SHARING_VIOLATION: return EACCES; + case ERROR_LOCK_VIOLATION: return EACCES; + case ERROR_WRONG_DISK: return EACCES; + case ERROR_SHARING_BUFFER_EXCEEDED: return EACCES; + case ERROR_BAD_NETPATH: return ENOENT; + case ERROR_NETWORK_ACCESS_DENIED: return EACCES; + case ERROR_BAD_NET_NAME: return ENOENT; + case ERROR_FILE_EXISTS: return EEXIST; + case ERROR_CANNOT_MAKE: return EACCES; + case ERROR_FAIL_I24: return EACCES; + case ERROR_NO_PROC_SLOTS: return EAGAIN; + case ERROR_DRIVE_LOCKED: return EACCES; + case ERROR_BROKEN_PIPE: return EPIPE; + case ERROR_DISK_FULL: return ENOSPC; + case ERROR_INVALID_TARGET_HANDLE: return EBADF; + case ERROR_WAIT_NO_CHILDREN: return ECHILD; + case ERROR_CHILD_NOT_COMPLETE: return ECHILD; + case ERROR_DIRECT_ACCESS_HANDLE: return EBADF; + case ERROR_SEEK_ON_DEVICE: return EACCES; + case ERROR_DIR_NOT_EMPTY: return ENOTEMPTY; + case ERROR_NOT_LOCKED: return EACCES; + case ERROR_BAD_PATHNAME: return ENOENT; + case ERROR_MAX_THRDS_REACHED: return EAGAIN; + case ERROR_LOCK_FAILED: return EACCES; + case ERROR_INVALID_STARTING_CODESEG: return ENOEXEC; + case ERROR_INVALID_STACKSEG: return ENOEXEC; + case ERROR_INVALID_MODULETYPE: return ENOEXEC; + case ERROR_INVALID_EXE_SIGNATURE: return ENOEXEC; + case ERROR_EXE_MARKED_INVALID: return ENOEXEC; + case ERROR_BAD_EXE_FORMAT: return ENOEXEC; + case ERROR_ITERATED_DATA_EXCEEDS_64k: return ENOEXEC; + case ERROR_INVALID_MINALLOCSIZE: return ENOEXEC; + case ERROR_DYNLINK_FROM_INVALID_RING: return ENOEXEC; + case ERROR_IOPL_NOT_ENABLED: return ENOEXEC; + case ERROR_INVALID_SEGDPL: return ENOEXEC; + case ERROR_AUTODATASEG_EXCEEDS_64k: return ENOEXEC; + case ERROR_RING2SEG_MUST_BE_MOVABLE: return ENOEXEC; + case ERROR_RELOC_CHAIN_XEEDS_SEGLIM: return ENOEXEC; + case ERROR_INFLOOP_IN_RELOC_CHAIN: return ENOEXEC; + case ERROR_FILENAME_EXCED_RANGE: return ENOENT; + case ERROR_NESTING_NOT_ALLOWED: return EAGAIN; + case ERROR_NOT_ENOUGH_QUOTA: return ENOMEM; + + default: + return EIO; + } +} + +/* Wrapper to be used by other modules to set ERRNO from the Windows + * error. EC may be -1 to get the last error. */ +void +_gpgrt_w32_set_errno (int ec) +{ + if (ec == -1) + ec = GetLastError (); + _set_errno (map_w32_to_errno (ec)); +} + + +#endif /*HAVE_W32_SYSTEM*/ + +/* + * Replacement for a missing memrchr. + */ +#ifndef HAVE_MEMRCHR +static void * +memrchr (const void *buffer, int c, size_t n) +{ + const unsigned char *p = buffer; + + for (p += n; n ; n--) + if (*--p == c) + return (void *)p; + return NULL; +} +#endif /*HAVE_MEMRCHR*/ + + + +/* + * Wrappers to lock a stream or the list of streams. + */ +#if 0 +# define dbg_lock_0(f) fprintf (stderr, "estream: " f); +# define dbg_lock_1(f, a) fprintf (stderr, "estream: " f, (a)); +# define dbg_lock_2(f, a, b) fprintf (stderr, "estream: " f, (a), (b)); +#else +# define dbg_lock_0(f) +# define dbg_lock_1(f, a) +# define dbg_lock_2(f, a, b) +#endif + +static int +init_stream_lock (estream_t _GPGRT__RESTRICT stream) +{ + int rc; + + if (!stream->intern->samethread) + { + dbg_lock_1 ("enter init_stream_lock for %p\n", stream); + memset (&stream->intern->lock, 0 , sizeof stream->intern->lock); + rc = _gpgrt_lock_init (&stream->intern->lock); + dbg_lock_2 ("leave init_stream_lock for %p: rc=%d\n", stream, rc); + } + else + rc = 0; + return rc; +} + + +static void +destroy_stream_lock (estream_t _GPGRT__RESTRICT stream) +{ + if (!stream->intern->samethread) + { + dbg_lock_1 ("enter destroy_stream_lock for %p\n", stream); + _gpgrt_lock_destroy (&stream->intern->lock); + dbg_lock_1 ("leave destroy_stream_lock for %p\n", stream); + } +} + + +static void +lock_stream (estream_t _GPGRT__RESTRICT stream) +{ + if (!stream->intern->samethread) + { + dbg_lock_1 ("enter lock_stream for %p\n", stream); + _gpgrt_lock_lock (&stream->intern->lock); + dbg_lock_1 ("leave lock_stream for %p\n", stream); + } +} + + +static int +trylock_stream (estream_t _GPGRT__RESTRICT stream) +{ + int rc; + + if (!stream->intern->samethread) + { + dbg_lock_1 ("enter trylock_stream for %p\n", stream); + rc = _gpgrt_lock_trylock (&stream->intern->lock)? 0 : -1; + dbg_lock_2 ("leave trylock_stream for %p: rc=%d\n", stream, rc); + } + else + rc = 0; + return rc; +} + + +static void +unlock_stream (estream_t _GPGRT__RESTRICT stream) +{ + if (!stream->intern->samethread) + { + dbg_lock_1 ("enter unlock_stream for %p\n", stream); + _gpgrt_lock_unlock (&stream->intern->lock); + dbg_lock_1 ("leave unlock_stream for %p\n", stream); + } +} + + +static void +lock_list (void) +{ + dbg_lock_0 ("enter lock_list\n"); + _gpgrt_lock_lock (&estream_list_lock); + dbg_lock_0 ("leave lock_list\n"); +} + + +static void +unlock_list (void) +{ + dbg_lock_0 ("enter unlock_list\n"); + _gpgrt_lock_unlock (&estream_list_lock); + dbg_lock_0 ("leave unlock_list\n"); +} + + +#undef dbg_lock_0 +#undef dbg_lock_1 +#undef dbg_lock_2 + + + +/* + * Manipulation of the list of stream. + */ + +/* + * Add STREAM to the list of registered stream objects. If + * WITH_LOCKED_LIST is true it is assumed that the list of streams is + * already locked. The implementation is straightforward: We first + * look for an unused entry in the list and use that; if none is + * available we put a new item at the head. We drawback of the + * strategy never to shorten the list is that a one time allocation of + * many streams will lead to scanning unused entries later. If that + * turns out to be a problem, we may either free some items from the + * list or append new entries at the end; or use a table. Returns 0 + * on success; on error or non-zero is returned and ERRNO set. + */ +static int +do_list_add (estream_t stream, int with_locked_list) +{ + estream_list_t item; + + if (!with_locked_list) + lock_list (); + + for (item = estream_list; item && item->stream; item = item->next) + ; + if (!item) + { + item = mem_alloc (sizeof *item); + if (item) + { + item->next = estream_list; + estream_list = item; + } + } + if (item) + item->stream = stream; + + if (!with_locked_list) + unlock_list (); + + return item? 0 : -1; +} + +/* + * Remove STREAM from the list of registered stream objects. + */ +static void +do_list_remove (estream_t stream, int with_locked_list) +{ + estream_list_t item, item_prev = NULL; + + if (!with_locked_list) + lock_list (); + + for (item = estream_list; item; item = item->next) + if (item->stream == stream) + break; + else + item_prev = item; + + if (item) + { + if (item_prev) + item_prev->next = item->next; + else + estream_list = item->next; + mem_free (item); + } + + if (!with_locked_list) + unlock_list (); +} + + + +/* + * The atexit handler for the entire gpgrt. + */ +static void +do_deinit (void) +{ + /* Flush all streams. */ + _gpgrt_fflush (NULL); + + /* We should release the estream_list. However there is one + problem: That list is also used to search for the standard + estream file descriptors. If we would remove the entire list, + any use of es_foo in another atexit function may re-create the + list and the streams with possible undesirable effects. Given + that we don't close the stream either, it should not matter that + we keep the list and let the OS clean it up at process end. */ + + /* Reset the syscall clamp. */ + _gpgrt_set_syscall_clamp (NULL, NULL); +} + + +/* + * Initialization of the estream module. + */ +int +_gpgrt_estream_init (void) +{ + static int initialized; + + if (!initialized) + { + initialized = 1; + atexit (do_deinit); + } + return 0; +} + + +/* + * Implementation of memory based I/O. + */ + +/* Cookie for memory objects. */ +typedef struct estream_cookie_mem +{ + unsigned int modeflags; /* Open flags. */ + unsigned char *memory; /* Allocated data buffer. */ + size_t memory_size; /* Allocated size of MEMORY. */ + size_t memory_limit; /* Caller supplied maximum allowed + allocation size or 0 for no limit. */ + size_t offset; /* Current offset in MEMORY. */ + size_t data_len; /* Used length of data in MEMORY. */ + size_t block_size; /* Block size. */ + struct { + unsigned int grow: 1; /* MEMORY is allowed to grow. */ + } flags; + func_realloc_t func_realloc; + func_free_t func_free; +} *estream_cookie_mem_t; + + +/* + * Create function for memory objects. DATA is either NULL or a user + * supplied buffer with the initial conetnt of the memory buffer. If + * DATA is NULL, DATA_N and DATA_LEN need to be 0 as well. If DATA is + * not NULL, DATA_N gives the allocated size of DATA and DATA_LEN the + * used length in DATA. If this function succeeds DATA is now owned + * by this function. If GROW is false FUNC_REALLOC is not + * required. + */ +static int +func_mem_create (void *_GPGRT__RESTRICT *_GPGRT__RESTRICT cookie, + unsigned char *_GPGRT__RESTRICT data, size_t data_n, + size_t data_len, + size_t block_size, unsigned int grow, + func_realloc_t func_realloc, func_free_t func_free, + unsigned int modeflags, + size_t memory_limit) +{ + estream_cookie_mem_t mem_cookie; + int err; + + if (!data && (data_n || data_len)) + { + _set_errno (EINVAL); + return -1; + } + if (grow && func_free && !func_realloc) + { + _set_errno (EINVAL); + return -1; + } + + /* Round a memory limit up to the next block length. */ + if (memory_limit && block_size) + { + memory_limit += block_size - 1; + memory_limit /= block_size; + memory_limit *= block_size; + } + + mem_cookie = mem_alloc (sizeof (*mem_cookie)); + if (!mem_cookie) + err = -1; + else + { + mem_cookie->modeflags = modeflags; + mem_cookie->memory = data; + mem_cookie->memory_size = data_n; + mem_cookie->memory_limit = memory_limit; + mem_cookie->offset = 0; + mem_cookie->data_len = data_len; + mem_cookie->block_size = block_size; + mem_cookie->flags.grow = !!grow; + mem_cookie->func_realloc + = grow? (func_realloc ? func_realloc : mem_realloc) : NULL; + mem_cookie->func_free = func_free ? func_free : mem_free; + *cookie = mem_cookie; + err = 0; + } + + return err; +} + + +/* + * Read function for memory objects. + */ +static gpgrt_ssize_t +func_mem_read (void *cookie, void *buffer, size_t size) +{ + estream_cookie_mem_t mem_cookie = cookie; + gpgrt_ssize_t ret; + + if (!size) /* Just the pending data check. */ + return (mem_cookie->data_len - mem_cookie->offset)? 0 : -1; + + if (size > mem_cookie->data_len - mem_cookie->offset) + size = mem_cookie->data_len - mem_cookie->offset; + + if (size) + { + memcpy (buffer, mem_cookie->memory + mem_cookie->offset, size); + mem_cookie->offset += size; + } + + ret = size; + return ret; +} + + +/* + * Write function for memory objects. + */ +static gpgrt_ssize_t +func_mem_write (void *cookie, const void *buffer, size_t size) +{ + estream_cookie_mem_t mem_cookie = cookie; + gpgrt_ssize_t ret; + size_t nleft; + + if (!size) + return 0; /* A flush is a NOP for memory objects. */ + + if (mem_cookie->modeflags & O_APPEND) + { + /* Append to data. */ + mem_cookie->offset = mem_cookie->data_len; + } + + gpgrt_assert (mem_cookie->memory_size >= mem_cookie->offset); + nleft = mem_cookie->memory_size - mem_cookie->offset; + + /* If we are not allowed to grow the buffer, limit the size to the + left space. */ + if (!mem_cookie->flags.grow && size > nleft) + size = nleft; + + /* Enlarge the memory buffer if needed. */ + if (size > nleft) + { + unsigned char *newbuf; + size_t newsize; + + if (!mem_cookie->memory_size) + newsize = size; /* Not yet allocated. */ + else + newsize = mem_cookie->memory_size + (size - nleft); + if (newsize < mem_cookie->offset) + { + _set_errno (EINVAL); + return -1; + } + + /* Round up to the next block length. BLOCK_SIZE should always + be set; we check anyway. */ + if (mem_cookie->block_size) + { + newsize += mem_cookie->block_size - 1; + if (newsize < mem_cookie->offset) + { + _set_errno (EINVAL); + return -1; + } + newsize /= mem_cookie->block_size; + newsize *= mem_cookie->block_size; + } + + /* Check for a total limit. */ + if (mem_cookie->memory_limit && newsize > mem_cookie->memory_limit) + { + _set_errno (ENOSPC); + return -1; + } + + gpgrt_assert (mem_cookie->func_realloc); + newbuf = mem_cookie->func_realloc (mem_cookie->memory, newsize); + if (!newbuf) + return -1; + + mem_cookie->memory = newbuf; + mem_cookie->memory_size = newsize; + + gpgrt_assert (mem_cookie->memory_size >= mem_cookie->offset); + nleft = mem_cookie->memory_size - mem_cookie->offset; + + gpgrt_assert (size <= nleft); + } + + memcpy (mem_cookie->memory + mem_cookie->offset, buffer, size); + if (mem_cookie->offset + size > mem_cookie->data_len) + mem_cookie->data_len = mem_cookie->offset + size; + mem_cookie->offset += size; + + ret = size; + return ret; +} + + +/* + * Seek function for memory objects. + */ +static int +func_mem_seek (void *cookie, gpgrt_off_t *offset, int whence) +{ + estream_cookie_mem_t mem_cookie = cookie; + gpgrt_off_t pos_new; + + switch (whence) + { + case SEEK_SET: + pos_new = *offset; + break; + + case SEEK_CUR: + pos_new = mem_cookie->offset += *offset; + break; + + case SEEK_END: + pos_new = mem_cookie->data_len += *offset; + break; + + default: + _set_errno (EINVAL); + return -1; + } + + if (pos_new > mem_cookie->memory_size) + { + size_t newsize; + void *newbuf; + + if (!mem_cookie->flags.grow) + { + _set_errno (ENOSPC); + return -1; + } + + newsize = pos_new + mem_cookie->block_size - 1; + if (newsize < pos_new) + { + _set_errno (EINVAL); + return -1; + } + newsize /= mem_cookie->block_size; + newsize *= mem_cookie->block_size; + + if (mem_cookie->memory_limit && newsize > mem_cookie->memory_limit) + { + _set_errno (ENOSPC); + return -1; + } + + gpgrt_assert (mem_cookie->func_realloc); + newbuf = mem_cookie->func_realloc (mem_cookie->memory, newsize); + if (!newbuf) + return -1; + + mem_cookie->memory = newbuf; + mem_cookie->memory_size = newsize; + } + + if (pos_new > mem_cookie->data_len) + { + /* Fill spare space with zeroes. */ + memset (mem_cookie->memory + mem_cookie->data_len, + 0, pos_new - mem_cookie->data_len); + mem_cookie->data_len = pos_new; + } + + mem_cookie->offset = pos_new; + *offset = pos_new; + + return 0; +} + + +/* + * The IOCTL function for memory objects. + */ +static int +func_mem_ioctl (void *cookie, int cmd, void *ptr, size_t *len) +{ + estream_cookie_mem_t mem_cookie = cookie; + int ret; + + if (cmd == COOKIE_IOCTL_SNATCH_BUFFER) + { + /* Return the internal buffer of the stream to the caller and + invalidate it for the stream. */ + *(void**)ptr = mem_cookie->memory; + *len = mem_cookie->data_len; + mem_cookie->memory = NULL; + mem_cookie->memory_size = 0; + mem_cookie->offset = 0; + ret = 0; + } + else if (cmd == COOKIE_IOCTL_TRUNCATE) + { + gpgrt_off_t length = *(gpgrt_off_t *)ptr; + + ret = func_mem_seek (cookie, &length, SEEK_SET); + if (ret != -1) + mem_cookie->data_len = mem_cookie->offset; + } + else + { + _set_errno (EINVAL); + ret = -1; + } + + return ret; +} + + +/* + * The destroy function for memory objects. + */ +static int +func_mem_destroy (void *cookie) +{ + estream_cookie_mem_t mem_cookie = cookie; + + if (cookie) + { + mem_cookie->func_free (mem_cookie->memory); + mem_free (mem_cookie); + } + return 0; +} + +/* + * Access object for the memory functions. + */ +static struct cookie_io_functions_s estream_functions_mem = + { + { + func_mem_read, + func_mem_write, + func_mem_seek, + func_mem_destroy, + }, + func_mem_ioctl, + }; + + + +/* + * Implementation of file descriptor based I/O. + */ + +/* Cookie for fd objects. */ +typedef struct estream_cookie_fd +{ + int fd; /* The file descriptor we are using for actual output. */ + int no_close; /* If set we won't close the file descriptor. */ + int nonblock; /* Non-blocking mode is enabled. */ +} *estream_cookie_fd_t; + + +/* + * Create function for objects indentified by a libc file descriptor. + */ +static int +func_fd_create (void **cookie, int fd, unsigned int modeflags, int no_close) +{ + estream_cookie_fd_t fd_cookie; + int err; + + trace (("enter: fd=%d mf=%x nc=%d", fd, modeflags, no_close)); + + fd_cookie = mem_alloc (sizeof (*fd_cookie)); + if (! fd_cookie) + err = -1; + else + { +#ifdef HAVE_DOSISH_SYSTEM + /* Make sure it is in binary mode if requested. */ + if ( (modeflags & O_BINARY) ) + setmode (fd, O_BINARY); +#endif + fd_cookie->fd = fd; + fd_cookie->no_close = no_close; + fd_cookie->nonblock = !!(modeflags & O_NONBLOCK); + *cookie = fd_cookie; + err = 0; + } + + trace_errno (err, ("leave: cookie=%p err=%d", *cookie, err)); + return err; +} + + +/* + * Read function for fd objects. + */ +static gpgrt_ssize_t +func_fd_read (void *cookie, void *buffer, size_t size) + +{ + estream_cookie_fd_t file_cookie = cookie; + gpgrt_ssize_t bytes_read; + + trace (("enter: cookie=%p buffer=%p size=%d", cookie, buffer, (int)size)); + + if (!size) + bytes_read = -1; /* We don't know whether anything is pending. */ + else if (IS_INVALID_FD (file_cookie->fd)) + { + _gpgrt_yield (); + bytes_read = 0; + } + else + { + _gpgrt_pre_syscall (); + do + { + bytes_read = read (file_cookie->fd, buffer, size); + } + while (bytes_read == -1 && errno == EINTR); + _gpgrt_post_syscall (); + } + + trace_errno (bytes_read == -1, ("leave: bytes_read=%d", (int)bytes_read)); + return bytes_read; +} + + +/* + * Write function for fd objects. + */ +static gpgrt_ssize_t +func_fd_write (void *cookie, const void *buffer, size_t size) +{ + estream_cookie_fd_t file_cookie = cookie; + gpgrt_ssize_t bytes_written; + + trace (("enter: cookie=%p buffer=%p size=%d", cookie, buffer, (int)size)); + + if (IS_INVALID_FD (file_cookie->fd)) + { + _gpgrt_yield (); + bytes_written = size; /* Yeah: Success writing to the bit bucket. */ + } + else if (buffer) + { + _gpgrt_pre_syscall (); + do + { + bytes_written = write (file_cookie->fd, buffer, size); + } + while (bytes_written == -1 && errno == EINTR); + _gpgrt_post_syscall (); + } + else + bytes_written = size; /* Note that for a flush SIZE should be 0. */ + + trace_errno (bytes_written == -1, + ("leave: bytes_written=%d", (int)bytes_written)); + return bytes_written; +} + + +/* + * Seek function for fd objects. + */ +static int +func_fd_seek (void *cookie, gpgrt_off_t *offset, int whence) +{ + estream_cookie_fd_t file_cookie = cookie; + gpgrt_off_t offset_new; + int err; + + if (IS_INVALID_FD (file_cookie->fd)) + { + _set_errno (ESPIPE); + err = -1; + } + else + { + _gpgrt_pre_syscall (); + offset_new = lseek (file_cookie->fd, *offset, whence); + _gpgrt_post_syscall (); + if (offset_new == -1) + err = -1; + else + { + *offset = offset_new; + err = 0; + } + } + + return err; +} + + +/* + * The IOCTL function for fd objects. + */ +static int +func_fd_ioctl (void *cookie, int cmd, void *ptr, size_t *len) +{ + estream_cookie_fd_t fd_cookie = cookie; + int ret; + + if (cmd == COOKIE_IOCTL_NONBLOCK && !len) + { + fd_cookie->nonblock = !!ptr; + if (IS_INVALID_FD (fd_cookie->fd)) + { + _set_errno (EINVAL); + ret = -1; + } + else + { +#ifdef _WIN32 + _set_errno (EOPNOTSUPP); /* FIXME: Implement for Windows. */ + ret = -1; +#else + _set_errno (0); + ret = fcntl (fd_cookie->fd, F_GETFL, 0); + if (ret == -1 && errno) + ; + else if (fd_cookie->nonblock) + ret = fcntl (fd_cookie->fd, F_SETFL, (ret | O_NONBLOCK)); + else + ret = fcntl (fd_cookie->fd, F_SETFL, (ret & ~O_NONBLOCK)); +#endif + } + } + else + { + _set_errno (EINVAL); + ret = -1; + } + + return ret; +} + +/* + * The destroy function for fd objects. + */ +static int +func_fd_destroy (void *cookie) +{ + estream_cookie_fd_t fd_cookie = cookie; + int err; + + trace (("enter: cookie=%p", cookie)); + + if (fd_cookie) + { + if (IS_INVALID_FD (fd_cookie->fd)) + err = 0; + else + err = fd_cookie->no_close? 0 : close (fd_cookie->fd); + mem_free (fd_cookie); + } + else + err = 0; + + trace_errno (err,("leave: err=%d", err)); + return err; +} + + +/* + * Access object for the fd functions. + */ +static struct cookie_io_functions_s estream_functions_fd = + { + { + func_fd_read, + func_fd_write, + func_fd_seek, + func_fd_destroy, + }, + func_fd_ioctl, + }; + + + + +/* + * Implementation of W32 handle based I/O. + */ +#ifdef HAVE_W32_SYSTEM + +/* Cookie for fd objects. */ +typedef struct estream_cookie_w32 +{ + HANDLE hd; /* The handle we are using for actual output. */ + int no_close; /* If set we won't close the handle. */ + int no_syscall_clamp; /* Do not use the syscall clamp. */ +} *estream_cookie_w32_t; + + +/* + * Create function for w32 handle objects. + */ +static int +func_w32_create (void **cookie, HANDLE hd, + unsigned int modeflags, int no_close, int no_syscall_clamp) +{ + estream_cookie_w32_t w32_cookie; + int err; + + trace (("enter: hd=%p mf=%x nc=%d nsc=%d", + hd, modeflags, no_close, no_syscall_clamp)); + w32_cookie = mem_alloc (sizeof (*w32_cookie)); + if (!w32_cookie) + err = -1; + else + { + /* CR/LF translations are not supported when using the bare W32 + API. If that is really required we need to implemented that + in the upper layer. */ + (void)modeflags; + + w32_cookie->hd = hd; + w32_cookie->no_close = no_close; + w32_cookie->no_syscall_clamp = no_syscall_clamp; + *cookie = w32_cookie; + err = 0; + } + + trace_errno (err, ("leave: cookie=%p err=%d", *cookie, err)); + return err; +} + +/* + * Read function for W32 handle objects. + * + * Note that this function may also be used by the reader thread of + * w32-stream. In that case the NO_SYSCALL_CLAMP is set. + */ +static gpgrt_ssize_t +func_w32_read (void *cookie, void *buffer, size_t size) +{ + estream_cookie_w32_t w32_cookie = cookie; + gpgrt_ssize_t bytes_read; + + trace (("enter: cookie=%p buffer=%p size=%d", cookie, buffer, (int)size)); + + if (!size) + bytes_read = -1; /* We don't know whether anything is pending. */ + else if (w32_cookie->hd == INVALID_HANDLE_VALUE) + { + _gpgrt_yield (); + bytes_read = 0; + } + else + { + if (!w32_cookie->no_syscall_clamp) + _gpgrt_pre_syscall (); + do + { + DWORD nread, ec; + + trace (("cookie=%p calling ReadFile", cookie)); + if (!ReadFile (w32_cookie->hd, buffer, size, &nread, NULL)) + { + ec = GetLastError (); + trace (("cookie=%p ReadFile failed: ec=%ld", cookie,ec)); + if (ec == ERROR_BROKEN_PIPE) + bytes_read = 0; /* Like our pth_read we handle this as EOF. */ + else + { + _set_errno (map_w32_to_errno (ec)); + bytes_read = -1; + } + } + else + bytes_read = (int)nread; + } + while (bytes_read == -1 && errno == EINTR); + if (!w32_cookie->no_syscall_clamp) + _gpgrt_post_syscall (); + } + + trace_errno (bytes_read==-1,("leave: bytes_read=%d", (int)bytes_read)); + return bytes_read; +} + + +/* + * Write function for W32 handle objects. + * + * Note that this function may also be used by the writer thread of + * w32-stream. In that case the NO_SYSCALL_CLAMP is set. + */ +static gpgrt_ssize_t +func_w32_write (void *cookie, const void *buffer, size_t size) +{ + estream_cookie_w32_t w32_cookie = cookie; + gpgrt_ssize_t bytes_written; + + trace (("enter: cookie=%p buffer=%p size=%d", cookie, buffer, (int)size)); + + if (w32_cookie->hd == INVALID_HANDLE_VALUE) + { + _gpgrt_yield (); + bytes_written = size; /* Yeah: Success writing to the bit bucket. */ + } + else if (buffer) + { + if (!w32_cookie->no_syscall_clamp) + _gpgrt_pre_syscall (); + do + { + DWORD nwritten; + + trace (("cookie=%p calling WriteFile", cookie)); + if (!WriteFile (w32_cookie->hd, buffer, size, &nwritten, NULL)) + { + DWORD ec = GetLastError (); + trace (("cookie=%p WriteFile failed: ec=%ld", cookie, ec)); + _set_errno (map_w32_to_errno (ec)); + bytes_written = -1; + } + else + bytes_written = (int)nwritten; + } + while (bytes_written == -1 && errno == EINTR); + if (!w32_cookie->no_syscall_clamp) + _gpgrt_post_syscall (); + } + else + bytes_written = size; /* Note that for a flush SIZE should be 0. */ + + trace_errno (bytes_written==-1, + ("leave: bytes_written=%d", (int)bytes_written)); + return bytes_written; +} + + +/* + * Seek function for W32 handle objects. + */ +static int +func_w32_seek (void *cookie, gpgrt_off_t *offset, int whence) +{ + estream_cookie_w32_t w32_cookie = cookie; + DWORD method; + LARGE_INTEGER distance, newoff; + + if (w32_cookie->hd == INVALID_HANDLE_VALUE) + { + _set_errno (ESPIPE); + return -1; + } + + if (whence == SEEK_SET) + { + method = FILE_BEGIN; + distance.QuadPart = (unsigned long long)(*offset); + } + else if (whence == SEEK_CUR) + { + method = FILE_CURRENT; + distance.QuadPart = (long long)(*offset); + } + else if (whence == SEEK_END) + { + method = FILE_END; + distance.QuadPart = (long long)(*offset); + } + else + { + _set_errno (EINVAL); + return -1; + } +#ifdef HAVE_W32CE_SYSTEM +# warning need to use SetFilePointer +#else + if (!w32_cookie->no_syscall_clamp) + _gpgrt_pre_syscall (); + if (!SetFilePointerEx (w32_cookie->hd, distance, &newoff, method)) + { + _set_errno (map_w32_to_errno (GetLastError ())); + _gpgrt_post_syscall (); + return -1; + } + if (!w32_cookie->no_syscall_clamp) + _gpgrt_post_syscall (); +#endif + /* Note that gpgrt_off_t is always 64 bit. */ + *offset = (gpgrt_off_t)newoff.QuadPart; + return 0; +} + + +/* + * Destroy function for W32 handle objects. + */ +static int +func_w32_destroy (void *cookie) +{ + estream_cookie_w32_t w32_cookie = cookie; + int err; + + trace (("enter: cookie=%p", cookie)); + + if (w32_cookie) + { + if (w32_cookie->hd == INVALID_HANDLE_VALUE) + err = 0; + else if (w32_cookie->no_close) + err = 0; + else + { + trace (("cookie=%p closing handle %p", cookie, w32_cookie->hd)); + if (!CloseHandle (w32_cookie->hd)) + { + DWORD ec = GetLastError (); + trace (("cookie=%p CloseHandle failed: ec=%ld", cookie,ec)); + _set_errno (map_w32_to_errno (ec)); + err = -1; + } + else + err = 0; + } + mem_free (w32_cookie); + } + else + err = 0; + + trace_errno (err, ("leave: err=%d", err)); + return err; +} + + +/* + * Access object for the W32 handle based objects. + */ +static struct cookie_io_functions_s estream_functions_w32 = + { + { + func_w32_read, + func_w32_write, + func_w32_seek, + func_w32_destroy, + }, + NULL, + }; +#endif /*HAVE_W32_SYSTEM*/ + + + + +/* + * Implementation of stdio based I/O. + */ + +/* Cookie for fp objects. */ +typedef struct estream_cookie_fp +{ + FILE *fp; /* The file pointer we are using for actual output. */ + int no_close; /* If set we won't close the file pointer. */ +} *estream_cookie_fp_t; + + +/* + * Create function for stdio based objects. + */ +static int +func_fp_create (void **cookie, FILE *fp, + unsigned int modeflags, int no_close) +{ + estream_cookie_fp_t fp_cookie; + int err; + + fp_cookie = mem_alloc (sizeof *fp_cookie); + if (!fp_cookie) + err = -1; + else + { +#ifdef HAVE_DOSISH_SYSTEM + /* Make sure it is in binary mode if requested. */ + if ( (modeflags & O_BINARY) ) + setmode (fileno (fp), O_BINARY); +#else + (void)modeflags; +#endif + fp_cookie->fp = fp; + fp_cookie->no_close = no_close; + *cookie = fp_cookie; + err = 0; + } + + return err; +} + + +/* + * Read function for stdio based objects. + */ +static gpgrt_ssize_t +func_fp_read (void *cookie, void *buffer, size_t size) + +{ + estream_cookie_fp_t file_cookie = cookie; + gpgrt_ssize_t bytes_read; + + if (!size) + return -1; /* We don't know whether anything is pending. */ + + if (file_cookie->fp) + { + _gpgrt_pre_syscall (); + bytes_read = fread (buffer, 1, size, file_cookie->fp); + _gpgrt_post_syscall (); + } + else + bytes_read = 0; + if (!bytes_read && ferror (file_cookie->fp)) + return -1; + return bytes_read; +} + + +/* + * Write function for stdio bases objects. + */ +static gpgrt_ssize_t +func_fp_write (void *cookie, const void *buffer, size_t size) +{ + estream_cookie_fp_t file_cookie = cookie; + size_t bytes_written; + + if (file_cookie->fp) + { + _gpgrt_pre_syscall (); + if (buffer) + { +#ifdef HAVE_W32_SYSTEM + /* Using an fwrite to stdout connected to the console fails + with the error "Not enough space" for an fwrite size of + >= 52KB (tested on Windows XP SP2). To solve this we + always chunk the writes up into smaller blocks. */ + bytes_written = 0; + while (bytes_written < size) + { + size_t cnt = size - bytes_written; + + if (cnt > 32*1024) + cnt = 32*1024; + if (fwrite ((const char*)buffer + bytes_written, + cnt, 1, file_cookie->fp) != 1) + break; /* Write error. */ + bytes_written += cnt; + } +#else + bytes_written = fwrite (buffer, 1, size, file_cookie->fp); +#endif + } + else /* Only flush requested. */ + bytes_written = size; + + fflush (file_cookie->fp); + _gpgrt_post_syscall (); + } + else + bytes_written = size; /* Successfully written to the bit bucket. */ + + if (bytes_written != size) + return -1; + return bytes_written; +} + + +/* + * Seek function for stdio based objects. + */ +static int +func_fp_seek (void *cookie, gpgrt_off_t *offset, int whence) +{ + estream_cookie_fp_t file_cookie = cookie; + long int offset_new; + + if (!file_cookie->fp) + { + _set_errno (ESPIPE); + return -1; + } + + _gpgrt_pre_syscall (); + if ( fseek (file_cookie->fp, (long int)*offset, whence) ) + { + /* fprintf (stderr, "\nfseek failed: errno=%d (%s)\n", */ + /* errno,strerror (errno)); */ + _gpgrt_post_syscall (); + return -1; + } + + offset_new = ftell (file_cookie->fp); + _gpgrt_post_syscall (); + if (offset_new == -1) + { + /* fprintf (stderr, "\nftell failed: errno=%d (%s)\n", */ + /* errno,strerror (errno)); */ + return -1; + } + *offset = offset_new; + return 0; +} + + +/* + * Destroy function for stdio based objects. + */ +static int +func_fp_destroy (void *cookie) +{ + estream_cookie_fp_t fp_cookie = cookie; + int err; + + if (fp_cookie) + { + if (fp_cookie->fp) + { + _gpgrt_pre_syscall (); + fflush (fp_cookie->fp); + _gpgrt_post_syscall (); + err = fp_cookie->no_close? 0 : fclose (fp_cookie->fp); + } + else + err = 0; + mem_free (fp_cookie); + } + else + err = 0; + + return err; +} + + +/* + * Access object for stdio based objects. + */ +static struct cookie_io_functions_s estream_functions_fp = + { + { + func_fp_read, + func_fp_write, + func_fp_seek, + func_fp_destroy, + }, + NULL, + }; + + + + +/* + * Implementation of file name based I/O. + * + * Note that only a create function is required because the other + * operations ares handled by file descriptor based I/O. + */ + +#ifdef HAVE_W32_SYSTEM +static int +any8bitchar (const char *string) +{ + if (string) + for ( ; *string; string++) + if ((*string & 0x80)) + return 1; + return 0; +} +#endif /*HAVE_W32_SYSTEM*/ + +/* Create function for objects identified by a file name. */ +static int +func_file_create (void **cookie, int *filedes, + const char *path, unsigned int modeflags, unsigned int cmode) +{ + estream_cookie_fd_t file_cookie; + int err; + int fd; + + err = 0; + + file_cookie = mem_alloc (sizeof (*file_cookie)); + if (! file_cookie) + { + err = -1; + goto out; + } + +#ifdef HAVE_W32_SYSTEM + if (any8bitchar (path)) + { + wchar_t *wpath; + + wpath = _gpgrt_utf8_to_wchar (path); + if (!wpath) + fd = -1; + else + { + fd = _wopen (wpath, modeflags, cmode); + _gpgrt_free_wchar (wpath); + } + } + else /* Avoid unnecessary conversion. */ + fd = open (path, modeflags, cmode); +#else + fd = open (path, modeflags, cmode); +#endif + if (fd == -1) + { + err = -1; + goto out; + } +#ifdef HAVE_DOSISH_SYSTEM + /* Make sure it is in binary mode if requested. */ + if ( (modeflags & O_BINARY) ) + setmode (fd, O_BINARY); +#endif + + file_cookie->fd = fd; + file_cookie->no_close = 0; + *cookie = file_cookie; + *filedes = fd; + + out: + + if (err) + mem_free (file_cookie); + + return err; +} + + + +/* Flags used by parse_mode and friends. */ +#define X_SAMETHREAD (1 << 0) +#define X_SYSOPEN (1 << 1) +#define X_POLLABLE (1 << 2) + +/* Parse the mode flags of fopen et al. In addition to the POSIX + * defined mode flags keyword parameters are supported. These are + * key/value pairs delimited by comma and optional white spaces. + * Keywords and values may not contain a comma or white space; unknown + * keywords are skipped. Supported keywords are: + * + * mode=<string> + * + * Creates a file and gives the new file read and write permissions + * for the user and read permission for the group. The format of + * the string is the same as shown by the -l option of the ls(1) + * command. However the first letter must be a dash and it is + * allowed to leave out trailing dashes. If this keyword parameter + * is not given the default mode for creating files is "-rw-rw-r--" + * (664). Note that the system still applies the current umask to + * the mode when creating a file. Example: + * + * "wb,mode=-rw-r--" + * + * samethread + * + * Assumes that the object is only used by the creating thread and + * disables any internal locking. This keyword is also found on + * IBM systems. + * + * nonblock + * + * The object is opened in non-blocking mode. This is the same as + * calling gpgrt_set_nonblock on the file. + * + * sysopen + * + * The object is opened in sysmode. On POSIX this is a NOP but + * under Windows the direct W32 API functions (HANDLE) are used + * instead of their libc counterparts (fd). + * FIXME: The functionality is not yet implemented. + * + * pollable + * + * The object is opened in a way suitable for use with es_poll. On + * POSIX this is a NOP but under Windows we create up to two + * threads, one for reading and one for writing, do any I/O there, + * and synchronize with them in order to support es_poll. + * + * Note: R_CMODE is optional because is only required by functions + * which are able to creat a file. + */ +static int +parse_mode (const char *modestr, + unsigned int *modeflags, + unsigned int *r_xmode, + unsigned int *r_cmode) +{ + unsigned int omode, oflags, cmode; + int got_cmode = 0; + + *r_xmode = 0; + + switch (*modestr) + { + case 'r': + omode = O_RDONLY; + oflags = 0; + break; + case 'w': + omode = O_WRONLY; + oflags = O_TRUNC | O_CREAT; + break; + case 'a': + omode = O_WRONLY; + oflags = O_APPEND | O_CREAT; + break; + default: + _set_errno (EINVAL); + return -1; + } + for (modestr++; *modestr; modestr++) + { + switch (*modestr) + { + case '+': + omode = O_RDWR; + break; + case 'b': + oflags |= O_BINARY; + break; + case 'x': + oflags |= O_EXCL; + break; + case ',': + goto keyvalue; + default: /* Ignore unknown flags. */ + break; + } + } + + keyvalue: + /* Parse key/value pairs (similar to fopen on mainframes). */ + for (cmode=0; *modestr == ','; modestr += strcspn (modestr, ",")) + { + modestr++; + modestr += strspn (modestr, " \t"); + if (!strncmp (modestr, "mode=", 5)) + { + static struct { + char letter; + unsigned int value; + } table[] = { { '-', 0 }, + { 'r', S_IRUSR }, { 'w', S_IWUSR }, { 'x', S_IXUSR }, + { 'r', S_IRGRP }, { 'w', S_IWGRP }, { 'x', S_IXGRP }, + { 'r', S_IROTH }, { 'w', S_IWOTH }, { 'x', S_IXOTH }}; + int idx; + + got_cmode = 1; + modestr += 5; + /* For now we only support a string as used by ls(1) and no + octal numbers. The first character must be a dash. */ + for (idx=0; idx < 10 && *modestr; idx++, modestr++) + { + if (*modestr == table[idx].letter) + cmode |= table[idx].value; + else if (*modestr != '-') + break; + } + if (*modestr && !strchr (" \t,", *modestr)) + { + _set_errno (EINVAL); + return -1; + } + } + else if (!strncmp (modestr, "samethread", 10)) + { + modestr += 10; + if (*modestr && !strchr (" \t,", *modestr)) + { + _set_errno (EINVAL); + return -1; + } + *r_xmode |= X_SAMETHREAD; + } + else if (!strncmp (modestr, "nonblock", 8)) + { + modestr += 8; + if (*modestr && !strchr (" \t,", *modestr)) + { + _set_errno (EINVAL); + return -1; + } + oflags |= O_NONBLOCK; +#if HAVE_W32_SYSTEM + /* Currently, nonblock implies pollable on Windows. */ + *r_xmode |= X_POLLABLE; +#endif + } + else if (!strncmp (modestr, "sysopen", 7)) + { + modestr += 7; + if (*modestr && !strchr (" \t,", *modestr)) + { + _set_errno (EINVAL); + return -1; + } + *r_xmode |= X_SYSOPEN; + } + else if (!strncmp (modestr, "pollable", 8)) + { + modestr += 8; + if (*modestr && !strchr (" \t,", *modestr)) + { + _set_errno (EINVAL); + return -1; + } + *r_xmode |= X_POLLABLE; + } + } + if (!got_cmode) + cmode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); + + *modeflags = (omode | oflags); + if (r_cmode) + *r_cmode = cmode; + return 0; +} + + + +/* + * Low level stream functionality. + */ + +static int +fill_stream (estream_t stream) +{ + size_t bytes_read = 0; + int err; + + if (!stream->intern->func_read) + { + _set_errno (EOPNOTSUPP); + err = -1; + } + else if (!stream->buffer_size) + err = 0; + else + { + gpgrt_cookie_read_function_t func_read = stream->intern->func_read; + gpgrt_ssize_t ret; + + ret = (*func_read) (stream->intern->cookie, + stream->buffer, stream->buffer_size); + if (ret == -1) + { + bytes_read = 0; + err = -1; +#if EWOULDBLOCK != EAGAIN + if (errno == EWOULDBLOCK) + _set_errno (EAGAIN); +#endif + } + else + { + bytes_read = ret; + err = 0; + } + } + + if (err) + { + if (errno != EAGAIN) + { + if (errno == EPIPE) + stream->intern->indicators.hup = 1; + stream->intern->indicators.err = 1; + } + } + else if (!bytes_read) + stream->intern->indicators.eof = 1; + + stream->intern->offset += stream->data_len; + stream->data_len = bytes_read; + stream->data_offset = 0; + + return err; +} + +static int +flush_stream (estream_t stream) +{ + gpgrt_cookie_write_function_t func_write = stream->intern->func_write; + int err; + + gpgrt_assert (stream->flags.writing); + + if (stream->data_offset) + { + size_t bytes_written; + size_t data_flushed; + gpgrt_ssize_t ret; + + if (! func_write) + { + _set_errno (EOPNOTSUPP); + err = -1; + goto out; + } + + /* Note: to prevent an endless loop caused by user-provided + write-functions that pretend to have written more bytes than + they were asked to write, we have to check for + "(stream->data_offset - data_flushed) > 0" instead of + "stream->data_offset - data_flushed". */ + + data_flushed = 0; + err = 0; + + while ((((gpgrt_ssize_t) (stream->data_offset - data_flushed)) > 0) + && !err) + { + ret = (*func_write) (stream->intern->cookie, + stream->buffer + data_flushed, + stream->data_offset - data_flushed); + if (ret == -1) + { + bytes_written = 0; + err = -1; +#if EWOULDBLOCK != EAGAIN + if (errno == EWOULDBLOCK) + _set_errno (EAGAIN); +#endif + } + else + bytes_written = ret; + + data_flushed += bytes_written; + if (err) + break; + } + + stream->data_flushed += data_flushed; + if (stream->data_offset == data_flushed) + { + stream->intern->offset += stream->data_offset; + stream->data_offset = 0; + stream->data_flushed = 0; + } + } + else + err = 0; + + /* Always propagate flush event in case gpgrt_fflush was called + * explictly to do flush buffers in caller's cookie functions. */ + (*func_write) (stream->intern->cookie, NULL, 0); + + out: + + if (err && errno != EAGAIN) + { + if (errno == EPIPE) + stream->intern->indicators.hup = 1; + stream->intern->indicators.err = 1; + } + + return err; +} + + +/* + * Discard buffered data for STREAM. + */ +static void +es_empty (estream_t stream) +{ + gpgrt_assert (!stream->flags.writing); + stream->data_len = 0; + stream->data_offset = 0; + stream->unread_data_len = 0; +} + + +/* + * Initialize STREAM. + */ +static void +init_stream_obj (estream_t stream, + void *cookie, es_syshd_t *syshd, + gpgrt_stream_backend_kind_t kind, + struct cookie_io_functions_s functions, + unsigned int modeflags, unsigned int xmode) +{ + stream->intern->kind = kind; + stream->intern->cookie = cookie; + stream->intern->opaque = NULL; + stream->intern->offset = 0; + stream->intern->func_read = functions.public.func_read; + stream->intern->func_write = functions.public.func_write; + stream->intern->func_seek = functions.public.func_seek; + stream->intern->func_ioctl = functions.func_ioctl; + stream->intern->func_close = functions.public.func_close; + stream->intern->strategy = _IOFBF; + stream->intern->syshd = *syshd; + stream->intern->print_ntotal = 0; + stream->intern->indicators.err = 0; + stream->intern->indicators.eof = 0; + stream->intern->indicators.hup = 0; + stream->intern->is_stdstream = 0; + stream->intern->stdstream_fd = 0; + stream->intern->deallocate_buffer = 0; + stream->intern->printable_fname = NULL; + stream->intern->printable_fname_inuse = 0; + stream->intern->samethread = !! (xmode & X_SAMETHREAD); + stream->intern->onclose = NULL; + + stream->data_len = 0; + stream->data_offset = 0; + stream->data_flushed = 0; + stream->unread_data_len = 0; + /* Depending on the modeflags we set whether we start in writing or + reading mode. This is required in case we are working on a + stream which is not seeekable (like stdout). Without this + pre-initialization we would do a seek at the first write call and + as this will fail no output will be delivered. */ + if ((modeflags & O_WRONLY) || (modeflags & O_RDWR) ) + stream->flags.writing = 1; + else + stream->flags.writing = 0; +} + + +/* + * Deinitialize the STREAM object. This does _not_ free the memory, + * destroys the lock, or closes the underlying descriptor. + */ +static int +deinit_stream_obj (estream_t stream) +{ + gpgrt_cookie_close_function_t func_close; + int err, tmp_err; + + trace (("enter: stream %p", stream)); + func_close = stream->intern->func_close; + + err = 0; + if (stream->flags.writing) + { + tmp_err = flush_stream (stream); + if (!err) + err = tmp_err; + } + if (func_close) + { + trace (("stream %p calling func_close", stream)); + tmp_err = func_close (stream->intern->cookie); + if (!err) + err = tmp_err; + } + + mem_free (stream->intern->printable_fname); + stream->intern->printable_fname = NULL; + stream->intern->printable_fname_inuse = 0; + while (stream->intern->onclose) + { + notify_list_t tmp = stream->intern->onclose->next; + mem_free (stream->intern->onclose); + stream->intern->onclose = tmp; + } + + trace_errno (err, ("leave: stream %p err=%d", stream, err)); + return err; +} + + +/* + * Create a new stream and initialize it. On success the new stream + * handle is tsored at R_STREAM. On failure NULL is stored at + * R_STREAM. + */ +static int +create_stream (estream_t *r_stream, void *cookie, es_syshd_t *syshd, + gpgrt_stream_backend_kind_t kind, + struct cookie_io_functions_s functions, unsigned int modeflags, + unsigned int xmode, int with_locked_list) +{ + estream_internal_t stream_internal_new; + estream_t stream_new; + int err; +#if HAVE_W32_SYSTEM + void *old_cookie = NULL; +#endif + + stream_new = NULL; + stream_internal_new = NULL; + +#if HAVE_W32_SYSTEM + if ((xmode & X_POLLABLE) && kind != BACKEND_W32) + { + /* We require the W32 backend, because only that allows us to + * write directly using the native W32 API and to disable the + * system clamp. Note that func_w32_create has already been + * called with the flag to disable the system call clamp. */ + _set_errno (EINVAL); + err = -1; + goto out; + } +#endif /*HAVE_W32_SYSTEM*/ + + stream_new = mem_alloc (sizeof (*stream_new)); + if (! stream_new) + { + err = -1; + goto out; + } + + stream_internal_new = mem_alloc (sizeof (*stream_internal_new)); + if (! stream_internal_new) + { + err = -1; + goto out; + } + + stream_new->buffer = stream_internal_new->buffer; + stream_new->buffer_size = sizeof (stream_internal_new->buffer); + stream_new->unread_buffer = stream_internal_new->unread_buffer; + stream_new->unread_buffer_size = sizeof (stream_internal_new->unread_buffer); + stream_new->intern = stream_internal_new; + +#if HAVE_W32_SYSTEM + if ((xmode & X_POLLABLE)) + { + void *new_cookie; + + err = _gpgrt_w32_pollable_create (&new_cookie, modeflags, + functions, cookie); + if (err) + goto out; + + modeflags &= ~O_NONBLOCK; + old_cookie = cookie; + cookie = new_cookie; + kind = BACKEND_W32_POLLABLE; + functions = _gpgrt_functions_w32_pollable; + } +#endif /*HAVE_W32_SYSTEM*/ + + init_stream_obj (stream_new, cookie, syshd, kind, functions, modeflags, + xmode); + init_stream_lock (stream_new); + + err = do_list_add (stream_new, with_locked_list); + if (err) + goto out; + + *r_stream = stream_new; + + out: + + if (err) + { + trace_errno (err, ("leave: err=%d", err)); + if (stream_new) + { + deinit_stream_obj (stream_new); + destroy_stream_lock (stream_new); + mem_free (stream_new->intern); + mem_free (stream_new); + } + } +#if HAVE_W32_SYSTEM + else if (old_cookie) + trace (("leave: success stream=%p cookie=%p,%p", + *r_stream, old_cookie, cookie)); +#endif + else + trace (("leave: success stream=%p cookie=%p", *r_stream, cookie)); + + return err; +} + + +/* + * Deinitialize a stream object and destroy it. With CANCEL_MODE set + * try to cancel as much as possible (see _gpgrt_fcancel). + */ +static int +do_close (estream_t stream, int cancel_mode, int with_locked_list) +{ + int err; + + trace (("stream %p %s", stream, with_locked_list? "(with locked list)":"")); + + if (stream) + { + do_list_remove (stream, with_locked_list); + if (cancel_mode) + { + stream->flags.writing = 0; + es_empty (stream); + } + while (stream->intern->onclose) + { + notify_list_t tmp = stream->intern->onclose->next; + + if (stream->intern->onclose->fnc) + stream->intern->onclose->fnc (stream, + stream->intern->onclose->fnc_value); + mem_free (stream->intern->onclose); + stream->intern->onclose = tmp; + } + err = deinit_stream_obj (stream); + destroy_stream_lock (stream); + if (stream->intern->deallocate_buffer) + mem_free (stream->buffer); + mem_free (stream->intern); + mem_free (stream); + } + else + err = 0; + + trace_errno (err, ("stream %p err=%d", stream, err)); + return err; +} + + +/* + * The onclose worker function which is called with a locked + * stream. + */ +static int +do_onclose (estream_t stream, int mode, + void (*fnc) (estream_t, void*), void *fnc_value) +{ + notify_list_t item; + + if (!mode) + { + for (item = stream->intern->onclose; item; item = item->next) + if (item->fnc && item->fnc == fnc && item->fnc_value == fnc_value) + item->fnc = NULL; /* Disable this notification. */ + } + else + { + item = mem_alloc (sizeof *item); + if (!item) + return -1; + item->fnc = fnc; + item->fnc_value = fnc_value; + item->next = stream->intern->onclose; + stream->intern->onclose = item; + } + return 0; +} + + +/* + * Try to read BYTES_TO_READ bytes from STREAM into BUFFER in + * unbuffered-mode, storing the amount of bytes read at BYTES_READ. + */ +static int +do_read_nbf (estream_t _GPGRT__RESTRICT stream, + unsigned char *_GPGRT__RESTRICT buffer, + size_t bytes_to_read, size_t *_GPGRT__RESTRICT bytes_read) +{ + gpgrt_cookie_read_function_t func_read = stream->intern->func_read; + size_t data_read; + gpgrt_ssize_t ret; + int err; + + data_read = 0; + err = 0; + + while (bytes_to_read - data_read) + { + ret = (*func_read) (stream->intern->cookie, + buffer + data_read, bytes_to_read - data_read); + if (ret == -1) + { + err = -1; +#if EWOULDBLOCK != EAGAIN + if (errno == EWOULDBLOCK) + _set_errno (EAGAIN); +#endif + break; + } + else if (ret) + data_read += ret; + else + break; + } + + stream->intern->offset += data_read; + *bytes_read = data_read; + + return err; +} + + +/* + * Helper for check_pending. + */ +static int +check_pending_nbf (estream_t _GPGRT__RESTRICT stream) +{ + gpgrt_cookie_read_function_t func_read = stream->intern->func_read; + char buffer[1]; + + if (!(*func_read) (stream->intern->cookie, buffer, 0)) + return 1; /* Pending bytes. */ + return 0; /* No pending bytes or error. */ +} + + +/* + * Try to read BYTES_TO_READ bytes from STREAM into BUFFER in + * fully-buffered-mode, storing the amount of bytes read at + * BYTES_READ. + */ +static int +do_read_fbf (estream_t _GPGRT__RESTRICT stream, + unsigned char *_GPGRT__RESTRICT buffer, + size_t bytes_to_read, size_t *_GPGRT__RESTRICT bytes_read) +{ + size_t data_available; + size_t data_to_read; + size_t data_read; + int err; + + data_read = 0; + err = 0; + + while ((bytes_to_read - data_read) && (! err)) + { + if (stream->data_offset == stream->data_len) + { + /* Nothing more to read in current container, try to + fill container with new data. */ + err = fill_stream (stream); + if (! err) + if (! stream->data_len) + /* Filling did not result in any data read. */ + break; + } + + if (! err) + { + /* Filling resulted in some new data. */ + + data_to_read = bytes_to_read - data_read; + data_available = stream->data_len - stream->data_offset; + if (data_to_read > data_available) + data_to_read = data_available; + + memcpy (buffer + data_read, + stream->buffer + stream->data_offset, data_to_read); + stream->data_offset += data_to_read; + data_read += data_to_read; + } + } + + *bytes_read = data_read; + + return err; +} + + +/* + * Helper for check_pending. + */ +static int +check_pending_fbf (estream_t _GPGRT__RESTRICT stream) +{ + gpgrt_cookie_read_function_t func_read = stream->intern->func_read; + char buffer[1]; + + if (stream->data_offset == stream->data_len) + { + /* Nothing more to read in current container, check whether it + would be possible to fill the container with new data. */ + if (!(*func_read) (stream->intern->cookie, buffer, 0)) + return 1; /* Pending bytes. */ + } + else + return 1; + return 0; +} + + +/* + * Try to read BYTES_TO_READ bytes from STREAM into BUFFER in + * line-buffered-mode, storing the amount of bytes read at BYTES_READ. + */ +static int +do_read_lbf (estream_t _GPGRT__RESTRICT stream, + unsigned char *_GPGRT__RESTRICT buffer, + size_t bytes_to_read, size_t *_GPGRT__RESTRICT bytes_read) +{ + int err; + + err = do_read_fbf (stream, buffer, bytes_to_read, bytes_read); + + return err; +} + + +/* + * Try to read BYTES_TO_READ bytes from STREAM into BUFFER, storing + * the amount of bytes read at BYTES_READ. + */ +static int +es_readn (estream_t _GPGRT__RESTRICT stream, + void *_GPGRT__RESTRICT buffer_arg, + size_t bytes_to_read, size_t *_GPGRT__RESTRICT bytes_read) +{ + unsigned char *buffer = (unsigned char *)buffer_arg; + size_t data_read_unread, data_read; + int err; + + data_read_unread = 0; + data_read = 0; + err = 0; + + if (stream->flags.writing) + { + /* Switching to reading mode -> flush output. */ + err = flush_stream (stream); + if (err) + goto out; + stream->flags.writing = 0; + } + + /* Read unread data first. */ + while ((bytes_to_read - data_read_unread) && stream->unread_data_len) + { + buffer[data_read_unread] + = stream->unread_buffer[stream->unread_data_len - 1]; + stream->unread_data_len--; + data_read_unread++; + } + + switch (stream->intern->strategy) + { + case _IONBF: + err = do_read_nbf (stream, + buffer + data_read_unread, + bytes_to_read - data_read_unread, &data_read); + break; + case _IOLBF: + err = do_read_lbf (stream, + buffer + data_read_unread, + bytes_to_read - data_read_unread, &data_read); + break; + case _IOFBF: + err = do_read_fbf (stream, + buffer + data_read_unread, + bytes_to_read - data_read_unread, &data_read); + break; + } + + out: + + if (bytes_read) + *bytes_read = data_read_unread + data_read; + + return err; +} + + +/* + * Return true if at least one byte is pending for read. This is a + * best effort check and it it possible that bytes are still pending + * even if false is returned. If the stream is in writing mode it is + * switched to read mode. + */ +static int +check_pending (estream_t _GPGRT__RESTRICT stream) +{ + if (stream->flags.writing) + { + /* Switching to reading mode -> flush output. */ + if (flush_stream (stream)) + return 0; /* Better return 0 on error. */ + stream->flags.writing = 0; + } + + /* Check unread data first. */ + if (stream->unread_data_len) + return 1; + + switch (stream->intern->strategy) + { + case _IONBF: + return check_pending_nbf (stream); + case _IOLBF: + case _IOFBF: + return check_pending_fbf (stream); + } + + return 0; +} + + +/* + * Try to unread DATA_N bytes from DATA into STREAM, storing the + * amount of bytes successfully unread at BYTES_UNREAD. + */ +static void +es_unreadn (estream_t _GPGRT__RESTRICT stream, + const unsigned char *_GPGRT__RESTRICT data, size_t data_n, + size_t *_GPGRT__RESTRICT bytes_unread) +{ + size_t space_left; + + space_left = stream->unread_buffer_size - stream->unread_data_len; + + if (data_n > space_left) + data_n = space_left; + + if (! data_n) + goto out; + + memcpy (stream->unread_buffer + stream->unread_data_len, data, data_n); + stream->unread_data_len += data_n; + stream->intern->indicators.eof = 0; + + out: + + if (bytes_unread) + *bytes_unread = data_n; +} + + +/* + * Seek in STREAM. + */ +static int +es_seek (estream_t _GPGRT__RESTRICT stream, gpgrt_off_t offset, int whence, + gpgrt_off_t *_GPGRT__RESTRICT offset_new) +{ + gpgrt_cookie_seek_function_t func_seek = stream->intern->func_seek; + int err, ret; + gpgrt_off_t off; + + if (! func_seek) + { + _set_errno (EOPNOTSUPP); + err = -1; + goto out; + } + + if (stream->flags.writing) + { + /* Flush data first in order to prevent flushing it to the wrong + offset. */ + err = flush_stream (stream); + if (err) + goto out; + stream->flags.writing = 0; + } + + off = offset; + if (whence == SEEK_CUR) + { + off = off - stream->data_len + stream->data_offset; + off -= stream->unread_data_len; + } + + ret = (*func_seek) (stream->intern->cookie, &off, whence); + if (ret == -1) + { + err = -1; +#if EWOULDBLOCK != EAGAIN + if (errno == EWOULDBLOCK) + _set_errno (EAGAIN); +#endif + goto out; + } + + err = 0; + es_empty (stream); + + if (offset_new) + *offset_new = off; + + stream->intern->indicators.eof = 0; + stream->intern->offset = off; + + out: + + if (err) + { + if (errno == EPIPE) + stream->intern->indicators.hup = 1; + stream->intern->indicators.err = 1; + } + + return err; +} + + +/* + * Write BYTES_TO_WRITE bytes from BUFFER into STREAM in + * unbuffered-mode, storing the amount of bytes written at + * BYTES_WRITTEN. + */ +static int +es_write_nbf (estream_t _GPGRT__RESTRICT stream, + const unsigned char *_GPGRT__RESTRICT buffer, + size_t bytes_to_write, size_t *_GPGRT__RESTRICT bytes_written) +{ + gpgrt_cookie_write_function_t func_write = stream->intern->func_write; + size_t data_written; + gpgrt_ssize_t ret; + int err; + + if (bytes_to_write && (! func_write)) + { + _set_errno (EOPNOTSUPP); + err = -1; + goto out; + } + + data_written = 0; + err = 0; + + while (bytes_to_write - data_written) + { + ret = (*func_write) (stream->intern->cookie, + buffer + data_written, + bytes_to_write - data_written); + if (ret == -1) + { + err = -1; +#if EWOULDBLOCK != EAGAIN + if (errno == EWOULDBLOCK) + _set_errno (EAGAIN); +#endif + break; + } + else + data_written += ret; + } + + stream->intern->offset += data_written; + *bytes_written = data_written; + + out: + + return err; +} + + +/* + * Write BYTES_TO_WRITE bytes from BUFFER into STREAM in + * fully-buffered-mode, storing the amount of bytes written at + * BYTES_WRITTEN. + */ +static int +es_write_fbf (estream_t _GPGRT__RESTRICT stream, + const unsigned char *_GPGRT__RESTRICT buffer, + size_t bytes_to_write, size_t *_GPGRT__RESTRICT bytes_written) +{ + size_t space_available; + size_t data_to_write; + size_t data_written; + int err; + + data_written = 0; + err = 0; + + while ((bytes_to_write - data_written) && (! err)) + { + if (stream->data_offset == stream->buffer_size) + /* Container full, flush buffer. */ + err = flush_stream (stream); + + if (! err) + { + /* Flushing resulted in empty container. */ + + data_to_write = bytes_to_write - data_written; + space_available = stream->buffer_size - stream->data_offset; + if (data_to_write > space_available) + data_to_write = space_available; + + memcpy (stream->buffer + stream->data_offset, + buffer + data_written, data_to_write); + stream->data_offset += data_to_write; + data_written += data_to_write; + } + } + + *bytes_written = data_written; + + return err; +} + + +/* Write BYTES_TO_WRITE bytes from BUFFER into STREAM in + line-buffered-mode, storing the amount of bytes written in + *BYTES_WRITTEN. */ +static int +es_write_lbf (estream_t _GPGRT__RESTRICT stream, + const unsigned char *_GPGRT__RESTRICT buffer, + size_t bytes_to_write, size_t *_GPGRT__RESTRICT bytes_written) +{ + size_t data_flushed = 0; + size_t data_buffered = 0; + unsigned char *nlp; + int err = 0; + + nlp = memrchr (buffer, '\n', bytes_to_write); + if (nlp) + { + /* Found a newline, directly write up to (including) this + character. */ + err = flush_stream (stream); + if (!err) + err = es_write_nbf (stream, buffer, nlp - buffer + 1, &data_flushed); + } + + if (!err) + { + /* Write remaining data fully buffered. */ + err = es_write_fbf (stream, buffer + data_flushed, + bytes_to_write - data_flushed, &data_buffered); + } + + *bytes_written = data_flushed + data_buffered; + return err; +} + + +/* Write BYTES_TO_WRITE bytes from BUFFER into STREAM in, storing the + amount of bytes written in BYTES_WRITTEN. */ +static int +es_writen (estream_t _GPGRT__RESTRICT stream, + const void *_GPGRT__RESTRICT buffer, + size_t bytes_to_write, size_t *_GPGRT__RESTRICT bytes_written) +{ + size_t data_written; + int err; + + data_written = 0; + err = 0; + + if (!stream->flags.writing) + { + /* Switching to writing mode -> discard input data and seek to + position at which reading has stopped. We can do this only + if a seek function has been registered. */ + if (stream->intern->func_seek) + { + err = es_seek (stream, 0, SEEK_CUR, NULL); + if (err) + { + if (errno == ESPIPE) + err = 0; + else + goto out; + } + stream->flags.writing = 1; + } + } + + switch (stream->intern->strategy) + { + case _IONBF: + err = es_write_nbf (stream, buffer, bytes_to_write, &data_written); + break; + + case _IOLBF: + err = es_write_lbf (stream, buffer, bytes_to_write, &data_written); + break; + + case _IOFBF: + err = es_write_fbf (stream, buffer, bytes_to_write, &data_written); + break; + } + + out: + + if (bytes_written) + *bytes_written = data_written; + + return err; +} + + +static int +peek_stream (estream_t _GPGRT__RESTRICT stream, + unsigned char **_GPGRT__RESTRICT data, + size_t *_GPGRT__RESTRICT data_len) +{ + int err; + + if (stream->flags.writing) + { + /* Switching to reading mode -> flush output. */ + err = flush_stream (stream); + if (err) + goto out; + stream->flags.writing = 0; + } + + if (stream->data_offset == stream->data_len) + { + /* Refill container. */ + err = fill_stream (stream); + if (err) + goto out; + } + + if (data) + *data = stream->buffer + stream->data_offset; + if (data_len) + *data_len = stream->data_len - stream->data_offset; + err = 0; + + out: + + return err; +} + + +/* Skip SIZE bytes of input data contained in buffer. */ +static int +skip_stream (estream_t stream, size_t size) +{ + int err; + + if (stream->data_offset + size > stream->data_len) + { + _set_errno (EINVAL); + err = -1; + } + else + { + stream->data_offset += size; + err = 0; + } + + return err; +} + + +static int +doreadline (estream_t _GPGRT__RESTRICT stream, size_t max_length, + char *_GPGRT__RESTRICT *_GPGRT__RESTRICT line, + size_t *_GPGRT__RESTRICT line_length) +{ + size_t line_size; + estream_t line_stream; + char *line_new; + void *line_stream_cookie; + char *newline; + unsigned char *data; + size_t data_len; + int err; + es_syshd_t syshd; + + line_new = NULL; + line_stream = NULL; + line_stream_cookie = NULL; + + err = func_mem_create (&line_stream_cookie, NULL, 0, 0, + BUFFER_BLOCK_SIZE, 1, + mem_realloc, mem_free, + O_RDWR, + 0); + if (err) + goto out; + + memset (&syshd, 0, sizeof syshd); + err = create_stream (&line_stream, line_stream_cookie, + &syshd, BACKEND_MEM, + estream_functions_mem, O_RDWR, 1, 0); + if (err) + goto out; + + { + size_t space_left = max_length; + + line_size = 0; + for (;;) + { + if (max_length && (space_left == 1)) + break; + + err = peek_stream (stream, &data, &data_len); + if (err || (! data_len)) + break; + + if (data_len > (space_left - 1)) + data_len = space_left - 1; + + newline = memchr (data, '\n', data_len); + if (newline) + { + data_len = (newline - (char *) data) + 1; + err = _gpgrt_write (line_stream, data, data_len, NULL); + if (! err) + { + /* Not needed: space_left -= data_len */ + line_size += data_len; + skip_stream (stream, data_len); + break; /* endless loop */ + } + } + else + { + err = _gpgrt_write (line_stream, data, data_len, NULL); + if (! err) + { + space_left -= data_len; + line_size += data_len; + skip_stream (stream, data_len); + } + } + if (err) + break; + } + } + if (err) + goto out; + + /* Complete line has been written to line_stream. */ + + if ((max_length > 1) && (! line_size)) + { + stream->intern->indicators.eof = 1; + goto out; + } + + err = es_seek (line_stream, 0, SEEK_SET, NULL); + if (err) + goto out; + + if (! *line) + { + line_new = mem_alloc (line_size + 1); + if (! line_new) + { + err = -1; + goto out; + } + } + else + line_new = *line; + + err = _gpgrt_read (line_stream, line_new, line_size, NULL); + if (err) + goto out; + + line_new[line_size] = '\0'; + + if (! *line) + *line = line_new; + if (line_length) + *line_length = line_size; + + out: + + if (line_stream) + do_close (line_stream, 0, 0); + else if (line_stream_cookie) + func_mem_destroy (line_stream_cookie); + + if (err) + { + if (! *line) + mem_free (line_new); + stream->intern->indicators.err = 1; + } + + return err; +} + + +/* Output function used by estream_format. */ +static int +print_writer (void *outfncarg, const char *buf, size_t buflen) +{ + estream_t stream = outfncarg; + size_t nwritten; + int rc; + + nwritten = 0; + rc = es_writen (stream, buf, buflen, &nwritten); + stream->intern->print_ntotal += nwritten; + return rc; +} + + +/* The core of our printf function. This is called in locked state. */ +static int +do_print_stream (estream_t _GPGRT__RESTRICT stream, + gpgrt_string_filter_t sf, void *sfvalue, + const char *_GPGRT__RESTRICT format, va_list ap) +{ + int rc; + + stream->intern->print_ntotal = 0; + rc = _gpgrt_estream_format (print_writer, stream, sf, sfvalue, format, ap); + if (rc) + return -1; + return (int)stream->intern->print_ntotal; +} + + +static int +es_set_buffering (estream_t _GPGRT__RESTRICT stream, + char *_GPGRT__RESTRICT buffer, int mode, size_t size) +{ + int err; + + /* Flush or empty buffer depending on mode. */ + if (stream->flags.writing) + { + err = flush_stream (stream); + if (err) + goto out; + } + else + es_empty (stream); + + stream->intern->indicators.eof = 0; + + /* Free old buffer in case that was allocated by this function. */ + if (stream->intern->deallocate_buffer) + { + stream->intern->deallocate_buffer = 0; + mem_free (stream->buffer); + stream->buffer = NULL; + } + + if (mode == _IONBF) + stream->buffer_size = 0; + else + { + void *buffer_new; + + if (buffer) + buffer_new = buffer; + else + { + if (!size) + size = BUFSIZ; + buffer_new = mem_alloc (size); + if (! buffer_new) + { + err = -1; + goto out; + } + } + + stream->buffer = buffer_new; + stream->buffer_size = size; + if (! buffer) + stream->intern->deallocate_buffer = 1; + } + stream->intern->strategy = mode; + err = 0; + + out: + + return err; +} + + +static gpgrt_off_t +es_offset_calculate (estream_t stream) +{ + gpgrt_off_t offset; + + offset = stream->intern->offset + stream->data_offset; + if (offset < stream->unread_data_len) + /* Offset undefined. */ + offset = 0; + else + offset -= stream->unread_data_len; + + return offset; +} + + +static void +es_opaque_ctrl (estream_t _GPGRT__RESTRICT stream, + void *_GPGRT__RESTRICT opaque_new, + void **_GPGRT__RESTRICT opaque_old) +{ + if (opaque_old) + *opaque_old = stream->intern->opaque; + if (opaque_new) + stream->intern->opaque = opaque_new; +} + + +/* API. */ + +estream_t +_gpgrt_fopen (const char *_GPGRT__RESTRICT path, + const char *_GPGRT__RESTRICT mode) +{ + unsigned int modeflags, cmode, xmode; + int create_called; + estream_t stream; + void *cookie; + int err; + int fd; + es_syshd_t syshd; + + stream = NULL; + cookie = NULL; + create_called = 0; + + err = parse_mode (mode, &modeflags, &xmode, &cmode); + if (err) + goto out; + + err = func_file_create (&cookie, &fd, path, modeflags, cmode); + if (err) + goto out; + + syshd.type = ES_SYSHD_FD; + syshd.u.fd = fd; + create_called = 1; + err = create_stream (&stream, cookie, &syshd, BACKEND_FD, + estream_functions_fd, modeflags, xmode, 0); + if (err) + goto out; + + if (stream && path) + fname_set_internal (stream, path, 1); + + out: + + if (err && create_called) + (*estream_functions_fd.public.func_close) (cookie); + + return stream; +} + + + +/* Create a new estream object in memory. If DATA is not NULL this + buffer will be used as the memory buffer; thus after this functions + returns with the success the the memory at DATA belongs to the new + estream. The allocated length of DATA is given by DATA_LEN and its + used length by DATA_N. Usually this is malloced buffer; if a + static buffer is provided, the caller must pass false for GROW and + provide a dummy function for FUNC_FREE. FUNC_FREE and FUNC_REALLOC + allow the caller to provide custom functions for realloc and free + to be used by the new estream object. Note that the realloc + function is also used for initial allocation. If DATA is NULL a + buffer is internally allocated; either using internal function or + those provide by the caller. It is an error to provide a realloc + function but no free function. Providing only a free function is + allowed as long as GROW is false. */ +estream_t +_gpgrt_mopen (void *_GPGRT__RESTRICT data, size_t data_n, size_t data_len, + unsigned int grow, + func_realloc_t func_realloc, func_free_t func_free, + const char *_GPGRT__RESTRICT mode) +{ + int create_called = 0; + estream_t stream = NULL; + void *cookie = NULL; + unsigned int modeflags, xmode; + int err; + es_syshd_t syshd; + + err = parse_mode (mode, &modeflags, &xmode, NULL); + if (err) + goto out; + + err = func_mem_create (&cookie, data, data_n, data_len, + BUFFER_BLOCK_SIZE, grow, + func_realloc, func_free, modeflags, 0); + if (err) + goto out; + + memset (&syshd, 0, sizeof syshd); + create_called = 1; + err = create_stream (&stream, cookie, &syshd, BACKEND_MEM, + estream_functions_mem, modeflags, xmode, 0); + + out: + + if (err && create_called) + (*estream_functions_mem.public.func_close) (cookie); + + return stream; +} + + + +estream_t +_gpgrt_fopenmem (size_t memlimit, const char *_GPGRT__RESTRICT mode) +{ + unsigned int modeflags, xmode; + estream_t stream = NULL; + void *cookie = NULL; + es_syshd_t syshd; + + /* Memory streams are always read/write. We use MODE only to get + the append flag. */ + if (parse_mode (mode, &modeflags, &xmode, NULL)) + return NULL; + modeflags |= O_RDWR; + + if (func_mem_create (&cookie, NULL, 0, 0, + BUFFER_BLOCK_SIZE, 1, + mem_realloc, mem_free, modeflags, + memlimit)) + return NULL; + + memset (&syshd, 0, sizeof syshd); + if (create_stream (&stream, cookie, &syshd, BACKEND_MEM, + estream_functions_mem, modeflags, xmode, 0)) + (*estream_functions_mem.public.func_close) (cookie); + + return stream; +} + + +/* This is the same as es_fopenmem but intializes the memory with a + copy of (DATA,DATALEN). The stream is initially set to the + beginning. If MEMLIMIT is not 0 but shorter than DATALEN it + DATALEN will be used as the value for MEMLIMIT. */ +estream_t +_gpgrt_fopenmem_init (size_t memlimit, const char *_GPGRT__RESTRICT mode, + const void *data, size_t datalen) +{ + estream_t stream; + + if (memlimit && memlimit < datalen) + memlimit = datalen; + + stream = _gpgrt_fopenmem (memlimit, mode); + if (stream && data && datalen) + { + if (es_writen (stream, data, datalen, NULL)) + { + int saveerrno = errno; + _gpgrt_fclose (stream); + stream = NULL; + _set_errno (saveerrno); + } + else + { + es_seek (stream, 0L, SEEK_SET, NULL); + stream->intern->indicators.eof = 0; + stream->intern->indicators.err = 0; + } + } + return stream; +} + + + +estream_t +_gpgrt_fopencookie (void *_GPGRT__RESTRICT cookie, + const char *_GPGRT__RESTRICT mode, + gpgrt_cookie_io_functions_t functions) +{ + unsigned int modeflags, xmode; + estream_t stream; + int err; + es_syshd_t syshd; + struct cookie_io_functions_s io_functions = { functions, NULL }; + + stream = NULL; + modeflags = 0; + + err = parse_mode (mode, &modeflags, &xmode, NULL); + if (err) + goto out; + + memset (&syshd, 0, sizeof syshd); + err = create_stream (&stream, cookie, &syshd, BACKEND_USER, io_functions, + modeflags, xmode, 0); + if (err) + goto out; + + out: + return stream; +} + + + +static estream_t +do_fdopen (int filedes, const char *mode, int no_close, int with_locked_list) +{ + int create_called = 0; + estream_t stream = NULL; + void *cookie = NULL; + unsigned int modeflags, xmode; + int err; + es_syshd_t syshd; + + err = parse_mode (mode, &modeflags, &xmode, NULL); + if (err) + goto out; + if ((xmode & X_SYSOPEN)) + { + /* Not allowed for fdopen. */ + _set_errno (EINVAL); + err = -1; + goto out; + } + + err = func_fd_create (&cookie, filedes, modeflags, no_close); + if (err) + goto out; + + syshd.type = ES_SYSHD_FD; + syshd.u.fd = filedes; + create_called = 1; + err = create_stream (&stream, cookie, &syshd, + BACKEND_FD, estream_functions_fd, + modeflags, xmode, with_locked_list); + + if (!err && stream) + { + if ((modeflags & O_NONBLOCK)) + err = stream->intern->func_ioctl (cookie, COOKIE_IOCTL_NONBLOCK, + "", NULL); + } + + out: + if (err && create_called) + (*estream_functions_fd.public.func_close) (cookie); + + return stream; +} + +estream_t +_gpgrt_fdopen (int filedes, const char *mode) +{ + return do_fdopen (filedes, mode, 0, 0); +} + +/* A variant of es_fdopen which does not close FILEDES at the end. */ +estream_t +_gpgrt_fdopen_nc (int filedes, const char *mode) +{ + return do_fdopen (filedes, mode, 1, 0); +} + + + +static estream_t +do_fpopen (FILE *fp, const char *mode, int no_close, int with_locked_list) +{ + unsigned int modeflags, cmode, xmode; + int create_called = 0; + estream_t stream = NULL; + void *cookie = NULL; + int err; + es_syshd_t syshd; + + err = parse_mode (mode, &modeflags, &xmode, &cmode); + if (err) + goto out; + if ((xmode & X_SYSOPEN)) + { + /* Not allowed for fpopen. */ + _set_errno (EINVAL); + err = -1; + goto out; + } + + if (fp) + fflush (fp); + err = func_fp_create (&cookie, fp, modeflags, no_close); + if (err) + goto out; + + syshd.type = ES_SYSHD_FD; + syshd.u.fd = fp? fileno (fp): -1; + create_called = 1; + err = create_stream (&stream, cookie, &syshd, + BACKEND_FP, estream_functions_fp, + modeflags, xmode, with_locked_list); + + out: + if (err && create_called) + (*estream_functions_fp.public.func_close) (cookie); + + return stream; +} + + +/* Create an estream from the stdio stream FP. This mechanism is + useful in case the stdio streams have special properties and may + not be mixed with fd based functions. This is for example the case + under Windows where the 3 standard streams are associated with the + console whereas a duped and fd-opened stream of one of this stream + won't be associated with the console. As this messes things up it + is easier to keep on using the standard I/O stream as a backend for + estream. */ +estream_t +_gpgrt_fpopen (FILE *fp, const char *mode) +{ + return do_fpopen (fp, mode, 0, 0); +} + + +/* Same as es_fpopen but does not close FP at the end. */ +estream_t +_gpgrt_fpopen_nc (FILE *fp, const char *mode) +{ + return do_fpopen (fp, mode, 1, 0); +} + + + +#ifdef HAVE_W32_SYSTEM +estream_t +do_w32open (HANDLE hd, const char *mode, + int no_close, int with_locked_list) +{ + unsigned int modeflags, cmode, xmode; + int create_called = 0; + estream_t stream = NULL; + void *cookie = NULL; + int err; + es_syshd_t syshd; + + /* For obvious reasons we ignore sysmode here. */ + err = parse_mode (mode, &modeflags, &xmode, &cmode); + if (err) + goto leave; + + /* If we are pollable we create the function cookie with syscall + * clamp disabled. This is because functions are called from + * separatre reader and writer threads in w32-stream. */ + err = func_w32_create (&cookie, hd, modeflags, + no_close, !!(xmode & X_POLLABLE)); + if (err) + goto leave; + + syshd.type = ES_SYSHD_HANDLE; + syshd.u.handle = hd; + create_called = 1; + err = create_stream (&stream, cookie, &syshd, + BACKEND_W32, estream_functions_w32, + modeflags, xmode, with_locked_list); + + leave: + if (err && create_called) + (*estream_functions_w32.public.func_close) (cookie); + + return stream; +} +#endif /*HAVE_W32_SYSTEM*/ + +static estream_t +do_sysopen (es_syshd_t *syshd, const char *mode, int no_close) +{ + estream_t stream; + + switch (syshd->type) + { + case ES_SYSHD_FD: + case ES_SYSHD_SOCK: + stream = do_fdopen (syshd->u.fd, mode, no_close, 0); + break; + +#ifdef HAVE_W32_SYSTEM + case ES_SYSHD_HANDLE: + stream = do_w32open (syshd->u.handle, mode, no_close, 0); + break; +#endif + + /* FIXME: Support RVIDs under Wince? */ + + default: + _set_errno (EINVAL); + stream = NULL; + } + return stream; +} + +/* On POSIX systems this function is an alias for es_fdopen. Under + Windows it uses the bare W32 API and thus a HANDLE instead of a + file descriptor. */ +estream_t +_gpgrt_sysopen (es_syshd_t *syshd, const char *mode) +{ + return do_sysopen (syshd, mode, 0); +} + +/* Same as es_sysopen but the handle/fd will not be closed by + es_fclose. */ +estream_t +_gpgrt_sysopen_nc (es_syshd_t *syshd, const char *mode) +{ + return do_sysopen (syshd, mode, 1); +} + + + +/* Set custom standard descriptors to be used for stdin, stdout and + stderr. This function needs to be called before any of the + standard streams are accessed. This internal version uses a double + dash inside its name. */ +void +_gpgrt__set_std_fd (int no, int fd) +{ + /* fprintf (stderr, "es_set_std_fd(%d, %d)\n", no, fd); */ + lock_list (); + if (no >= 0 && no < 3 && !custom_std_fds_valid[no]) + { + custom_std_fds[no] = fd; + custom_std_fds_valid[no] = 1; + } + unlock_list (); +} + + +/* Return the stream used for stdin, stdout or stderr. + This internal version uses a double dash inside its name. */ +estream_t +_gpgrt__get_std_stream (int fd) +{ + estream_list_t list_obj; + estream_t stream = NULL; + + fd %= 3; /* We only allow 0, 1 or 2 but we don't want to return an error. */ + + lock_list (); + + for (list_obj = estream_list; list_obj; list_obj = list_obj->next) + if (list_obj->stream && list_obj->stream->intern->is_stdstream + && list_obj->stream->intern->stdstream_fd == fd) + { + stream = list_obj->stream; + break; + } + if (!stream) + { + /* Standard stream not yet created. We first try to create them + from registered file descriptors. */ + if (!fd && custom_std_fds_valid[0]) + stream = do_fdopen (custom_std_fds[0], "r", 1, 1); + else if (fd == 1 && custom_std_fds_valid[1]) + stream = do_fdopen (custom_std_fds[1], "a", 1, 1); + else if (custom_std_fds_valid[2]) + stream = do_fdopen (custom_std_fds[2], "a", 1, 1); + + if (!stream) + { + /* Second try is to use the standard C streams. */ + if (!fd) + stream = do_fpopen (stdin, "r", 1, 1); + else if (fd == 1) + stream = do_fpopen (stdout, "a", 1, 1); + else + stream = do_fpopen (stderr, "a", 1, 1); + } + + if (!stream) + { + /* Last try: Create a bit bucket. */ + stream = do_fpopen (NULL, fd? "a":"r", 0, 1); + if (!stream) + { + fprintf (stderr, "fatal: error creating a dummy estream" + " for %d: %s\n", fd, strerror (errno)); + _gpgrt_abort(); + } + } + + stream->intern->is_stdstream = 1; + stream->intern->stdstream_fd = fd; + if (fd == 2) + es_set_buffering (stream, NULL, _IOLBF, 0); + fname_set_internal (stream, + fd == 0? "[stdin]" : + fd == 1? "[stdout]" : "[stderr]", 0); + } + + unlock_list (); + return stream; +} + +/* Note: A "samethread" keyword given in "mode" is ignored and the + * value used by STREAM is used instead. Note that this function is + * the reasons why some of the init and deinit code is split up into + * several functions. */ +estream_t +_gpgrt_freopen (const char *_GPGRT__RESTRICT path, + const char *_GPGRT__RESTRICT mode, + estream_t _GPGRT__RESTRICT stream) +{ + int err; + + if (path) + { + unsigned int modeflags, cmode, xmode, dummy; + int create_called; + void *cookie; + int fd; + es_syshd_t syshd; + + cookie = NULL; + create_called = 0; + + xmode = stream->intern->samethread ? X_SAMETHREAD : 0; + + lock_stream (stream); + + deinit_stream_obj (stream); + + err = parse_mode (mode, &modeflags, &dummy, &cmode); + if (err) + goto leave; + (void)dummy; + + err = func_file_create (&cookie, &fd, path, modeflags, cmode); + if (err) + goto leave; + + syshd.type = ES_SYSHD_FD; + syshd.u.fd = fd; + create_called = 1; + init_stream_obj (stream, cookie, &syshd, BACKEND_FD, + estream_functions_fd, modeflags, xmode); + + leave: + + if (err) + { + if (create_called) + func_fd_destroy (cookie); + + do_close (stream, 0, 0); + stream = NULL; + } + else + { + if (path) + fname_set_internal (stream, path, 1); + unlock_stream (stream); + } + } + else + { + /* FIXME? We don't support re-opening at the moment. */ + _set_errno (EINVAL); + deinit_stream_obj (stream); + do_close (stream, 0, 0); + stream = NULL; + } + + return stream; +} + + +int +_gpgrt_fclose (estream_t stream) +{ + int err; + + err = do_close (stream, 0, 0); + + return err; +} + + +/* gpgrt_fcancel does the same as gpgrt_fclose but tries to avoid + * flushing out any data still held in internal buffers. It may or + * may not remove a new file created for that stream by the open + * function. */ +int +_gpgrt_fcancel (estream_t stream) +{ + int err; + + err = do_close (stream, 1, 0); + + return err; +} + + +/* This is a special version of es_fclose which can be used with + es_fopenmem to return the memory buffer. This is feature is useful + to write to a memory buffer using estream. Note that the function + does not close the stream if the stream does not support snatching + the buffer. On error NULL is stored at R_BUFFER. Note that if no + write operation has happened, NULL may also be stored at BUFFER on + success. The caller needs to release the returned memory using + gpgrt_free. */ +int +_gpgrt_fclose_snatch (estream_t stream, void **r_buffer, size_t *r_buflen) +{ + int err; + + /* Note: There is no need to lock the stream in a close call. The + object will be destroyed after the close and thus any other + contender for the lock would work on a closed stream. */ + + if (r_buffer) + { + cookie_ioctl_function_t func_ioctl = stream->intern->func_ioctl; + size_t buflen; + + *r_buffer = NULL; + + if (!func_ioctl) + { + _set_errno (EOPNOTSUPP); + err = -1; + goto leave; + } + + if (stream->flags.writing) + { + err = flush_stream (stream); + if (err) + goto leave; + stream->flags.writing = 0; + } + + err = func_ioctl (stream->intern->cookie, COOKIE_IOCTL_SNATCH_BUFFER, + r_buffer, &buflen); + if (err) + goto leave; + if (r_buflen) + *r_buflen = buflen; + } + + err = do_close (stream, 0, 0); + + leave: + if (err && r_buffer) + { + mem_free (*r_buffer); + *r_buffer = NULL; + } + return err; +} + + +/* Register or unregister a close notification function for STREAM. + FNC is the function to call and FNC_VALUE the value passed as + second argument. To register the notification the value for MODE + must be 1. If mode is 0 the function tries to remove or disable an + already registered notification; for this to work the value of FNC + and FNC_VALUE must be the same as with the registration and + FNC_VALUE must be a unique value. No error will be returned if + MODE is 0. + + FIXME: I think the next comment is not anymore correct: + Unregister should only be used in the error case because it may not + be able to remove memory internally allocated for the onclose + handler. + + FIXME: Unregister is not thread safe. + + The notification will be called right before the stream is + closed. If gpgrt_fcancel is used, the cancellation of internal + buffers is done before the notifications. The notification handler + may not call any estream function for STREAM, neither direct nor + indirectly. */ +int +_gpgrt_onclose (estream_t stream, int mode, + void (*fnc) (estream_t, void*), void *fnc_value) +{ + int err; + + lock_stream (stream); + err = do_onclose (stream, mode, fnc, fnc_value); + unlock_stream (stream); + + return err; +} + + +int +_gpgrt_fileno_unlocked (estream_t stream) +{ + es_syshd_t syshd; + + if (_gpgrt_syshd_unlocked (stream, &syshd)) + return -1; + switch (syshd.type) + { + case ES_SYSHD_FD: return syshd.u.fd; + case ES_SYSHD_SOCK: return syshd.u.sock; + default: + _set_errno (EINVAL); + return -1; + } +} + + +/* Return the handle of a stream which has been opened by es_sysopen. + The caller needs to pass a structure which will be filled with the + sys handle. Return 0 on success or true on error and sets errno. + This is the unlocked version. */ +int +_gpgrt_syshd_unlocked (estream_t stream, es_syshd_t *syshd) +{ + if (!stream || !syshd || stream->intern->syshd.type == ES_SYSHD_NONE) + { + if (syshd) + syshd->type = ES_SYSHD_NONE; + _set_errno (EINVAL); + return -1; + } + + *syshd = stream->intern->syshd; + return 0; +} + + +void +_gpgrt_flockfile (estream_t stream) +{ + lock_stream (stream); +} + + +int +_gpgrt_ftrylockfile (estream_t stream) +{ + return trylock_stream (stream); +} + + +void +_gpgrt_funlockfile (estream_t stream) +{ + unlock_stream (stream); +} + + +int +_gpgrt_fileno (estream_t stream) +{ + int ret; + + lock_stream (stream); + ret = _gpgrt_fileno_unlocked (stream); + unlock_stream (stream); + + return ret; +} + + +/* Return the handle of a stream which has been opened by es_sysopen. + The caller needs to pass a structure which will be filled with the + sys handle. Return 0 on success or true on error and sets errno. + This is the unlocked version. */ +int +_gpgrt_syshd (estream_t stream, es_syshd_t *syshd) +{ + int ret; + + lock_stream (stream); + ret = _gpgrt_syshd_unlocked (stream, syshd); + unlock_stream (stream); + + return ret; +} + + +int +_gpgrt__pending_unlocked (estream_t stream) +{ + return check_pending (stream); +} + + +/* Return true if there is at least one byte pending for read on + STREAM. This does only work if the backend supports checking for + pending bytes and is thus mostly useful with cookie based backends. + + Note that if this function is used with cookie based functions, the + read cookie may be called with 0 for the SIZE argument. If bytes + are pending the function is expected to return -1 in this case and + thus deviates from the standard behavior of read(2). */ +int +_gpgrt__pending (estream_t stream) +{ + int ret; + + lock_stream (stream); + ret = _gpgrt__pending_unlocked (stream); + unlock_stream (stream); + + return ret; +} + + +int +_gpgrt_feof_unlocked (estream_t stream) +{ + return stream->intern->indicators.eof; +} + + +int +_gpgrt_feof (estream_t stream) +{ + int ret; + + lock_stream (stream); + ret = _gpgrt_feof_unlocked (stream); + unlock_stream (stream); + + return ret; +} + + +int +_gpgrt_ferror_unlocked (estream_t stream) +{ + return stream->intern->indicators.err; +} + + +int +_gpgrt_ferror (estream_t stream) +{ + int ret; + + lock_stream (stream); + ret = _gpgrt_ferror_unlocked (stream); + unlock_stream (stream); + + return ret; +} + + +void +_gpgrt_clearerr_unlocked (estream_t stream) +{ + stream->intern->indicators.eof = 0; + stream->intern->indicators.err = 0; + /* We do not reset the HUP indicator because there is no way to + get out of this state. */ +} + + +void +_gpgrt_clearerr (estream_t stream) +{ + lock_stream (stream); + _gpgrt_clearerr_unlocked (stream); + unlock_stream (stream); +} + + +static int +do_fflush (estream_t stream) +{ + int err; + + if (stream->flags.writing) + err = flush_stream (stream); + else + { + es_empty (stream); + err = 0; + } + + return err; +} + + +int +_gpgrt_fflush (estream_t stream) +{ + int err; + + if (stream) + { + lock_stream (stream); + err = do_fflush (stream); + unlock_stream (stream); + } + else + { + estream_list_t item; + + err = 0; + lock_list (); + for (item = estream_list; item; item = item->next) + if (item->stream) + { + lock_stream (item->stream); + err |= do_fflush (item->stream); + unlock_stream (item->stream); + } + unlock_list (); + } + return err ? EOF : 0; +} + + +int +_gpgrt_fseek (estream_t stream, long int offset, int whence) +{ + int err; + + lock_stream (stream); + err = es_seek (stream, offset, whence, NULL); + unlock_stream (stream); + + return err; +} + + +int +_gpgrt_fseeko (estream_t stream, gpgrt_off_t offset, int whence) +{ + int err; + + lock_stream (stream); + err = es_seek (stream, offset, whence, NULL); + unlock_stream (stream); + + return err; +} + + +long int +_gpgrt_ftell (estream_t stream) +{ + long int ret; + + lock_stream (stream); + ret = es_offset_calculate (stream); + unlock_stream (stream); + + return ret; +} + + +gpgrt_off_t +_gpgrt_ftello (estream_t stream) +{ + gpgrt_off_t ret = -1; + + lock_stream (stream); + ret = es_offset_calculate (stream); + unlock_stream (stream); + + return ret; +} + + +void +_gpgrt_rewind (estream_t stream) +{ + lock_stream (stream); + es_seek (stream, 0L, SEEK_SET, NULL); + /* Note that es_seek already cleared the EOF flag. */ + stream->intern->indicators.err = 0; + unlock_stream (stream); +} + + +int +_gpgrt_ftruncate (estream_t stream, gpgrt_off_t length) +{ + cookie_ioctl_function_t func_ioctl; + int ret; + + lock_stream (stream); + func_ioctl = stream->intern->func_ioctl; + if (!func_ioctl) + { + _set_errno (EOPNOTSUPP); + ret = -1; + } + else + { + ret = func_ioctl (stream->intern->cookie, COOKIE_IOCTL_TRUNCATE, + &length, NULL); + } + unlock_stream (stream); + return ret; +} + + +int +_gpgrt__getc_underflow (estream_t stream) +{ + int err; + unsigned char c; + size_t bytes_read; + + err = es_readn (stream, &c, 1, &bytes_read); + + return (err || (! bytes_read)) ? EOF : c; +} + + +int +_gpgrt__putc_overflow (int c, estream_t stream) +{ + unsigned char d = c; + int err; + + err = es_writen (stream, &d, 1, NULL); + + return err ? EOF : c; +} + + +int +_gpgrt_fgetc (estream_t stream) +{ + int ret; + + lock_stream (stream); + ret = _gpgrt_getc_unlocked (stream); + unlock_stream (stream); + + return ret; +} + + +int +_gpgrt_fputc (int c, estream_t stream) +{ + int ret; + + lock_stream (stream); + ret = _gpgrt_putc_unlocked (c, stream); + unlock_stream (stream); + + return ret; +} + + +int +_gpgrt_ungetc (int c, estream_t stream) +{ + unsigned char data = (unsigned char) c; + size_t data_unread; + + lock_stream (stream); + es_unreadn (stream, &data, 1, &data_unread); + unlock_stream (stream); + + return data_unread ? c : EOF; +} + + +int +_gpgrt_read (estream_t _GPGRT__RESTRICT stream, + void *_GPGRT__RESTRICT buffer, size_t bytes_to_read, + size_t *_GPGRT__RESTRICT bytes_read) +{ + int err; + + if (bytes_to_read) + { + lock_stream (stream); + err = es_readn (stream, buffer, bytes_to_read, bytes_read); + unlock_stream (stream); + } + else + err = 0; + + return err; +} + + +int +_gpgrt_write (estream_t _GPGRT__RESTRICT stream, + const void *_GPGRT__RESTRICT buffer, size_t bytes_to_write, + size_t *_GPGRT__RESTRICT bytes_written) +{ + int err; + + if (bytes_to_write) + { + lock_stream (stream); + err = es_writen (stream, buffer, bytes_to_write, bytes_written); + unlock_stream (stream); + } + else + err = 0; + + return err; +} + + +size_t +_gpgrt_fread (void *_GPGRT__RESTRICT ptr, size_t size, size_t nitems, + estream_t _GPGRT__RESTRICT stream) +{ + size_t ret, bytes; + + if (size && nitems) + { + lock_stream (stream); + es_readn (stream, ptr, size * nitems, &bytes); + unlock_stream (stream); + + ret = bytes / size; + } + else + ret = 0; + + return ret; +} + + +size_t +_gpgrt_fwrite (const void *_GPGRT__RESTRICT ptr, size_t size, size_t nitems, + estream_t _GPGRT__RESTRICT stream) +{ + size_t ret, bytes; + + if (size && nitems) + { + lock_stream (stream); + es_writen (stream, ptr, size * nitems, &bytes); + unlock_stream (stream); + + ret = bytes / size; + } + else + ret = 0; + + return ret; +} + + +char * +_gpgrt_fgets (char *_GPGRT__RESTRICT buffer, int length, + estream_t _GPGRT__RESTRICT stream) +{ + unsigned char *s = (unsigned char*)buffer; + int c; + + if (!length) + return NULL; + + c = EOF; + lock_stream (stream); + while (length > 1 && (c = _gpgrt_getc_unlocked (stream)) != EOF && c != '\n') + { + *s++ = c; + length--; + } + unlock_stream (stream); + + if (c == EOF && s == (unsigned char*)buffer) + return NULL; /* Nothing read. */ + + if (c != EOF && length > 1) + *s++ = c; + + *s = 0; + return buffer; +} + + +int +_gpgrt_fputs_unlocked (const char *_GPGRT__RESTRICT s, + estream_t _GPGRT__RESTRICT stream) +{ + size_t length; + int err; + + length = strlen (s); + err = es_writen (stream, s, length, NULL); + return err ? EOF : 0; +} + +int +_gpgrt_fputs (const char *_GPGRT__RESTRICT s, estream_t _GPGRT__RESTRICT stream) +{ + size_t length; + int err; + + length = strlen (s); + lock_stream (stream); + err = es_writen (stream, s, length, NULL); + unlock_stream (stream); + + return err ? EOF : 0; +} + + +gpgrt_ssize_t +_gpgrt_getline (char *_GPGRT__RESTRICT *_GPGRT__RESTRICT lineptr, + size_t *_GPGRT__RESTRICT n, estream_t _GPGRT__RESTRICT stream) +{ + char *line = NULL; + size_t line_n = 0; + int err; + + lock_stream (stream); + err = doreadline (stream, 0, &line, &line_n); + unlock_stream (stream); + if (err) + goto out; + + if (*n) + { + /* Caller wants us to use his buffer. */ + + if (*n < (line_n + 1)) + { + /* Provided buffer is too small -> resize. */ + + void *p; + + p = mem_realloc (*lineptr, line_n + 1); + if (! p) + err = -1; + else + { + if (*lineptr != p) + *lineptr = p; + } + } + + if (! err) + { + memcpy (*lineptr, line, line_n + 1); + if (*n != line_n) + *n = line_n; + } + mem_free (line); + } + else + { + /* Caller wants new buffers. */ + *lineptr = line; + *n = line_n; + } + + out: + + return err ? err : (gpgrt_ssize_t)line_n; +} + + + +/* Same as fgets() but if the provided buffer is too short a larger + one will be allocated. This is similar to getline. A line is + considered a byte stream ending in a LF. + + If MAX_LENGTH is not NULL, it shall point to a value with the + maximum allowed allocation. + + Returns the length of the line. EOF is indicated by a line of + length zero. A truncated line is indicated my setting the value at + MAX_LENGTH to 0. If the returned value is less then 0 not enough + memory was available or another error occurred; ERRNO is then set + accordingly. + + If a line has been truncated, the file pointer is moved forward to + the end of the line so that the next read starts with the next + line. Note that MAX_LENGTH must be re-initialized in this case. + + The caller initially needs to provide the address of a variable, + initialized to NULL, at ADDR_OF_BUFFER and don't change this value + anymore with the following invocations. LENGTH_OF_BUFFER should be + the address of a variable, initialized to 0, which is also + maintained by this function. Thus, both paramaters should be + considered the state of this function. + + Note: The returned buffer is allocated with enough extra space to + allow the caller to append a CR,LF,Nul. The buffer should be + released using gpgrt_free. + */ +gpgrt_ssize_t +_gpgrt_read_line (estream_t stream, + char **addr_of_buffer, size_t *length_of_buffer, + size_t *max_length) +{ + int c; + char *buffer = *addr_of_buffer; + size_t length = *length_of_buffer; + size_t nbytes = 0; + size_t maxlen = max_length? *max_length : 0; + char *p; + + if (!buffer) + { + /* No buffer given - allocate a new one. */ + length = 256; + buffer = mem_alloc (length); + *addr_of_buffer = buffer; + if (!buffer) + { + *length_of_buffer = 0; + if (max_length) + *max_length = 0; + return -1; + } + *length_of_buffer = length; + } + + if (length < 4) + { + /* This should never happen. If it does, the function has been + called with wrong arguments. */ + _set_errno (EINVAL); + return -1; + } + length -= 3; /* Reserve 3 bytes for CR,LF,EOL. */ + + lock_stream (stream); + p = buffer; + while ((c = _gpgrt_getc_unlocked (stream)) != EOF) + { + if (nbytes == length) + { + /* Enlarge the buffer. */ + if (maxlen && length > maxlen) + { + /* We are beyond our limit: Skip the rest of the line. */ + while (c != '\n' && (c=_gpgrt_getc_unlocked (stream)) != EOF) + ; + *p++ = '\n'; /* Always append a LF (we reserved some space). */ + nbytes++; + if (max_length) + *max_length = 0; /* Indicate truncation. */ + break; /* the while loop. */ + } + length += 3; /* Adjust for the reserved bytes. */ + length += length < 1024? 256 : 1024; + *addr_of_buffer = mem_realloc (buffer, length); + if (!*addr_of_buffer) + { + int save_errno = errno; + mem_free (buffer); + *length_of_buffer = 0; + if (max_length) + *max_length = 0; + unlock_stream (stream); + _set_errno (save_errno); + return -1; + } + buffer = *addr_of_buffer; + *length_of_buffer = length; + length -= 3; + p = buffer + nbytes; + } + *p++ = c; + nbytes++; + if (c == '\n') + break; + } + *p = 0; /* Make sure the line is a string. */ + unlock_stream (stream); + + return nbytes; +} + +/* Wrapper around free() to match the memory allocation system used by + estream. Should be used for all buffers returned to the caller by + libestream. If a custom allocation handler has been set with + gpgrt_set_alloc_func that register function may be used + instead. This function has been moved to init.c. */ +/* void */ +/* _gpgrt_free (void *a) */ +/* { */ +/* mem_free (a); */ +/* } */ + + +int +_gpgrt_vfprintf_unlocked (estream_t _GPGRT__RESTRICT stream, + gpgrt_string_filter_t sf, void *sfvalue, + const char *_GPGRT__RESTRICT format, + va_list ap) +{ + return do_print_stream (stream, sf, sfvalue, format, ap); +} + + +int +_gpgrt_vfprintf (estream_t _GPGRT__RESTRICT stream, + gpgrt_string_filter_t sf, void *sfvalue, + const char *_GPGRT__RESTRICT format, + va_list ap) +{ + int ret; + + lock_stream (stream); + ret = do_print_stream (stream, sf, sfvalue, format, ap); + unlock_stream (stream); + + return ret; +} + + +int +_gpgrt_fprintf_unlocked (estream_t _GPGRT__RESTRICT stream, + const char *_GPGRT__RESTRICT format, ...) +{ + int ret; + + va_list ap; + va_start (ap, format); + ret = do_print_stream (stream, NULL, NULL, format, ap); + va_end (ap); + + return ret; +} + + +int +_gpgrt_fprintf (estream_t _GPGRT__RESTRICT stream, + const char *_GPGRT__RESTRICT format, ...) +{ + int ret; + + va_list ap; + va_start (ap, format); + lock_stream (stream); + ret = do_print_stream (stream, NULL, NULL, format, ap); + unlock_stream (stream); + va_end (ap); + + return ret; +} + + +static int +tmpfd (void) +{ +#ifdef HAVE_W32_SYSTEM + int attempts, n; +#ifdef HAVE_W32CE_SYSTEM + wchar_t buffer[MAX_PATH+9+12+1]; +# define mystrlen(a) wcslen (a) + wchar_t *name, *p; +#else + char buffer[MAX_PATH+9+12+1]; +# define mystrlen(a) strlen (a) + char *name, *p; +#endif + HANDLE file; + int pid = GetCurrentProcessId (); + unsigned int value; + int i; + + n = GetTempPath (MAX_PATH+1, buffer); + if (!n || n > MAX_PATH || mystrlen (buffer) > MAX_PATH) + { + _set_errno (ENOENT); + return -1; + } + p = buffer + mystrlen (buffer); +#ifdef HAVE_W32CE_SYSTEM + wcscpy (p, L"_estream"); +#else + strcpy (p, "_estream"); +#endif + p += 8; + /* We try to create the directory but don't care about an error as + it may already exist and the CreateFile would throw an error + anyway. */ + CreateDirectory (buffer, NULL); + *p++ = '\\'; + name = p; + for (attempts=0; attempts < 10; attempts++) + { + p = name; + value = (GetTickCount () ^ ((pid<<16) & 0xffff0000)); + for (i=0; i < 8; i++) + { + *p++ = tohex (((value >> 28) & 0x0f)); + value <<= 4; + } +#ifdef HAVE_W32CE_SYSTEM + wcscpy (p, L".tmp"); +#else + strcpy (p, ".tmp"); +#endif + file = CreateFile (buffer, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + CREATE_NEW, + FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, + NULL); + if (file != INVALID_HANDLE_VALUE) + { +#ifdef HAVE_W32CE_SYSTEM + int fd = (int)file; +#else + int fd = _open_osfhandle ((intptr_t)file, 0); + if (fd == -1) + { + CloseHandle (file); + return -1; + } +#endif + return fd; + } + Sleep (1); /* One ms as this is the granularity of GetTickCount. */ + } + _set_errno (ENOENT); + return -1; +#else /*!HAVE_W32_SYSTEM*/ + FILE *fp; + int fp_fd; + int fd; + + fp = NULL; + fd = -1; + + fp = tmpfile (); + if (! fp) + goto out; + + fp_fd = fileno (fp); + fd = dup (fp_fd); + + out: + + if (fp) + fclose (fp); + + return fd; +#endif /*!HAVE_W32_SYSTEM*/ +} + +estream_t +_gpgrt_tmpfile (void) +{ + unsigned int modeflags; + int create_called = 0; + estream_t stream = NULL; + void *cookie = NULL; + int err; + int fd; + es_syshd_t syshd; + + modeflags = O_RDWR | O_TRUNC | O_CREAT; + + fd = tmpfd (); + if (fd == -1) + { + err = -1; + goto out; + } + + err = func_fd_create (&cookie, fd, modeflags, 0); + if (err) + goto out; + + syshd.type = ES_SYSHD_FD; + syshd.u.fd = fd; + create_called = 1; + err = create_stream (&stream, cookie, &syshd, + BACKEND_FD, estream_functions_fd, + modeflags, 0, 0); + + out: + if (err) + { + if (create_called) + func_fd_destroy (cookie); + else if (fd != -1) + close (fd); + stream = NULL; + } + + return stream; +} + + +int +_gpgrt_setvbuf (estream_t _GPGRT__RESTRICT stream, + char *_GPGRT__RESTRICT buf, int type, size_t size) +{ + int err; + + if ((type == _IOFBF || type == _IOLBF || type == _IONBF) + && (!buf || size || type == _IONBF)) + { + lock_stream (stream); + err = es_set_buffering (stream, buf, type, size); + unlock_stream (stream); + } + else + { + _set_errno (EINVAL); + err = -1; + } + + return err; +} + + +/* Put a stream into binary mode. This is only needed for the + standard streams if they are to be used in a binary way. On Unix + systems it is never needed but MSDOS based systems require such a + call. It needs to be called before any I/O is done on STREAM. */ +void +_gpgrt_set_binary (estream_t stream) +{ + lock_stream (stream); + if (!(stream->intern->modeflags & O_BINARY)) + { + stream->intern->modeflags |= O_BINARY; +#ifdef HAVE_DOSISH_SYSTEM + if (stream->intern->func_read == func_fd_read) + { + estream_cookie_fd_t fd_cookie = stream->intern->cookie; + + if (!IS_INVALID_FD (fd_cookie->fd)) + setmode (fd_cookie->fd, O_BINARY); + } + else if (stream->intern->func_read == func_fp_read) + { + estream_cookie_fp_t fp_cookie = stream->intern->cookie; + + if (fp_cookie->fp) + setmode (fileno (fp_cookie->fp), O_BINARY); + } +#endif + } + unlock_stream (stream); +} + + +/* Set non-blocking mode for STREAM. Use true for ONOFF to enable and + false to disable non-blocking mode. Returns 0 on success or -1 on + error and sets ERRNO. Note that not all backends support + non-blocking mode. + + In non-blocking mode a system call will not block but return an + error and set errno to EAGAIN. The estream API always uses EAGAIN + and not EWOULDBLOCK. If a buffered function like es_fgetc() or + es_fgets() returns an error and both, feof() and ferror() return + false the caller may assume that the error condition was EAGAIN. + + Switching back from non-blocking to blocking may raise problems + with buffering, thus care should be taken. Although read+write + sockets are supported in theory, switching from write to read may + result into problems because estream may first flush the write + buffers and there is no way to handle that non-blocking (EAGAIN) + case. Explicit flushing should thus be done before before + switching to read. */ +int +_gpgrt_set_nonblock (estream_t stream, int onoff) +{ + cookie_ioctl_function_t func_ioctl; + int ret; + + lock_stream (stream); + func_ioctl = stream->intern->func_ioctl; + if (!func_ioctl) + { + _set_errno (EOPNOTSUPP); + ret = -1; + } + else + { + unsigned int save_flags = stream->intern->modeflags; + + if (onoff) + stream->intern->modeflags |= O_NONBLOCK; + else + stream->intern->modeflags &= ~O_NONBLOCK; + + ret = func_ioctl (stream->intern->cookie, COOKIE_IOCTL_NONBLOCK, + onoff?"":NULL, NULL); + if (ret) + stream->intern->modeflags = save_flags; + } + unlock_stream (stream); + return ret; +} + + +/* Return true if STREAM is in non-blocking mode. */ +int +_gpgrt_get_nonblock (estream_t stream) +{ + int ret; + + lock_stream (stream); + ret = !!(stream->intern->modeflags & O_NONBLOCK); + unlock_stream (stream); + return ret; +} + + +/* A version of poll(2) working on estream handles. Note that not all + estream types work with this function. In contrast to the standard + poll function the gpgrt_poll_t object uses a set of bit flags + instead of the EVENTS and REVENTS members. An item with the IGNORE + flag set is entirely ignored. The TIMEOUT values is given in + milliseconds, a value of -1 waits indefinitely, and a value of 0 + returns immediately. + + A positive return value gives the number of fds with new + information. A return value of 0 indicates a timeout and -1 + indicates an error in which case ERRNO is set. */ +int +_gpgrt_poll (gpgrt_poll_t *fds, unsigned int nfds, int timeout) +{ + gpgrt_poll_t *item; + int count = 0; + int idx; +#ifndef HAVE_W32_SYSTEM +# ifdef HAVE_POLL_H + struct pollfd *poll_fds = NULL; + nfds_t poll_nfds; +# else + fd_set readfds, writefds, exceptfds; + int any_readfd, any_writefd, any_exceptfd; + int max_fd; +#endif + int fd, ret, any; +#endif /*HAVE_W32_SYSTEM*/ + + trace (("enter: nfds=%u timeout=%d", nfds, timeout)); + + if (!fds) + { + _set_errno (EINVAL); + count = -1; + goto leave; + } + + /* Clear all response fields (even for ignored items). */ + for (item = fds, idx = 0; idx < nfds; item++, idx++) + { + item->got_read = 0; + item->got_write = 0; + item->got_oob = 0; + item->got_rdhup = 0; + item->got_err = 0; + item->got_hup = 0; + item->got_nval = 0; + } + + /* Check for pending reads. */ + for (item = fds, idx = 0; idx < nfds; item++, idx++) + { + if (item->ignore) + continue; + if (!item->want_read) + continue; + if (_gpgrt__pending (item->stream)) + { + item->got_read = 1; + count++; + } + } + + /* Check for space in the write buffers. */ + for (item = fds, idx = 0; idx < nfds; item++, idx++) + { + if (item->ignore) + continue; + if (!item->want_write) + continue; + /* FIXME */ + } + + if (count) + goto leave; + + /* Now do the real select. */ +#ifdef HAVE_W32_SYSTEM + + _gpgrt_pre_syscall (); + count = _gpgrt_w32_poll (fds, nfds, timeout); + _gpgrt_post_syscall (); + +#else /*!HAVE_W32_SYSTEM*/ +# ifdef HAVE_POLL_H + poll_fds = xtrymalloc (sizeof (*poll_fds)*nfds); + if (!poll_fds) + { + count = -1; + goto leave; + } + poll_nfds = 0; + for (item = fds, idx = 0; idx < nfds; item++, idx++) + { + if (item->ignore) + continue; + fd = _gpgrt_fileno (item->stream); + if (fd == -1) + continue; /* Stream does not support polling. */ + + if (item->want_read || item->want_write || item->want_oob) + { + poll_fds[poll_nfds].fd = fd; + poll_fds[poll_nfds].events = ((item->want_read ? POLLIN : 0) + |(item->want_write ? POLLOUT : 0) + |(item->want_oob ? POLLPRI : 0)); + poll_fds[poll_nfds].revents = 0; + poll_nfds++; + } + } + + _gpgrt_pre_syscall (); + do + ret = poll (poll_fds, poll_nfds, timeout); + while (ret == -1 && (errno == EINTR || errno == EAGAIN)); + _gpgrt_post_syscall (); +# else /* !HAVE_POLL_H */ + any_readfd = any_writefd = any_exceptfd = 0; + max_fd = 0; + for (item = fds, idx = 0; idx < nfds; item++, idx++) + { + if (item->ignore) + continue; + fd = _gpgrt_fileno (item->stream); + if (fd == -1) + continue; /* Stream does not support polling. */ + + if (item->want_read) + { + if (!any_readfd) + { + FD_ZERO (&readfds); + any_readfd = 1; + } + FD_SET (fd, &readfds); + if (fd > max_fd) + max_fd = fd; + } + if (item->want_write) + { + if (!any_writefd) + { + FD_ZERO (&writefds); + any_writefd = 1; + } + FD_SET (fd, &writefds); + if (fd > max_fd) + max_fd = fd; + } + if (item->want_oob) + { + if (!any_exceptfd) + { + FD_ZERO (&exceptfds); + any_exceptfd = 1; + } + FD_SET (fd, &exceptfds); + if (fd > max_fd) + max_fd = fd; + } + } + + _gpgrt_pre_syscall (); + do + { + struct timeval timeout_val; + + timeout_val.tv_sec = timeout / 1000; + timeout_val.tv_usec = (timeout % 1000) * 1000; + ret = select (max_fd+1, + any_readfd? &readfds : NULL, + any_writefd? &writefds : NULL, + any_exceptfd? &exceptfds : NULL, + timeout == -1 ? NULL : &timeout_val); + } + while (ret == -1 && errno == EINTR); + _gpgrt_post_syscall (); +# endif + + if (ret == -1) + { +# ifdef HAVE_POLL_H + trace_errno (1, ("poll failed: ")); +# else + trace_errno (1, ("select failed: ")); +# endif + count = -1; + goto leave; + } + if (!ret) + { + /* Timeout. Note that in this case we can't return got_err for + * an invalid stream. */ + count = 0; + goto leave; + } + +# ifdef HAVE_POLL_H + poll_nfds = 0; + for (item = fds, idx = 0; idx < nfds; item++, idx++) + { + if (item->ignore) + continue; + fd = _gpgrt_fileno (item->stream); + if (fd == -1) + { + item->got_err = 1; /* Stream does not support polling. */ + count++; + continue; + } + + any = 0; + if (item->stream->intern->indicators.hup) + { + item->got_hup = 1; + any = 1; + } + if (item->want_read && (poll_fds[poll_nfds].revents & (POLLIN|POLLHUP))) + { + item->got_read = 1; + any = 1; + } + if (item->want_write && (poll_fds[poll_nfds].revents & POLLOUT)) + { + item->got_write = 1; + any = 1; + } + if (item->want_oob && (poll_fds[poll_nfds].revents & ~(POLLIN|POLLOUT))) + { + item->got_oob = 1; + any = 1; + } + + if (item->want_read || item->want_write || item->want_oob) + poll_nfds++; + if (any) + count++; + } +# else + for (item = fds, idx = 0; idx < nfds; item++, idx++) + { + if (item->ignore) + continue; + fd = _gpgrt_fileno (item->stream); + if (fd == -1) + { + item->got_err = 1; /* Stream does not support polling. */ + count++; + continue; + } + + any = 0; + if (item->stream->intern->indicators.hup) + { + item->got_hup = 1; + any = 1; + } + if (item->want_read && FD_ISSET (fd, &readfds)) + { + item->got_read = 1; + any = 1; + } + if (item->want_write && FD_ISSET (fd, &writefds)) + { + item->got_write = 1; + any = 1; + } + if (item->want_oob && FD_ISSET (fd, &exceptfds)) + { + item->got_oob = 1; + any = 1; + } + + if (any) + count++; + } +# endif +#endif /*!HAVE_W32_SYSTEM*/ + + leave: +#ifndef HAVE_W32_SYSTEM +# ifdef HAVE_POLL_H + xfree (poll_fds); +# endif +#endif +#ifdef ENABLE_TRACING + trace (("leave: count=%d", count)); + if (count > 0) + { + for (item = fds, idx = 0; idx < nfds; item++, idx++) + { + trace ((" %3d %c%c%c%c%c %c%c%c%c%c%c%c", + idx, + fds[idx].want_read? 'r':'-', + fds[idx].want_write? 'w':'-', + fds[idx].want_oob? 'o':'-', + fds[idx].want_rdhup? 'h':'-', + fds[idx].ignore? 'i':'-', + fds[idx].got_read? 'r':'-', + fds[idx].got_write? 'w':'-', + fds[idx].got_oob? 'o':'-', + fds[idx].got_rdhup? 'h':'-', + fds[idx].got_hup? 'H':'-', + fds[idx].got_err? 'e':'-', + fds[idx].got_nval? 'n':'-' + )); + } + } +#endif /*ENABLE_TRACING*/ + return count; +} + + +void +_gpgrt_opaque_set (estream_t stream, void *opaque) +{ + lock_stream (stream); + es_opaque_ctrl (stream, opaque, NULL); + unlock_stream (stream); +} + + +void * +_gpgrt_opaque_get (estream_t stream) +{ + void *opaque; + + lock_stream (stream); + es_opaque_ctrl (stream, NULL, &opaque); + unlock_stream (stream); + + return opaque; +} + + +static void +fname_set_internal (estream_t stream, const char *fname, int quote) +{ + if (stream->intern->printable_fname + && !stream->intern->printable_fname_inuse) + { + mem_free (stream->intern->printable_fname); + stream->intern->printable_fname = NULL; + } + if (stream->intern->printable_fname) + return; /* Can't change because it is in use. */ + + if (*fname != '[') + quote = 0; + else + quote = !!quote; + + stream->intern->printable_fname = mem_alloc (strlen (fname) + quote + 1); + if (quote) + stream->intern->printable_fname[0] = '\\'; + strcpy (stream->intern->printable_fname+quote, fname); +} + + +/* Set the filename attribute of STREAM. There is no error return. + as long as STREAM is valid. This function is called internally by + functions which open a filename. */ +void +_gpgrt_fname_set (estream_t stream, const char *fname) +{ + if (fname) + { + lock_stream (stream); + fname_set_internal (stream, fname, 1); + unlock_stream (stream); + } +} + + +/* Return the filename attribute of STREAM. In case no filename has + been set, "[?]" will be returned. The returned file name is valid + as long as STREAM is valid. */ +const char * +_gpgrt_fname_get (estream_t stream) +{ + const char *fname; + + lock_stream (stream); + fname = stream->intern->printable_fname; + if (fname) + stream->intern->printable_fname_inuse = 1; + unlock_stream (stream); + if (!fname) + fname = "[?]"; + return fname; +} + + + +/* Print a BUFFER to STREAM while replacing all control characters and + the characters in DELIMITERS by standard C escape sequences. + Returns 0 on success or -1 on error. If BYTES_WRITTEN is not NULL + the number of bytes actually written are stored at this + address. */ +int +_gpgrt_write_sanitized (estream_t _GPGRT__RESTRICT stream, + const void * _GPGRT__RESTRICT buffer, size_t length, + const char * delimiters, + size_t * _GPGRT__RESTRICT bytes_written) +{ + const unsigned char *p = buffer; + size_t count = 0; + int ret; + + lock_stream (stream); + for (; length; length--, p++, count++) + { + if (*p < 0x20 + || *p == 0x7f + || (delimiters + && (strchr (delimiters, *p) || *p == '\\'))) + { + _gpgrt_putc_unlocked ('\\', stream); + count++; + if (*p == '\n') + { + _gpgrt_putc_unlocked ('n', stream); + count++; + } + else if (*p == '\r') + { + _gpgrt_putc_unlocked ('r', stream); + count++; + } + else if (*p == '\f') + { + _gpgrt_putc_unlocked ('f', stream); + count++; + } + else if (*p == '\v') + { + _gpgrt_putc_unlocked ('v', stream); + count++; + } + else if (*p == '\b') + { + _gpgrt_putc_unlocked ('b', stream); + count++; + } + else if (!*p) + { + _gpgrt_putc_unlocked('0', stream); + count++; + } + else + { + _gpgrt_fprintf_unlocked (stream, "x%02x", *p); + count += 3; + } + } + else + { + _gpgrt_putc_unlocked (*p, stream); + count++; + } + } + + if (bytes_written) + *bytes_written = count; + ret = _gpgrt_ferror_unlocked (stream)? -1 : 0; + unlock_stream (stream); + + return ret; +} + + +/* Write LENGTH bytes of BUFFER to STREAM as a hex encoded string. + RESERVED must be 0. Returns 0 on success or -1 on error. If + BYTES_WRITTEN is not NULL the number of bytes actually written are + stored at this address. */ +int +_gpgrt_write_hexstring (estream_t _GPGRT__RESTRICT stream, + const void *_GPGRT__RESTRICT buffer, size_t length, + int reserved, size_t *_GPGRT__RESTRICT bytes_written ) +{ + int ret; + const unsigned char *s; + size_t count = 0; + + (void)reserved; + +#define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A')) + + if (!length) + return 0; + + lock_stream (stream); + + for (s = buffer; length; s++, length--) + { + _gpgrt_putc_unlocked ( tohex ((*s>>4)&15), stream); + _gpgrt_putc_unlocked ( tohex (*s&15), stream); + count += 2; + } + + if (bytes_written) + *bytes_written = count; + ret = _gpgrt_ferror_unlocked (stream)? -1 : 0; + + unlock_stream (stream); + + return ret; + +#undef tohex +} diff --git a/comm/third_party/libgpg-error/src/gen-lock-obj.sh b/comm/third_party/libgpg-error/src/gen-lock-obj.sh new file mode 100755 index 0000000000..a710f0ccee --- /dev/null +++ b/comm/third_party/libgpg-error/src/gen-lock-obj.sh @@ -0,0 +1,136 @@ +#! /bin/sh +# +# gen-lock-obj.sh - Build tool to construct the lock object. +# +# Copyright (C) 2020, 2021 g10 Code GmbH +# +# This file is part of libgpg-error. +# +# libgpg-error is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# libgpg-error is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <https://www.gnu.org/licenses/>. +# + +# +# Following variables should be defined to invoke this script +# +# CC +# OBJDUMP +# AWK +# ac_ext +# ac_object +# host +# LOCK_ABI_VERSION +# +# An example: +# +# LOCK_ABI_VERSION=1 host=x86_64-pc-linux-gnu host_alias=x86_64-linux-gnu \ +# CC=$host_alias-gcc OBJDUMP=$host_alias-objdump ac_ext=c ac_objext=o \ +# AWK=gawk ./gen-lock-obj.sh +# + +if test -n `echo -n`; then + ECHO_C='\c' + ECHO_N='' +else + ECHO_C='' + ECHO_N='-n' +fi + +if test "$1" = --disable-threads; then + cat <<EOF +## lock-obj-pub.$host.h - NO LOCK SUPPORT +## File created by gen-lock-obj.sh - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +/* Dummy object - no locking available. */ +typedef struct +{ + long _vers; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {-1} +EOF +else +AWK_VERSION_OUTPUT=$($AWK 'BEGIN { print PROCINFO["version"] }') +if test -n "$AWK_VERSION_OUTPUT"; then + # It's GNU awk, which supports PROCINFO. + AWK_OPTION=--non-decimal-data +fi + +cat <<'EOF' >conftest.$ac_ext +#include <pthread.h> +pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; +EOF + +if $CC -c conftest.$ac_ext; then : + ac_mtx_size=$($OBJDUMP -j .bss -t conftest.$ac_objext \ + | $AWK $AWK_OPTION ' +/mtx$/ { mtx_size = int("0x" $5) } +END { print mtx_size }') +else + echo "Can't determine mutex size" + exit 1 +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +cat <<EOF +## lock-obj-pub.$host.h +## File created by gen-lock-obj.sh - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[$ac_mtx_size]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +EOF + +# FIXME: Support different alignment conditions of: +# +# USE_16BYTE_ALIGNMENT +# USE_DOUBLE_FOR_ALIGNMENT +# USE_LONG_DOUBLE_FOR_ALIGNMENT +# + +echo ${ECHO_N} "#define GPGRT_LOCK_INITIALIZER {$LOCK_ABI_VERSION,{{${ECHO_C}" + +i=0 +while test "$i" -lt $ac_mtx_size; do + if test "$i" -ne 0 -a "$(( $i % 8 ))" -eq 0; then + echo ' \' + echo ${ECHO_N} " ${ECHO_C}" + fi + echo ${ECHO_N} "0${ECHO_C}" + if test "$i" -lt $(($ac_mtx_size - 1)); then + echo ${ECHO_N} ",${ECHO_C}" + fi + i=$(( i + 1 )) +done +fi + +cat <<'EOF' +}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## +EOF + +exit 0 diff --git a/comm/third_party/libgpg-error/src/gen-posix-lock-obj.c b/comm/third_party/libgpg-error/src/gen-posix-lock-obj.c new file mode 100644 index 0000000000..e6f33ae3cb --- /dev/null +++ b/comm/third_party/libgpg-error/src/gen-posix-lock-obj.c @@ -0,0 +1,175 @@ +/* gen-posix-lock-obj.c - Build tool to construct the lock object. + Copyright (C) 2014 g10 Code GmbH + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, see <https://www.gnu.org/licenses/>. + */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_W32_SYSTEM +# error This module may not be build for Windows. +#endif + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <errno.h> +#ifdef USE_POSIX_THREADS +# include <pthread.h> +#endif + +#include "posix-lock-obj.h" + +#define PGM "gen-posix-lock-obj" + +/* Check that configure did its job. */ +#ifdef USE_POSIX_THREADS +#if SIZEOF_PTHREAD_MUTEX_T < 4 +# error sizeof pthread_mutex_t is not known. +#endif +#endif + +/* Special requirements for certain platforms. */ +# define USE_LONG_DOUBLE_FOR_ALIGNMENT 0 +#if defined(__sun) && !defined (__LP64__) && !defined(_LP64) +/* Solaris on 32-bit architecture. */ +# define USE_DOUBLE_FOR_ALIGNMENT 1 +#else +# define USE_DOUBLE_FOR_ALIGNMENT 0 +#endif +#if defined(__hppa__) +# define USE_16BYTE_ALIGNMENT 1 +#else +# define USE_16BYTE_ALIGNMENT 0 +#endif + +#if USE_16BYTE_ALIGNMENT && !HAVE_GCC_ATTRIBUTE_ALIGNED +# error compiler is not able to enforce a 16 byte alignment +#endif + +#ifdef USE_POSIX_THREADS +static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; +#endif + +int +main (void) +{ +#ifdef USE_POSIX_THREADS + unsigned char *p; + int i; +#endif + struct { + long vers; +#ifdef USE_POSIX_THREADS + pthread_mutex_t mtx; +#endif + } dummyobj; + + +#ifdef USE_POSIX_THREADS + if (sizeof mtx != SIZEOF_PTHREAD_MUTEX_T) + { + fprintf (stderr, PGM ": pthread_mutex_t mismatch\n"); + exit (1); + } +#endif /*USE_POSIX_THREADS*/ + + if (sizeof (dummyobj) != sizeof (_gpgrt_lock_t)) + { + fprintf (stderr, PGM ": internal and external lock object mismatch\n"); + exit (1); + } + + printf ("## lock-obj-pub.%s.h%s\n" + "## File created by " PGM " - DO NOT EDIT\n" + "## To be included by mkheader into gpg-error.h\n" + "\n", + HOST_TRIPLET_STRING, +#ifdef USE_POSIX_THREADS + "" +#else + " - NO LOCK SUPPORT" +#endif + ); + +#ifdef USE_POSIX_THREADS + + /* To force a probably suitable alignment of the structure we use a + union and include a long and a pointer to a long. */ + printf ("typedef struct\n" + "{\n" + " long _vers;\n" + " union {\n" + " volatile char _priv[%d];\n" + "%s" + " long _x_align;\n" + " long *_xp_align;\n" + " } u;\n" + "} gpgrt_lock_t;\n" + "\n" + "#define GPGRT_LOCK_INITIALIZER {%d,{{", + SIZEOF_PTHREAD_MUTEX_T, +# if USE_16BYTE_ALIGNMENT + " int _x16_align __attribute__ ((aligned (16)));\n", +# elif USE_DOUBLE_FOR_ALIGNMENT + " double _xd_align;\n", +# elif USE_LONG_DOUBLE_FOR_ALIGNMENT + " long double _xld_align;\n", +# else + "", +# endif + LOCK_ABI_VERSION); + p = (unsigned char *)&mtx; + for (i=0; i < sizeof mtx; i++) + { + if (i && !(i % 8)) + printf (" \\\n%*s", 36, ""); + printf ("%u", p[i]); + if (i < sizeof mtx - 1) + putchar (','); + } + fputs ("}}}\n", stdout); + +#else /*!USE_POSIX_THREADS*/ + + printf ("/* Dummy object - no locking available. */\n" + "typedef struct\n" + "{\n" + " long _vers;\n" + "} gpgrt_lock_t;\n" + "\n" + "#define GPGRT_LOCK_INITIALIZER {%d}\n", + LOCK_ABI_VERSION); + +#endif /*!USE_POSIX_THREADS*/ + + fputs ("##\n" + "## Loc" "al Variables:\n" + "## mode: c\n" + "## buffer-read-only: t\n" + "## End:\n" + "##\n", stdout); + + if (ferror (stdout)) + { + fprintf (stderr, PGM ": error writing to stdout: %s\n", strerror (errno)); + return 1; + } + + return 0; +} diff --git a/comm/third_party/libgpg-error/src/gen-w32-lock-obj.c b/comm/third_party/libgpg-error/src/gen-w32-lock-obj.c new file mode 100644 index 0000000000..f8da67f53a --- /dev/null +++ b/comm/third_party/libgpg-error/src/gen-w32-lock-obj.c @@ -0,0 +1,55 @@ +/* gen-w32-lock-obj.c - Build tool to get the size of the lock object. + Copyright (C) 2014 g10 Code GmbH + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, see <https://www.gnu.org/licenses/>. + */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#ifndef HAVE_W32_SYSTEM +# error This module may only be build for Windows. +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <windows.h> + +#include "w32-lock-obj.h" + + +int +main (void) +{ + _gpgrt_lock_t lk; + unsigned char *p; + int i; + + printf ("sizeof CRITICAL_SECTION = %u\n", (int)sizeof (CRITICAL_SECTION)); + printf ("sizeof _gpgrt_lock_t = %u\n", (int)sizeof lk); + + memset (&lk, 0, sizeof lk); + lk.vers = LOCK_ABI_VERSION; + lk.started = -1; + printf ("#define GPGRT_LOCK_INITIALIZER {"); + p = (unsigned char *)&lk; + for (i=0; i < sizeof lk - 1; i++) + printf ("%u,", p[i]); + printf ("%u}\n", p[sizeof(lk)-1]); + + return 0; +} diff --git a/comm/third_party/libgpg-error/src/gettext.h b/comm/third_party/libgpg-error/src/gettext.h new file mode 100644 index 0000000000..aba29db6dd --- /dev/null +++ b/comm/third_party/libgpg-error/src/gettext.h @@ -0,0 +1,76 @@ +/* Convenience header for conditional use of GNU <libintl.h>. + Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +#ifndef _LIBGETTEXT_H +#define _LIBGETTEXT_H 1 + +/* NLS can be disabled through the configure --disable-nls option. */ +#if ENABLE_NLS + +#if HAVE_W32_SYSTEM + /* We have a gettext implementation in gpg-error.h which get + included anyway. */ +#else /*!HAVE_W32_SYSTEM*/ + /* Get declarations of GNU message catalog functions. */ +# include <libintl.h> +#endif /*!HAVE_W32_SYSTEM*/ + +#else /*!ENABLE_NLS*/ + +/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which + chokes if dcgettext is defined as a macro. So include it now, to make + later inclusions of <locale.h> a NOP. We don't include <libintl.h> + as well because people using "gettext.h" will not include <libintl.h>, + and also including <libintl.h> would fail on SunOS 4, whereas <locale.h> + is OK. */ +#if defined(__sun) +# include <locale.h> +#endif + +/* Disabled NLS. + The casts to 'const char *' serve the purpose of producing warnings + for invalid uses of the value returned from these functions. + On pre-ANSI systems without 'const', the config.h file is supposed to + contain "#define const". */ +# define gettext(Msgid) ((const char *) (Msgid)) +# define dgettext(Domainname, Msgid) ((const char *) (Msgid)) +# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid)) +# define ngettext(Msgid1, Msgid2, N) \ + ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) +# define dngettext(Domainname, Msgid1, Msgid2, N) \ + ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) +# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ + ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) +# define textdomain(Domainname) ((const char *) (Domainname)) +# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname)) +# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset)) + +#endif /*!ENABLE_NLS*/ + +/* A pseudo function call that serves as a marker for the automated + extraction of messages, but does not call gettext(). The run-time + translation is done at a different place in the code. + The argument, String, should be a literal string. Concatenated strings + and other string expressions won't work. + The macro's expansion is not parenthesized, so that it is suitable as + initializer for static 'char[]' or 'const char[]' variables. */ +#define gettext_noop(String) String + + + +#endif /* _LIBGETTEXT_H */ diff --git a/comm/third_party/libgpg-error/src/gpg-error-config-test.sh b/comm/third_party/libgpg-error/src/gpg-error-config-test.sh new file mode 100755 index 0000000000..081358c914 --- /dev/null +++ b/comm/third_party/libgpg-error/src/gpg-error-config-test.sh @@ -0,0 +1,98 @@ +#!/bin/sh + +srcdir=${0%/*} + +PKG_CONFIG_PATH="." + +export PKG_CONFIG_PATH + +if [ "$1" = --old-new ]; then + PKG_CONFIG_CMD=./gpg-error-config-old + # Old gpg-error-config never supports PKG_CONFIG_SYSROOT_DIR + unset PKG_CONFIG_SYSROOT_DIR +else + pkg_config_min_version=0.29 + PKG_CONFIG_SYSROOT_DIR="/var/example-target" + export PKG_CONFIG_SYSROOT_DIR + PKG_CONFIG_CMD="pkg-config gpg-error" + check_ver=$( ($PKG_CONFIG_CMD --version; echo $pkg_config_min_version) | \ + sort -t '.' -n -k1,1 -k2,2 -k3,3 | sed 1q ) + if [ $check_ver != $pkg_config_min_version ]; then + exit 77 # Skip tests, because it's too old + fi + if ! $PKG_CONFIG_CMD --exists >/dev/null; then + exit 77 # Skip tests + fi +fi + +test_failed="" + +failure () { + ( + echo "Test result: $*" + echo "====================: $PKG_CONFIG_CMD" + echo "$OUTPUT_OLD" + echo "====================: gpgrt-config" + echo "$OUTPUT_NEW" + echo "====================" + ) >> gpg-error-config-test.log + test_failed=yes +} + +rm -f gpg-error-config-test.log + +OUTPUT_OLD=$(echo $($PKG_CONFIG_CMD --libs)) +OUTPUT_NEW=$($srcdir/gpgrt-config --libs) +[ "$OUTPUT_OLD" = "$OUTPUT_NEW" ] || failure --libs + +OUTPUT_OLD=$(echo $($PKG_CONFIG_CMD --cflags)) +OUTPUT_NEW=$($srcdir/gpgrt-config --cflags) +[ "$OUTPUT_OLD" = "$OUTPUT_NEW" ] || failure --cflags + +OUTPUT_OLD=$(echo $($PKG_CONFIG_CMD --cflags --libs)) +OUTPUT_NEW=$($srcdir/gpgrt-config --cflags --libs) +[ "$OUTPUT_OLD" = "$OUTPUT_NEW" ] || failure --cflags --libs + +if [ "$PKG_CONFIG_CMD" = ./gpg-error-config-old ]; then + OUTPUT_OLD=$(echo $($PKG_CONFIG_CMD --version)) + OUTPUT_NEW=$($srcdir/gpgrt-config --version) + [ "$OUTPUT_OLD" = "$OUTPUT_NEW" ] || failure --version + + OUTPUT_OLD=$(echo $($PKG_CONFIG_CMD --mt --libs)) + OUTPUT_NEW=$($srcdir/gpgrt-config --mt --libs) + [ "$OUTPUT_OLD" = "$OUTPUT_NEW" ] || failure --mt --libs + + OUTPUT_OLD=$(echo $($PKG_CONFIG_CMD --mt --cflags)) + OUTPUT_NEW=$($srcdir/gpgrt-config --mt --cflags) + [ "$OUTPUT_OLD" = "$OUTPUT_NEW" ] || failure --mt --cflags + + OUTPUT_OLD=$(echo $($PKG_CONFIG_CMD --cflags --libs)) + OUTPUT_NEW=$($srcdir/gpgrt-config --cflags --libs) + [ "$OUTPUT_OLD" = "$OUTPUT_NEW" ] || failure --cflags --libs + + OUTPUT_OLD=$(echo $($PKG_CONFIG_CMD --mt --cflags --libs)) + OUTPUT_NEW=$($srcdir/gpgrt-config --mt --cflags --libs) + [ "$OUTPUT_OLD" = "$OUTPUT_NEW" ] || failure --mt --cflags --libs + + OUTPUT_OLD=$(echo $($PKG_CONFIG_CMD --variable=mtcflags)) + OUTPUT_NEW=$($srcdir/gpgrt-config --variable=mtcflags) + [ "$OUTPUT_OLD" = "$OUTPUT_NEW" ] || failure --variable=mtcflags + + OUTPUT_OLD=$(echo $($PKG_CONFIG_CMD --variable=mtlibs)) + OUTPUT_NEW=$($srcdir/gpgrt-config --variable=mtlibs) + [ "$OUTPUT_OLD" = "$OUTPUT_NEW" ] || failure --variable=mtlibs + + OUTPUT_OLD=$(echo $($PKG_CONFIG_CMD --variable=host)) + OUTPUT_NEW=$($srcdir/gpgrt-config --variable=host) + [ "$OUTPUT_OLD" = "$OUTPUT_NEW" ] || failure --variable=host +fi + +if [ -n "$test_failed" ]; then + OUTPUT_OLD=$($PKG_CONFIG_CMD --version) + OUTPUT_NEW=$($srcdir/gpgrt-config --version) + failure --version + + exit 99 +fi + +exit 0 diff --git a/comm/third_party/libgpg-error/src/gpg-error-config-test.sh.in b/comm/third_party/libgpg-error/src/gpg-error-config-test.sh.in new file mode 100644 index 0000000000..b888aa2097 --- /dev/null +++ b/comm/third_party/libgpg-error/src/gpg-error-config-test.sh.in @@ -0,0 +1,98 @@ +#!@INSTALLSHELLPATH@ + +srcdir=${0%/*} + +PKG_CONFIG_PATH="." + +export PKG_CONFIG_PATH + +if [ "$1" = --old-new ]; then + PKG_CONFIG_CMD=./gpg-error-config-old + # Old gpg-error-config never supports PKG_CONFIG_SYSROOT_DIR + unset PKG_CONFIG_SYSROOT_DIR +else + pkg_config_min_version=0.29 + PKG_CONFIG_SYSROOT_DIR="/var/example-target" + export PKG_CONFIG_SYSROOT_DIR + PKG_CONFIG_CMD="pkg-config gpg-error" + check_ver=$( ($PKG_CONFIG_CMD --version; echo $pkg_config_min_version) | \ + sort -t '.' -n -k1,1 -k2,2 -k3,3 | sed 1q ) + if [ $check_ver != $pkg_config_min_version ]; then + exit 77 # Skip tests, because it's too old + fi + if ! $PKG_CONFIG_CMD --exists >/dev/null; then + exit 77 # Skip tests + fi +fi + +test_failed="" + +failure () { + ( + echo "Test result: $*" + echo "====================: $PKG_CONFIG_CMD" + echo "$OUTPUT_OLD" + echo "====================: gpgrt-config" + echo "$OUTPUT_NEW" + echo "====================" + ) >> gpg-error-config-test.log + test_failed=yes +} + +rm -f gpg-error-config-test.log + +OUTPUT_OLD=$(echo $($PKG_CONFIG_CMD --libs)) +OUTPUT_NEW=$($srcdir/gpgrt-config --libs) +[ "$OUTPUT_OLD" = "$OUTPUT_NEW" ] || failure --libs + +OUTPUT_OLD=$(echo $($PKG_CONFIG_CMD --cflags)) +OUTPUT_NEW=$($srcdir/gpgrt-config --cflags) +[ "$OUTPUT_OLD" = "$OUTPUT_NEW" ] || failure --cflags + +OUTPUT_OLD=$(echo $($PKG_CONFIG_CMD --cflags --libs)) +OUTPUT_NEW=$($srcdir/gpgrt-config --cflags --libs) +[ "$OUTPUT_OLD" = "$OUTPUT_NEW" ] || failure --cflags --libs + +if [ "$PKG_CONFIG_CMD" = ./gpg-error-config-old ]; then + OUTPUT_OLD=$(echo $($PKG_CONFIG_CMD --version)) + OUTPUT_NEW=$($srcdir/gpgrt-config --version) + [ "$OUTPUT_OLD" = "$OUTPUT_NEW" ] || failure --version + + OUTPUT_OLD=$(echo $($PKG_CONFIG_CMD --mt --libs)) + OUTPUT_NEW=$($srcdir/gpgrt-config --mt --libs) + [ "$OUTPUT_OLD" = "$OUTPUT_NEW" ] || failure --mt --libs + + OUTPUT_OLD=$(echo $($PKG_CONFIG_CMD --mt --cflags)) + OUTPUT_NEW=$($srcdir/gpgrt-config --mt --cflags) + [ "$OUTPUT_OLD" = "$OUTPUT_NEW" ] || failure --mt --cflags + + OUTPUT_OLD=$(echo $($PKG_CONFIG_CMD --cflags --libs)) + OUTPUT_NEW=$($srcdir/gpgrt-config --cflags --libs) + [ "$OUTPUT_OLD" = "$OUTPUT_NEW" ] || failure --cflags --libs + + OUTPUT_OLD=$(echo $($PKG_CONFIG_CMD --mt --cflags --libs)) + OUTPUT_NEW=$($srcdir/gpgrt-config --mt --cflags --libs) + [ "$OUTPUT_OLD" = "$OUTPUT_NEW" ] || failure --mt --cflags --libs + + OUTPUT_OLD=$(echo $($PKG_CONFIG_CMD --variable=mtcflags)) + OUTPUT_NEW=$($srcdir/gpgrt-config --variable=mtcflags) + [ "$OUTPUT_OLD" = "$OUTPUT_NEW" ] || failure --variable=mtcflags + + OUTPUT_OLD=$(echo $($PKG_CONFIG_CMD --variable=mtlibs)) + OUTPUT_NEW=$($srcdir/gpgrt-config --variable=mtlibs) + [ "$OUTPUT_OLD" = "$OUTPUT_NEW" ] || failure --variable=mtlibs + + OUTPUT_OLD=$(echo $($PKG_CONFIG_CMD --variable=host)) + OUTPUT_NEW=$($srcdir/gpgrt-config --variable=host) + [ "$OUTPUT_OLD" = "$OUTPUT_NEW" ] || failure --variable=host +fi + +if [ -n "$test_failed" ]; then + OUTPUT_OLD=$($PKG_CONFIG_CMD --version) + OUTPUT_NEW=$($srcdir/gpgrt-config --version) + failure --version + + exit 99 +fi + +exit 0 diff --git a/comm/third_party/libgpg-error/src/gpg-error-config.in b/comm/third_party/libgpg-error/src/gpg-error-config.in new file mode 100644 index 0000000000..3b45928cfc --- /dev/null +++ b/comm/third_party/libgpg-error/src/gpg-error-config.in @@ -0,0 +1,103 @@ +#!@INSTALLSHELLPATH@ +# Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc. +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This file is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# SPDX-License-Identifier: FSFULLR + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +includedir=@includedir@ +libdir=@libdir@ + +if echo "$0" | grep gpg-error-config 2>/dev/null >/dev/null; then + myname="gpg-error-config" +else + myname="gpgrt-config" +fi + +output="" +mt=no + +usage() +{ + cat <<EOF +Usage: $myname [OPTIONS] +Options: + [--mt] (must be the first option) + [--prefix] + [--exec-prefix] + [--version] + [--libs] + [--cflags] +EOF + exit $1 +} + +if test $# -eq 0; then + usage 1 1>&2 +fi + +while test $# -gt 0; do + case "$1" in + -*=*) + optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` + ;; + *) + optarg= + ;; + esac + + case $1 in + --mt) + mt=yes + ;; + --prefix) + output="$output $prefix" + ;; + --exec-prefix) + output="$output $exec_prefix" + ;; + --modversion|--version) + echo "@PACKAGE_VERSION@" + exit 0 + ;; + --variable=*) + case "${1#*=}" in + prefix) echo "$prefix" ;; + exec_prefix) echo "$exec_prefix" ;; + host) echo "@GPG_ERROR_CONFIG_HOST@" ;; + mtcflags) echo "@GPG_ERROR_CONFIG_MT_CFLAGS@" ;; + mtlibs) echo "@GPG_ERROR_CONFIG_MT_LIBS@";; + esac + exit 0 + ;; + --cflags) + output="$output @GPG_ERROR_CONFIG_CFLAGS@" + if test $mt = yes ; then + output="$output @GPG_ERROR_CONFIG_MT_CFLAGS@" + fi + ;; + --libs) + output="$output @GPG_ERROR_CONFIG_LIBS@" + if test $mt = yes ; then + output="$output @GPG_ERROR_CONFIG_MT_LIBS@" + fi + ;; + --host) + echo "@GPG_ERROR_CONFIG_HOST@" + exit 0 + ;; + *) + usage 1 1>&2 + ;; + esac + shift +done + +echo $output diff --git a/comm/third_party/libgpg-error/src/gpg-error.c b/comm/third_party/libgpg-error/src/gpg-error.c new file mode 100644 index 0000000000..4e8bd8b836 --- /dev/null +++ b/comm/third_party/libgpg-error/src/gpg-error.c @@ -0,0 +1,767 @@ +/* gpg-error.c - Determining gpg-error error codes. + Copyright (C) 2004, 2016 g10 Code GmbH + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with libgpg-error; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> + +#ifdef HAVE_LOCALE_H +# include <locale.h> +#endif +#ifdef ENABLE_NLS +#ifdef HAVE_W32_SYSTEM +# include "gettext.h" +#else +# include <libintl.h> +#endif +# define _(a) gettext (a) +# ifdef gettext_noop +# define N_(a) gettext_noop (a) +# else +# define N_(a) (a) +# endif +#else +# define _(a) (a) +# define N_(a) (a) +#endif + +#include <gpg-error.h> + + +#if HAVE_W32_SYSTEM +/* The implementation follows below. */ +static char *get_locale_dir (void); +static void drop_locale_dir (char *locale_dir); +#else +#define get_locale_dir() LOCALEDIR +#define drop_locale_dir(dir) +#endif + +static void +i18n_init (void) +{ +#ifdef ENABLE_NLS + char *locale_dir; + +#ifdef HAVE_LC_MESSAGES + setlocale (LC_TIME, ""); + setlocale (LC_MESSAGES, ""); +#else +# ifndef HAVE_W32_SYSTEM + setlocale (LC_ALL, "" ); +# endif +#endif + + /* Note that for this program we would only need the textdomain call + because libgpg-error already initializes itself to its locale dir + (via gpg_err_init or a constructor). However this is only done + for the static standard locale and thus if the above setlocale + calls select a different locale the bindtext below will do + something else. */ + + locale_dir = get_locale_dir (); + if (locale_dir) + { + bindtextdomain (PACKAGE, locale_dir); + drop_locale_dir (locale_dir); + } + textdomain (PACKAGE); +#endif +} + + +#ifdef HAVE_W32_SYSTEM + +#include <windows.h> + + +static char * +get_locale_dir (void) +{ + static wchar_t moddir[MAX_PATH+5]; + char *result, *p; + int nbytes; + + if (!GetModuleFileNameW (NULL, moddir, MAX_PATH)) + *moddir = 0; + +#define SLDIR "\\share\\locale" + if (*moddir) + { + nbytes = WideCharToMultiByte (CP_UTF8, 0, moddir, -1, NULL, 0, NULL, NULL); + if (nbytes < 0) + return NULL; + + result = malloc (nbytes + strlen (SLDIR) + 1); + if (result) + { + nbytes = WideCharToMultiByte (CP_UTF8, 0, moddir, -1, + result, nbytes, NULL, NULL); + if (nbytes < 0) + { + free (result); + result = NULL; + } + else + { + p = strrchr (result, '\\'); + if (p) + *p = 0; + /* If we are installed below "bin" strip that part and + use the top directory instead. */ + p = strrchr (result, '\\'); + if (p && !strcmp (p+1, "bin")) + *p = 0; + /* Append the static part. */ + strcat (result, SLDIR); + } + } + } + else /* Use the old default value. */ + { + result = malloc (10 + strlen (SLDIR) + 1); + if (result) + { + strcpy (result, "c:\\gnupg"); + strcat (result, SLDIR); + } + } +#undef SLDIR + return result; +} + + +static void +drop_locale_dir (char *locale_dir) +{ + free (locale_dir); +} + +#endif /* HAVE_W32_SYSTEM */ + + +const char *gpg_strerror_sym (gpg_error_t err); +const char *gpg_strsource_sym (gpg_error_t err); + + +/* Parse string STR assuming it is either a single number N or in the + * form K.N to denote an error source code K and and error code N. + * Returns false on error (e.g. invalid number) or true for valid + * codes; if true is returned a full error code is stored at ERR. */ +static int +get_err_from_number (char *str, gpg_error_t *err) +{ + unsigned long nr; + char *tail; + + gpg_err_set_errno (0); + nr = strtoul (str, &tail, 0); + if (errno) + return 0; + + if (nr > UINT_MAX) + return 0; + + if (*tail) + { + unsigned long cnr = strtoul (tail + 1, &tail, 0); + if (errno || *tail) + return 0; + + if (nr >= GPG_ERR_SOURCE_DIM || cnr >= GPG_ERR_CODE_DIM) + return 0; + + nr = gpg_err_make (nr, cnr); + } + + *err = (unsigned int) nr; + return 1; +} + + +/* Helper function to parse a symbol either with a "GPG_ERR_SOURCE_" + * or "GPG_ERR_" prefix. If the symbol is not available false is + * return; else the symbols value is ORed into the value at ERR + * (shifted for a GPG_ERR_SOURCE_) and true returned. HAVE_SOURCE and + * HAVE_CODE are expected to be addresses where a 0 is stored; a 1 is + * stored at the respective address to mark whether a code or source + * value was found. If one of those state variables already point to + * a true value the function will return 0 and not change the value at + * ERR. */ +static int +get_err_from_symbol_one (char *str, gpg_error_t *err, + int *have_source, int *have_code) +{ + static const char src_prefix[] = "GPG_ERR_SOURCE_"; + static const char code_prefix[] = "GPG_ERR_"; + + if (!strncasecmp (src_prefix, str, sizeof (src_prefix) - 1)) + { + gpg_err_source_t src; + + if (*have_source) + return 0; + *have_source = 1; + str += sizeof (src_prefix) - 1; + + for (src = 0; src < GPG_ERR_SOURCE_DIM; src++) + { + const char *src_sym; + + src_sym = gpg_strsource_sym (src << GPG_ERR_SOURCE_SHIFT); + if (src_sym && !strcasecmp (str, src_sym + sizeof (src_prefix) - 1)) + { + *err |= src << GPG_ERR_SOURCE_SHIFT; + return 1; + } + } + } + else if (!strncasecmp (code_prefix, str, sizeof (code_prefix) - 1)) + { + gpg_err_code_t code; + + if (*have_code) + return 0; + *have_code = 1; + str += sizeof (code_prefix) - 1; + + for (code = 0; code < GPG_ERR_CODE_DIM; code++) + { + const char *code_sym = gpg_strerror_sym (code); + if (code_sym + && !strcasecmp (str, code_sym + sizeof (code_prefix) - 1)) + { + *err |= code; + return 1; + } + } + } + return 0; +} + + +/* Parse string STR assuming it is either a single symbol C or in the + * form S.C to denote an error source symbold S and and error code + * symbold C. Returns false on error (e.g. invalid number) or true + * for valid codes; if true is returned a full error code is stored at + * ERR. */ +static int +get_err_from_symbol (char *str, gpg_error_t *err) +{ + char *str2 = str; + int have_source = 0; + int have_code = 0; + int ret; + char *saved_pos = NULL; + char saved_char; + + *err = 0; + while (*str2 && ((*str2 >= 'A' && *str2 <= 'Z') + || (*str2 >= '0' && *str2 <= '9') + || *str2 == '_')) + str2++; + if (*str2) + { + saved_pos = str2; + saved_char = *str2; + *str2 = '\0'; + str2++; + } + else + str2 = NULL; + + ret = get_err_from_symbol_one (str, err, &have_source, &have_code); + if (ret && str2) + ret = get_err_from_symbol_one (str2, err, &have_source, &have_code); + + if (saved_pos) + *saved_pos = saved_char; + return ret; +} + + +/* Parse string STR assuming it partial code symbol and store its + * value at ERR and return true. */ +static int +get_err_from_codesymbol (char *str, gpg_error_t *err) +{ + static const char code_prefix[] = "GPG_ERR_"; + gpg_err_code_t code; + + *err = 0; + + /* Skip an optional prefix. */ + if (!strncasecmp (code_prefix, str, sizeof (code_prefix) - 1)) + str += sizeof (code_prefix) - 1; + + for (code = 0; code < GPG_ERR_CODE_DIM; code++) + { + const char *code_sym = gpg_strerror_sym (code); + if (code_sym + && !strcasecmp (str, code_sym + sizeof (code_prefix) - 1)) + { + *err |= code; + return 1; + } + } + return 0; +} + + +/* Helper function to parse a string which maps back to a source or + * code value. If no source or code for the symbold is available + * false is return; else the source or code value is ORed into the + * value at ERR (shifted for a GPG_ERR_SOURCE_) and true returned. + * The match is first tried on source values and then on code values. + * HAVE_SOURCE and HAVE_CODE are expected to be addresses where a 0 is + * stored; a 1 is stored at the respective address to mark whether a + * code or source value was found. If one of those state variables + * already point to a true value the function will return 0 and not + * change the value at ERR. */ +static int +get_err_from_str_one (char *str, gpg_error_t *err, + int *have_source, int *have_code) +{ + gpg_err_source_t src; + gpg_err_code_t code; + + for (src = 0; src < GPG_ERR_SOURCE_DIM; src++) + { + const char *src_str = gpg_strsource (src << GPG_ERR_SOURCE_SHIFT); + if (src_str && !strcasecmp (str, src_str)) + { + if (*have_source) + return 0; + + *have_source = 1; + *err |= src << GPG_ERR_SOURCE_SHIFT; + return 1; + } + } + + for (code = 0; code < GPG_ERR_CODE_DIM; code++) + { + const char *code_str = gpg_strerror (code); + if (code_str && !strcasecmp (str, code_str)) + { + if (*have_code) + return 0; + + *have_code = 1; + *err |= code; + return 1; + } + } + + return 0; +} + + +/* Parse string STR assuming it is either a single desription string C + * or in the form S.C to denote an error source descrition S and and + * error code description C. Returns false on error (e.g. invalid + * symbol) or true for valid codes; if true is returned a full error + * code is stored at ERR. */ +static int +get_err_from_str (char *str, gpg_error_t *err) +{ + char *str2 = str; + int have_source = 0; + int have_code = 0; + int ret; + char *saved_pos = NULL; + char saved_char = 0; /* (avoid warning) */ + + *err = 0; + /* First match on the entire string to handle the case that it is + * code description with spaces. */ + ret = get_err_from_str_one (str, err, &have_source, &have_code); + if (ret) + return ret; + + /* Then figure out whether the first string is a simple word. */ + while (*str2 && ((*str2 >= 'A' && *str2 <= 'Z') + || (*str2 >= 'a' && *str2 <= 'z') + || (*str2 >= '0' && *str2 <= '9') + || *str2 == '_')) + str2++; + if (*str2) + { + saved_pos = str2; + saved_char = *str2; + *((char *) str2) = '\0'; + str2++; + while (*str2 && !((*str2 >= 'A' && *str2 <= 'Z') + || (*str2 >= 'a' && *str2 <= 'z') + || (*str2 >= '0' && *str2 <= '9') + || *str2 == '_')) + str2++; + } + else + str2 = NULL; + + ret = get_err_from_str_one (str, err, &have_source, &have_code); + if (ret && str2) + ret = get_err_from_str_one (str2, err, &have_source, &have_code); + + if (saved_pos) + *saved_pos = saved_char; + return ret; +} + + +static void +print_desc (const char *symbol) +{ + static int initialized; + static FILE *fp; + char line[512]; + char *p; + int indesc = 0; + int blanklines = 0; + int last_was_keyword = 0; + + if (!symbol) + return; + + if (!initialized) + { + initialized = 1; + fp = fopen (PKGDATADIR "/errorref.txt", "r"); + } + if (!fp) + return; + rewind (fp); + while (fgets (line, sizeof line, fp)) + { + if (*line == '#') + continue; + if (*line && line[strlen(line)-1] == '\n') + line[strlen(line)-1] = 0; + + if (!strncmp (line, "GPG_ERR_", 8)) + { + if (indesc == 1 && last_was_keyword) + continue; /* Skip keywords immediately following a matched + * keyword. */ + last_was_keyword = 1; + + indesc = 0; + p = strchr (line, ' '); + if (!p) + continue; + *p = 0; + if (!strcmp (line, symbol)) + { + indesc = 1; + continue; /* Skip this line. */ + } + } + else + last_was_keyword = 0; + if (!indesc) + continue; + if (indesc == 1 && !*line) + continue; /* Skip leading empty lines in a description. */ + if (indesc == 1) + putchar ('\n'); /* One leading empty line. */ + indesc = 2; + if (!*line) + { + blanklines++; + continue; + } + for (; blanklines; blanklines--) + putchar ('\n'); + printf ("%s\n", line); + } + putchar ('\n'); /* One trailing blank line. */ +} + + + + + +static const char * +my_strusage (int level) +{ + const char *p; + + switch (level) + { + case 9: p = "LGPL-2.1-or-later"; break; + + case 11: p = "gpg-error"; break; + case 12: p = PACKAGE_NAME; break; + case 13: p = PACKAGE_VERSION; break; + case 14: p = "Copyright (C) 2019 g10 Code GmbH"; break; + case 19: p = _("Please report bugs to <https://bugs.gnupg.org>.\n"); break; + + case 1: + case 40: + p = ("Usage: gpg-error [options] error-numbers"); + break; + case 41: + p = ("Map error numbers to strings and vice versa.\n"); + break; + + case 42: + p = "1"; /* Flag: print 40 as part of 41. */ + break; + + default: p = NULL; break; + } + return p; +} + + + +int +main (int argc, char *argv[]) +{ + enum { CMD_DEFAULT = 0, + CMD_LIB_VERSION = 501, + CMD_LIST, + CMD_DEFINES, + CMD_LOCALE, + OPT_DESC + }; + static gpgrt_opt_t opts[] = { + ARGPARSE_c (CMD_LIB_VERSION, "lib-version", + "Print library version"), + ARGPARSE_c (CMD_LIST, "list", + "Print all error codes"), + ARGPARSE_c (CMD_DEFINES, "defines", + "Print all error codes as #define lines"), +#if HAVE_W32_SYSTEM + ARGPARSE_c (CMD_LOCALE, "locale", + "Return the locale used for gettext"), +#else + ARGPARSE_c (CMD_LOCALE, "locale", + "@"), +#endif + ARGPARSE_s_n (OPT_DESC, "desc", + "Print with error description"), + ARGPARSE_end() + }; + gpgrt_argparse_t pargs = { &argc, &argv }; + + int i; + int libversion = 0; + int listmode = 0; + int localemode = 0; + int desc = 0; + const char *s, *s2; + const char *source_sym; + const char *error_sym; + gpg_error_t err; + + gpgrt_init (); + i18n_init (); + gpgrt_set_strusage (my_strusage); + gpgrt_log_set_prefix (gpgrt_strusage (11), GPGRT_LOG_WITH_PREFIX); + + + while (gpgrt_argparse (NULL, &pargs, opts)) + { + switch (pargs.r_opt) + { + case CMD_LIB_VERSION: libversion = 1; break; + case CMD_LIST: listmode = 1; break; + case CMD_DEFINES: listmode = 2; break; + case CMD_LOCALE: localemode = 1; break; + case OPT_DESC: desc = 1; break; + default: pargs.err = ARGPARSE_PRINT_WARNING; break; + } + } + gpgrt_argparse (NULL, &pargs, NULL); /* Free internal memory. */ + + if (libversion) + { + if (argc) + gpgrt_usage (1); + } + else if (localemode) + { + if (argc > 1) + gpgrt_usage (1); + } + else if ((argc && listmode) || (!argc && !listmode)) + gpgrt_usage (1); + + + if (libversion) + { + argc--; argv++; + printf ("Version from header: %s (0x%06x)\n", + GPG_ERROR_VERSION, GPG_ERROR_VERSION_NUMBER); + printf ("Version from binary: %s\n", gpg_error_check_version (NULL)); + s = gpg_error_check_version ("\x01\x01"); + while (*s && *s == '\n') + s++; + fputs ("Copyright blurb ...: ", stdout); + for (; *s; s++) + { + if (*s == '\n') + { + for (s2=s+1; *s2 == '\n'; s2++) + ; + if (!*s2) + break; /* Cut off trailing LFs. */ + fputs ("\n ", stdout); + } + else + putc (*s, stdout); + } + putc ('\n', stdout); + } + else if (localemode) + { +#if HAVE_W32_SYSTEM + if (argc) + { + /* Warning: What we do here is not allowed because + * gpgrt_w32_override_locale needs to be called as early as + * possible. However for this very purpose it is okay. */ + if (**argv >= '0' && **argv <= '9') + gpgrt_w32_override_locale (NULL, strtoul (*argv, NULL, 0)); + else + gpgrt_w32_override_locale (*argv, 0); + } + + printf ("%s\n", gettext_localename ()); +#else + log_info ("this command is only useful on Windows\n"); +#endif + } + else if (listmode == 1) + { + for (i=0; i < GPG_ERR_SOURCE_DIM; i++) + { + /* We use error code 1 because gpg_err_make requires a + non-zero error code. */ + err = gpg_err_make (i, 1); + err -= 1; + source_sym = gpg_strsource_sym (err); + if (source_sym) + { + printf ("%u = (%u, -) = (%s, -) = (%s, -)\n", + err, gpg_err_source (err), + source_sym, gpg_strsource (err)); + if (desc) + print_desc (source_sym); + } + } + for (i=0; i < GPG_ERR_CODE_DIM; i++) + { + err = gpg_err_make (GPG_ERR_SOURCE_UNKNOWN, i); + error_sym = gpg_strerror_sym (err); + if (error_sym) + { + printf ("%u = (-, %u) = (-, %s) = (-, %s)\n", + err, gpg_err_code (err), + error_sym, gpg_strerror (err)); + if (desc) + print_desc (error_sym); + } + } + } + else if (listmode == 2) + { + int n, nmax; + + for (i=0, nmax=0; i < GPG_ERR_SOURCE_DIM; i++) + { + err = gpg_err_make (i, 1); + source_sym = gpg_strsource_sym (err); + if (source_sym) + { + n = strlen (source_sym); + if (n > nmax) + nmax = n; + } + } + for (i=0; i < GPG_ERR_SOURCE_DIM; i++) + { + err = gpg_err_make (i, 1); + source_sym = gpg_strsource_sym (err); + if (source_sym) + printf ("#define %-*s %3u\n", nmax,source_sym,gpg_err_source (err)); + } + + + for (i=0, nmax = 0; i < GPG_ERR_CODE_DIM; i++) + { + err = gpg_err_make (GPG_ERR_SOURCE_UNKNOWN, i); + error_sym = gpg_strerror_sym (err); + if (error_sym) + { + n = strlen (error_sym); + if (n > nmax) + nmax = n; + } + } + for (i=0; i < GPG_ERR_CODE_DIM; i++) + { + err = gpg_err_make (GPG_ERR_SOURCE_UNKNOWN, i); + error_sym = gpg_strerror_sym (err); + if (error_sym) + printf ("#define %-*s %5u\n", nmax, error_sym, gpg_err_code (err)); + } + } + else /* Standard mode. */ + { + for (i=0; i < argc; i++) + { + /* First check the arg is a number N or K.N, + * then check the arg for CODESYM or SOURCESYM.CODESYM, + * then check the arg for CODESYM or CODESYM w/o GPG_ERR_ prefix, + * then check the arg for code description + * or symbol dot code description. + */ + if (get_err_from_number (argv[i], &err) + || get_err_from_symbol (argv[i], &err) + || get_err_from_codesymbol (argv[i], &err) + || get_err_from_str (argv[i], &err)) + { + source_sym = gpg_strsource_sym (err); + error_sym = gpg_strerror_sym (err); + + printf ("%u = (%u, %u) = (%s, %s) = (%s, %s)\n", + err, gpg_err_source (err), gpg_err_code (err), + source_sym ? source_sym : "-", error_sym ? error_sym:"-", + gpg_strsource (err), gpg_strerror (err)); + if (desc) + print_desc (error_sym); + } + else + log_error (_("warning: could not recognize %s\n"), argv[i]); + } + } + + exit (0); +} diff --git a/comm/third_party/libgpg-error/src/gpg-error.def.in b/comm/third_party/libgpg-error/src/gpg-error.def.in new file mode 100644 index 0000000000..769be1bbc8 --- /dev/null +++ b/comm/third_party/libgpg-error/src/gpg-error.def.in @@ -0,0 +1,245 @@ +/* libgpg-error.def - Exported symbols for W32 + * Copyright (C) 2014 g10 Code GmbH + * + * This file is part of libgpg-error. + * + * libgpg-error is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * libgpg-error is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <https://www.gnu.org/licenses/>. + * SPDX-License-Identifier: LGPL-2.1+ + * + * Note: This file should be updated manually and the ordinals shall + * never be changed. Also check gpg-error.vers and visibility.h. + * + * This file needs to be pre-processed. + */ + +#include <config.h> + +EXPORTS + gpg_strerror @1 + gpg_strerror_r @2 + gpg_strsource @3 + gpg_err_code_from_errno @4 + gpg_err_code_to_errno @5 + /* @6 - Not anymore used. */ + gpg_err_code_from_syserror @7 + gpg_err_set_errno @8 +#ifdef HAVE_W32CE_SYSTEM + _gpg_w32ce_get_errno @9 + _gpg_w32ce_strerror @10 +#endif +#ifdef HAVE_W32_SYSTEM + _gpg_w32_bindtextdomain @11 + _gpg_w32_textdomain @12 + _gpg_w32_gettext @13 + _gpg_w32_dgettext @14 + _gpg_w32_dngettext @15 + _gpg_w32_gettext_localename @16 + _gpg_w32_gettext_use_utf8 @17 +#endif + /* @18 - Not anymore used. */ + gpg_error_check_version @19 + + gpgrt_lock_init @20 + gpgrt_lock_lock @21 + gpgrt_lock_unlock @22 + gpgrt_lock_destroy @23 + gpgrt_yield @24 + gpgrt_lock_trylock @25 + + gpgrt_set_syscall_clamp @26 + + gpgrt_fopen @27 + gpgrt_mopen @28 + gpgrt_fopenmem @29 + gpgrt_fopenmem_init @30 + gpgrt_fdopen @31 + gpgrt_fdopen_nc @32 + gpgrt_sysopen @33 + gpgrt_sysopen_nc @34 + gpgrt_fpopen @35 + gpgrt_fpopen_nc @36 + gpgrt_freopen @37 + gpgrt_fopencookie @38 + gpgrt_fclose @39 + gpgrt_fclose_snatch @40 + gpgrt_onclose @41 + gpgrt_fileno @42 + gpgrt_fileno_unlocked @43 + gpgrt_syshd @44 + gpgrt_syshd_unlocked @45 + _gpgrt_set_std_fd @46 + _gpgrt_get_std_stream @47 + gpgrt_flockfile @48 + gpgrt_ftrylockfile @49 + gpgrt_funlockfile @50 + gpgrt_feof @51 + gpgrt_feof_unlocked @52 + gpgrt_ferror @53 + gpgrt_ferror_unlocked @54 + gpgrt_clearerr @55 + gpgrt_clearerr_unlocked @56 + gpgrt_fflush @57 + gpgrt_fseek @58 + gpgrt_fseeko @59 + gpgrt_ftell @60 + gpgrt_ftello @61 + gpgrt_rewind @62 + gpgrt_fgetc @63 + _gpgrt_getc_underflow @64 + gpgrt_fputc @65 + _gpgrt_putc_overflow @66 + gpgrt_ungetc @67 + gpgrt_read @68 + gpgrt_write @69 + gpgrt_write_sanitized @70 + gpgrt_write_hexstring @71 + gpgrt_fread @72 + gpgrt_fwrite @73 + gpgrt_fgets @74 + gpgrt_fputs @75 + gpgrt_fputs_unlocked @76 + gpgrt_getline @77 + gpgrt_read_line @78 + gpgrt_free @79 + gpgrt_fprintf @80 + gpgrt_fprintf_unlocked @81 + gpgrt_printf @82 + gpgrt_printf_unlocked @83 + gpgrt_vfprintf @84 + gpgrt_vfprintf_unlocked @85 + gpgrt_setvbuf @86 + gpgrt_setbuf @87 + gpgrt_set_binary @88 + gpgrt_tmpfile @89 + gpgrt_opaque_set @90 + gpgrt_opaque_get @91 + gpgrt_fname_set @92 + gpgrt_fname_get @93 + gpgrt_asprintf @94 + gpgrt_vasprintf @95 + gpgrt_bsprintf @96 + gpgrt_vbsprintf @97 + gpgrt_snprintf @98 + gpgrt_vsnprintf @99 + + gpgrt_check_version @100 + gpg_err_init @101 + gpg_err_deinit @102 + gpgrt_set_alloc_func @103 + + _gpgrt_pending @104 + _gpgrt_pending_unlocked @105 + + gpgrt_set_nonblock @106 + gpgrt_get_nonblock @107 + gpgrt_poll @108 + +#ifdef HAVE_W32_SYSTEM + gpgrt_w32_iconv_open @109 + gpgrt_w32_iconv_close @110 + gpgrt_w32_iconv @111 +#endif + + gpgrt_get_syscall_clamp @112 + + gpgrt_b64dec_start @113 + gpgrt_b64dec_proc @114 + gpgrt_b64dec_finish @115 + + gpgrt_get_errorcount @116 + gpgrt_inc_errorcount @117 + gpgrt_log_set_sink @118 + gpgrt_log_set_socket_dir_cb @119 + gpgrt_log_set_pid_suffix_cb @120 + gpgrt_log_set_prefix @121 + gpgrt_log_get_prefix @122 + gpgrt_log_test_fd @123 + gpgrt_log_get_fd @124 + gpgrt_log_get_stream @125 + gpgrt_log @126 + gpgrt_logv @127 + gpgrt_logv_prefix @128 + gpgrt_log_string @129 + gpgrt_log_bug @130 + gpgrt_log_fatal @131 + gpgrt_log_error @132 + gpgrt_log_info @133 + gpgrt_log_debug @134 + gpgrt_log_debug_string @135 + gpgrt_log_printf @136 + gpgrt_log_printhex @137 + gpgrt_log_clock @138 + gpgrt_log_flush @139 + _gpgrt_log_assert @140 + + gpgrt_realloc @141 + gpgrt_malloc @142 + gpgrt_calloc @143 + gpgrt_strdup @144 + gpgrt_strconcat @145 + + gpgrt_w32_reg_query_string @146 + + gpgrt_getenv @147 + gpgrt_setenv @148 + gpgrt_mkdir @149 + gpgrt_chdir @150 + gpgrt_getcwd @151 + +;; API not yet finished for: +;; gpgrt_make_pipe @152 +;; gpgrt_spawn_process @153 +;; gpgrt_spawn_process_fd @154 +;; gpgrt_spawn_process_detached @155 +;; gpgrt_wait_process @156 +;; gpgrt_wait_processes @157 +;; gpgrt_kill_process @158 +;; gpgrt_release_process @159 + + gpgrt_argparse @160 + gpgrt_usage @161 + gpgrt_strusage @162 + gpgrt_set_strusage @163 + gpgrt_set_usage_outfnc @164 + gpgrt_set_fixed_string_mapper @165 + + gpgrt_b64enc_start @166 + gpgrt_b64enc_write @167 + gpgrt_b64enc_finish @168 + + gpgrt_cmp_version @169 + + gpgrt_ftruncate @170 + gpgrt_fprintf_sf @171 + gpgrt_fprintf_sf_unlocked @172 + + gpgrt_w32_override_locale @173 + + gpgrt_add_emergency_cleanup @174 + gpgrt_abort @175 + + gpgrt_set_confdir @176 + gpgrt_argparser @177 + + gpgrt_fnameconcat @178 + gpgrt_absfnameconcat @179 + + gpgrt_reallocarray @180 + gpgrt_fclose @181 + + gpgrt_fcancel @182 + + gpgrt_access @183 + +;; end of file with public symbols for Windows. diff --git a/comm/third_party/libgpg-error/src/gpg-error.h.in b/comm/third_party/libgpg-error/src/gpg-error.h.in new file mode 100644 index 0000000000..d2c3b8d3a1 --- /dev/null +++ b/comm/third_party/libgpg-error/src/gpg-error.h.in @@ -0,0 +1,1378 @@ +/* gpg-error.h or gpgrt.h - Common code for GnuPG and others. -*- c -*- + * Copyright (C) 2001-2020 g10 Code GmbH + * + * This file is part of libgpg-error (aka libgpgrt). + * + * libgpg-error is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * libgpg-error is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <https://www.gnu.org/licenses/>. + * SPDX-License-Identifier: LGPL-2.1+ + * + * @configure_input@ + */ + +/* The GnuPG project consists of many components. Error codes are + * exchanged between all components. The common error codes and their + * user-presentable descriptions are kept into a shared library to + * allow adding new error codes and components without recompiling any + * of the other components. In addition to error codes this library + * also features several other groups of functions which are common to + * all GnuPG components. They may be used by independet project as + * well. The interfaces will not change in a backward incompatible way. + * + * An error code together with an error source build up an error + * value. As the error value is been passed from one component to + * another, it preserves the information about the source and nature + * of the error. + * + * A component of the GnuPG project can define the following macros to + * tune the behaviour of the library: + * + * GPG_ERR_SOURCE_DEFAULT: Define to an error source of type + * gpg_err_source_t to make that source the default for gpg_error(). + * Otherwise GPG_ERR_SOURCE_UNKNOWN is used as default. + * + * GPG_ERR_ENABLE_GETTEXT_MACROS: Define to provide macros to map the + * internal gettext API to standard names. This has only an effect on + * Windows platforms. + * + * GPGRT_ENABLE_ES_MACROS: Define to provide "es_" macros for the + * estream functions. + * + * GPGRT_ENABLE_LOG_MACROS: Define to provide short versions of the + * log functions. + * + * GPGRT_ENABLE_ARGPARSE_MACROS: Needs to be defined to provide the + * mandatory macros of the argparse interface. + */ + +#ifndef GPG_ERROR_H +#define GPG_ERROR_H 1 +#ifndef GPGRT_H +#define GPGRT_H 1 + +#include <stddef.h> +#include <stdio.h> +#include <stdarg.h> + +/* The version string of this header. */ +#define GPG_ERROR_VERSION @version@ +#define GPGRT_VERSION @version@ + +/* The version number of this header. */ +#define GPG_ERROR_VERSION_NUMBER @version-number@ +#define GPGRT_VERSION_NUMBER @version-number@ + + +#ifdef __GNUC__ +# define GPG_ERR_INLINE __inline__ +#elif defined(_MSC_VER) && _MSC_VER >= 1300 +# define GPG_ERR_INLINE __inline +#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +# define GPG_ERR_INLINE inline +#else +# ifndef GPG_ERR_INLINE +# define GPG_ERR_INLINE +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#if 0 /* just to make Emacs auto-indent happy */ +} +#endif +#endif /* __cplusplus */ + + + +/* The error source type gpg_err_source_t. + * + * Where as the Poo out of a welle small + * Taketh his firste springing and his sours. + * --Chaucer. + */ + +/* Only use free slots, never change or reorder the existing + * entries. */ +typedef enum + { +@include:err-sources@ + /* This is one more than the largest allowed entry. */ + GPG_ERR_SOURCE_DIM = 128 + } gpg_err_source_t; + + +/* The error code type gpg_err_code_t. */ + +/* Only use free slots, never change or reorder the existing + * entries. */ +typedef enum + { +@include:err-codes@ + /* The following error codes are used to map system errors. */ +#define GPG_ERR_SYSTEM_ERROR (1 << 15) +@include:errnos@ + /* This is one more than the largest allowed entry. */ + GPG_ERR_CODE_DIM = 65536 + } gpg_err_code_t; + + +/* The error value type gpg_error_t. */ + +/* We would really like to use bit-fields in a struct, but using + * structs as return values can cause binary compatibility issues, in + * particular if you want to do it efficiently (also see + * -freg-struct-return option to GCC). */ +typedef unsigned int gpg_error_t; + +/* We use the lowest 16 bits of gpg_error_t for error codes. The 16th + * bit indicates system errors. */ +#define GPG_ERR_CODE_MASK (GPG_ERR_CODE_DIM - 1) + +/* Bits 17 to 24 are reserved. */ + +/* We use the upper 7 bits of gpg_error_t for error sources. */ +#define GPG_ERR_SOURCE_MASK (GPG_ERR_SOURCE_DIM - 1) +#define GPG_ERR_SOURCE_SHIFT 24 + +/* The highest bit is reserved. It shouldn't be used to prevent + * potential negative numbers when transmitting error values as + * text. */ + + +/* + * GCC feature test. + */ +#if __GNUC__ +# define _GPG_ERR_GCC_VERSION (__GNUC__ * 10000 \ + + __GNUC_MINOR__ * 100 \ + + __GNUC_PATCHLEVEL__) +#else +# define _GPG_ERR_GCC_VERSION 0 +#endif + +#undef _GPG_ERR_HAVE_CONSTRUCTOR +#if _GPG_ERR_GCC_VERSION > 30100 +# define _GPG_ERR_CONSTRUCTOR __attribute__ ((__constructor__)) +# define _GPG_ERR_HAVE_CONSTRUCTOR +#else +# define _GPG_ERR_CONSTRUCTOR +#endif + +#define GPGRT_GCC_VERSION _GPG_ERR_GCC_VERSION + +#if _GPG_ERR_GCC_VERSION >= 29200 +# define _GPGRT__RESTRICT __restrict__ +#else +# define _GPGRT__RESTRICT +#endif + +/* The noreturn attribute. */ +#if _GPG_ERR_GCC_VERSION >= 20500 +# define GPGRT_ATTR_NORETURN __attribute__ ((__noreturn__)) +#else +# define GPGRT_ATTR_NORETURN +#endif + +/* The printf attributes. */ +#if _GPG_ERR_GCC_VERSION >= 40400 +# define GPGRT_ATTR_PRINTF(f, a) \ + __attribute__ ((format(__gnu_printf__,f,a))) +# define GPGRT_ATTR_NR_PRINTF(f, a) \ + __attribute__ ((__noreturn__, format(__gnu_printf__,f,a))) +#elif _GPG_ERR_GCC_VERSION >= 20500 +# define GPGRT_ATTR_PRINTF(f, a) \ + __attribute__ ((format(printf,f,a))) +# define GPGRT_ATTR_NR_PRINTF(f, a) \ + __attribute__ ((__noreturn__, format(printf,f,a))) +#else +# define GPGRT_ATTR_PRINTF(f, a) +# define GPGRT_ATTR_NR_PRINTF(f, a) +#endif +#if _GPG_ERR_GCC_VERSION >= 20800 +# define GPGRT_ATTR_FORMAT_ARG(a) __attribute__ ((__format_arg__ (a))) +#else +# define GPGRT_ATTR_FORMAT_ARG(a) +#endif + +/* The sentinel attribute. */ +#if _GPG_ERR_GCC_VERSION >= 40000 +# define GPGRT_ATTR_SENTINEL(a) __attribute__ ((sentinel(a))) +#else +# define GPGRT_ATTR_SENTINEL(a) +#endif + +/* The used and unused attributes. + * I am not sure since when the unused attribute is really supported. + * In any case it it only needed for gcc versions which print a + * warning. Thus let us require gcc >= 3.5. */ +#if _GPG_ERR_GCC_VERSION >= 40000 +# define GPGRT_ATTR_USED __attribute__ ((used)) +#else +# define GPGRT_ATTR_USED +#endif +#if _GPG_ERR_GCC_VERSION >= 30500 +# define GPGRT_ATTR_UNUSED __attribute__ ((unused)) +#else +# define GPGRT_ATTR_UNUSED +#endif + +/* The deprecated attribute. */ +#if _GPG_ERR_GCC_VERSION >= 30100 +# define GPGRT_ATTR_DEPRECATED __attribute__ ((__deprecated__)) +#else +# define GPGRT_ATTR_DEPRECATED +#endif + +/* The pure attribute. */ +#if _GPG_ERR_GCC_VERSION >= 29600 +# define GPGRT_ATTR_PURE __attribute__ ((__pure__)) +#else +# define GPGRT_ATTR_PURE +#endif + +/* The malloc attribute. */ +#if _GPG_ERR_GCC_VERSION >= 30200 +# define GPGRT_ATTR_MALLOC __attribute__ ((__malloc__)) +#else +# define GPGRT_ATTR_MALLOC +#endif + +/* A macro defined if a GCC style __FUNCTION__ macro is available. */ +#undef GPGRT_HAVE_MACRO_FUNCTION +#if _GPG_ERR_GCC_VERSION >= 20500 +# define GPGRT_HAVE_MACRO_FUNCTION 1 +#endif + +/* A macro defined if the pragma GCC push_options is available. */ +#undef GPGRT_HAVE_PRAGMA_GCC_PUSH +#if _GPG_ERR_GCC_VERSION >= 40400 +# define GPGRT_HAVE_PRAGMA_GCC_PUSH 1 +#endif + +/* Detect LeakSanitizer (LSan) support for GCC and Clang based on + * whether AddressSanitizer (ASAN) is enabled via -fsanitize=address). + * Note that -fsanitize=leak just affect the linker options which + * cannot be detected here. In that case you have to define the + * GPGRT_HAVE_LEAK_SANITIZER macro manually. */ +#ifdef __GNUC__ +# ifdef __SANITIZE_ADDRESS__ +# define GPGRT_HAVE_LEAK_SANITIZER +# elif defined(__has_feature) +# if __has_feature(address_sanitizer) +# define GPGRT_HAVE_LEAK_SANITIZER +# endif +# endif +#endif + + +/* The new name for the inline macro. */ +#define GPGRT_INLINE GPG_ERR_INLINE + +#ifdef GPGRT_HAVE_LEAK_SANITIZER +# include <sanitizer/lsan_interface.h> +#endif + +/* Mark heap objects as non-leaked memory. */ +static GPGRT_INLINE void +gpgrt_annotate_leaked_object (const void *p) +{ +#ifdef GPGRT_HAVE_LEAK_SANITIZER + __lsan_ignore_object(p); +#else + (void)p; +#endif +} + + +/* + * Initialization function. + */ + +/* Initialize the library. This function should be run early. */ +gpg_error_t gpg_err_init (void) _GPG_ERR_CONSTRUCTOR; + +/* If this is defined, the library is already initialized by the + constructor and does not need to be initialized explicitely. */ +#undef GPG_ERR_INITIALIZED +#ifdef _GPG_ERR_HAVE_CONSTRUCTOR +# define GPG_ERR_INITIALIZED 1 +# define gpgrt_init() do { gpg_err_init (); } while (0) +#else +# define gpgrt_init() do { ; } while (0) +#endif + +/* See the source on how to use the deinit function; it is usually not + required. */ +void gpg_err_deinit (int mode); + +/* Register blocking system I/O clamping functions. */ +void gpgrt_set_syscall_clamp (void (*pre)(void), void (*post)(void)); + +/* Get current I/O clamping functions. */ +void gpgrt_get_syscall_clamp (void (**r_pre)(void), void (**r_post)(void)); + +/* Register a custom malloc/realloc/free function. */ +void gpgrt_set_alloc_func (void *(*f)(void *a, size_t n)); + +/* Register an emergency cleanup handler. */ +void gpgrt_add_emergency_cleanup (void (*f)(void)); + +/* Wrapper around abort to make sure emergency cleanups are run. */ +void gpgrt_abort (void) GPGRT_ATTR_NORETURN; + + + +/* + * Constructor and accessor functions. + */ + +/* Construct an error value from an error code and source. Within a + * subsystem, use gpg_error. */ +static GPG_ERR_INLINE gpg_error_t +gpg_err_make (gpg_err_source_t source, gpg_err_code_t code) +{ + return code == GPG_ERR_NO_ERROR ? GPG_ERR_NO_ERROR + : (((source & GPG_ERR_SOURCE_MASK) << GPG_ERR_SOURCE_SHIFT) + | (code & GPG_ERR_CODE_MASK)); +} + + +/* The user should define GPG_ERR_SOURCE_DEFAULT before including this + * file to specify a default source for gpg_error. */ +#ifndef GPG_ERR_SOURCE_DEFAULT +#define GPG_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_UNKNOWN +#endif + +static GPG_ERR_INLINE gpg_error_t +gpg_error (gpg_err_code_t code) +{ + return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, code); +} + + +/* Retrieve the error code from an error value. */ +static GPG_ERR_INLINE gpg_err_code_t +gpg_err_code (gpg_error_t err) +{ + return (gpg_err_code_t) (err & GPG_ERR_CODE_MASK); +} + + +/* Retrieve the error source from an error value. */ +static GPG_ERR_INLINE gpg_err_source_t +gpg_err_source (gpg_error_t err) +{ + return (gpg_err_source_t) ((err >> GPG_ERR_SOURCE_SHIFT) + & GPG_ERR_SOURCE_MASK); +} + + +/* String functions. */ + +/* Return a pointer to a string containing a description of the error + * code in the error value ERR. This function is not thread-safe. */ +const char *gpg_strerror (gpg_error_t err); + +/* Return the error string for ERR in the user-supplied buffer BUF of + * size BUFLEN. This function is, in contrast to gpg_strerror, + * thread-safe if a thread-safe strerror_r() function is provided by + * the system. If the function succeeds, 0 is returned and BUF + * contains the string describing the error. If the buffer was not + * large enough, ERANGE is returned and BUF contains as much of the + * beginning of the error string as fits into the buffer. */ +int gpg_strerror_r (gpg_error_t err, char *buf, size_t buflen); + +/* Return a pointer to a string containing a description of the error + * source in the error value ERR. */ +const char *gpg_strsource (gpg_error_t err); + + +/* + * Mapping of system errors (errno). + */ + +/* Retrieve the error code for the system error ERR. This returns + * GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped (report + * this). */ +gpg_err_code_t gpg_err_code_from_errno (int err); + +/* Retrieve the system error for the error code CODE. This returns 0 + * if CODE is not a system error code. */ +int gpg_err_code_to_errno (gpg_err_code_t code); + +/* Retrieve the error code directly from the ERRNO variable. This + * returns GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped + * (report this) and GPG_ERR_MISSING_ERRNO if ERRNO has the value 0. */ +gpg_err_code_t gpg_err_code_from_syserror (void); + +/* Mapper for SQLite primary error codes. */ +static GPG_ERR_INLINE gpg_error_t +gpg_err_code_from_sqlite (int sqlres) +{ + return sqlres? GPG_ERR_SQL_OK + (sqlres & 0xff) : 0; +} + + +/* Set the ERRNO variable. This function is the preferred way to set + * ERRNO due to peculiarities on WindowsCE. */ +void gpg_err_set_errno (int err); + +/* Return or check the version. Both functions are identical. */ +const char *gpgrt_check_version (const char *req_version); +const char *gpg_error_check_version (const char *req_version); + +/* System specific type definitions. */ +@define:pid_t@ +@define:gpgrt_ssize_t@ +@define:gpgrt_off_t@ + +@include:os-add@ + +/* Self-documenting convenience functions. */ + +static GPG_ERR_INLINE gpg_error_t +gpg_err_make_from_errno (gpg_err_source_t source, int err) +{ + return gpg_err_make (source, gpg_err_code_from_errno (err)); +} + + +static GPG_ERR_INLINE gpg_error_t +gpg_error_from_errno (int err) +{ + return gpg_error (gpg_err_code_from_errno (err)); +} + +static GPG_ERR_INLINE gpg_error_t +gpg_error_from_syserror (void) +{ + return gpg_error (gpg_err_code_from_syserror ()); +} + + + +/* + * Malloc and friends + */ + +void *gpgrt_realloc (void *a, size_t n); +void *gpgrt_reallocarray (void *a, size_t oldnmemb, size_t nmemb, size_t size); +void *gpgrt_malloc (size_t n); +void *gpgrt_calloc (size_t n, size_t m); +char *gpgrt_strdup (const char *string); +char *gpgrt_strconcat (const char *s1, ...) GPGRT_ATTR_SENTINEL(0); +void gpgrt_free (void *a); + + +/* + * System specific function wrappers. + */ + +/* A getenv replacement which mallocs the returned string. */ +char *gpgrt_getenv (const char *name); + +/* A setenv and a unsetenv replacement.*/ +gpg_err_code_t gpgrt_setenv (const char *name, + const char *value, int overwrite); +#define gpgrt_unsetenv(n) gpgrt_setenv ((n), NULL, 1) + +/* A wrapper around mkdir using a string for the mode. */ +gpg_err_code_t gpgrt_mkdir (const char *name, const char *modestr); + +/* A simple wrapper around chdir. */ +gpg_err_code_t gpgrt_chdir (const char *name); + +/* Return the current WD as a malloced string. */ +char *gpgrt_getcwd (void); + +/* A wrapper around access to handle UTF-8 on Windows. */ +gpg_err_code_t gpgrt_access (const char *fname, int mode); + + + + +/* + * Lock functions. + */ + +@include:lock-obj@ + +#define GPGRT_LOCK_DEFINE(name) \ + static gpgrt_lock_t name = GPGRT_LOCK_INITIALIZER + +/* NB: If GPGRT_LOCK_DEFINE is not used, zero out the lock variable + before passing it to gpgrt_lock_init. */ +gpg_err_code_t gpgrt_lock_init (gpgrt_lock_t *lockhd); +gpg_err_code_t gpgrt_lock_lock (gpgrt_lock_t *lockhd); +gpg_err_code_t gpgrt_lock_trylock (gpgrt_lock_t *lockhd); +gpg_err_code_t gpgrt_lock_unlock (gpgrt_lock_t *lockhd); +gpg_err_code_t gpgrt_lock_destroy (gpgrt_lock_t *lockhd); + + + +/* + * Thread functions. + */ + +gpg_err_code_t gpgrt_yield (void); + + + + +/* + * Estream + */ + +/* The definition of this struct is entirely private. You must not + use it for anything. It is only here so some functions can be + implemented as macros. */ +struct _gpgrt_stream_internal; +struct _gpgrt__stream +{ + /* The layout of this struct must never change. It may be grown, + but only if all functions which access the new members are + versioned. */ + + /* Various flags. */ + struct { + unsigned int magic: 16; + unsigned int writing: 1; + unsigned int reserved: 15; + } flags; + + /* A pointer to the stream buffer. */ + unsigned char *buffer; + + /* The size of the buffer in bytes. */ + size_t buffer_size; + + /* The length of the usable data in the buffer, only valid when in + read mode (see flags). */ + size_t data_len; + + /* The current position of the offset pointer, valid in read and + write mode. */ + size_t data_offset; + + size_t data_flushed; + unsigned char *unread_buffer; + size_t unread_buffer_size; + + /* The number of unread bytes. */ + size_t unread_data_len; + + /* A pointer to our internal data for this stream. */ + struct _gpgrt_stream_internal *intern; +}; + +/* The opaque type for an estream. */ +typedef struct _gpgrt__stream *gpgrt_stream_t; +#ifdef GPGRT_ENABLE_ES_MACROS +typedef struct _gpgrt__stream *estream_t; +#endif + +typedef @api_ssize_t@ (*gpgrt_cookie_read_function_t) (void *cookie, + void *buffer, size_t size); +typedef @api_ssize_t@ (*gpgrt_cookie_write_function_t) (void *cookie, + const void *buffer, + size_t size); +typedef int (*gpgrt_cookie_seek_function_t) (void *cookie, + gpgrt_off_t *pos, int whence); +typedef int (*gpgrt_cookie_close_function_t) (void *cookie); + +struct _gpgrt_cookie_io_functions +{ + gpgrt_cookie_read_function_t func_read; + gpgrt_cookie_write_function_t func_write; + gpgrt_cookie_seek_function_t func_seek; + gpgrt_cookie_close_function_t func_close; +}; +typedef struct _gpgrt_cookie_io_functions gpgrt_cookie_io_functions_t; +#ifdef GPGRT_ENABLE_ES_MACROS +typedef struct _gpgrt_cookie_io_functions es_cookie_io_functions_t; +#define es_cookie_read_function_t gpgrt_cookie_read_function_t +#define es_cookie_write_function_t gpgrt_cookie_read_function_t +#define es_cookie_seek_function_t gpgrt_cookie_read_function_t +#define es_cookie_close_function_t gpgrt_cookie_read_function_t +#endif + +enum gpgrt_syshd_types + { + GPGRT_SYSHD_NONE = 0, /* No system handle available. */ + GPGRT_SYSHD_FD = 1, /* A file descriptor as returned by open(). */ + GPGRT_SYSHD_SOCK = 2, /* A socket as returned by socket(). */ + GPGRT_SYSHD_RVID = 3, /* A rendezvous id (see libassuan's gpgcedev.c). */ + GPGRT_SYSHD_HANDLE = 4 /* A HANDLE object (Windows). */ + }; + +struct _gpgrt_syshd +{ + enum gpgrt_syshd_types type; + union { + int fd; + int sock; + int rvid; + void *handle; + } u; +}; +typedef struct _gpgrt_syshd gpgrt_syshd_t; +#ifdef GPGRT_ENABLE_ES_MACROS +typedef struct _gpgrt_syshd es_syshd_t; +#define ES_SYSHD_NONE GPGRT_SYSHD_NONE +#define ES_SYSHD_FD GPGRT_SYSHD_FD +#define ES_SYSHD_SOCK GPGRT_SYSHD_SOCK +#define ES_SYSHD_RVID GPGRT_SYSHD_RVID +#define ES_SYSHD_HANDLE GPGRT_SYSHD_HANDLE +#endif + +/* The object used with gpgrt_poll. */ +struct _gpgrt_poll_s +{ + gpgrt_stream_t stream; + unsigned int want_read:1; + unsigned int want_write:1; + unsigned int want_oob:1; + unsigned int want_rdhup:1; + unsigned int _reserv1:4; + unsigned int got_read:1; + unsigned int got_write:1; + unsigned int got_oob:1; + unsigned int got_rdhup:1; + unsigned int _reserv2:4; + unsigned int got_err:1; + unsigned int got_hup:1; + unsigned int got_nval:1; + unsigned int _reserv3:4; + unsigned int ignore:1; + unsigned int user:8; /* For application use. */ +}; +typedef struct _gpgrt_poll_s gpgrt_poll_t; +#ifdef GPGRT_ENABLE_ES_MACROS +typedef struct _gpgrt_poll_s es_poll_t; +#endif + +/* The type of the string filter function as used by fprintf_sf et al. */ +typedef char *(*gpgrt_string_filter_t) (const char *s, int n, void *opaque); + + + +gpgrt_stream_t gpgrt_fopen (const char *_GPGRT__RESTRICT path, + const char *_GPGRT__RESTRICT mode); +gpgrt_stream_t gpgrt_mopen (void *_GPGRT__RESTRICT data, + size_t data_n, size_t data_len, + unsigned int grow, + void *(*func_realloc) (void *mem, size_t size), + void (*func_free) (void *mem), + const char *_GPGRT__RESTRICT mode); +gpgrt_stream_t gpgrt_fopenmem (size_t memlimit, + const char *_GPGRT__RESTRICT mode); +gpgrt_stream_t gpgrt_fopenmem_init (size_t memlimit, + const char *_GPGRT__RESTRICT mode, + const void *data, size_t datalen); +gpgrt_stream_t gpgrt_fdopen (int filedes, const char *mode); +gpgrt_stream_t gpgrt_fdopen_nc (int filedes, const char *mode); +gpgrt_stream_t gpgrt_sysopen (gpgrt_syshd_t *syshd, const char *mode); +gpgrt_stream_t gpgrt_sysopen_nc (gpgrt_syshd_t *syshd, const char *mode); +gpgrt_stream_t gpgrt_fpopen (FILE *fp, const char *mode); +gpgrt_stream_t gpgrt_fpopen_nc (FILE *fp, const char *mode); +gpgrt_stream_t gpgrt_freopen (const char *_GPGRT__RESTRICT path, + const char *_GPGRT__RESTRICT mode, + gpgrt_stream_t _GPGRT__RESTRICT stream); +gpgrt_stream_t gpgrt_fopencookie (void *_GPGRT__RESTRICT cookie, + const char *_GPGRT__RESTRICT mode, + gpgrt_cookie_io_functions_t functions); +int gpgrt_fclose (gpgrt_stream_t stream); +int gpgrt_fcancel (gpgrt_stream_t stream); +int gpgrt_fclose_snatch (gpgrt_stream_t stream, + void **r_buffer, size_t *r_buflen); +int gpgrt_onclose (gpgrt_stream_t stream, int mode, + void (*fnc) (gpgrt_stream_t, void*), void *fnc_value); +int gpgrt_fileno (gpgrt_stream_t stream); +int gpgrt_fileno_unlocked (gpgrt_stream_t stream); +int gpgrt_syshd (gpgrt_stream_t stream, gpgrt_syshd_t *syshd); +int gpgrt_syshd_unlocked (gpgrt_stream_t stream, gpgrt_syshd_t *syshd); + +void _gpgrt_set_std_fd (int no, int fd); +gpgrt_stream_t _gpgrt_get_std_stream (int fd); + +#define gpgrt_stdin _gpgrt_get_std_stream (0) +#define gpgrt_stdout _gpgrt_get_std_stream (1) +#define gpgrt_stderr _gpgrt_get_std_stream (2) + + +void gpgrt_flockfile (gpgrt_stream_t stream); +int gpgrt_ftrylockfile (gpgrt_stream_t stream); +void gpgrt_funlockfile (gpgrt_stream_t stream); + +int gpgrt_feof (gpgrt_stream_t stream); +int gpgrt_feof_unlocked (gpgrt_stream_t stream); +int gpgrt_ferror (gpgrt_stream_t stream); +int gpgrt_ferror_unlocked (gpgrt_stream_t stream); +void gpgrt_clearerr (gpgrt_stream_t stream); +void gpgrt_clearerr_unlocked (gpgrt_stream_t stream); + +int _gpgrt_pending (gpgrt_stream_t stream); /* (private) */ +int _gpgrt_pending_unlocked (gpgrt_stream_t stream); /* (private) */ + +#define gpgrt_pending(stream) _gpgrt_pending (stream) + +#define gpgrt_pending_unlocked(stream) \ + (((!(stream)->flags.writing) \ + && (((stream)->data_offset < (stream)->data_len) \ + || ((stream)->unread_data_len))) \ + ? 1 : _gpgrt_pending_unlocked ((stream))) + +int gpgrt_fflush (gpgrt_stream_t stream); +int gpgrt_fseek (gpgrt_stream_t stream, long int offset, int whence); +int gpgrt_fseeko (gpgrt_stream_t stream, gpgrt_off_t offset, int whence); +int gpgrt_ftruncate (gpgrt_stream_t stream, gpgrt_off_t length); +long int gpgrt_ftell (gpgrt_stream_t stream); +gpgrt_off_t gpgrt_ftello (gpgrt_stream_t stream); +void gpgrt_rewind (gpgrt_stream_t stream); + +int gpgrt_fgetc (gpgrt_stream_t stream); +int gpgrt_fputc (int c, gpgrt_stream_t stream); + +int _gpgrt_getc_underflow (gpgrt_stream_t stream); /* (private) */ +int _gpgrt_putc_overflow (int c, gpgrt_stream_t stream); /* (private) */ + +#define gpgrt_getc_unlocked(stream) \ + (((!(stream)->flags.writing) \ + && ((stream)->data_offset < (stream)->data_len) \ + && (! (stream)->unread_data_len)) \ + ? ((int) (stream)->buffer[((stream)->data_offset)++]) \ + : _gpgrt_getc_underflow ((stream))) + +#define gpgrt_putc_unlocked(c, stream) \ + (((stream)->flags.writing \ + && ((stream)->data_offset < (stream)->buffer_size) \ + && (c != '\n')) \ + ? ((int) ((stream)->buffer[((stream)->data_offset)++] = (c))) \ + : _gpgrt_putc_overflow ((c), (stream))) + +#define gpgrt_getc(stream) gpgrt_fgetc (stream) +#define gpgrt_putc(c, stream) gpgrt_fputc (c, stream) + +int gpgrt_ungetc (int c, gpgrt_stream_t stream); + +int gpgrt_read (gpgrt_stream_t _GPGRT__RESTRICT stream, + void *_GPGRT__RESTRICT buffer, size_t bytes_to_read, + size_t *_GPGRT__RESTRICT bytes_read); +int gpgrt_write (gpgrt_stream_t _GPGRT__RESTRICT stream, + const void *_GPGRT__RESTRICT buffer, size_t bytes_to_write, + size_t *_GPGRT__RESTRICT bytes_written); +int gpgrt_write_sanitized (gpgrt_stream_t _GPGRT__RESTRICT stream, + const void *_GPGRT__RESTRICT buffer, size_t length, + const char *delimiters, + size_t *_GPGRT__RESTRICT bytes_written); +int gpgrt_write_hexstring (gpgrt_stream_t _GPGRT__RESTRICT stream, + const void *_GPGRT__RESTRICT buffer, size_t length, + int reserved, + size_t *_GPGRT__RESTRICT bytes_written); + +size_t gpgrt_fread (void *_GPGRT__RESTRICT ptr, size_t size, size_t nitems, + gpgrt_stream_t _GPGRT__RESTRICT stream); +size_t gpgrt_fwrite (const void *_GPGRT__RESTRICT ptr, size_t size, + size_t nitems, gpgrt_stream_t _GPGRT__RESTRICT stream); + +char *gpgrt_fgets (char *_GPGRT__RESTRICT s, int n, + gpgrt_stream_t _GPGRT__RESTRICT stream); +int gpgrt_fputs (const char *_GPGRT__RESTRICT s, + gpgrt_stream_t _GPGRT__RESTRICT stream); +int gpgrt_fputs_unlocked (const char *_GPGRT__RESTRICT s, + gpgrt_stream_t _GPGRT__RESTRICT stream); + +@api_ssize_t@ gpgrt_getline (char *_GPGRT__RESTRICT *_GPGRT__RESTRICT lineptr, + size_t *_GPGRT__RESTRICT n, + gpgrt_stream_t stream); +@api_ssize_t@ gpgrt_read_line (gpgrt_stream_t stream, + char **addr_of_buffer, size_t *length_of_buffer, + size_t *max_length); + +int gpgrt_fprintf (gpgrt_stream_t _GPGRT__RESTRICT stream, + const char *_GPGRT__RESTRICT format, ...) + GPGRT_ATTR_PRINTF(2,3); +int gpgrt_fprintf_unlocked (gpgrt_stream_t _GPGRT__RESTRICT stream, + const char *_GPGRT__RESTRICT format, ...) + GPGRT_ATTR_PRINTF(2,3); + +int gpgrt_fprintf_sf (gpgrt_stream_t _GPGRT__RESTRICT stream, + gpgrt_string_filter_t sf, void *sfvalue, + const char *_GPGRT__RESTRICT format, + ...) GPGRT_ATTR_PRINTF(4,5); +int gpgrt_fprintf_sf_unlocked (gpgrt_stream_t _GPGRT__RESTRICT stream, + gpgrt_string_filter_t sf, void *sfvalue, + const char *_GPGRT__RESTRICT format, + ...) GPGRT_ATTR_PRINTF(4,5); + +int gpgrt_printf (const char *_GPGRT__RESTRICT format, ...) + GPGRT_ATTR_PRINTF(1,2); +int gpgrt_printf_unlocked (const char *_GPGRT__RESTRICT format, ...) + GPGRT_ATTR_PRINTF(1,2); + +int gpgrt_vfprintf (gpgrt_stream_t _GPGRT__RESTRICT stream, + const char *_GPGRT__RESTRICT format, va_list ap) + GPGRT_ATTR_PRINTF(2,0); +int gpgrt_vfprintf_unlocked (gpgrt_stream_t _GPGRT__RESTRICT stream, + const char *_GPGRT__RESTRICT format, va_list ap) + GPGRT_ATTR_PRINTF(2,0); + +int gpgrt_setvbuf (gpgrt_stream_t _GPGRT__RESTRICT stream, + char *_GPGRT__RESTRICT buf, int mode, size_t size); +void gpgrt_setbuf (gpgrt_stream_t _GPGRT__RESTRICT stream, + char *_GPGRT__RESTRICT buf); + +void gpgrt_set_binary (gpgrt_stream_t stream); +int gpgrt_set_nonblock (gpgrt_stream_t stream, int onoff); +int gpgrt_get_nonblock (gpgrt_stream_t stream); + +int gpgrt_poll (gpgrt_poll_t *fdlist, unsigned int nfds, int timeout); + +gpgrt_stream_t gpgrt_tmpfile (void); + +void gpgrt_opaque_set (gpgrt_stream_t _GPGRT__RESTRICT stream, + void *_GPGRT__RESTRICT opaque); +void *gpgrt_opaque_get (gpgrt_stream_t stream); + +void gpgrt_fname_set (gpgrt_stream_t stream, const char *fname); +const char *gpgrt_fname_get (gpgrt_stream_t stream); + +int gpgrt_asprintf (char **r_buf, const char * _GPGRT__RESTRICT format, ...) + GPGRT_ATTR_PRINTF(2,3); +int gpgrt_vasprintf (char **r_buf, const char * _GPGRT__RESTRICT format, + va_list ap) + GPGRT_ATTR_PRINTF(2,0); +char *gpgrt_bsprintf (const char * _GPGRT__RESTRICT format, ...) + GPGRT_ATTR_PRINTF(1,2); +char *gpgrt_vbsprintf (const char * _GPGRT__RESTRICT format, va_list ap) + GPGRT_ATTR_PRINTF(1,0); +int gpgrt_snprintf (char *buf, size_t bufsize, + const char * _GPGRT__RESTRICT format, ...) + GPGRT_ATTR_PRINTF(3,4); +int gpgrt_vsnprintf (char *buf,size_t bufsize, + const char * _GPGRT__RESTRICT format, va_list arg_ptr) + GPGRT_ATTR_PRINTF(3,0); + + +#ifdef GPGRT_ENABLE_ES_MACROS +# define es_fopen gpgrt_fopen +# define es_mopen gpgrt_mopen +# define es_fopenmem gpgrt_fopenmem +# define es_fopenmem_init gpgrt_fopenmem_init +# define es_fdopen gpgrt_fdopen +# define es_fdopen_nc gpgrt_fdopen_nc +# define es_sysopen gpgrt_sysopen +# define es_sysopen_nc gpgrt_sysopen_nc +# define es_fpopen gpgrt_fpopen +# define es_fpopen_nc gpgrt_fpopen_nc +# define es_freopen gpgrt_freopen +# define es_fopencookie gpgrt_fopencookie +# define es_fclose gpgrt_fclose +# define es_fclose_snatch gpgrt_fclose_snatch +# define es_onclose gpgrt_onclose +# define es_fileno gpgrt_fileno +# define es_fileno_unlocked gpgrt_fileno_unlocked +# define es_syshd gpgrt_syshd +# define es_syshd_unlocked gpgrt_syshd_unlocked +# define es_stdin _gpgrt_get_std_stream (0) +# define es_stdout _gpgrt_get_std_stream (1) +# define es_stderr _gpgrt_get_std_stream (2) +# define es_flockfile gpgrt_flockfile +# define es_ftrylockfile gpgrt_ftrylockfile +# define es_funlockfile gpgrt_funlockfile +# define es_feof gpgrt_feof +# define es_feof_unlocked gpgrt_feof_unlocked +# define es_ferror gpgrt_ferror +# define es_ferror_unlocked gpgrt_ferror_unlocked +# define es_clearerr gpgrt_clearerr +# define es_clearerr_unlocked gpgrt_clearerr_unlocked +# define es_pending gpgrt_pending +# define es_pending_unlocked gpgrt_pending_unlocked +# define es_fflush gpgrt_fflush +# define es_fseek gpgrt_fseek +# define es_fseeko gpgrt_fseeko +# define es_ftruncate gpgrt_ftruncate +# define es_ftell gpgrt_ftell +# define es_ftello gpgrt_ftello +# define es_rewind gpgrt_rewind +# define es_fgetc gpgrt_fgetc +# define es_fputc gpgrt_fputc +# define es_getc_unlocked gpgrt_getc_unlocked +# define es_putc_unlocked gpgrt_putc_unlocked +# define es_getc gpgrt_getc +# define es_putc gpgrt_putc +# define es_ungetc gpgrt_ungetc +# define es_read gpgrt_read +# define es_write gpgrt_write +# define es_write_sanitized gpgrt_write_sanitized +# define es_write_hexstring gpgrt_write_hexstring +# define es_fread gpgrt_fread +# define es_fwrite gpgrt_fwrite +# define es_fgets gpgrt_fgets +# define es_fputs gpgrt_fputs +# define es_fputs_unlocked gpgrt_fputs_unlocked +# define es_getline gpgrt_getline +# define es_read_line gpgrt_read_line +# define es_free gpgrt_free +# define es_fprintf gpgrt_fprintf +# define es_fprintf_unlocked gpgrt_fprintf_unlocked +# define es_printf gpgrt_printf +# define es_printf_unlocked gpgrt_printf_unlocked +# define es_vfprintf gpgrt_vfprintf +# define es_vfprintf_unlocked gpgrt_vfprintf_unlocked +# define es_setvbuf gpgrt_setvbuf +# define es_setbuf gpgrt_setbuf +# define es_set_binary gpgrt_set_binary +# define es_set_nonblock gpgrt_set_nonblock +# define es_get_nonblock gpgrt_get_nonblock +# define es_poll gpgrt_poll +# define es_tmpfile gpgrt_tmpfile +# define es_opaque_set gpgrt_opaque_set +# define es_opaque_get gpgrt_opaque_get +# define es_fname_set gpgrt_fname_set +# define es_fname_get gpgrt_fname_get +# define es_asprintf gpgrt_asprintf +# define es_vasprintf gpgrt_vasprintf +# define es_bsprintf gpgrt_bsprintf +# define es_vbsprintf gpgrt_vbsprintf +#endif /*GPGRT_ENABLE_ES_MACROS*/ + + + +/* + * Base64 encode and decode functions. + */ + +struct _gpgrt_b64state; +typedef struct _gpgrt_b64state *gpgrt_b64state_t; + +gpgrt_b64state_t gpgrt_b64enc_start (gpgrt_stream_t stream, const char *title); +gpg_err_code_t gpgrt_b64enc_write (gpgrt_b64state_t state, + const void *buffer, size_t nbytes); +gpg_err_code_t gpgrt_b64enc_finish (gpgrt_b64state_t state); + +gpgrt_b64state_t gpgrt_b64dec_start (const char *title); +gpg_error_t gpgrt_b64dec_proc (gpgrt_b64state_t state, + void *buffer, size_t length, + size_t *r_nbytes); +gpg_error_t gpgrt_b64dec_finish (gpgrt_b64state_t state); + + + +/* + * Logging functions + */ + +/* Flag values for gpgrt_log_set_prefix. */ +#define GPGRT_LOG_WITH_PREFIX 1 +#define GPGRT_LOG_WITH_TIME 2 +#define GPGRT_LOG_WITH_PID 4 +#define GPGRT_LOG_RUN_DETACHED 256 +#define GPGRT_LOG_NO_REGISTRY 512 + +/* Log levels as used by gpgrt_log. */ +enum gpgrt_log_levels + { + GPGRT_LOGLVL_BEGIN, + GPGRT_LOGLVL_CONT, + GPGRT_LOGLVL_INFO, + GPGRT_LOGLVL_WARN, + GPGRT_LOGLVL_ERROR, + GPGRT_LOGLVL_FATAL, + GPGRT_LOGLVL_BUG, + GPGRT_LOGLVL_DEBUG + }; + + +/* The next 4 functions are not thread-safe - call them early. */ +void gpgrt_log_set_sink (const char *name, gpgrt_stream_t stream, int fd); +void gpgrt_log_set_socket_dir_cb (const char *(*fnc)(void)); +void gpgrt_log_set_pid_suffix_cb (int (*cb)(unsigned long *r_value)); +void gpgrt_log_set_prefix (const char *text, unsigned int flags); + +int gpgrt_get_errorcount (int clear); +void gpgrt_inc_errorcount (void); +const char *gpgrt_log_get_prefix (unsigned int *flags); +int gpgrt_log_test_fd (int fd); +int gpgrt_log_get_fd (void); +gpgrt_stream_t gpgrt_log_get_stream (void); + +void gpgrt_log (int level, const char *fmt, ...) GPGRT_ATTR_PRINTF(2,3); +void gpgrt_logv (int level, const char *fmt, va_list arg_ptr); +void gpgrt_logv_prefix (int level, const char *prefix, + const char *fmt, va_list arg_ptr); +void gpgrt_log_string (int level, const char *string); +void gpgrt_log_bug (const char *fmt, ...) GPGRT_ATTR_NR_PRINTF(1,2); +void gpgrt_log_fatal (const char *fmt, ...) GPGRT_ATTR_NR_PRINTF(1,2); +void gpgrt_log_error (const char *fmt, ...) GPGRT_ATTR_PRINTF(1,2); +void gpgrt_log_info (const char *fmt, ...) GPGRT_ATTR_PRINTF(1,2); +void gpgrt_log_debug (const char *fmt, ...) GPGRT_ATTR_PRINTF(1,2); +void gpgrt_log_debug_string (const char *string, + const char *fmt, ...) GPGRT_ATTR_PRINTF(2,3); +void gpgrt_log_printf (const char *fmt, ...) GPGRT_ATTR_PRINTF(1,2); +void gpgrt_log_printhex (const void *buffer, size_t length, + const char *fmt, ...) GPGRT_ATTR_PRINTF(3,4); +void gpgrt_log_clock (const char *fmt, ...) GPGRT_ATTR_PRINTF(1,2); +void gpgrt_log_flush (void); +void _gpgrt_log_assert (const char *expr, const char *file, int line, + const char *func) GPGRT_ATTR_NORETURN; + +#ifdef GPGRT_HAVE_MACRO_FUNCTION +# define gpgrt_assert(expr) \ + ((expr) \ + ? (void) 0 \ + : _gpgrt_log_assert (#expr, __FILE__, __LINE__, __FUNCTION__)) +#else /*!GPGRT_HAVE_MACRO_FUNCTION*/ +# define gpgrt_assert(expr) \ + ((expr) \ + ? (void) 0 \ + : _gpgrt_log_assert (#expr, __FILE__, __LINE__, NULL)) +#endif /*!GPGRT_HAVE_MACRO_FUNCTION*/ + +#ifdef GPGRT_ENABLE_LOG_MACROS +# define log_get_errorcount gpgrt_get_errorcount +# define log_inc_errorcount gpgrt_inc_errorcount +# define log_set_file(a) gpgrt_log_set_sink ((a), NULL, -1) +# define log_set_fd(a) gpgrt_log_set_sink (NULL, NULL, (a)) +# define log_set_stream(a) gpgrt_log_set_sink (NULL, (a), -1) +# define log_set_socket_dir_cb gpgrt_log_set_socket_dir_cb +# define log_set_pid_suffix_cb gpgrt_log_set_pid_suffix_cb +# define log_set_prefix gpgrt_log_set_prefix +# define log_get_prefix gpgrt_log_get_prefix +# define log_test_fd gpgrt_log_test_fd +# define log_get_fd gpgrt_log_get_fd +# define log_get_stream gpgrt_log_get_stream +# define log_log gpgrt_log +# define log_logv gpgrt_logv +# define log_logv_prefix gpgrt_logv_prefix +# define log_string gpgrt_log_string +# define log_bug gpgrt_log_bug +# define log_fatal gpgrt_log_fatal +# define log_error gpgrt_log_error +# define log_info gpgrt_log_info +# define log_debug gpgrt_log_debug +# define log_debug_string gpgrt_log_debug_string +# define log_printf gpgrt_log_printf +# define log_printhex gpgrt_log_printhex +# define log_clock gpgrt_log_clock +# define log_flush gpgrt_log_flush +# ifdef GPGRT_HAVE_MACRO_FUNCTION +# define log_assert(expr) \ + ((expr) \ + ? (void) 0 \ + : _gpgrt_log_assert (#expr, __FILE__, __LINE__, __FUNCTION__)) +# else /*!GPGRT_HAVE_MACRO_FUNCTION*/ +# define log_assert(expr) \ + ((expr) \ + ? (void) 0 \ + : _gpgrt_log_assert (#expr, __FILE__, __LINE__, NULL)) +# endif /*!GPGRT_HAVE_MACRO_FUNCTION*/ + +#endif /*GPGRT_ENABLE_LOG_MACROS*/ + + +/* + * Spawn functions (Not yet available) + */ +#define GPGRT_SPAWN_NONBLOCK 16 /* Set the streams to non-blocking. */ +#define GPGRT_SPAWN_RUN_ASFW 64 /* Use AllowSetForegroundWindow on W32. */ +#define GPGRT_SPAWN_DETACHED 128 /* Start the process in the background. */ + +#if 0 + +/* Function and convenience macros to create pipes. */ +gpg_err_code_t gpgrt_make_pipe (int filedes[2], gpgrt_stream_t *r_fp, + int direction, int nonblock); +#define gpgrt_create_pipe(a) gpgrt_make_pipe ((a),NULL, 0, 0); +#define gpgrt_create_inbound_pipe(a,b,c) gpgrt_make_pipe ((a), (b), -1,(c)); +#define gpgrt_create_outbound_pipe(a,b,c) gpgrt_make_pipe ((a), (b), 1,(c)); + + +/* Fork and exec PGMNAME. */ +gpg_err_code_t gpgrt_spawn_process (const char *pgmname, const char *argv[], + int *execpt, void (*preexec)(void), + unsigned int flags, + gpgrt_stream_t *r_infp, + gpgrt_stream_t *r_outfp, + gpgrt_stream_t *r_errfp, + pid_t *pid); + +/* Fork and exec PGNNAME and connect the process to the given FDs. */ +gpg_err_code_t gpgrt_spawn_process_fd (const char *pgmname, const char *argv[], + int infd, int outfd, int errfd, + pid_t *pid); + +/* Fork and exec PGMNAME as a detached process. */ +gpg_err_code_t gpgrt_spawn_process_detached (const char *pgmname, + const char *argv[], + const char *envp[] ); + +/* Wait for a single process. */ +gpg_err_code_t gpgrt_wait_process (const char *pgmname, pid_t pid, int hang, + int *r_exitcode); + +/* Wait for a multiple processes. */ +gpg_err_code_t gpgrt_wait_processes (const char **pgmnames, pid_t *pids, + size_t count, int hang, int *r_exitcodes); + +/* Kill the process identified by PID. */ +void gpgrt_kill_process (pid_t pid); + +/* Release process resources identified by PID. */ +void gpgrt_release_process (pid_t pid); + +#endif /*0*/ + + + +/* + * Option parsing. + */ + +struct _gpgrt_argparse_internal_s; +typedef struct +{ + int *argc; /* Pointer to ARGC (value subject to change). */ + char ***argv; /* Pointer to ARGV (value subject to change). */ + unsigned int flags; /* Global flags. May be set prior to calling the + parser. The parser may change the value. */ + int err; /* Print error description for last option. + Either 0, ARGPARSE_PRINT_WARNING or + ARGPARSE_PRINT_ERROR. */ + unsigned int lineno;/* The current line number. */ + int r_opt; /* Returns option code. */ + int r_type; /* Returns type of option value. */ + union { + int ret_int; + long ret_long; + unsigned long ret_ulong; + char *ret_str; + } r; /* Return values */ + + struct _gpgrt_argparse_internal_s *internal; +} gpgrt_argparse_t; + + +typedef struct +{ + int short_opt; + const char *long_opt; + unsigned int flags; + const char *description; /* Optional description. */ +} gpgrt_opt_t; + + +#ifdef GPGRT_ENABLE_ARGPARSE_MACROS + +/* Global flags for (gpgrt_argparse_t).flags. */ +#define ARGPARSE_FLAG_KEEP 1 /* Do not remove options form argv. */ +#define ARGPARSE_FLAG_ALL 2 /* Do not stop at last option but return + remaining args with R_OPT set to -1. */ +#define ARGPARSE_FLAG_MIXED 4 /* Assume options and args are mixed. */ +#define ARGPARSE_FLAG_NOSTOP 8 /* Do not stop processing at "--". */ +#define ARGPARSE_FLAG_ARG0 16 /* Do not skip the first arg. */ +#define ARGPARSE_FLAG_ONEDASH 32 /* Allow long options with one dash. */ +#define ARGPARSE_FLAG_NOVERSION 64 /* No output for "--version". */ +#define ARGPARSE_FLAG_RESET 128 /* Request to reset the internal state. */ +#define ARGPARSE_FLAG_STOP_SEEN 256 /* Set to true if a "--" has been seen. */ +#define ARGPARSE_FLAG_NOLINENO 512 /* Do not zero the lineno field. */ +#define ARGPARSE_FLAG_SYS 1024 /* Use system config file. */ +#define ARGPARSE_FLAG_USER 2048 /* Use user config file. */ +#define ARGPARSE_FLAG_VERBOSE 4096 /* Print additional argparser info. */ +#define ARGPARSE_FLAG_USERVERS 8192 /* Try version-ed user config files. */ +#define ARGPARSE_FLAG_WITHATTR 16384 /* Return attribute bits. */ + +/* Constants for (gpgrt_argparse_t).err. */ +#define ARGPARSE_PRINT_WARNING 1 /* Print a diagnostic. */ +#define ARGPARSE_PRINT_ERROR 2 /* Print a diagnostic and call exit. */ + +/* Special return values of gpgrt_argparse. */ +#define ARGPARSE_IS_ARG (-1) +#define ARGPARSE_INVALID_OPTION (-2) +#define ARGPARSE_MISSING_ARG (-3) +#define ARGPARSE_KEYWORD_TOO_LONG (-4) +#define ARGPARSE_READ_ERROR (-5) +#define ARGPARSE_UNEXPECTED_ARG (-6) +#define ARGPARSE_INVALID_COMMAND (-7) +#define ARGPARSE_AMBIGUOUS_OPTION (-8) +#define ARGPARSE_AMBIGUOUS_COMMAND (-9) +#define ARGPARSE_INVALID_ALIAS (-10) +#define ARGPARSE_OUT_OF_CORE (-11) +#define ARGPARSE_INVALID_ARG (-12) +#define ARGPARSE_PERMISSION_ERROR (-13) +#define ARGPARSE_NO_CONFFILE (-14) +#define ARGPARSE_CONFFILE (-15) +#define ARGPARSE_INVALID_META (-16) +#define ARGPARSE_UNKNOWN_META (-17) +#define ARGPARSE_UNEXPECTED_META (-18) + +/* Flags for the option descriptor (gpgrt_opt_t)->flags. Note that a + * TYPE constant may be or-ed with the OPT constants but when used as + * return value in r_type these OPT constants are normally not + * included. However with ARGPARSE_FLAG_WITHATTR used and an option + * would normally not be returned, it is returned but + * ARGPARSE_OPT_IGNORE is then set; further ARPARSE_ATTR_* are set. + */ +#define ARGPARSE_TYPE_MASK 0x0007 /* Mask for the type bits. */ +#define ARGPARSE_TYPE_NONE 0 /* Does not take an argument. */ +#define ARGPARSE_TYPE_INT 1 /* Takes an int argument. */ +#define ARGPARSE_TYPE_STRING 2 /* Takes a string argument. */ +#define ARGPARSE_TYPE_LONG 3 /* Takes a long argument. */ +#define ARGPARSE_TYPE_ULONG 4 /* Takes an unsigned long argument. */ +#define ARGPARSE_OPT_OPTIONAL (1<<3) /* Argument is optional. */ +#define ARGPARSE_OPT_PREFIX (1<<4) /* Allow 0x etc. prefixed values. */ +#define ARGPARSE_OPT_IGNORE (1<<6) /* Ignore command or option. */ +#define ARGPARSE_OPT_COMMAND (1<<7) /* The argument is a command. */ +#define ARGPARSE_OPT_CONFFILE (1<<8) /* The value is a conffile. */ +#define ARGPARSE_OPT_HEADER (1<<9) /* The value is printed as a header. */ +#define ARGPARSE_OPT_VERBATIM (1<<10)/* The value is printed verbatim. */ +#define ARGPARSE_ATTR_FORCE (1<<14)/* Attribute force is set. */ +#define ARGPARSE_ATTR_IGNORE (1<<15)/* Attribute ignore is set. */ + +/* A set of macros to make option definitions easier to read. */ +#define ARGPARSE_x(s,l,t,f,d) \ + { (s), (l), ARGPARSE_TYPE_ ## t | (f), (d) } + +#define ARGPARSE_s(s,l,t,d) \ + { (s), (l), ARGPARSE_TYPE_ ## t, (d) } +#define ARGPARSE_s_n(s,l,d) \ + { (s), (l), ARGPARSE_TYPE_NONE, (d) } +#define ARGPARSE_s_i(s,l,d) \ + { (s), (l), ARGPARSE_TYPE_INT, (d) } +#define ARGPARSE_s_s(s,l,d) \ + { (s), (l), ARGPARSE_TYPE_STRING, (d) } +#define ARGPARSE_s_l(s,l,d) \ + { (s), (l), ARGPARSE_TYPE_LONG, (d) } +#define ARGPARSE_s_u(s,l,d) \ + { (s), (l), ARGPARSE_TYPE_ULONG, (d) } + +#define ARGPARSE_o(s,l,t,d) \ + { (s), (l), (ARGPARSE_TYPE_ ## t | ARGPARSE_OPT_OPTIONAL), (d) } +#define ARGPARSE_o_n(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_OPTIONAL), (d) } +#define ARGPARSE_o_i(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_INT | ARGPARSE_OPT_OPTIONAL), (d) } +#define ARGPARSE_o_s(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_STRING | ARGPARSE_OPT_OPTIONAL), (d) } +#define ARGPARSE_o_l(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_LONG | ARGPARSE_OPT_OPTIONAL), (d) } +#define ARGPARSE_o_u(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_ULONG | ARGPARSE_OPT_OPTIONAL), (d) } + +#define ARGPARSE_p(s,l,t,d) \ + { (s), (l), (ARGPARSE_TYPE_ ## t | ARGPARSE_OPT_PREFIX), (d) } +#define ARGPARSE_p_n(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_PREFIX), (d) } +#define ARGPARSE_p_i(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_INT | ARGPARSE_OPT_PREFIX), (d) } +#define ARGPARSE_p_s(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_STRING | ARGPARSE_OPT_PREFIX), (d) } +#define ARGPARSE_p_l(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_LONG | ARGPARSE_OPT_PREFIX), (d) } +#define ARGPARSE_p_u(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_ULONG | ARGPARSE_OPT_PREFIX), (d) } + +#define ARGPARSE_op(s,l,t,d) \ + { (s), (l), (ARGPARSE_TYPE_ ## t \ + | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } +#define ARGPARSE_op_n(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_NONE \ + | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } +#define ARGPARSE_op_i(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_INT \ + | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } +#define ARGPARSE_op_s(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_STRING \ + | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } +#define ARGPARSE_op_l(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_LONG \ + | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } +#define ARGPARSE_op_u(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_ULONG \ + | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } + +#define ARGPARSE_c(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_COMMAND), (d) } + +#define ARGPARSE_conffile(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_STRING|ARGPARSE_OPT_CONFFILE), (d) } + +#define ARGPARSE_noconffile(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_NONE|ARGPARSE_OPT_CONFFILE), (d) } + +/* This macro is for stub or obsolete options. */ +#define ARGPARSE_ignore(s,l) \ + { (s), (l), (ARGPARSE_OPT_IGNORE), "@" } + +/* This is a legacy version of ARGPARSE_verbatim which really does + * verbatim printing. */ +#define ARGPARSE_group(s,d) \ + { (s), NULL, 0, (d) } + +/* Verbatim print the string D in the help output. It does not make + * use of the "@" hack as ARGPARSE_group does. */ +#define ARGPARSE_verbatim(d) \ + { 1, NULL, (ARGPARSE_OPT_VERBATIM), (d) } + +/* Same as ARGPARSE_verbatim but also print a colon and a LF. N can + * be used give a symbolic name to the header. Nothing is printed if + * D is the empty string. */ +#define ARGPARSE_header(n,d) \ + { 1, (n), (ARGPARSE_OPT_HEADER), (d) } + +/* Mark the end of the list (mandatory). */ +#define ARGPARSE_end() \ + { 0, NULL, 0, NULL } + +#endif /* GPGRT_ENABLE_ARGPARSE_MACROS */ + +/* Values used for gpgrt_set_confdir. */ +#define GPGRT_CONFDIR_USER 1 /* The user's configuration dir. */ +#define GPGRT_CONFDIR_SYS 2 /* The systems's configuration dir. */ + +/* Take care: gpgrt_argparse keeps state in ARG and requires that + * either ARGPARSE_FLAG_RESET is used after OPTS has been changed or + * gpgrt_argparse (NULL, ARG, NULL) is called first. */ +int gpgrt_argparse (gpgrt_stream_t fp, + gpgrt_argparse_t *arg, gpgrt_opt_t *opts); +int gpgrt_argparser (gpgrt_argparse_t *arg, gpgrt_opt_t *opts, + const char *confname); +void gpgrt_usage (int level); +const char *gpgrt_strusage (int level); +void gpgrt_set_strusage (const char *(*f)(int)); +void gpgrt_set_usage_outfnc (int (*f)(int, const char *)); +void gpgrt_set_fixed_string_mapper (const char *(*f)(const char*)); +void gpgrt_set_confdir (int what, const char *name); + + +/* + * Various helper functions + */ + +/* Compare arbitrary version strings. For the standard m.n.o version + * numbering scheme a LEVEL of 3 is suitable; see the manual. */ +int gpgrt_cmp_version (const char *a, const char *b, int level); + +/* Construct a filename from the NULL terminated list of parts. Tilde + * expansion is done for the first argument. The caller must release + * the result using gpgrt_free; on error ERRNO is set and NULL + * returned. The second function returns an absolute filename. */ +char *gpgrt_fnameconcat (const char *first, ...) GPGRT_ATTR_SENTINEL(0); +char *gpgrt_absfnameconcat (const char *first, ...) GPGRT_ATTR_SENTINEL(0); + + +#ifdef __cplusplus +} +#endif +#endif /* GPGRT_H */ +#endif /* GPG_ERROR_H */ diff --git a/comm/third_party/libgpg-error/src/gpg-error.m4 b/comm/third_party/libgpg-error/src/gpg-error.m4 new file mode 100644 index 0000000000..d910754e8d --- /dev/null +++ b/comm/third_party/libgpg-error/src/gpg-error.m4 @@ -0,0 +1,206 @@ +# gpg-error.m4 - autoconf macro to detect libgpg-error. +# Copyright (C) 2002, 2003, 2004, 2011, 2014, 2018, 2020, 2021 +# g10 Code GmbH +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This file is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# +# Last-changed: 2021-02-16 + + +dnl AM_PATH_GPG_ERROR([MINIMUM-VERSION, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl +dnl Test for libgpg-error and define GPG_ERROR_CFLAGS, GPG_ERROR_LIBS, +dnl GPG_ERROR_MT_CFLAGS, and GPG_ERROR_MT_LIBS. The _MT_ variants are +dnl used for programs requireing real multi thread support. +dnl +dnl If a prefix option is not used, the config script is first +dnl searched in $SYSROOT/bin and then along $PATH. If the used +dnl config script does not match the host specification the script +dnl is added to the gpg_config_script_warn variable. +dnl +AC_DEFUN([AM_PATH_GPG_ERROR], +[ AC_REQUIRE([AC_CANONICAL_HOST]) + gpg_error_config_prefix="" + dnl --with-libgpg-error-prefix=PFX is the preferred name for this option, + dnl since that is consistent with how our three siblings use the directory/ + dnl package name in --with-$dir_name-prefix=PFX. + AC_ARG_WITH(libgpg-error-prefix, + AS_HELP_STRING([--with-libgpg-error-prefix=PFX], + [prefix where GPG Error is installed (optional)]), + [gpg_error_config_prefix="$withval"]) + + dnl Accept --with-gpg-error-prefix and make it work the same as + dnl --with-libgpg-error-prefix above, for backwards compatibility, + dnl but do not document this old, inconsistently-named option. + AC_ARG_WITH(gpg-error-prefix,, + [gpg_error_config_prefix="$withval"]) + + if test x"${GPG_ERROR_CONFIG}" = x ; then + if test x"${gpg_error_config_prefix}" != x ; then + GPG_ERROR_CONFIG="${gpg_error_config_prefix}/bin/gpg-error-config" + else + case "${SYSROOT}" in + /*) + if test -x "${SYSROOT}/bin/gpg-error-config" ; then + GPG_ERROR_CONFIG="${SYSROOT}/bin/gpg-error-config" + fi + ;; + '') + ;; + *) + AC_MSG_WARN([Ignoring \$SYSROOT as it is not an absolute path.]) + ;; + esac + fi + fi + + AC_PATH_PROG(GPG_ERROR_CONFIG, gpg-error-config, no) + min_gpg_error_version=ifelse([$1], ,1.33,$1) + ok=no + + AC_PATH_PROG(GPGRT_CONFIG, gpgrt-config, no) + if test "$GPGRT_CONFIG" != "no"; then + # Determine gpgrt_libdir + # + # Get the prefix of gpgrt-config assuming it's something like: + # <PREFIX>/bin/gpgrt-config + gpgrt_prefix=${GPGRT_CONFIG%/*/*} + possible_libdir1=${gpgrt_prefix}/lib + # Determine by using system libdir-format with CC, it's like: + # Normal style: /usr/lib + # GNU cross style: /usr/<triplet>/lib + # Debian style: /usr/lib/<multiarch-name> + # Fedora/openSUSE style: /usr/lib, /usr/lib32 or /usr/lib64 + # It is assumed that CC is specified to the one of host on cross build. + if libdir_candidates=$(${CC:-cc} -print-search-dirs | \ + sed -n -e "/^libraries/{s/libraries: =//;s/:/\n/gp}"); then + # From the output of -print-search-dirs, select valid pkgconfig dirs. + libdir_candidates=$(for dir in $libdir_candidates; do + if p=$(cd $dir 2>/dev/null && pwd); then + test -d "$p/pkgconfig" && echo $p; + fi + done) + + for possible_libdir0 in $libdir_candidates; do + # possible_libdir0: + # Fallback candidate, the one of system-installed (by $CC) + # (/usr/<triplet>/lib, /usr/lib/<multiarch-name> or /usr/lib32) + # possible_libdir1: + # Another candidate, user-locally-installed + # (<gpgrt_prefix>/lib) + # possible_libdir2 + # Most preferred + # (<gpgrt_prefix>/<triplet>/lib, + # <gpgrt_prefix>/lib/<multiarch-name> or <gpgrt_prefix>/lib32) + if test "${possible_libdir0##*/}" = "lib"; then + possible_prefix0=${possible_libdir0%/lib} + possible_prefix0_triplet=${possible_prefix0##*/} + if test -z "$possible_prefix0_triplet"; then + continue + fi + possible_libdir2=${gpgrt_prefix}/$possible_prefix0_triplet/lib + else + possible_prefix0=${possible_libdir0%%/lib*} + possible_libdir2=${gpgrt_prefix}${possible_libdir0#$possible_prefix0} + fi + if test -f ${possible_libdir2}/pkgconfig/gpg-error.pc; then + gpgrt_libdir=${possible_libdir2} + elif test -f ${possible_libdir1}/pkgconfig/gpg-error.pc; then + gpgrt_libdir=${possible_libdir1} + elif test -f ${possible_libdir0}/pkgconfig/gpg-error.pc; then + gpgrt_libdir=${possible_libdir0} + fi + if test -n "$gpgrt_libdir"; then break; fi + done + else + # When we cannot determine system libdir-format, use this: + gpgrt_libdir=${possible_libdir1} + fi + else + unset GPGRT_CONFIG + fi + + if test -n "$gpgrt_libdir"; then + GPGRT_CONFIG="$GPGRT_CONFIG --libdir=$gpgrt_libdir" + if $GPGRT_CONFIG gpg-error >/dev/null 2>&1; then + GPG_ERROR_CONFIG="$GPGRT_CONFIG gpg-error" + AC_MSG_NOTICE([Use gpgrt-config with $gpgrt_libdir as gpg-error-config]) + gpg_error_config_version=`$GPG_ERROR_CONFIG --modversion` + else + unset GPGRT_CONFIG + fi + elif test "$GPG_ERROR_CONFIG" != "no"; then + gpg_error_config_version=`$GPG_ERROR_CONFIG --version` + fi + if test "$GPG_ERROR_CONFIG" != "no"; then + req_major=`echo $min_gpg_error_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` + req_minor=`echo $min_gpg_error_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` + major=`echo $gpg_error_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` + minor=`echo $gpg_error_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` + if test "$major" -gt "$req_major"; then + ok=yes + else + if test "$major" -eq "$req_major"; then + if test "$minor" -ge "$req_minor"; then + ok=yes + fi + fi + fi + fi + AC_MSG_CHECKING(for GPG Error - version >= $min_gpg_error_version) + if test $ok = yes; then + GPG_ERROR_CFLAGS=`$GPG_ERROR_CONFIG --cflags` + GPG_ERROR_LIBS=`$GPG_ERROR_CONFIG --libs` + if test -z "$GPGRT_CONFIG"; then + GPG_ERROR_MT_CFLAGS=`$GPG_ERROR_CONFIG --mt --cflags 2>/dev/null` + GPG_ERROR_MT_LIBS=`$GPG_ERROR_CONFIG --mt --libs 2>/dev/null` + else + GPG_ERROR_MT_CFLAGS=`$GPG_ERROR_CONFIG --variable=mtcflags 2>/dev/null` + GPG_ERROR_MT_CFLAGS="$GPG_ERROR_CFLAGS${GPG_ERROR_CFLAGS:+ }$GPG_ERROR_MT_CFLAGS" + GPG_ERROR_MT_LIBS=`$GPG_ERROR_CONFIG --variable=mtlibs 2>/dev/null` + GPG_ERROR_MT_LIBS="$GPG_ERROR_LIBS${GPG_ERROR_LIBS:+ }$GPG_ERROR_MT_LIBS" + fi + AC_MSG_RESULT([yes ($gpg_error_config_version)]) + ifelse([$2], , :, [$2]) + if test -z "$GPGRT_CONFIG"; then + gpg_error_config_host=`$GPG_ERROR_CONFIG --host 2>/dev/null || echo none` + else + gpg_error_config_host=`$GPG_ERROR_CONFIG --variable=host 2>/dev/null || echo none` + fi + if test x"$gpg_error_config_host" != xnone ; then + if test x"$gpg_error_config_host" != x"$host" ; then + AC_MSG_WARN([[ +*** +*** The config script "$GPG_ERROR_CONFIG" was +*** built for $gpg_error_config_host and thus may not match the +*** used host $host. +*** You may want to use the configure option --with-libgpg-error-prefix +*** to specify a matching config script or use \$SYSROOT. +***]]) + gpg_config_script_warn="$gpg_config_script_warn libgpg-error" + fi + fi + else + GPG_ERROR_CFLAGS="" + GPG_ERROR_LIBS="" + GPG_ERROR_MT_CFLAGS="" + GPG_ERROR_MT_LIBS="" + AC_MSG_RESULT(no) + ifelse([$3], , :, [$3]) + fi + AC_SUBST(GPG_ERROR_CFLAGS) + AC_SUBST(GPG_ERROR_LIBS) + AC_SUBST(GPG_ERROR_MT_CFLAGS) + AC_SUBST(GPG_ERROR_MT_LIBS) +]) diff --git a/comm/third_party/libgpg-error/src/gpg-error.pc.in b/comm/third_party/libgpg-error/src/gpg-error.pc.in new file mode 100644 index 0000000000..970bb6c31e --- /dev/null +++ b/comm/third_party/libgpg-error/src/gpg-error.pc.in @@ -0,0 +1,15 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +includedir=@includedir@ +libdir=@libdir@ +host=@GPG_ERROR_CONFIG_HOST@ +mtcflags=@GPG_ERROR_CONFIG_MT_CFLAGS@ +mtlibs=@GPG_ERROR_CONFIG_MT_LIBS@ + +Name: gpg-error +Description: GPG Runtime +Version: @PACKAGE_VERSION@ +Cflags: @GPG_ERROR_CONFIG_CFLAGS@ +Libs: @GPG_ERROR_CONFIG_LIBS@ +Libs.private: @GPG_ERROR_CONFIG_LIBS_PRIVATE@ +URL: https://www.gnupg.org/software/libgpg-error/index.html diff --git a/comm/third_party/libgpg-error/src/gpg-error.vers b/comm/third_party/libgpg-error/src/gpg-error.vers new file mode 100644 index 0000000000..aaea22a968 --- /dev/null +++ b/comm/third_party/libgpg-error/src/gpg-error.vers @@ -0,0 +1,213 @@ +# libgpg-error.vers - What symbols to export -*- std -*- +# Copyright (C) 2014 g10 Code GmbH +# +# This file is part of libgpg-error. +# +# libgpg-error is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of the +# License, or (at your option) any later version. +# +# libgpg-error is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <https://www.gnu.org/licenses/>. +# SPDX-License-Identifier: LGPL-2.1+ +# +# NOTE: When adding new functions, please make sure to add them to +# visibility.h and gpg-error.def.in as well. + + +GPG_ERROR_1.0 { + global: + gpg_strerror; + gpg_strerror_r; + gpg_strsource; + gpg_err_code_from_errno; + gpg_err_code_to_errno; + gpg_err_code_from_syserror; + gpg_err_set_errno; + gpg_error_check_version; + + gpgrt_lock_init; + gpgrt_lock_lock; + gpgrt_lock_unlock; + gpgrt_lock_destroy; + gpgrt_yield; + gpgrt_lock_trylock; + + gpgrt_set_syscall_clamp; + gpgrt_get_syscall_clamp; + + gpgrt_fopen; + gpgrt_mopen; + gpgrt_fopenmem; + gpgrt_fopenmem_init; + gpgrt_fdopen; + gpgrt_fdopen_nc; + gpgrt_sysopen; + gpgrt_sysopen_nc; + gpgrt_fpopen; + gpgrt_fpopen_nc; + gpgrt_freopen; + gpgrt_fopencookie; + gpgrt_fclose; + gpgrt_fcancel; + gpgrt_fclose_snatch; + gpgrt_onclose; + gpgrt_fileno; + gpgrt_fileno_unlocked; + gpgrt_syshd; + gpgrt_syshd_unlocked; + _gpgrt_set_std_fd; + _gpgrt_get_std_stream; + gpgrt_flockfile; + gpgrt_ftrylockfile; + gpgrt_funlockfile; + _gpgrt_pending; + _gpgrt_pending_unlocked; + gpgrt_feof; + gpgrt_feof_unlocked; + gpgrt_ferror; + gpgrt_ferror_unlocked; + gpgrt_clearerr; + gpgrt_clearerr_unlocked; + gpgrt_fflush; + gpgrt_fseek; + gpgrt_fseeko; + gpgrt_ftell; + gpgrt_ftello; + gpgrt_rewind; + gpgrt_fgetc; + _gpgrt_getc_underflow; + gpgrt_fputc; + _gpgrt_putc_overflow; + gpgrt_ungetc; + gpgrt_read; + gpgrt_write; + gpgrt_write_sanitized; + gpgrt_write_hexstring; + gpgrt_fread; + gpgrt_fwrite; + gpgrt_fgets; + gpgrt_fputs; + gpgrt_fputs_unlocked; + gpgrt_getline; + gpgrt_read_line; + gpgrt_free; + gpgrt_fprintf; + gpgrt_fprintf_unlocked; + gpgrt_printf; + gpgrt_printf_unlocked; + gpgrt_vfprintf; + gpgrt_vfprintf_unlocked; + gpgrt_setvbuf; + gpgrt_setbuf; + gpgrt_set_binary; + gpgrt_set_nonblock; + gpgrt_get_nonblock; + gpgrt_poll; + gpgrt_tmpfile; + gpgrt_opaque_set; + gpgrt_opaque_get; + gpgrt_fname_set; + gpgrt_fname_get; + + gpgrt_asprintf; + gpgrt_vasprintf; + gpgrt_bsprintf; + gpgrt_vbsprintf; + gpgrt_snprintf; + gpgrt_vsnprintf; + + gpgrt_check_version; + gpg_err_init; + gpg_err_deinit; + gpgrt_set_alloc_func; + + gpgrt_b64dec_start; + gpgrt_b64dec_proc; + gpgrt_b64dec_finish; + + gpgrt_get_errorcount; + gpgrt_inc_errorcount; + gpgrt_log_set_sink; + gpgrt_log_set_socket_dir_cb; + gpgrt_log_set_pid_suffix_cb; + gpgrt_log_set_prefix; + gpgrt_log_get_prefix; + gpgrt_log_test_fd; + gpgrt_log_get_fd; + gpgrt_log_get_stream; + gpgrt_log; + gpgrt_logv; + gpgrt_logv_prefix; + gpgrt_log_string; + gpgrt_log_bug; + gpgrt_log_fatal; + gpgrt_log_error; + gpgrt_log_info; + gpgrt_log_debug; + gpgrt_log_debug_string; + gpgrt_log_printf; + gpgrt_log_printhex; + gpgrt_log_clock; + gpgrt_log_flush; + _gpgrt_log_assert; + + gpgrt_realloc; + gpgrt_reallocarray; + gpgrt_malloc; + gpgrt_calloc; + gpgrt_strdup; + gpgrt_strconcat; + + gpgrt_getenv; + gpgrt_setenv; + gpgrt_mkdir; + gpgrt_chdir; + gpgrt_getcwd; + +## API not yet finished for: +# gpgrt_make_pipe; +# gpgrt_spawn_process; +# gpgrt_spawn_process_fd; +# gpgrt_spawn_process_detached; +# gpgrt_wait_process; +# gpgrt_wait_processes; +# gpgrt_kill_process; +# gpgrt_release_process; + + gpgrt_argparse; + gpgrt_argparser; + gpgrt_usage; + gpgrt_strusage; + gpgrt_set_strusage; + gpgrt_set_usage_outfnc; + gpgrt_set_fixed_string_mapper; + gpgrt_set_confdir; + + gpgrt_b64enc_start; + gpgrt_b64enc_write; + gpgrt_b64enc_finish; + + gpgrt_cmp_version; + + gpgrt_ftruncate; + gpgrt_fprintf_sf; + gpgrt_fprintf_sf_unlocked; + + gpgrt_add_emergency_cleanup; + gpgrt_abort; + + gpgrt_fnameconcat; + gpgrt_absfnameconcat; + + gpgrt_access; + + local: + *; +}; diff --git a/comm/third_party/libgpg-error/src/gpg-error.w32-manifest.in b/comm/third_party/libgpg-error/src/gpg-error.w32-manifest.in new file mode 100644 index 0000000000..07f6891b45 --- /dev/null +++ b/comm/third_party/libgpg-error/src/gpg-error.w32-manifest.in @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> +<description>Error codes and shared functions for GnuPG and others</description> +<assemblyIdentity + type="win32" + name="GnuPG.libgpg-error" + version="@BUILD_VERSION@" + /> +<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> + <application> + <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/><!-- Vista --> + <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/><!-- 7 --> + <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/><!-- 8 --> + <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/><!-- 8.1 --> + </application> +</compatibility> +</assembly> diff --git a/comm/third_party/libgpg-error/src/gpgrt-config b/comm/third_party/libgpg-error/src/gpgrt-config new file mode 100755 index 0000000000..226465ef82 --- /dev/null +++ b/comm/third_party/libgpg-error/src/gpgrt-config @@ -0,0 +1,646 @@ +#!/bin/sh +# Copyright (C) 2018, 2021 g10 Code GmbH +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This file is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# SPDX-License-Identifier: FSFULLR + +#### start of functions for this script + +# +# Bourne shell functions for config file in pkg-config style, so that +# we can share such a config file between pkg-config and script +# + +# +# get_var: Get the variable value of NAME +# +# Variables are recorded in the shell variables named "VAR_<NAME>" +# +get_var () { + ___name=$1 + + eval echo \$VAR_$___name +} + +# +# get_attr: Get the attribute value of KEY +# +# Attributes are recorded in the shell variables named "ATTR_<KEY>" +# +get_attr () { + ___name=$1 + + eval echo \$ATTR_$___name +} + +# variant of get_attr for list (separated by ',') +get_attr_l () { + (IFS=', '; for x in "$(get_attr $1)"; do echo $x; done) +} + +# Remove ${varname} part in the beginning of a string. +remove_var_expr () { + ___varname=$1 + shift + + expr "$*" : "\${$___varname}\\(.*\\)" +} + +# Given a string, substitute variables. +substitute_vars () { + __string="$1" + __varname="" + __result="" + + while [ -n "$__string" ]; do + case "$__string" in + \$\$*) + __result="$__result\$" + __string="${__string#\$\$}" + ;; + \${*}*) + __varname="${__string#\$\{}" + __varname="${__varname%%\}*}" + __result="$__result$(get_var $__varname)" + __string=$(remove_var_expr $__varname $__string) + ;; + *) + __result="$__result$(printf %c "$__string")" + __string="${__string#$(printf %c "$__string")}" + ;; + esac + done + + echo "$__result" +} + +# +# Read a config from stdin +# +# Variables: +# For VAR=VALUE, value is stored in the shell variable VAR_*. +# +# Attributes: +# For KEY: VALUE, value is stored in the shell variable ATTR_*. +# +read_config_from_stdin () { + _filename=$1 + _line="" + _varname="" + _value="" + _key="" + _reading_attrs="" + + while read _line; do + if [ -z "$_line" ]; then + _reading_attrs=yes + continue + elif [ -z "$_reading_attrs" ]; then + case "$_line" in + *=*) + _varname="${_line%%=*}" + _value="${_line#*=}" + VAR_list="$VAR_list${VAR_list:+ }VAR_$_varname" + read VAR_$_varname <<EOF1 +$(substitute_vars "$_value") +EOF1 + continue + ;; + *) _reading_attrs=yes ;; + esac + fi + if [ -n "$_reading_attrs" ]; then + case "$_line" in + *:\ *) + _key="${_line%%:\ *}" + _value="${_line#*:\ }" + if expr "$_key" : ".*\..*" >/dev/null; then + _key="${_key%.*}_${_key#*.}" + fi + ATTR_list="$ATTR_list${ATTR_list:+ }ATTR_$_key" + read ATTR_$_key <<EOF2 +$(substitute_vars "$_value") +EOF2 + ;; + *:|*:\ ) ;; + *) + echo "Error reading $_filename: $_line" 1>&2 + exit 1 + ;; + esac + fi + done +} + + +find_file_in_path () { + _f=$1 + _p=$2 + _saved_IFS="$IFS" + _arg="" + IFS=":" # On Windows it should be ";"??? + + for _arg in $_p; do + if [ -r $_arg/$_f ]; then + RESULT="$_arg/$_f" + IFS="$_saved_IFS" + return 0 + fi + done + IFS="$_saved_IFS" + RESULT="" + return 1 +} + +read_config_file () { + if ! find_file_in_path $1.pc $2; then + if [ -z "$want_exists" ]; then + echo "Can't find $1.pc" 1>&2 + fi + exit 1 + fi + read_config_from_stdin $RESULT < $RESULT +} + +cleanup_vars_attrs () { + eval unset $VAR_list VAR_list + eval unset $ATTR_list ATTR_list +} + +not_listed_yet () { + ___m=$1 + ___arg="" + shift + + for ___arg; do + if [ $___m = $___arg ]; then + return 1 + fi + done + + return 0 +} + +list_only_once () { + __result="" + __arg="" + + for __arg; do + if not_listed_yet $__arg $__result; then + __result="$__result${__result:+ }$__arg" + fi + done + + echo $__result +} + +list_only_once_for_libs () { + __result="" + __rev_list="" + __arg="" + + # Scan the list and eliminate duplicates for non-"-lxxx" + # the resulted list is in reverse order + for __arg; do + case "$__arg" in + -l*) + # As-is + __rev_list="$__arg${__rev_list:+ }$__rev_list" + ;; + *) + if not_listed_yet $__arg $__rev_list; then + __rev_list="$__arg${__rev_list:+ }$__rev_list" + fi + ;; + esac + done + + # Scan again + for __arg in $__rev_list; do + case "$__arg" in + -l*) + if not_listed_yet $__arg $__result; then + __result="$__arg${__result:+ }$__result" + fi + ;; + *) + # As-is + __result="$__arg${__result:+ }$__result" + ;; + esac + done + + echo $__result +} + +arg1_is_same () { + [ "$1" = "=" -o "$1" = ">=" -o "$1" = "<=" ] +} + +arg1_is_less () { + [ "$1" = "!=" -o "$1" = "<" -o "$1" = "<=" ] +} + +arg1_is_great () { + [ "$1" = "!=" -o "$1" = ">" -o "$1" = ">=" ] +} + +# +# Evaluate comparison between versions in RPM way +# +eval_compare_version () { + ___str1="$1" + ___cmp="$2" + ___str2="$3" + ___char1="" + ___char2="" + ___chunk1="" + ___chunk2="" + + while [ -n "$___str1" -a -n "$___str2" ]; do + # Trim anything that's not alnum or tilde from the front + ___str1="$(expr "$___str1" : '[^0-9A-Za-z~]*\(.*\)')" + ___str2="$(expr "$___str2" : '[^0-9A-Za-z~]*\(.*\)')" + + # Get the first character + ___char1=${___str1%${___str1#?}} + ___char2=${___str2%${___str2#?}} + + if [ "$___char1" = ~ -o "$___char2" = ~ ]; then + if [ "$___char1" != ~ ]; then + arg1_is_great $___cmp + return + fi + if [ "$___char2" != ~ ]; then + arg1_is_less $___cmp + return + fi + ___str1=${___str1#~} + ___str2=${___str2#~} + continue + fi + + if [ -z "$___char1" -o -z "$___char2" ]; then + break + fi + + case "$___char1$___char2" in + [0-9][A-Za-z]) + arg1_is_great $___cmp + return + ;; + [A-Za-z][0-9]) + arg1_is_less $___cmp + return + ;; + [0-9][0-9]) + ___chunk1="$(expr "$___str1" : '\([0-9]*\)')" + ___chunk2="$(expr "$___str2" : '\([0-9]*\)')" + ;; + [A-Za-z][A-Za-z]) + ___chunk1="$(expr "$___str1" : '\([A-Za-z]*\)')" + ___chunk2="$(expr "$___str2" : '\([A-Za-z]*\)')" + ;; + esac + + # Compare chunks numerically if digits, or lexicographically + if expr "$___chunk1" "!=" "$___chunk2" >/dev/null; then + if expr "$___chunk1" ">" "$___chunk2" >/dev/null; then + arg1_is_great $___cmp + return + else + arg1_is_less $___cmp + return + fi + fi + + # Remove the chunk + ___str1="${___str1#$___chunk1}" + ___str2="${___str2#$___chunk2}" + done + + # Either STR1, STR2 or both is empty here + if [ -n "$___str1" ]; then + case "$___str1" in + ~*) arg1_is_less $___cmp ;; + *) arg1_is_great $___cmp ;; + esac + elif [ -n "$___str2" ]; then + case "$___str2" in + ~*) arg1_is_great $___cmp ;; + *) arg1_is_less $___cmp ;; + esac + else + arg1_is_same $___cmp + fi +} + +# +# Recursively solve package dependencies +# +# Result is in the PKG_LIST variable +# +all_required_config_files () { + all_list="" + new_list="" + p="" + pkg="" + cmp="" + + list=$* + while [ -n "$list" ]; do + for p in $list; do + if [ -z "$pkg" ]; then + pkg=$p + elif [ -z "$cmp" ]; then + case "$p" in + "="|"!="|"<"|">"|"<="|">=") cmp=$p ;; + *) + read_config_file $pkg $PKG_CONFIG_PATH + all_list="$all_list${all_list:+ }$pkg" + new_list="$new_list${new_list:+ }$(get_attr_l Requires)" + if [ -n "$enable_static" ]; then + new_list="$new_list${new_list:+ }$(get_attr_l Requires_private)" + fi + cleanup_vars_attrs + pkg=$p + ;; + esac + else + read_config_file $pkg $PKG_CONFIG_PATH + if ! eval_compare_version "$(get_attr Version)" $cmp $p; then + echo "Version mismatch for $pkg $cmp $p: $(get_attr Version)" 1>&2 + exit 1 + fi + all_list="$all_list${all_list:+ }$pkg" + new_list="$new_list${new_list:+ }$(get_attr_l Requires)" + if [ -n "$enable_static" ]; then + new_list="$new_list${new_list:+ }$(get_attr_l Requires_private)" + fi + cleanup_vars_attrs + pkg="" + cmp="" + fi + done + if [ -n "$cmp" ]; then + echo "No version after comparison operator ($cmp): $pkg" 1>&2 + exit 1 + elif [ -n "$pkg" ]; then + read_config_file $pkg $PKG_CONFIG_PATH + all_list="$all_list${all_list:+ }$pkg" + new_list="$new_list${new_list:+ }$(get_attr_l Requires)" + if [ -n "$enable_static" ]; then + new_list="$new_list${new_list:+ }$(get_attr_l Requires_private)" + fi + cleanup_vars_attrs + fi + + list="$new_list" + new_list="" + done + + PKG_LIST=$(list_only_once $all_list) +} + +# +# Modify -I or -L by PKG_CONFIG_SYSROOT_DIR variable +# +sysroot () { + _opt="$1" + _result="" + shift + + while [ $# -gt 0 ]; do + if [ $1 = $_opt ]; then + _result="$_result${_result:+ }$_opt" + shift + _result="$_result $PKG_CONFIG_SYSROOT_DIR$1" + elif expr "x$1" : "^x$_opt" >/dev/null; then + _result="$_result${_result:+ }$_opt$PKG_CONFIG_SYSROOT_DIR$(expr "x$1" : "^x$_opt\(.*\)")" + else + _result="$_result${_result:+ }$1" + fi + shift + done + echo "$_result" +} + +# Show usage +usage () { + cat <<EOF +Usage: gpgrt-config [--libdir=LIBDIR] [OPTIONS] MODULES +Options: + [--exists] + [--modversion] + [--libs] + [--cflags] + [--static] + [--variable=VARNAME] +EOF + exit $1 +} +#### end of functions for this script + +myname=${0##*/} +if [ $myname = gpgrt-config ]; then + default_module="gpg-error" +else + default_module=${myname%-config} +fi + +# First stage to process --libdir option + +libdir="" +while test $# -gt 0; do + case $1 in + --libdir=*) + libdir=${1#--libdir=} + shift + ;; + *) + break + ;; + esac +done + +if [ x"${PKG_CONFIG_LIBDIR:+set}" = xset -a -z "$PKG_CONFIG_LIBDIR" ]; then + # The variable set as empty, we use PKG_CONFIG_PATH in this case, + # ignoring --libdir option + if [ -z "$PKG_CONFIG_PATH" ]; then + echo "Please have valid PKG_CONFIG_PATH if PKG_CONFIG_LIBDIR is empty" 1>&2 + exit 1 + fi +else + if [ -n "$libdir" ]; then + # --libdir option is available, it overrides existing PKG_CONFIG_LIBDIR + PKG_CONFIG_LIBDIR=$libdir/pkgconfig + fi + if [ -z "$PKG_CONFIG_LIBDIR" ]; then + if [ -z "$PKG_CONFIG_PATH" ]; then + echo "Please use --libdir=LIBDIR option or set PKG_CONFIG_LIBDIR" 1>&2 + echo "Or set PKG_CONFIG_PATH" 1>&2 + exit 1 + fi + else + # PKG_CONFIG_LIBDIR is available here + # Modify PKG_CONFIG_PATH, prepending PKG_CONFIG_LIBDIR + PKG_CONFIG_PATH="$PKG_CONFIG_LIBDIR${PKG_CONFIG_PATH:+:}$PKG_CONFIG_PATH" + fi +fi +# PKG_CONFIG_PATH is ready here + +# + +if test $# -eq 0; then + usage 1 1>&2 +fi + + +# Second stage to do the main functionality + +module_list="" +want_var="" +want_attr="" +want_cflags="" +want_libs="" +want_exists="" +enable_static="" + +cflags="" +libs="" +mtcflags="" +mtlibs="" + +output="" + +mt="no" + +VAR_list=VAR_pc_sysrootdir +if [ -z "$PKG_CONFIG_SYSROOT_DIR" ]; then + VAR_pc_sysrootdir="/" +else + VAR_pc_sysrootdir="$PKG_CONFIG_SYSROOT_DIR" +fi + +while test $# -gt 0; do + case $1 in + #### pkg-config incompatible options: begin + --prefix) + # In future, use --variable=prefix instead. + want_var=prefix + ;; + --exec-prefix) + # In future, use --variable=exec_prefix instead. + want_var=exec_prefix + ;; + --version) + # In future, use --modversion instead. + want_attr=Version + ;; + --api-version) + # In future, use --variable=api_version instead. + want_var=api_version + ;; + --host) + # In future, use --variable=host instead. + want_var=host + ;; + --mt) + # In future, use --variable=mtcflags or --variable=mtlibs. + mt=yes + ;; + #### pkg-config incompatible options: end + --modversion) + want_attr=Version + ;; + --exists) + want_exists=yes + ;; + --cflags) + want_cflags=yes + ;; + --libs) + want_libs=yes + ;; + --static) + enable_static=yes + ;; + --variable=*) + want_var=${1#*=} + ;; + --help) + usage 0 + ;; + --*) + usage 1 1>&2 + ;; + *) + # Modules + module_list="$module_list${module_list:+ }$1" + ;; + esac + + shift +done + + +if [ -z "$module_list" ]; then + module_list=$default_module +elif expr "$module_list" : "=\|!=\|<\|>\|<=\|>=" >/dev/null; then + module_list="$default_module $module_list" +fi + +all_required_config_files $module_list + +for p in $PKG_LIST; do + read_config_file $p $PKG_CONFIG_PATH + # For want_var or want_attr, get it from the first package + if [ -n "$want_var" ]; then + output="$(get_var $want_var)" + break + elif [ -n "$want_attr" ]; then + output="$(get_attr $want_attr)" + break + else + cflags="$cflags${cflags:+ }$(get_attr Cflags)" + libs="$libs${libs:+ }$(get_attr Libs)" + if [ -n "$enable_static" ]; then + libs="$libs${libs:+ }$(get_attr Libs_private)" + fi + + if [ $p = "gpg-error" ]; then + mtcflags="$(get_var mtcflags)" + mtlibs="$(get_var mtlibs)" + fi + fi + cleanup_vars_attrs +done + +if [ -z "$want_var" -a -z "$want_attr" ]; then + if [ -n "$want_cflags" ]; then + output="$output${output:+ }$(sysroot -I $(list_only_once $cflags))" + # Backward compatibility to old gpg-error-config + if [ $mt = yes -a -n "$mtcflags" ]; then + output="$output${output:+ }$mtcflags" + fi + fi + if [ -n "$want_libs" ]; then + output="$output${output:+ }$(sysroot -L $(list_only_once_for_libs $libs))" + # Backward compatibility to old gpg-error-config + if [ $mt = yes -a -n "$mtlibs" ]; then + output="$output${output:+ }$mtlibs" + fi + fi +fi + +if [ -z "$want_exists" ]; then + echo "$output" +fi + +exit 0 diff --git a/comm/third_party/libgpg-error/src/gpgrt-config.in b/comm/third_party/libgpg-error/src/gpgrt-config.in new file mode 100644 index 0000000000..0fe14e8bf2 --- /dev/null +++ b/comm/third_party/libgpg-error/src/gpgrt-config.in @@ -0,0 +1,646 @@ +#!@INSTALLSHELLPATH@ +# Copyright (C) 2018, 2021 g10 Code GmbH +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This file is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# SPDX-License-Identifier: FSFULLR + +#### start of functions for this script + +# +# Bourne shell functions for config file in pkg-config style, so that +# we can share such a config file between pkg-config and script +# + +# +# get_var: Get the variable value of NAME +# +# Variables are recorded in the shell variables named "VAR_<NAME>" +# +get_var () { + ___name=$1 + + eval echo \$VAR_$___name +} + +# +# get_attr: Get the attribute value of KEY +# +# Attributes are recorded in the shell variables named "ATTR_<KEY>" +# +get_attr () { + ___name=$1 + + eval echo \$ATTR_$___name +} + +# variant of get_attr for list (separated by ',') +get_attr_l () { + (IFS=', '; for x in "$(get_attr $1)"; do echo $x; done) +} + +# Remove ${varname} part in the beginning of a string. +remove_var_expr () { + ___varname=$1 + shift + + expr "$*" : "\${$___varname}\\(.*\\)" +} + +# Given a string, substitute variables. +substitute_vars () { + __string="$1" + __varname="" + __result="" + + while [ -n "$__string" ]; do + case "$__string" in + \$\$*) + __result="$__result\$" + __string="${__string#\$\$}" + ;; + \${*}*) + __varname="${__string#\$\{}" + __varname="${__varname%%\}*}" + __result="$__result$(get_var $__varname)" + __string=$(remove_var_expr $__varname $__string) + ;; + *) + __result="$__result$(printf %c "$__string")" + __string="${__string#$(printf %c "$__string")}" + ;; + esac + done + + echo "$__result" +} + +# +# Read a config from stdin +# +# Variables: +# For VAR=VALUE, value is stored in the shell variable VAR_*. +# +# Attributes: +# For KEY: VALUE, value is stored in the shell variable ATTR_*. +# +read_config_from_stdin () { + _filename=$1 + _line="" + _varname="" + _value="" + _key="" + _reading_attrs="" + + while read _line; do + if [ -z "$_line" ]; then + _reading_attrs=yes + continue + elif [ -z "$_reading_attrs" ]; then + case "$_line" in + *=*) + _varname="${_line%%=*}" + _value="${_line#*=}" + VAR_list="$VAR_list${VAR_list:+ }VAR_$_varname" + read VAR_$_varname <<EOF1 +$(substitute_vars "$_value") +EOF1 + continue + ;; + *) _reading_attrs=yes ;; + esac + fi + if [ -n "$_reading_attrs" ]; then + case "$_line" in + *:\ *) + _key="${_line%%:\ *}" + _value="${_line#*:\ }" + if expr "$_key" : ".*\..*" >/dev/null; then + _key="${_key%.*}_${_key#*.}" + fi + ATTR_list="$ATTR_list${ATTR_list:+ }ATTR_$_key" + read ATTR_$_key <<EOF2 +$(substitute_vars "$_value") +EOF2 + ;; + *:|*:\ ) ;; + *) + echo "Error reading $_filename: $_line" 1>&2 + exit 1 + ;; + esac + fi + done +} + + +find_file_in_path () { + _f=$1 + _p=$2 + _saved_IFS="$IFS" + _arg="" + IFS=":" # On Windows it should be ";"??? + + for _arg in $_p; do + if [ -r $_arg/$_f ]; then + RESULT="$_arg/$_f" + IFS="$_saved_IFS" + return 0 + fi + done + IFS="$_saved_IFS" + RESULT="" + return 1 +} + +read_config_file () { + if ! find_file_in_path $1.pc $2; then + if [ -z "$want_exists" ]; then + echo "Can't find $1.pc" 1>&2 + fi + exit 1 + fi + read_config_from_stdin $RESULT < $RESULT +} + +cleanup_vars_attrs () { + eval unset $VAR_list VAR_list + eval unset $ATTR_list ATTR_list +} + +not_listed_yet () { + ___m=$1 + ___arg="" + shift + + for ___arg; do + if [ $___m = $___arg ]; then + return 1 + fi + done + + return 0 +} + +list_only_once () { + __result="" + __arg="" + + for __arg; do + if not_listed_yet $__arg $__result; then + __result="$__result${__result:+ }$__arg" + fi + done + + echo $__result +} + +list_only_once_for_libs () { + __result="" + __rev_list="" + __arg="" + + # Scan the list and eliminate duplicates for non-"-lxxx" + # the resulted list is in reverse order + for __arg; do + case "$__arg" in + -l*) + # As-is + __rev_list="$__arg${__rev_list:+ }$__rev_list" + ;; + *) + if not_listed_yet $__arg $__rev_list; then + __rev_list="$__arg${__rev_list:+ }$__rev_list" + fi + ;; + esac + done + + # Scan again + for __arg in $__rev_list; do + case "$__arg" in + -l*) + if not_listed_yet $__arg $__result; then + __result="$__arg${__result:+ }$__result" + fi + ;; + *) + # As-is + __result="$__arg${__result:+ }$__result" + ;; + esac + done + + echo $__result +} + +arg1_is_same () { + [ "$1" = "=" -o "$1" = ">=" -o "$1" = "<=" ] +} + +arg1_is_less () { + [ "$1" = "!=" -o "$1" = "<" -o "$1" = "<=" ] +} + +arg1_is_great () { + [ "$1" = "!=" -o "$1" = ">" -o "$1" = ">=" ] +} + +# +# Evaluate comparison between versions in RPM way +# +eval_compare_version () { + ___str1="$1" + ___cmp="$2" + ___str2="$3" + ___char1="" + ___char2="" + ___chunk1="" + ___chunk2="" + + while [ -n "$___str1" -a -n "$___str2" ]; do + # Trim anything that's not alnum or tilde from the front + ___str1="$(expr "$___str1" : '[^0-9A-Za-z~]*\(.*\)')" + ___str2="$(expr "$___str2" : '[^0-9A-Za-z~]*\(.*\)')" + + # Get the first character + ___char1=${___str1%${___str1#?}} + ___char2=${___str2%${___str2#?}} + + if [ "$___char1" = ~ -o "$___char2" = ~ ]; then + if [ "$___char1" != ~ ]; then + arg1_is_great $___cmp + return + fi + if [ "$___char2" != ~ ]; then + arg1_is_less $___cmp + return + fi + ___str1=${___str1#~} + ___str2=${___str2#~} + continue + fi + + if [ -z "$___char1" -o -z "$___char2" ]; then + break + fi + + case "$___char1$___char2" in + [0-9][A-Za-z]) + arg1_is_great $___cmp + return + ;; + [A-Za-z][0-9]) + arg1_is_less $___cmp + return + ;; + [0-9][0-9]) + ___chunk1="$(expr "$___str1" : '\([0-9]*\)')" + ___chunk2="$(expr "$___str2" : '\([0-9]*\)')" + ;; + [A-Za-z][A-Za-z]) + ___chunk1="$(expr "$___str1" : '\([A-Za-z]*\)')" + ___chunk2="$(expr "$___str2" : '\([A-Za-z]*\)')" + ;; + esac + + # Compare chunks numerically if digits, or lexicographically + if expr "$___chunk1" "!=" "$___chunk2" >/dev/null; then + if expr "$___chunk1" ">" "$___chunk2" >/dev/null; then + arg1_is_great $___cmp + return + else + arg1_is_less $___cmp + return + fi + fi + + # Remove the chunk + ___str1="${___str1#$___chunk1}" + ___str2="${___str2#$___chunk2}" + done + + # Either STR1, STR2 or both is empty here + if [ -n "$___str1" ]; then + case "$___str1" in + ~*) arg1_is_less $___cmp ;; + *) arg1_is_great $___cmp ;; + esac + elif [ -n "$___str2" ]; then + case "$___str2" in + ~*) arg1_is_great $___cmp ;; + *) arg1_is_less $___cmp ;; + esac + else + arg1_is_same $___cmp + fi +} + +# +# Recursively solve package dependencies +# +# Result is in the PKG_LIST variable +# +all_required_config_files () { + all_list="" + new_list="" + p="" + pkg="" + cmp="" + + list=$* + while [ -n "$list" ]; do + for p in $list; do + if [ -z "$pkg" ]; then + pkg=$p + elif [ -z "$cmp" ]; then + case "$p" in + "="|"!="|"<"|">"|"<="|">=") cmp=$p ;; + *) + read_config_file $pkg $PKG_CONFIG_PATH + all_list="$all_list${all_list:+ }$pkg" + new_list="$new_list${new_list:+ }$(get_attr_l Requires)" + if [ -n "$enable_static" ]; then + new_list="$new_list${new_list:+ }$(get_attr_l Requires_private)" + fi + cleanup_vars_attrs + pkg=$p + ;; + esac + else + read_config_file $pkg $PKG_CONFIG_PATH + if ! eval_compare_version "$(get_attr Version)" $cmp $p; then + echo "Version mismatch for $pkg $cmp $p: $(get_attr Version)" 1>&2 + exit 1 + fi + all_list="$all_list${all_list:+ }$pkg" + new_list="$new_list${new_list:+ }$(get_attr_l Requires)" + if [ -n "$enable_static" ]; then + new_list="$new_list${new_list:+ }$(get_attr_l Requires_private)" + fi + cleanup_vars_attrs + pkg="" + cmp="" + fi + done + if [ -n "$cmp" ]; then + echo "No version after comparison operator ($cmp): $pkg" 1>&2 + exit 1 + elif [ -n "$pkg" ]; then + read_config_file $pkg $PKG_CONFIG_PATH + all_list="$all_list${all_list:+ }$pkg" + new_list="$new_list${new_list:+ }$(get_attr_l Requires)" + if [ -n "$enable_static" ]; then + new_list="$new_list${new_list:+ }$(get_attr_l Requires_private)" + fi + cleanup_vars_attrs + fi + + list="$new_list" + new_list="" + done + + PKG_LIST=$(list_only_once $all_list) +} + +# +# Modify -I or -L by PKG_CONFIG_SYSROOT_DIR variable +# +sysroot () { + _opt="$1" + _result="" + shift + + while [ $# -gt 0 ]; do + if [ $1 = $_opt ]; then + _result="$_result${_result:+ }$_opt" + shift + _result="$_result $PKG_CONFIG_SYSROOT_DIR$1" + elif expr "x$1" : "^x$_opt" >/dev/null; then + _result="$_result${_result:+ }$_opt$PKG_CONFIG_SYSROOT_DIR$(expr "x$1" : "^x$_opt\(.*\)")" + else + _result="$_result${_result:+ }$1" + fi + shift + done + echo "$_result" +} + +# Show usage +usage () { + cat <<EOF +Usage: gpgrt-config [--libdir=LIBDIR] [OPTIONS] MODULES +Options: + [--exists] + [--modversion] + [--libs] + [--cflags] + [--static] + [--variable=VARNAME] +EOF + exit $1 +} +#### end of functions for this script + +myname=${0##*/} +if [ $myname = gpgrt-config ]; then + default_module="gpg-error" +else + default_module=${myname%-config} +fi + +# First stage to process --libdir option + +libdir="" +while test $# -gt 0; do + case $1 in + --libdir=*) + libdir=${1#--libdir=} + shift + ;; + *) + break + ;; + esac +done + +if [ x"${PKG_CONFIG_LIBDIR:+set}" = xset -a -z "$PKG_CONFIG_LIBDIR" ]; then + # The variable set as empty, we use PKG_CONFIG_PATH in this case, + # ignoring --libdir option + if [ -z "$PKG_CONFIG_PATH" ]; then + echo "Please have valid PKG_CONFIG_PATH if PKG_CONFIG_LIBDIR is empty" 1>&2 + exit 1 + fi +else + if [ -n "$libdir" ]; then + # --libdir option is available, it overrides existing PKG_CONFIG_LIBDIR + PKG_CONFIG_LIBDIR=$libdir/pkgconfig + fi + if [ -z "$PKG_CONFIG_LIBDIR" ]; then + if [ -z "$PKG_CONFIG_PATH" ]; then + echo "Please use --libdir=LIBDIR option or set PKG_CONFIG_LIBDIR" 1>&2 + echo "Or set PKG_CONFIG_PATH" 1>&2 + exit 1 + fi + else + # PKG_CONFIG_LIBDIR is available here + # Modify PKG_CONFIG_PATH, prepending PKG_CONFIG_LIBDIR + PKG_CONFIG_PATH="$PKG_CONFIG_LIBDIR${PKG_CONFIG_PATH:+:}$PKG_CONFIG_PATH" + fi +fi +# PKG_CONFIG_PATH is ready here + +# + +if test $# -eq 0; then + usage 1 1>&2 +fi + + +# Second stage to do the main functionality + +module_list="" +want_var="" +want_attr="" +want_cflags="" +want_libs="" +want_exists="" +enable_static="" + +cflags="" +libs="" +mtcflags="" +mtlibs="" + +output="" + +mt="no" + +VAR_list=VAR_pc_sysrootdir +if [ -z "$PKG_CONFIG_SYSROOT_DIR" ]; then + VAR_pc_sysrootdir="/" +else + VAR_pc_sysrootdir="$PKG_CONFIG_SYSROOT_DIR" +fi + +while test $# -gt 0; do + case $1 in + #### pkg-config incompatible options: begin + --prefix) + # In future, use --variable=prefix instead. + want_var=prefix + ;; + --exec-prefix) + # In future, use --variable=exec_prefix instead. + want_var=exec_prefix + ;; + --version) + # In future, use --modversion instead. + want_attr=Version + ;; + --api-version) + # In future, use --variable=api_version instead. + want_var=api_version + ;; + --host) + # In future, use --variable=host instead. + want_var=host + ;; + --mt) + # In future, use --variable=mtcflags or --variable=mtlibs. + mt=yes + ;; + #### pkg-config incompatible options: end + --modversion) + want_attr=Version + ;; + --exists) + want_exists=yes + ;; + --cflags) + want_cflags=yes + ;; + --libs) + want_libs=yes + ;; + --static) + enable_static=yes + ;; + --variable=*) + want_var=${1#*=} + ;; + --help) + usage 0 + ;; + --*) + usage 1 1>&2 + ;; + *) + # Modules + module_list="$module_list${module_list:+ }$1" + ;; + esac + + shift +done + + +if [ -z "$module_list" ]; then + module_list=$default_module +elif expr "$module_list" : "=\|!=\|<\|>\|<=\|>=" >/dev/null; then + module_list="$default_module $module_list" +fi + +all_required_config_files $module_list + +for p in $PKG_LIST; do + read_config_file $p $PKG_CONFIG_PATH + # For want_var or want_attr, get it from the first package + if [ -n "$want_var" ]; then + output="$(get_var $want_var)" + break + elif [ -n "$want_attr" ]; then + output="$(get_attr $want_attr)" + break + else + cflags="$cflags${cflags:+ }$(get_attr Cflags)" + libs="$libs${libs:+ }$(get_attr Libs)" + if [ -n "$enable_static" ]; then + libs="$libs${libs:+ }$(get_attr Libs_private)" + fi + + if [ $p = "gpg-error" ]; then + mtcflags="$(get_var mtcflags)" + mtlibs="$(get_var mtlibs)" + fi + fi + cleanup_vars_attrs +done + +if [ -z "$want_var" -a -z "$want_attr" ]; then + if [ -n "$want_cflags" ]; then + output="$output${output:+ }$(sysroot -I $(list_only_once $cflags))" + # Backward compatibility to old gpg-error-config + if [ $mt = yes -a -n "$mtcflags" ]; then + output="$output${output:+ }$mtcflags" + fi + fi + if [ -n "$want_libs" ]; then + output="$output${output:+ }$(sysroot -L $(list_only_once_for_libs $libs))" + # Backward compatibility to old gpg-error-config + if [ $mt = yes -a -n "$mtlibs" ]; then + output="$output${output:+ }$mtlibs" + fi + fi +fi + +if [ -z "$want_exists" ]; then + echo "$output" +fi + +exit 0 diff --git a/comm/third_party/libgpg-error/src/gpgrt-int.h b/comm/third_party/libgpg-error/src/gpgrt-int.h new file mode 100644 index 0000000000..fde5ee4e86 --- /dev/null +++ b/comm/third_party/libgpg-error/src/gpgrt-int.h @@ -0,0 +1,844 @@ +/* gpgrt-int.h - Internal definitions + * Copyright (C) 2014, 2017 g10 Code GmbH + * + * This file is part of libgpg-error. + * + * libgpg-error is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * libgpg-error is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <https://www.gnu.org/licenses/>. + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#ifndef _GPGRT_GPGRT_INT_H +#define _GPGRT_GPGRT_INT_H + +#include "gpg-error.h" +#include "visibility.h" +#include "protos.h" + +/* + * Internal i18n macros. + */ +#ifdef ENABLE_NLS +# ifdef HAVE_W32_SYSTEM +# include "gettext.h" +# else +# include <libintl.h> +# endif +# define _(a) gettext (a) +# ifdef gettext_noop +# define N_(a) gettext_noop (a) +# else +# define N_(a) (a) +# endif +#else /*!ENABLE_NLS*/ +# define _(a) (a) +# define N_(a) (a) +#endif /*!ENABLE_NLS */ + + +/* + * Hacks mainly required for Slowaris. + */ +#ifdef _GPGRT_NEED_AFLOCAL +# ifndef HAVE_W32_SYSTEM +# include <sys/socket.h> +# include <sys/un.h> +# else +# ifdef HAVE_WINSOCK2_H +# include <winsock2.h> +# endif +# include <windows.h> +# endif + +# ifndef PF_LOCAL +# ifdef PF_UNIX +# define PF_LOCAL PF_UNIX +# else +# define PF_LOCAL AF_UNIX +# endif +# endif /*PF_LOCAL*/ +# ifndef AF_LOCAL +# define AF_LOCAL AF_UNIX +# endif /*AF_UNIX*/ + +/* We used to avoid this macro in GnuPG and inlined the AF_LOCAL name + * length computation directly with the little twist of adding 1 extra + * byte. It seems that this was needed once on an old HP/UX box and + * there are also rumours that 4.3 Reno and DEC systems need it. This + * one-off buglet did not harm any current system until it came to Mac + * OS X where the kernel (as of May 2009) exhibited a strange bug: The + * systems basically froze in the connect call if the passed name + * contained an invalid directory part. Ignore the old Unices. */ +# ifndef SUN_LEN +# define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \ + + strlen ((ptr)->sun_path)) +# endif /*SUN_LEN*/ +#endif /*_GPGRT_NEED_AFLOCAL*/ + + +/* + * Common helper macros. + */ +#ifndef DIM +# define DIM(array) (sizeof (array) / sizeof (*array)) +#endif + + + +/* + * Local error function prototypes. + */ +const char *_gpg_strerror (gpg_error_t err); +int _gpg_strerror_r (gpg_error_t err, char *buf, size_t buflen); +const char *_gpg_strsource (gpg_error_t err); +gpg_err_code_t _gpg_err_code_from_errno (int err); +int _gpg_err_code_to_errno (gpg_err_code_t code); +gpg_err_code_t _gpg_err_code_from_syserror (void); +void _gpg_err_set_errno (int err); + +gpg_error_t _gpg_err_init (void); +void _gpg_err_deinit (int mode); + +void _gpgrt_add_emergency_cleanup (void (*f)(void)); +void _gpgrt_abort (void) GPGRT_ATTR_NORETURN; + +void _gpgrt_set_alloc_func (void *(*f)(void *a, size_t n)); + +void *_gpgrt_realloc (void *a, size_t n); +void *_gpgrt_reallocarray (void *a, size_t oldnmemb, size_t nmemb, size_t size); +void *_gpgrt_malloc (size_t n); +void *_gpgrt_calloc (size_t n, size_t m); +char *_gpgrt_strdup (const char *string); +char *_gpgrt_strconcat (const char *s1, ...) GPGRT_ATTR_SENTINEL(0); +void _gpgrt_free (void *a); +/* The next is only to be used by visibility.c. */ +char *_gpgrt_strconcat_core (const char *s1, va_list arg_ptr); + +#define xfree(a) _gpgrt_free ((a)) +#define xtrymalloc(a) _gpgrt_malloc ((a)) +#define xtrycalloc(a,b) _gpgrt_calloc ((a),(b)) +#define xtryrealloc(a,b) _gpgrt_realloc ((a),(b)) +#define xtryreallocarray(a,b,c,d) _gpgrt_reallocarray ((a),(b),(c),(d)) +#define xtrystrdup(a) _gpgrt_strdup ((a)) + +void _gpgrt_pre_syscall (void); +void _gpgrt_post_syscall (void); + +const char *_gpg_error_check_version (const char *req_version); + +gpg_err_code_t _gpgrt_lock_init (gpgrt_lock_t *lockhd); +gpg_err_code_t _gpgrt_lock_lock (gpgrt_lock_t *lockhd); +gpg_err_code_t _gpgrt_lock_trylock (gpgrt_lock_t *lockhd); +gpg_err_code_t _gpgrt_lock_unlock (gpgrt_lock_t *lockhd); +gpg_err_code_t _gpgrt_lock_destroy (gpgrt_lock_t *lockhd); +gpg_err_code_t _gpgrt_yield (void); + + + +/* + * Tracing + */ + +/* The trace macro is used this way: + * trace (("enter - foo=%d bar=%s", foo, bar)); + * Note the double parenthesis, they are important. + * To append the current errno to the output, use + * trace_errno (EXTPR,("leave - baz=%d", faz)); + * If EXPR evaluates to true the output of strerror (errno) + * is appended to the output. Note that the trace function does + * not modify ERRNO. To enable tracing you need to have this + * #define ENABLE_TRACING "modulename" + * before you include gpgrt-int.h. + */ +#ifdef ENABLE_TRACING +# define trace(X) do { \ + _gpgrt_internal_trace_begin \ + (ENABLE_TRACING, __func__, __LINE__, 0); \ + _gpgrt_internal_trace X; \ + _gpgrt_internal_trace_end (); \ + } while (0) +# define trace_errno(C,X) do { \ + _gpgrt_internal_trace_begin \ + (ENABLE_TRACING, __func__, __LINE__, (C)); \ + _gpgrt_internal_trace X; \ + _gpgrt_internal_trace_end (); \ + } while (0) +# define trace_start(X) do { \ + _gpgrt_internal_trace_begin \ + (ENABLE_TRACING, __func__, __LINE__, 0); \ + _gpgrt_internal_trace_printf X; \ + } while (0) +# define trace_append(X) do { \ + _gpgrt_internal_trace_printf X; \ + } while (0) +# define trace_finish(X) do { \ + _gpgrt_internal_trace_printf X; \ + _gpgrt_internal_trace_end (); \ + } while (0) +#else +# define trace(X) do { } while (0) +# define trace_errno(C,X) do { } while (0) +# define trace_start(X) do { } while (0) +# define trace_append(X) do { } while (0) +# define trace_finish(X) do { } while (0) +#endif /*!ENABLE_TRACING*/ + +void _gpgrt_internal_trace_begin (const char *mod, const char *file, int line, + int with_errno); +void _gpgrt_internal_trace (const char *format, + ...) GPGRT_ATTR_PRINTF(1,2); +void _gpgrt_internal_trace_printf (const char *format, + ...) GPGRT_ATTR_PRINTF(1,2); +void _gpgrt_internal_trace_end (void); + + + +/* + * Local definitions for estream. + */ + +#if HAVE_W32_SYSTEM +# ifndef O_NONBLOCK +# define O_NONBLOCK 0x40000000 /* FIXME: Is that safe? */ +# endif +#endif + +/* + * A private cookie function to implement an internal IOCTL service. + */ +typedef int (*cookie_ioctl_function_t) (void *cookie, int cmd, + void *ptr, size_t *len); +#define COOKIE_IOCTL_SNATCH_BUFFER 1 +#define COOKIE_IOCTL_NONBLOCK 2 +#define COOKIE_IOCTL_TRUNCATE 3 + +/* An internal variant of gpgrt_cookie_close_function_t with a slot + * for the ioctl function. */ +struct cookie_io_functions_s +{ + struct _gpgrt_cookie_io_functions public; + cookie_ioctl_function_t func_ioctl; +}; + +typedef enum + { + BACKEND_MEM, + BACKEND_FD, + BACKEND_W32, + BACKEND_FP, + BACKEND_USER, + BACKEND_W32_POLLABLE + } gpgrt_stream_backend_kind_t; + + +/* + * A type to hold notification functions. + */ +struct notify_list_s +{ + struct notify_list_s *next; + void (*fnc) (estream_t, void*); /* The notification function. */ + void *fnc_value; /* The value to be passed to FNC. */ +}; +typedef struct notify_list_s *notify_list_t; + + +/* + * Buffer management layer. + */ + +/* BUFSIZ on Windows is 512 but on current Linux it is 8k. We better + * use the 8k for Windows as well. */ +#ifdef HAVE_W32_SYSTEM +# define BUFFER_BLOCK_SIZE 8192 +#else +# define BUFFER_BLOCK_SIZE BUFSIZ +#endif +#define BUFFER_UNREAD_SIZE 16 + + +/* + * The private object describing a stream. + */ +struct _gpgrt_stream_internal +{ + unsigned char buffer[BUFFER_BLOCK_SIZE]; + unsigned char unread_buffer[BUFFER_UNREAD_SIZE]; + + gpgrt_lock_t lock; /* Lock. Used by *_stream_lock(). */ + + gpgrt_stream_backend_kind_t kind; + void *cookie; /* Cookie. */ + void *opaque; /* Opaque data. */ + unsigned int modeflags; /* Flags for the backend. */ + char *printable_fname; /* Malloced filename for es_fname_get. */ + gpgrt_off_t offset; + gpgrt_cookie_read_function_t func_read; + gpgrt_cookie_write_function_t func_write; + gpgrt_cookie_seek_function_t func_seek; + gpgrt_cookie_close_function_t func_close; + cookie_ioctl_function_t func_ioctl; + int strategy; + es_syshd_t syshd; /* A copy of the system handle. */ + struct + { + unsigned int err: 1; + unsigned int eof: 1; + unsigned int hup: 1; + } indicators; + unsigned int deallocate_buffer: 1; + unsigned int is_stdstream:1; /* This is a standard stream. */ + unsigned int stdstream_fd:2; /* 0, 1 or 2 for a standard stream. */ + unsigned int printable_fname_inuse: 1; /* es_fname_get has been used. */ + unsigned int samethread: 1; /* The "samethread" mode keyword. */ + size_t print_ntotal; /* Bytes written from in print_writer. */ + notify_list_t onclose; /* On close notify function list. */ +}; +typedef struct _gpgrt_stream_internal *estream_internal_t; + + +/* + * Local prototypes for estream. + */ +int _gpgrt_estream_init (void); +void _gpgrt_set_syscall_clamp (void (*pre)(void), void (*post)(void)); +void _gpgrt_get_syscall_clamp (void (**r_pre)(void), void (**r_post)(void)); + +gpgrt_stream_t _gpgrt_fopen (const char *_GPGRT__RESTRICT path, + const char *_GPGRT__RESTRICT mode); +gpgrt_stream_t _gpgrt_mopen (void *_GPGRT__RESTRICT data, + size_t data_n, size_t data_len, + unsigned int grow, + void *(*func_realloc) (void *mem, size_t size), + void (*func_free) (void *mem), + const char *_GPGRT__RESTRICT mode); +gpgrt_stream_t _gpgrt_fopenmem (size_t memlimit, + const char *_GPGRT__RESTRICT mode); +gpgrt_stream_t _gpgrt_fopenmem_init (size_t memlimit, + const char *_GPGRT__RESTRICT mode, + const void *data, size_t datalen); +gpgrt_stream_t _gpgrt_fdopen (int filedes, const char *mode); +gpgrt_stream_t _gpgrt_fdopen_nc (int filedes, const char *mode); +gpgrt_stream_t _gpgrt_sysopen (gpgrt_syshd_t *syshd, const char *mode); +gpgrt_stream_t _gpgrt_sysopen_nc (gpgrt_syshd_t *syshd, const char *mode); +gpgrt_stream_t _gpgrt_fpopen (FILE *fp, const char *mode); +gpgrt_stream_t _gpgrt_fpopen_nc (FILE *fp, const char *mode); +gpgrt_stream_t _gpgrt_freopen (const char *_GPGRT__RESTRICT path, + const char *_GPGRT__RESTRICT mode, + gpgrt_stream_t _GPGRT__RESTRICT stream); +gpgrt_stream_t _gpgrt_fopencookie (void *_GPGRT__RESTRICT cookie, + const char *_GPGRT__RESTRICT mode, + gpgrt_cookie_io_functions_t functions); +int _gpgrt_fclose (gpgrt_stream_t stream); +int _gpgrt_fcancel (gpgrt_stream_t stream); +int _gpgrt_fclose_snatch (gpgrt_stream_t stream, + void **r_buffer, size_t *r_buflen); +int _gpgrt_onclose (gpgrt_stream_t stream, int mode, + void (*fnc) (gpgrt_stream_t, void*), void *fnc_value); +int _gpgrt_fileno (gpgrt_stream_t stream); +int _gpgrt_fileno_unlocked (gpgrt_stream_t stream); +int _gpgrt_syshd (gpgrt_stream_t stream, gpgrt_syshd_t *syshd); +int _gpgrt_syshd_unlocked (gpgrt_stream_t stream, gpgrt_syshd_t *syshd); + +void _gpgrt__set_std_fd (int no, int fd); +gpgrt_stream_t _gpgrt__get_std_stream (int fd); +/* The es_stderr et al macros are pretty common so that we want to use + * them too. This requires that we redefine them. */ +#undef es_stdin +#define es_stdin _gpgrt__get_std_stream (0) +#undef es_stdout +#define es_stdout _gpgrt__get_std_stream (1) +#undef es_stderr +#define es_stderr _gpgrt__get_std_stream (2) + +void _gpgrt_flockfile (gpgrt_stream_t stream); +int _gpgrt_ftrylockfile (gpgrt_stream_t stream); +void _gpgrt_funlockfile (gpgrt_stream_t stream); + +int _gpgrt_feof (gpgrt_stream_t stream); +int _gpgrt_feof_unlocked (gpgrt_stream_t stream); +int _gpgrt_ferror (gpgrt_stream_t stream); +int _gpgrt_ferror_unlocked (gpgrt_stream_t stream); +void _gpgrt_clearerr (gpgrt_stream_t stream); +void _gpgrt_clearerr_unlocked (gpgrt_stream_t stream); +int _gpgrt__pending (gpgrt_stream_t stream); +int _gpgrt__pending_unlocked (gpgrt_stream_t stream); + +int _gpgrt_fflush (gpgrt_stream_t stream); +int _gpgrt_fseek (gpgrt_stream_t stream, long int offset, int whence); +int _gpgrt_fseeko (gpgrt_stream_t stream, gpgrt_off_t offset, int whence); +long int _gpgrt_ftell (gpgrt_stream_t stream); +gpgrt_off_t _gpgrt_ftello (gpgrt_stream_t stream); +void _gpgrt_rewind (gpgrt_stream_t stream); +int _gpgrt_ftruncate (estream_t stream, gpgrt_off_t length); + +int _gpgrt_fgetc (gpgrt_stream_t stream); +int _gpgrt_fputc (int c, gpgrt_stream_t stream); + +int _gpgrt__getc_underflow (gpgrt_stream_t stream); +int _gpgrt__putc_overflow (int c, gpgrt_stream_t stream); + +/* Note: Keeps the next two macros in sync + with their counterparts in gpg-error.h. */ +#define _gpgrt_getc_unlocked(stream) \ + (((!(stream)->flags.writing) \ + && ((stream)->data_offset < (stream)->data_len) \ + && (! (stream)->unread_data_len)) \ + ? ((int) (stream)->buffer[((stream)->data_offset)++]) \ + : _gpgrt__getc_underflow ((stream))) + +#define _gpgrt_putc_unlocked(c, stream) \ + (((stream)->flags.writing \ + && ((stream)->data_offset < (stream)->buffer_size) \ + && (c != '\n')) \ + ? ((int) ((stream)->buffer[((stream)->data_offset)++] = (c))) \ + : _gpgrt__putc_overflow ((c), (stream))) + +int _gpgrt_ungetc (int c, gpgrt_stream_t stream); + +int _gpgrt_read (gpgrt_stream_t _GPGRT__RESTRICT stream, + void *_GPGRT__RESTRICT buffer, size_t bytes_to_read, + size_t *_GPGRT__RESTRICT bytes_read); +int _gpgrt_write (gpgrt_stream_t _GPGRT__RESTRICT stream, + const void *_GPGRT__RESTRICT buffer, size_t bytes_to_write, + size_t *_GPGRT__RESTRICT bytes_written); +int _gpgrt_write_sanitized (gpgrt_stream_t _GPGRT__RESTRICT stream, + const void *_GPGRT__RESTRICT buffer, size_t length, + const char *delimiters, + size_t *_GPGRT__RESTRICT bytes_written); +int _gpgrt_write_hexstring (gpgrt_stream_t _GPGRT__RESTRICT stream, + const void *_GPGRT__RESTRICT buffer, size_t length, + int reserved, + size_t *_GPGRT__RESTRICT bytes_written); + +size_t _gpgrt_fread (void *_GPGRT__RESTRICT ptr, size_t size, size_t nitems, + gpgrt_stream_t _GPGRT__RESTRICT stream); +size_t _gpgrt_fwrite (const void *_GPGRT__RESTRICT ptr, + size_t size, size_t memb, + gpgrt_stream_t _GPGRT__RESTRICT stream); + +char *_gpgrt_fgets (char *_GPGRT__RESTRICT s, int n, + gpgrt_stream_t _GPGRT__RESTRICT stream); +int _gpgrt_fputs (const char *_GPGRT__RESTRICT s, + gpgrt_stream_t _GPGRT__RESTRICT stream); +int _gpgrt_fputs_unlocked (const char *_GPGRT__RESTRICT s, + gpgrt_stream_t _GPGRT__RESTRICT stream); + +gpgrt_ssize_t _gpgrt_getline (char *_GPGRT__RESTRICT *_GPGRT__RESTRICT lineptr, + size_t *_GPGRT__RESTRICT n, + gpgrt_stream_t stream); +gpgrt_ssize_t _gpgrt_read_line (gpgrt_stream_t stream, + char **addr_of_buffer, size_t *length_of_buffer, + size_t *max_length); + +int _gpgrt_fprintf (gpgrt_stream_t _GPGRT__RESTRICT stream, + const char *_GPGRT__RESTRICT format, ...) + GPGRT_ATTR_PRINTF(2,3); +int _gpgrt_fprintf_unlocked (gpgrt_stream_t _GPGRT__RESTRICT stream, + const char *_GPGRT__RESTRICT format, ...) + GPGRT_ATTR_PRINTF(2,3); + +int _gpgrt_vfprintf (gpgrt_stream_t _GPGRT__RESTRICT stream, + gpgrt_string_filter_t sf, void *sfvalue, + const char *_GPGRT__RESTRICT format, va_list ap) + GPGRT_ATTR_PRINTF(4,0); +int _gpgrt_vfprintf_unlocked (gpgrt_stream_t _GPGRT__RESTRICT stream, + gpgrt_string_filter_t sf, void *sfvalue, + const char *_GPGRT__RESTRICT format, va_list ap) + GPGRT_ATTR_PRINTF(4,0); + +int _gpgrt_setvbuf (gpgrt_stream_t _GPGRT__RESTRICT stream, + char *_GPGRT__RESTRICT buf, int mode, size_t size); + +void _gpgrt_set_binary (gpgrt_stream_t stream); +int _gpgrt_set_nonblock (gpgrt_stream_t stream, int onoff); +int _gpgrt_get_nonblock (gpgrt_stream_t stream); + +int _gpgrt_poll (gpgrt_poll_t *fds, unsigned int nfds, int timeout); + +gpgrt_stream_t _gpgrt_tmpfile (void); + +void _gpgrt_opaque_set (gpgrt_stream_t _GPGRT__RESTRICT stream, + void *_GPGRT__RESTRICT opaque); +void *_gpgrt_opaque_get (gpgrt_stream_t stream); + +void _gpgrt_fname_set (gpgrt_stream_t stream, const char *fname); +const char *_gpgrt_fname_get (gpgrt_stream_t stream); + +#include "estream-printf.h" + +/* Make sure we always use our snprintf */ +#undef snprintf +#define snprintf _gpgrt_estream_snprintf + + +#if HAVE_W32_SYSTEM +/* Prototypes for w32-estream.c. */ +extern struct cookie_io_functions_s _gpgrt_functions_w32_pollable; +int _gpgrt_w32_pollable_create (void *_GPGRT__RESTRICT *_GPGRT__RESTRICT cookie, + unsigned int modeflags, + struct cookie_io_functions_s next_functions, + void *next_cookie); +int _gpgrt_w32_poll (gpgrt_poll_t *fds, size_t nfds, int timeout); +#endif /*HAVE_W32_SYSTEM*/ + + + +/* + * Local prototypes for the encoders. + */ + +struct _gpgrt_b64state +{ + int idx; + int quad_count; + estream_t stream; + char *title; + unsigned char radbuf[4]; + unsigned int crc; + gpg_err_code_t lasterr; + unsigned int flags; + unsigned int stop_seen:1; + unsigned int invalid_encoding:1; + unsigned int using_decoder:1; +}; + +gpgrt_b64state_t _gpgrt_b64enc_start (estream_t stream, const char *title); +gpg_err_code_t _gpgrt_b64enc_write (gpgrt_b64state_t state, + const void *buffer, size_t nbytes); +gpg_err_code_t _gpgrt_b64enc_finish (gpgrt_b64state_t state); + +gpgrt_b64state_t _gpgrt_b64dec_start (const char *title); +gpg_err_code_t _gpgrt_b64dec_proc (gpgrt_b64state_t state, void *buffer, + size_t length, size_t *r_nbytes); +gpg_err_code_t _gpgrt_b64dec_finish (gpgrt_b64state_t state); + + + +/* + * Local prototypes for logging + */ +int _gpgrt_get_errorcount (int clear); +void _gpgrt_inc_errorcount (void); +void _gpgrt_log_set_sink (const char *name, estream_t stream, int fd); +void _gpgrt_log_set_socket_dir_cb (const char *(*fnc)(void)); +void _gpgrt_log_set_pid_suffix_cb (int (*cb)(unsigned long *r_value)); +void _gpgrt_log_set_prefix (const char *text, unsigned int flags); +const char *_gpgrt_log_get_prefix (unsigned int *flags); +int _gpgrt_log_test_fd (int fd); +int _gpgrt_log_get_fd (void); +estream_t _gpgrt_log_get_stream (void); + +void _gpgrt_log (int level, const char *fmt, ...) GPGRT_ATTR_PRINTF(2,3); +void _gpgrt_logv (int level, const char *fmt, va_list arg_ptr); +void _gpgrt_logv_prefix (int level, const char *prefix, + const char *fmt, va_list arg_ptr); + +void _gpgrt_log_string (int level, const char *string); + +void _gpgrt_log_bug (const char *fmt, ...) GPGRT_ATTR_NR_PRINTF(1,2); +void _gpgrt_log_fatal (const char *fmt, ...) GPGRT_ATTR_NR_PRINTF(1,2); +void _gpgrt_log_error (const char *fmt, ...) GPGRT_ATTR_PRINTF(1,2); +void _gpgrt_log_info (const char *fmt, ...) GPGRT_ATTR_PRINTF(1,2); +void _gpgrt_log_debug (const char *fmt, ...) GPGRT_ATTR_PRINTF(1,2); +void _gpgrt_log_debug_string (const char *string, const char *fmt, + ...) GPGRT_ATTR_PRINTF(2,3); + +void _gpgrt_log_printf (const char *fmt, ...) GPGRT_ATTR_PRINTF(1,2); + +void _gpgrt_log_flush (void); + +void _gpgrt_logv_printhex (const void *buffer, size_t length, + const char *fmt, va_list arg_ptr); +void _gpgrt_log_printhex (const void *buffer, size_t length, + const char *fmt, ...) GPGRT_ATTR_PRINTF(3,4);; + +void _gpgrt_logv_clock (const char *fmt, va_list arg_ptr); +void _gpgrt_log_clock (const char *fmt, ...) GPGRT_ATTR_PRINTF(1,2); + +void _gpgrt__log_assert (const char *expr, const char *file, int line, + const char *func) GPGRT_ATTR_NORETURN; + +/* Redefine the assert macro to use our internal function. */ +#undef gpgrt_assert +#ifdef GPGRT_HAVE_MACRO_FUNCTION +#define gpgrt_assert(expr) \ + ((expr) \ + ? (void) 0 \ + : _gpgrt__log_assert (#expr, __FILE__, __LINE__, __FUNCTION__)) +#else /*!GPGRT_HAVE_MACRO_FUNCTION*/ +/* # define BUG() bug_at( __FILE__ , __LINE__ ) */ +#define gpgrt_assert(expr) \ + ((expr) \ + ? (void) 0 \ + : _gpgrt__log_assert (#expr, __FILE__, __LINE__, NULL)) +#endif /*!GPGRT_HAVE_MACRO_FUNCTION*/ + +/* Note: The next function is only to be used by visibility.c. */ +int _gpgrt_logv_internal (int level, int ignore_arg_ptr, + const char *extrastring, + const char *prefmt, const char *fmt, + va_list arg_ptr); + + +/* + * Local prototypes for the spawn functions. + * + * We put the docs here because we have separate implementations in + * the files spawn-posix.c and spawn-w32.c + */ + +/* Return the maximum number of currently allowed file descriptors. + * Only useful on POSIX systems. */ +/* int get_max_fds (void); */ + + +/* Close all file descriptors starting with descriptor FIRST. If + * EXCEPT is not NULL, it is expected to be a list of file descriptors + * which are not to close. This list shall be sorted in ascending + * order with its end marked by -1. */ +/* void close_all_fds (int first, int *except); */ + + +/* Returns an array with all currently open file descriptors. The end + * of the array is marked by -1. The caller needs to release this + * array using the *standard free* and not with xfree. This allow the + * use of this function right at startup even before libgcrypt has + * been initialized. Returns NULL on error and sets ERRNO accordingly. */ +/* int *get_all_open_fds (void); */ + +/* Create a pipe. The DIRECTION parameter gives the type of the created pipe: + * DIRECTION < 0 := Inbound pipe: On Windows the write end is inheritable. + * DIRECTION > 0 := Outbound pipe: On Windows the read end is inheritable. + * If R_FP is NULL a standard pipe and no stream is created, DIRECTION + * should then be 0. */ +gpg_err_code_t _gpgrt_make_pipe (int filedes[2], estream_t *r_fp, + int direction, int nonblock); + +/* Convenience macros to create a pipe. */ +#define _gpgrt_create_pipe(a) _gpgrt_make_pipe ((a),NULL, 0, 0); +#define _gpgrt_create_inbound_pipe(a,b,c) _gpgrt_make_pipe ((a), (b), -1, (c)); +#define _gpgrt_create_outbound_pipe(a,b,c) _gpgrt_make_pipe ((a), (b), 1, (c)); + + +/* Fork and exec the program PGMNAME. + * + * If R_INFP is NULL connect stdin of the new process to /dev/null; if + * it is not NULL store the address of a pointer to a new estream + * there. If R_OUTFP is NULL connect stdout of the new process to + * /dev/null; if it is not NULL store the address of a pointer to a + * new estream there. If R_ERRFP is NULL connect stderr of the new + * process to /dev/null; if it is not NULL store the address of a + * pointer to a new estream there. On success the pid of the new + * process is stored at PID. On error -1 is stored at PID and if + * R_OUTFP or R_ERRFP are not NULL, NULL is stored there. + * + * The arguments for the process are expected in the NULL terminated + * array ARGV. The program name itself should not be included there. + * If PREEXEC is not NULL, the given function will be called right + * before the exec. + * + * IF EXCEPT is not NULL, it is expected to be an ordered list of file + * descriptors, terminated by an entry with the value (-1). These + * file descriptors won't be closed before spawning a new program. + * + * Returns 0 on success or an error code. Calling gpgrt_wait_process + * and gpgrt_release_process is required if the function succeeded. + * + * FLAGS is a bit vector: + * + * GPGRT_SPAWN_NONBLOCK + * If set the two output streams are created in non-blocking + * mode and the input stream is switched to non-blocking mode. + * This is merely a convenience feature because the caller + * could do the same with gpgrt_set_nonblock. Does not yet + * work for Windows. + * + * GPGRT_SPAWN_DETACHED + * If set the process will be started as a background process. + * This flag is only useful under W32 (but not W32CE) systems, + * so that no new console is created and pops up a console + * window when starting the server. Does not work on W32CE. + * + * GPGRT_SPAWN_RUN_ASFW + * On W32 (but not on W32CE) run AllowSetForegroundWindow for + * the child. Note that due to unknown problems this actually + * allows SetForegroundWindow for all children of this process. + */ +gpg_err_code_t +_gpgrt_spawn_process (const char *pgmname, const char *argv[], + int *execpt, void (*preexec)(void), unsigned int flags, + estream_t *r_infp, + estream_t *r_outfp, + estream_t *r_errfp, + pid_t *pid); + + +/* Simplified version of gpgrt_spawn_process. This function forks and + * then execs PGMNAME, while connecting INFD to stdin, OUTFD to stdout + * and ERRFD to stderr (any of them may be -1 to connect them to + * /dev/null). The arguments for the process are expected in the NULL + * terminated array ARGV. The program name itself should not be + * included there. Calling gpgrt_wait_process and + * gpgrt_release_process is required. Returns 0 on success or an + * error code. */ +gpg_err_code_t _gpgrt_spawn_process_fd (const char *pgmname, + const char *argv[], + int infd, int outfd, int errfd, + pid_t *pid); + +/* Spawn a new process and immediately detach from it. The name of + * the program to exec is PGMNAME and its arguments are in ARGV (the + * programname is automatically passed as first argument). + * Environment strings in ENVP are set. An error is returned if + * pgmname is not executable; to make this work it is necessary to + * provide an absolute file name. */ +gpg_err_code_t _gpgrt_spawn_process_detached (const char *pgmname, + const char *argv[], + const char *envp[] ); + +/* If HANG is true, waits for the process identified by PID to exit; + * if HANG is false, checks whether the process has terminated. + * PGMNAME should be the same as supplied to the spawn function and is + * only used for diagnostics. Return values: + * + * 0 + * The process exited successful. 0 is stored at R_EXITCODE. + * + * GPG_ERR_GENERAL + * The process exited without success. The exit code of process + * is then stored at R_EXITCODE. An exit code of -1 indicates + * that the process terminated abnormally (e.g. due to a signal). + * + * GPG_ERR_TIMEOUT + * The process is still running (returned only if HANG is false). + * + * GPG_ERR_INV_VALUE + * An invalid PID has been specified. + * + * Other error codes may be returned as well. Unless otherwise noted, + * -1 will be stored at R_EXITCODE. R_EXITCODE may be passed as NULL + * if the exit code is not required (in that case an error message will + * be printed). Note that under Windows PID is not the process id but + * the handle of the process. */ +gpg_err_code_t _gpgrt_wait_process (const char *pgmname, pid_t pid, int hang, + int *r_exitcode); + +/* Like _gpgrt_wait_process, but for COUNT processes. */ +gpg_err_code_t _gpgrt_wait_processes (const char **pgmnames, pid_t *pids, + size_t count, int hang, int *r_exitcodes); + +/* Kill a process; that is send an appropriate signal to the process. + * gpgrt_wait_process must be called to actually remove the process + * from the system. An invalid PID is ignored. */ +void _gpgrt_kill_process (pid_t pid); + +/* Release the process identified by PID. This function is actually + * only required for Windows but it does not harm to always call it. + * It is a nop if PID is invalid. */ +void _gpgrt_release_process (pid_t pid); + + +/* + * Local prototypes for argparse. + */ +int _gpgrt_argparse (estream_t fp, gpgrt_argparse_t *arg, gpgrt_opt_t *opts); +int _gpgrt_argparser (gpgrt_argparse_t *arg, gpgrt_opt_t *opts, + const char *confname); +void _gpgrt_usage (int level); +const char *_gpgrt_strusage (int level); +void _gpgrt_set_strusage (const char *(*f)(int)); +void _gpgrt_set_usage_outfnc (int (*fnc)(int, const char *)); +void _gpgrt_set_fixed_string_mapper (const char *(*f)(const char*)); +void _gpgrt_set_confdir (int what, const char *name); + + +/* + * Various helper functions + */ +int _gpgrt_cmp_version (const char *a, const char *b, int level); + + + +/* + * Internal platform abstraction functions (sysutils.c) + */ + +/* Return true if FD is valid. */ +int _gpgrt_fd_valid_p (int fd); + +/* A getenv variant which returns a malloced copy. */ +char *_gpgrt_getenv (const char *name); + +/* A setenv variant which can be used for unsetenv by setting VALUE to + * NULL and OVERRIDE to true. */ +gpg_err_code_t _gpgrt_setenv (const char *name, + const char *value, int overwrite); + +/* A wrapper around mkdir using a string for the mode (permissions). */ +gpg_err_code_t _gpgrt_mkdir (const char *name, const char *modestr); + +/* A simple wrapper around chdir. */ +gpg_err_code_t _gpgrt_chdir (const char *name); + +/* Return the current WD as a malloced string. */ +char *_gpgrt_getcwd (void); + +/* Wrapper for Windows to allow utf8 file names. */ +gpg_err_code_t _gpgrt_access (const char *fname, int mode); + +/* Return the home directory of user NAME. */ +char *_gpgrt_getpwdir (const char *name); + +/* Return the account name of the current user. */ +char *_gpgrt_getusername (void); + +/* Expand and concat file name parts. */ +char *_gpgrt_vfnameconcat (int want_abs, const char *first_part, + va_list arg_ptr); +char *_gpgrt_fnameconcat (const char *first_part, + ... ) GPGRT_ATTR_SENTINEL(0); +char *_gpgrt_absfnameconcat (const char *first_part, + ... ) GPGRT_ATTR_SENTINEL(0); + + +/* + * Platform specific functions (Windows) + */ +#ifdef HAVE_W32_SYSTEM + +char *_gpgrt_w32_reg_query_string (const char *root, + const char *dir, + const char *name); + + +#endif /*HAVE_W32_SYSTEM*/ + +/* + * Missing functions implemented inline. + */ + +#ifndef HAVE_STPCPY +static GPG_ERR_INLINE char * +_gpgrt_stpcpy (char *a, const char *b) +{ + while (*b) + *a++ = *b++; + *a = 0; + return a; +} +#define stpcpy(a,b) _gpgrt_stpcpy ((a), (b)) +#endif /*!HAVE_STPCPY*/ + + +#endif /*_GPGRT_GPGRT_INT_H*/ diff --git a/comm/third_party/libgpg-error/src/gpgrt.m4 b/comm/third_party/libgpg-error/src/gpgrt.m4 new file mode 100644 index 0000000000..40fcd1f801 --- /dev/null +++ b/comm/third_party/libgpg-error/src/gpgrt.m4 @@ -0,0 +1,112 @@ +# gpgrt.m4 - autoconf macro to detect libgpgrt +# Copyright (C) 2002, 2003, 2004, 2011, 2014, 2017, 2018 g10 Code GmbH +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This file is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# SPDX-License-Identifier: FSFULLR +# +# Last-changed: 2018-11-13 +# Note: This is a kind of duplicate of gpg-error.m4 which uses the +# future name of libgpg-error to prepare for a smooth migration in +# some distant time. + +dnl AM_PATH_GPGRT([MINIMUM-VERSION, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl +dnl Test for libgpgrt and define GPGRT_CFLAGS, GPGRT_LIBS, +dnl GPGRT_MT_CFLAGS, and GPGRT_MT_LIBS. The _MT_ variants are +dnl used for programs requiring real multi thread support. +dnl +AC_DEFUN([AM_PATH_GPGRT], +[ AC_REQUIRE([AC_CANONICAL_HOST]) + if test "$prefix" = NONE ; then + prefix_option_expanded=/usr/local + else + prefix_option_expanded="$prefix" + fi + if test "$exec_prefix" = NONE ; then + exec_prefix_option_expanded=$prefix_option_expanded + else + exec_prefix_option_expanded=$(prefix=$prefix_option_expanded eval echo $exec_prefix) + fi + libdir_option_expanded=$(prefix=$prefix_option_expanded exec_prefix=$exec_prefix_option_expanded eval echo $libdir) + + if test -f $libdir_option_expanded/pkgconfig/gpg-error.pc; then + gpgrt_libdir=$libdir_option_expanded + else + if crt1_path=$(${CC:-cc} -print-file-name=crt1.o 2>/dev/null); then + if possible_libdir=$(cd ${crt1_path%/*} && pwd 2>/dev/null); then + if test -f $possible_libdir/pkgconfig/gpg-error.pc; then + gpgrt_libdir=$possible_libdir + fi + fi + fi + fi + + if test -n "$gpgrt_libdir"; then + AC_PATH_PROG(GPGRT_CONFIG, gpgrt-config, no) + if test "$GPGRT_CONFIG" != "no"; then + GPGRT_CONFIG="$GPGRT_CONFIG --libdir=$gpgrt_libdir" + fi + fi + min_gpgrt_version=ifelse([$1], ,1.33,$1) + AC_MSG_CHECKING(for GPG Runtime - version >= $min_gpgrt_version) + ok=no + if test x"$GPGRT_CONFIG" != x -a "$GPGRT_CONFIG" != "no" ; then + req_major=`echo $min_gpgrt_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` + req_minor=`echo $min_gpgrt_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` + gpgrt_config_version=`$GPGRT_CONFIG --version` + major=`echo $gpgrt_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` + minor=`echo $gpgrt_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` + if test "$major" -gt "$req_major"; then + ok=yes + else + if test "$major" -eq "$req_major"; then + if test "$minor" -ge "$req_minor"; then + ok=yes + fi + fi + fi + fi + if test $ok = yes; then + GPGRT_CFLAGS=`$GPGRT_CONFIG --cflags` + GPGRT_LIBS=`$GPGRT_CONFIG --libs` + GPGRT_MT_CFLAGS=`$GPGRT_CONFIG --variable=mtcflags 2>/dev/null` + GPGRT_MT_CFLAGS="$GPGRT_CFLAGS${GPGRT_CFLAGS:+ }$GPGRT_MT_CFLAGS" + GPGRT_MT_LIBS=`$GPGRT_CONFIG --variable=mtlibs 2>/dev/null` + GPGRT_MT_LIBS="$GPGRT_LIBS${GPGRT_LIBS:+ }$GPGRT_MT_LIBS" + AC_MSG_RESULT([yes ($gpgrt_config_version)]) + ifelse([$2], , :, [$2]) + gpgrt_config_host=`$GPGRT_CONFIG --variable=host 2>/dev/null || echo none` + if test x"$gpgrt_config_host" != xnone ; then + if test x"$gpgrt_config_host" != x"$host" ; then + AC_MSG_WARN([[ +*** +*** The config script "$GPGRT_CONFIG" is for $gpgrt_config_host +*** and thus may not match the used host $host. +***]]) + gpg_config_script_warn="$gpg_config_script_warn libgpgrt" + fi + fi + else + GPGRT_CFLAGS="" + GPGRT_LIBS="" + GPGRT_MT_CFLAGS="" + GPGRT_MT_LIBS="" + AC_MSG_RESULT(no) + ifelse([$3], , :, [$3]) + fi + AC_SUBST(GPGRT_CFLAGS) + AC_SUBST(GPGRT_LIBS) + AC_SUBST(GPGRT_MT_CFLAGS) + AC_SUBST(GPGRT_MT_LIBS) +]) diff --git a/comm/third_party/libgpg-error/src/init.c b/comm/third_party/libgpg-error/src/init.c new file mode 100644 index 0000000000..623968219f --- /dev/null +++ b/comm/third_party/libgpg-error/src/init.c @@ -0,0 +1,741 @@ +/* init.c - Initialize the GnuPG error library. + Copyright (C) 2005, 2010 g10 Code GmbH + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, see <https://www.gnu.org/licenses/>. + */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include "gpgrt-int.h" +#include "gettext.h" +#include "init.h" + +#ifdef HAVE_W32CE_SYSTEM +# include "mkw32errmap.map.c" /* Generated map_w32codes () */ +# ifndef TLS_OUT_OF_INDEXES +# define TLS_OUT_OF_INDEXES 0xFFFFFFFF +# endif +# ifndef __MINGW32CE__ +# /* Replace the Mingw32CE provided abort function. */ +# define abort() do { TerminateProcess (GetCurrentProcess(), 8); } while (0) +# endif +#endif + + +/* Locale directory support. */ + +#if HAVE_W32_SYSTEM + +#include <windows.h> + +static int tls_index = TLS_OUT_OF_INDEXES; /* Index for the TLS functions. */ + +static char *get_locale_dir (void); +static void drop_locale_dir (char *locale_dir); + +#else /*!HAVE_W32_SYSTEM*/ + +#define get_locale_dir() LOCALEDIR +#define drop_locale_dir(dir) + +#endif /*!HAVE_W32_SYSTEM*/ + + +/* The list of emergency cleanup functions; see _gpgrt_abort and + * _gpgrt_add_emergency_cleanup. */ +struct emergency_cleanup_item_s; +typedef struct emergency_cleanup_item_s *emergency_cleanup_item_t; +struct emergency_cleanup_item_s +{ + emergency_cleanup_item_t next; + void (*func) (void); +}; +static emergency_cleanup_item_t emergency_cleanup_list; + + + + +/* The realloc function as set by gpgrt_set_alloc_func. */ +static void *(*custom_realloc)(void *a, size_t n); + + + +static void +real_init (void) +{ +#ifdef ENABLE_NLS + char *locale_dir; + + /* We only have to bind our locale directory to our text domain. */ + locale_dir = get_locale_dir (); + if (locale_dir) + { + bindtextdomain (PACKAGE, locale_dir); + drop_locale_dir (locale_dir); + } +#endif + _gpgrt_estream_init (); +} + +/* Initialize the library. This function should be run early. */ +gpg_error_t +_gpg_err_init (void) +{ +#ifdef HAVE_W32_SYSTEM +# ifdef DLL_EXPORT + /* We always have a constructor and thus this function is called + automatically. Due to the way the C init code of mingw works, + the constructors are called before our DllMain function is + called. The problem with that is that the TLS has not been setup + and w32-gettext.c requires TLS. To solve this we do nothing here + but call the actual init code from our DllMain. */ +# else /*!DLL_EXPORT*/ + /* Note that if the TLS is actually used, we can't release the TLS + as there is no way to know when a thread terminates (i.e. no + thread-specific-atexit). You are really better off to use the + DLL! */ + if (tls_index == TLS_OUT_OF_INDEXES) + { + tls_index = TlsAlloc (); + if (tls_index == TLS_OUT_OF_INDEXES) + { + /* No way to continue - commit suicide. */ + _gpgrt_abort (); + } + _gpg_w32__init_gettext_module (); + real_init (); + } +# endif /*!DLL_EXPORT*/ +#else + real_init (); +#endif + return 0; +} + + +/* Deinitialize libgpg-error. This function is only used in special + circumstances. No gpg-error function should be used after this + function has been called. A value of 0 passed for MODE + deinitializes the entire libgpg-error, a value of 1 releases + resources allocated for the current thread and only that thread may + not anymore access libgpg-error after such a call. Under Windows + this function may be called from the DllMain function of a DLL + which statically links to libgpg-error. */ +void +_gpg_err_deinit (int mode) +{ +#if defined (HAVE_W32_SYSTEM) && !defined(DLL_EXPORT) + struct tls_space_s *tls; + + tls = TlsGetValue (tls_index); + if (tls) + { + TlsSetValue (tls_index, NULL); + LocalFree (tls); + } + + if (mode == 0) + { + TlsFree (tls_index); + tls_index = TLS_OUT_OF_INDEXES; + } +#else + (void)mode; +#endif +} + + +/* Add the emergency cleanup function F to the list of those function. + * If the a function with that address has already been registered, it + * is not added a second time. These emergency functions are called + * whenever gpgrt_abort is called and at no other place. Like signal + * handles the emergency cleanup functions shall not call any + * non-trivial functions and return as soon as possible. They allow + * to cleanup internal states which should not go into a core dumps or + * similar. This is independent of any atexit functions. We don't + * use locks here because in an emergency case we can't use them + * anyway. */ +void +_gpgrt_add_emergency_cleanup (void (*f)(void)) +{ + emergency_cleanup_item_t item; + + for (item = emergency_cleanup_list; item; item = item->next) + if (item->func == f) + return; /* Function has already been registered. */ + + /* We use a standard malloc here. */ + item = malloc (sizeof *item); + if (item) + { + item->func = f; + item->next = emergency_cleanup_list; + emergency_cleanup_list = item; + } + else + _gpgrt_log_fatal ("out of core in gpgrt_add_emergency_cleanup\n"); +} + + +/* Run the emergency handlers. No locks are used because we are anyway + * in an emergency state. We also can't release any memory. */ +static void +run_emergency_cleanup (void) +{ + emergency_cleanup_item_t next; + void (*f)(void); + + while (emergency_cleanup_list) + { + next = emergency_cleanup_list->next; + f = emergency_cleanup_list->func; + emergency_cleanup_list->func = NULL; + emergency_cleanup_list = next; + if (f) + f (); + } +} + + +/* Wrapper around abort to be able to run all emergency cleanup + * functions. */ +void +_gpgrt_abort (void) +{ + run_emergency_cleanup (); + abort (); +} + + + +/* Register F as allocation function. This function is used for all + APIs which return an allocated buffer. F needs to have standard + realloc semantics. It should be called as early as possible and + not changed later. */ +void +_gpgrt_set_alloc_func (void *(*f)(void *a, size_t n)) +{ + custom_realloc = f; +} + + +/* The realloc to be used for data returned by the public API. */ +void * +_gpgrt_realloc (void *a, size_t n) +{ + if (custom_realloc) + return custom_realloc (a, n); + + if (!n) + { + free (a); + return NULL; + } + + if (!a) + return malloc (n); + + return realloc (a, n); +} + + +/* This is safe version of realloc useful for reallocing a calloced + * array. There are two ways to call it: The first example + * reallocates the array A to N elements each of SIZE but does not + * clear the newly allocated elements: + * + * p = gpgrt_reallocarray (a, n, n, nsize); + * + * Note that when NOLD is larger than N no cleaning is needed anyway. + * The second example reallocates an array of size NOLD to N elements + * each of SIZE but clear the newly allocated elements: + * + * p = gpgrt_reallocarray (a, nold, n, nsize); + * + * Note that gpgrt_reallocarray (NULL, 0, n, nsize) is equivalent to + * _gpgrt_calloc (n, nsize). + * + */ +void * +_gpgrt_reallocarray (void *a, size_t oldnmemb, size_t nmemb, size_t size) +{ + size_t oldbytes, bytes; + char *p; + + bytes = nmemb * size; /* size_t is unsigned so the behavior on overflow + * is defined. */ + if (size && bytes / size != nmemb) + { + _gpg_err_set_errno (ENOMEM); + return NULL; + } + + p = _gpgrt_realloc (a, bytes); + if (p && oldnmemb < nmemb) + { + /* OLDNMEMBS is lower than NMEMB thus the user asked for a + calloc. Clear all newly allocated members. */ + oldbytes = oldnmemb * size; + if (size && oldbytes / size != oldnmemb) + { + xfree (p); + _gpg_err_set_errno (ENOMEM); + return NULL; + } + memset (p + oldbytes, 0, bytes - oldbytes); + } + return p; +} + + +/* The malloc to be used for data returned by the public API. */ +void * +_gpgrt_malloc (size_t n) +{ + if (!n) + n++; + return _gpgrt_realloc (NULL, n); +} + + +void * +_gpgrt_calloc (size_t n, size_t m) +{ + size_t bytes; + void *p; + + bytes = n * m; /* size_t is unsigned so the behavior on overflow is + defined. */ + if (m && bytes / m != n) + { + _gpg_err_set_errno (ENOMEM); + return NULL; + } + + p = _gpgrt_realloc (NULL, bytes); + if (p) + memset (p, 0, bytes); + return p; +} + + +char * +_gpgrt_strdup (const char *string) +{ + size_t len = strlen (string); + char *p; + + p = _gpgrt_realloc (NULL, len + 1); + if (p) + strcpy (p, string); + return p; +} + + +/* Helper for _gpgrt_strconcat and gpgrt_strconcat. */ +char * +_gpgrt_strconcat_core (const char *s1, va_list arg_ptr) +{ + const char *argv[48]; + size_t argc; + size_t needed; + char *buffer, *p; + + argc = 0; + argv[argc++] = s1; + needed = strlen (s1); + while (((argv[argc] = va_arg (arg_ptr, const char *)))) + { + needed += strlen (argv[argc]); + if (argc >= DIM (argv)-1) + { + _gpg_err_set_errno (EINVAL); + return NULL; + } + argc++; + } + needed++; + buffer = _gpgrt_malloc (needed); + if (buffer) + { + for (p = buffer, argc=0; argv[argc]; argc++) + p = stpcpy (p, argv[argc]); + } + return buffer; +} + + +char * +_gpgrt_strconcat (const char *s1, ...) +{ + va_list arg_ptr; + char *result; + + if (!s1) + result = _gpgrt_strdup (""); + else + { + va_start (arg_ptr, s1); + result = _gpgrt_strconcat_core (s1, arg_ptr); + va_end (arg_ptr); + } + return result; +} + + +/* The free to be used for data returned by the public API. */ +void +_gpgrt_free (void *a) +{ + _gpgrt_realloc (a, 0); +} + + +void +_gpg_err_set_errno (int err) +{ +#ifdef HAVE_W32CE_SYSTEM + SetLastError (err); +#else /*!HAVE_W32CE_SYSTEM*/ + errno = err; +#endif /*!HAVE_W32CE_SYSTEM*/ +} + + + +/* Internal tracing functions. Except for TRACE_FP we use flockfile + * and funlockfile to protect their use. + * + * Warning: Take care with the trace functions - they may not use any + * of our services, in particular not the syscall clamp mechanism for + * reasons explained in w32-stream.c:create_reader. */ +static FILE *trace_fp; +static int trace_save_errno; +static int trace_with_errno; +static const char *trace_arg_module; +static const char *trace_arg_file; +static int trace_arg_line; +static int trace_missing_lf; +static int trace_prefix_done; + +void +_gpgrt_internal_trace_begin (const char *module, const char *file, int line, + int with_errno) +{ + int save_errno = errno; + + if (!trace_fp) + { + FILE *fp; + const char *s = getenv ("GPGRT_TRACE_FILE"); + + if (!s || !(fp = fopen (s, "wb"))) + fp = stderr; + trace_fp = fp; + } + +#ifdef HAVE_FLOCKFILE + flockfile (trace_fp); +#endif + trace_save_errno = save_errno; + trace_with_errno = with_errno; + trace_arg_module = module; + trace_arg_file = file; + trace_arg_line = line; + trace_missing_lf = 0; + trace_prefix_done = 0; +} + +static void +print_internal_trace_prefix (void) +{ + if (!trace_prefix_done) + { + trace_prefix_done = 1; + fprintf (trace_fp, "%s:%s:%d: ", + trace_arg_module,/* npth_is_protected ()?"":"^",*/ + trace_arg_file, trace_arg_line); + } +} + +static void +do_internal_trace (const char *format, va_list arg_ptr) +{ + print_internal_trace_prefix (); + vfprintf (trace_fp, format, arg_ptr); + if (trace_with_errno) + fprintf (trace_fp, " errno=%s", strerror (trace_save_errno)); + if (*format && format[strlen(format)-1] != '\n') + fputc ('\n', trace_fp); +} + +void +_gpgrt_internal_trace_printf (const char *format, ...) +{ + va_list arg_ptr; + + print_internal_trace_prefix (); + va_start (arg_ptr, format) ; + vfprintf (trace_fp, format, arg_ptr); + va_end (arg_ptr); + trace_missing_lf = (*format && format[strlen(format)-1] != '\n'); +} + + +void +_gpgrt_internal_trace (const char *format, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, format) ; + do_internal_trace (format, arg_ptr); + va_end (arg_ptr); +} + + +void +_gpgrt_internal_trace_end (void) +{ + int save_errno = trace_save_errno; + + if (trace_missing_lf) + fputc ('\n', trace_fp); +#ifdef HAVE_FLOCKFILE + funlockfile (trace_fp); +#endif + errno = save_errno; +} + + + +#ifdef HAVE_W32_SYSTEM +/***************************************** + ******** Below is only Windows code. **** + *****************************************/ + +static char * +get_locale_dir (void) +{ + static wchar_t moddir[MAX_PATH+5]; + char *result, *p; + int nbytes; + + if (!GetModuleFileNameW (NULL, moddir, MAX_PATH)) + *moddir = 0; + +#define SLDIR "\\share\\locale" + if (*moddir) + { + nbytes = WideCharToMultiByte (CP_UTF8, 0, moddir, -1, NULL, 0, NULL, NULL); + if (nbytes < 0) + return NULL; + + result = malloc (nbytes + strlen (SLDIR) + 1); + if (result) + { + nbytes = WideCharToMultiByte (CP_UTF8, 0, moddir, -1, + result, nbytes, NULL, NULL); + if (nbytes < 0) + { + free (result); + result = NULL; + } + else + { + p = strrchr (result, '\\'); + if (p) + *p = 0; + /* If we are installed below "bin" strip that part and + use the top directory instead. + + Background: Under Windows we don't install GnuPG + below bin/ but in the top directory with only share/, + lib/, and etc/ below it. One of the reasons is to + keep the the length of the filenames at bay so not to + increase the limited length of the PATH envvar. + Another and more important reason, however, is that + the very first GPG versions on W32 were installed + into a flat directory structure and for best + compatibility with these versions we didn't changed + that later. For WindowsCE we can right away install + it under bin, though. The hack with detection of the + bin directory part allows us to eventually migrate to + such a directory layout under plain Windows without + the need to change libgpg-error. */ + p = strrchr (result, '\\'); + if (p && !strcmp (p+1, "bin")) + *p = 0; + /* Append the static part. */ + strcat (result, SLDIR); + } + } + } + else /* Use the old default value. */ + { + result = malloc (10 + strlen (SLDIR) + 1); + if (result) + { + strcpy (result, "c:\\gnupg"); + strcat (result, SLDIR); + } + } +#undef SLDIR + return result; +} + + +static void +drop_locale_dir (char *locale_dir) +{ + free (locale_dir); +} + + +/* Return the tls object. This function is guaranteed to return a + valid non-NULL object. */ +struct tls_space_s * +get_tls (void) +{ + struct tls_space_s *tls; + + tls = TlsGetValue (tls_index); + if (!tls) + { + /* Called by a thread which existed before this DLL was loaded. + Allocate the space. */ + tls = LocalAlloc (LPTR, sizeof *tls); + if (!tls) + { + /* No way to continue - commit suicide. */ + _gpgrt_abort (); + } + tls->gt_use_utf8 = 0; + TlsSetValue (tls_index, tls); + } + + return tls; +} + + +/* Return the value of the ERRNO variable. This needs to be a + function so that we can have a per-thread ERRNO. This is used only + on WindowsCE because that OS misses an errno. */ +#ifdef HAVE_W32CE_SYSTEM +int +_gpg_w32ce_get_errno (void) +{ + return map_w32codes ( GetLastError () ); +} +#endif /*HAVE_W32CE_SYSTEM*/ + + +/* Replacement strerror function for WindowsCE. */ +#ifdef HAVE_W32CE_SYSTEM +char * +_gpg_w32ce_strerror (int err) +{ + struct tls_space_s *tls = get_tls (); + wchar_t tmpbuf[STRBUFFER_SIZE]; + int n; + + if (err == -1) + err = _gpg_w32ce_get_errno (); + + /* Note: On a German HTC Touch Pro2 device I also tried + LOCALE_USER_DEFAULT and LOCALE_SYSTEM_DEFAULT - both returned + English messages. */ + if (FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, + MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), + tmpbuf, STRBUFFER_SIZE -1, + NULL)) + { + n = WideCharToMultiByte (CP_UTF8, 0, tmpbuf, -1, + tls->strerror_buffer, + sizeof tls->strerror_buffer -1, + NULL, NULL); + } + else + n = -1; + + if (n < 0) + snprintf (tls->strerror_buffer, sizeof tls->strerror_buffer -1, + "[w32err=%d]", err); + return tls->strerror_buffer; +} +#endif /*HAVE_W32CE_SYSTEM*/ + + +/* Entry point called by the DLL loader. */ +#ifdef DLL_EXPORT +int WINAPI +DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserved) +{ + struct tls_space_s *tls; + (void)reserved; + (void)hinst; + + switch (reason) + { + case DLL_PROCESS_ATTACH: + tls_index = TlsAlloc (); + if (tls_index == TLS_OUT_OF_INDEXES) + return FALSE; +#ifndef _GPG_ERR_HAVE_CONSTRUCTOR + /* If we have not constructors (e.g. MSC) we call it here. */ + _gpg_w32__init_gettext_module (); +#endif + /* fallthru. */ + case DLL_THREAD_ATTACH: + tls = LocalAlloc (LPTR, sizeof *tls); + if (!tls) + return FALSE; + tls->gt_use_utf8 = 0; + TlsSetValue (tls_index, tls); + if (reason == DLL_PROCESS_ATTACH) + { + real_init (); + } + break; + + case DLL_THREAD_DETACH: + tls = TlsGetValue (tls_index); + if (tls) + LocalFree (tls); + break; + + case DLL_PROCESS_DETACH: + tls = TlsGetValue (tls_index); + if (tls) + LocalFree (tls); + TlsFree (tls_index); + break; + + default: + break; + } + + return TRUE; +} +#endif /*DLL_EXPORT*/ + +#endif /*HAVE_W32_SYSTEM*/ diff --git a/comm/third_party/libgpg-error/src/init.h b/comm/third_party/libgpg-error/src/init.h new file mode 100644 index 0000000000..90a716a17d --- /dev/null +++ b/comm/third_party/libgpg-error/src/init.h @@ -0,0 +1,70 @@ +/* init.h - Declarations for init.c + Copyright (C) 2010 g10 Code GmbH + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef INIT_H +#define INIT_H + +#if HAVE_W32_SYSTEM + +/* Forward declaration - defined in w32-gettext.c. */ +struct loaded_domain; + +/* An item for a linked list of loaded domains. */ +struct domainlist_s +{ + struct domainlist_s *next; + char *dname; /* Directory name for the mo file. */ + char *fname; /* File name for the MO file. */ + int load_failed; /* True if loading the domain failed. */ + struct loaded_domain *domain; /* NULL if not loaded. Never changed + once set to non-NULL. */ + char name[1]; /* Name of the domain. Never changed + once set. */ +}; + + + +/* 119 bytes for an error message should be enough. With this size we + can assume that the allocation does not take up more than 128 bytes + per thread. Note that this is only used for W32CE. */ +#define STRBUFFER_SIZE 120 + +/* The TLS space definition. */ +struct tls_space_s +{ + /* Flag used by w32-gettext. */ + int gt_use_utf8; + +#ifdef HAVE_W32CE_SYSTEM + char strerror_buffer[STRBUFFER_SIZE]; +#endif +}; + +/* Return the TLS. */ +struct tls_space_s *get_tls (void); + + +/* Explicit constructor for w32-gettext.c */ +#ifndef DLL_EXPORT +void _gpg_w32__init_gettext_module (void); +#endif + +#endif /*HAVE_W32_SYSTEM*/ + +#endif /*INIT_H*/ diff --git a/comm/third_party/libgpg-error/src/lock.h b/comm/third_party/libgpg-error/src/lock.h new file mode 100644 index 0000000000..a830b36b07 --- /dev/null +++ b/comm/third_party/libgpg-error/src/lock.h @@ -0,0 +1,24 @@ +/* lock.h - Declarations for *-lock.c + Copyright (C) 2014 g10 Code GmbH + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef LOCK_H +#define LOCK_H + + +#endif /*LOCK_H*/ diff --git a/comm/third_party/libgpg-error/src/logging.c b/comm/third_party/libgpg-error/src/logging.c new file mode 100644 index 0000000000..e4b7e401d0 --- /dev/null +++ b/comm/third_party/libgpg-error/src/logging.c @@ -0,0 +1,1341 @@ +/* logging.c - Useful logging functions + * Copyright (C) 1998-2001, 2003-2006, 2009-2010, + * 2017 Free Software Foundation, Inc. + * Copyright (C) 1998-1999, 2001-2006, 2008-2017 Werner Koch + * + * This file is part of Libgpg-error. + * + * Libgpg-error is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgpg-error is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <https://www.gnu.org/licenses/>. + * SPDX-License-Identifier: LGPL-2.1+ + * + * This file was originally a part of GnuPG. + */ + +#include <config.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#include <stddef.h> +#include <errno.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#ifdef HAVE_W32_SYSTEM +# ifdef HAVE_WINSOCK2_H +# include <winsock2.h> +# endif +# include <windows.h> +#else /*!HAVE_W32_SYSTEM*/ +# include <sys/socket.h> +# include <sys/un.h> +# include <netinet/in.h> +# include <arpa/inet.h> +#endif /*!HAVE_W32_SYSTEM*/ +#include <unistd.h> +#include <fcntl.h> +/* #include <execinfo.h> */ + +#define _GPGRT_NEED_AFLOCAL 1 +#include "gpgrt-int.h" + + +#ifdef HAVE_W32_SYSTEM +# ifndef S_IRWXG +# define S_IRGRP S_IRUSR +# define S_IWGRP S_IWUSR +# endif +# ifndef S_IRWXO +# define S_IROTH S_IRUSR +# define S_IWOTH S_IWUSR +# endif +#endif + + +#ifdef HAVE_W32CE_SYSTEM +# define isatty(a) (0) +#endif + +#undef WITH_IPV6 +#if defined (AF_INET6) && defined(PF_INET) \ + && defined (INET6_ADDRSTRLEN) && defined(HAVE_INET_PTON) +# define WITH_IPV6 1 +#endif + +#ifndef EAFNOSUPPORT +# define EAFNOSUPPORT EINVAL +#endif +#ifndef INADDR_NONE /* Slowaris is missing that. */ +#define INADDR_NONE ((unsigned long)(-1)) +#endif /*INADDR_NONE*/ + +#ifdef HAVE_W32_SYSTEM +#define sock_close(a) closesocket(a) +#else +#define sock_close(a) close(a) +#endif + + +static estream_t logstream; +static int log_socket = -1; +static char prefix_buffer[80]; +static int with_time; +static int with_prefix; +static int with_pid; +#ifdef HAVE_W32_SYSTEM +static int no_registry; +#endif +static int (*get_pid_suffix_cb)(unsigned long *r_value); +static const char * (*socket_dir_cb)(void); +static int running_detached; +static int force_prefixes; + +static int missing_lf; +static int errorcount; + + +/* An object to convey data to the fmt_string_filter. */ +struct fmt_string_filter_s +{ + char *last_result; +}; + + + +/* Get the error count as maintained by the log fucntions. With CLEAR + * set reset the counter. */ +int +_gpgrt_get_errorcount (int clear) +{ + int n = errorcount; + if (clear) + errorcount = 0; + return n; +} + + +/* Increment the error count as maintained by the log functions. */ +void +_gpgrt_inc_errorcount (void) +{ + /* Protect against counter overflow. */ + if (errorcount < 30000) + errorcount++; +} + + +/* The following 3 functions are used by _gpgrt_fopencookie to write logs + to a socket. */ +struct fun_cookie_s +{ + int fd; + int quiet; + int want_socket; + int is_socket; +#ifdef HAVE_W32CE_SYSTEM + int use_writefile; +#endif + char name[1]; +}; + + +/* Write NBYTES of BUFFER to file descriptor FD. */ +static int +writen (int fd, const void *buffer, size_t nbytes, int is_socket) +{ + const char *buf = buffer; + size_t nleft = nbytes; + int nwritten; +#ifndef HAVE_W32_SYSTEM + (void)is_socket; /* Not required. */ +#endif + + while (nleft > 0) + { +#ifdef HAVE_W32_SYSTEM + if (is_socket) + nwritten = send (fd, buf, nleft, 0); + else +#endif + nwritten = write (fd, buf, nleft); + + if (nwritten < 0 && errno == EINTR) + continue; + if (nwritten < 0) + return -1; + nleft -= nwritten; + buf = buf + nwritten; + } + + return 0; +} + + +/* Returns true if STR represents a valid port number in decimal + notation and no garbage is following. */ +static int +parse_portno (const char *str, unsigned short *r_port) +{ + unsigned int value; + + for (value=0; *str && (*str >= '0' && *str <= '9'); str++) + { + value = value * 10 + (*str - '0'); + if (value > 65535) + return 0; + } + if (*str || !value) + return 0; + + *r_port = value; + return 1; +} + + +static gpgrt_ssize_t +fun_writer (void *cookie_arg, const void *buffer, size_t size) +{ + struct fun_cookie_s *cookie = cookie_arg; + + /* FIXME: Use only estream with a callback for socket writing. This + avoids the ugly mix of fd and estream code. */ + + /* Note that we always try to reconnect to the socket but print + error messages only the first time an error occurred. If + RUNNING_DETACHED is set we don't fall back to stderr and even do + not print any error messages. This is needed because detached + processes often close stderr and by writing to file descriptor 2 + we might send the log message to a file not intended for logging + (e.g. a pipe or network connection). */ + if (cookie->want_socket && cookie->fd == -1) + { +#ifdef WITH_IPV6 + struct sockaddr_in6 srvr_addr_in6; +#endif + struct sockaddr_in srvr_addr_in; +#ifndef HAVE_W32_SYSTEM + struct sockaddr_un srvr_addr_un; +#endif + const char *name_for_err = ""; + size_t addrlen; + struct sockaddr *srvr_addr = NULL; + unsigned short port = 0; + int af = AF_LOCAL; + int pf = PF_LOCAL; + const char *name = cookie->name; + + /* Not yet open or meanwhile closed due to an error. */ + cookie->is_socket = 0; + + /* Check whether this is a TCP socket or a local socket. */ + if (!strncmp (name, "tcp://", 6) && name[6]) + { + name += 6; + af = AF_INET; + pf = PF_INET; + } +#ifndef HAVE_W32_SYSTEM + else if (!strncmp (name, "socket://", 9)) + name += 9; +#endif + + if (af == AF_LOCAL) + { + addrlen = 0; +#ifndef HAVE_W32_SYSTEM + memset (&srvr_addr, 0, sizeof srvr_addr); + srvr_addr_un.sun_family = af; + if (!*name) + { + if ((name = socket_dir_cb ()) && *name + && strlen (name) + 7 < sizeof (srvr_addr_un.sun_path)-1) + { + strncpy (srvr_addr_un.sun_path, + name, sizeof (srvr_addr_un.sun_path)-1); + strcat (srvr_addr_un.sun_path, "/S.log"); + srvr_addr_un.sun_path[sizeof (srvr_addr_un.sun_path)-1] = 0; + srvr_addr = (struct sockaddr *)&srvr_addr_un; + addrlen = SUN_LEN (&srvr_addr_un); + name_for_err = srvr_addr_un.sun_path; + } + } + else + { + if (strlen (name) < sizeof (srvr_addr_un.sun_path)-1) + { + strncpy (srvr_addr_un.sun_path, + name, sizeof (srvr_addr_un.sun_path)-1); + srvr_addr_un.sun_path[sizeof (srvr_addr_un.sun_path)-1] = 0; + srvr_addr = (struct sockaddr *)&srvr_addr_un; + addrlen = SUN_LEN (&srvr_addr_un); + } + } +#endif /*!HAVE_W32SYSTEM*/ + } + else + { + char *addrstr, *p; +#ifdef HAVE_INET_PTON + void *addrbuf = NULL; +#endif /*HAVE_INET_PTON*/ + + addrstr = _gpgrt_malloc (strlen (name) + 1); + if (!addrstr) + addrlen = 0; /* This indicates an error. */ + else if (*name == '[') + { + /* Check for IPv6 literal address. */ + strcpy (addrstr, name+1); + p = strchr (addrstr, ']'); + if (!p || p[1] != ':' || !parse_portno (p+2, &port)) + { + _gpg_err_set_errno (EINVAL); + addrlen = 0; + } + else + { + *p = 0; +#ifdef WITH_IPV6 + af = AF_INET6; + pf = PF_INET6; + memset (&srvr_addr_in6, 0, sizeof srvr_addr_in6); + srvr_addr_in6.sin6_family = af; + srvr_addr_in6.sin6_port = htons (port); +#ifdef HAVE_INET_PTON + addrbuf = &srvr_addr_in6.sin6_addr; +#endif /*HAVE_INET_PTON*/ + srvr_addr = (struct sockaddr *)&srvr_addr_in6; + addrlen = sizeof srvr_addr_in6; +#else + _gpg_err_set_errno (EAFNOSUPPORT); + addrlen = 0; +#endif + } + } + else + { + /* Check for IPv4 literal address. */ + strcpy (addrstr, name); + p = strchr (addrstr, ':'); + if (!p || !parse_portno (p+1, &port)) + { + _gpg_err_set_errno (EINVAL); + addrlen = 0; + } + else + { + *p = 0; + memset (&srvr_addr_in, 0, sizeof srvr_addr_in); + srvr_addr_in.sin_family = af; + srvr_addr_in.sin_port = htons (port); +#ifdef HAVE_INET_PTON + addrbuf = &srvr_addr_in.sin_addr; +#endif /*HAVE_INET_PTON*/ + srvr_addr = (struct sockaddr *)&srvr_addr_in; + addrlen = sizeof srvr_addr_in; + } + } + + if (addrlen) + { +#ifdef HAVE_INET_PTON + if (inet_pton (af, addrstr, addrbuf) != 1) + addrlen = 0; +#else /*!HAVE_INET_PTON*/ + /* We need to use the old function. If we are here v6 + support isn't enabled anyway and thus we can do fine + without. Note that Windows has a compatible inet_pton + function named inetPton, but only since Vista. */ + srvr_addr_in.sin_addr.s_addr = inet_addr (addrstr); + if (srvr_addr_in.sin_addr.s_addr == INADDR_NONE) + addrlen = 0; +#endif /*!HAVE_INET_PTON*/ + } + + _gpgrt_free (addrstr); + } + + cookie->fd = addrlen? socket (pf, SOCK_STREAM, 0) : -1; + if (cookie->fd == -1) + { + if (!cookie->quiet && !running_detached + && isatty (_gpgrt_fileno (es_stderr))) + _gpgrt_fprintf (es_stderr, + "failed to create socket for logging: %s\n", + strerror (errno)); + } + else + { + if (connect (cookie->fd, srvr_addr, addrlen) == -1) + { + if (!cookie->quiet && !running_detached + && isatty (_gpgrt_fileno (es_stderr))) + _gpgrt_fprintf (es_stderr, "can't connect to '%s%s': %s\n", + cookie->name, name_for_err, strerror(errno)); + sock_close (cookie->fd); + cookie->fd = -1; + } + } + + if (cookie->fd == -1) + { + if (!running_detached) + { + /* Due to all the problems with apps not running + detached but being called with stderr closed or used + for a different purposes, it does not make sense to + switch to stderr. We therefore disable it. */ + if (!cookie->quiet) + { + /* fputs ("switching logging to stderr\n", stderr);*/ + cookie->quiet = 1; + } + cookie->fd = -1; /*fileno (stderr);*/ + } + } + else /* Connection has been established. */ + { + cookie->quiet = 0; + cookie->is_socket = 1; + } + } + + log_socket = cookie->fd; + if (cookie->fd != -1) + { +#ifdef HAVE_W32CE_SYSTEM + if (cookie->use_writefile) + { + DWORD nwritten; + + WriteFile ((HANDLE)cookie->fd, buffer, size, &nwritten, NULL); + return (gpgrt_ssize_t)size; /* Okay. */ + } +#endif + if (!writen (cookie->fd, buffer, size, cookie->is_socket)) + return (gpgrt_ssize_t)size; /* Okay. */ + } + + if (!running_detached && cookie->fd != -1 + && isatty (_gpgrt_fileno (es_stderr))) + { + if (*cookie->name) + _gpgrt_fprintf (es_stderr, "error writing to '%s': %s\n", + cookie->name, strerror(errno)); + else + _gpgrt_fprintf (es_stderr, "error writing to file descriptor %d: %s\n", + cookie->fd, strerror(errno)); + } + if (cookie->is_socket && cookie->fd != -1) + { + sock_close (cookie->fd); + cookie->fd = -1; + log_socket = -1; + } + + return (gpgrt_ssize_t)size; +} + + +static int +fun_closer (void *cookie_arg) +{ + struct fun_cookie_s *cookie = cookie_arg; + + if (cookie->fd != -1 && cookie->fd != 2) + sock_close (cookie->fd); + _gpgrt_free (cookie); + log_socket = -1; + return 0; +} + + +/* Common function to either set the logging to a file or a file + descriptor. */ +static void +set_file_fd (const char *name, int fd, estream_t stream) +{ + estream_t fp; + int want_socket = 0; +#ifdef HAVE_W32CE_SYSTEM + int use_writefile = 0; +#endif + struct fun_cookie_s *cookie; + + /* Close an open log stream. */ + if (logstream) + { + if (logstream != es_stderr) + _gpgrt_fclose (logstream); + logstream = NULL; + } + + if (stream) + { + /* We don't use a cookie to log directly to a stream. */ + fp = stream; + goto leave; + } + + /* Figure out what kind of logging we want. */ + if (name && !strcmp (name, "-")) + { + name = NULL; + fd = _gpgrt_fileno (es_stderr); + } + + if (name && !strncmp (name, "tcp://", 6) && name[6]) + want_socket = 1; +#ifndef HAVE_W32_SYSTEM + else if (name && !strncmp (name, "socket://", 9)) + want_socket = 2; +#endif /*HAVE_W32_SYSTEM*/ +#ifdef HAVE_W32CE_SYSTEM + else if (name && !strcmp (name, "GPG2:")) + { + HANDLE hd; + + ActivateDevice (L"Drivers\\"GNUPG_NAME"_Log", 0); + /* Ignore a filename and write the debug output to the GPG2: + device. */ + hd = CreateFile (L"GPG2:", GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + fd = (hd == INVALID_HANDLE_VALUE)? -1 : (int)hd; + name = NULL; + force_prefixes = 1; + use_writefile = 1; + } +#endif /*HAVE_W32CE_SYSTEM*/ + + /* Setup a new stream. */ + + cookie = _gpgrt_malloc (sizeof *cookie + (name? strlen (name):0)); + if (!cookie) + return; /* oops */ + strcpy (cookie->name, name? name:""); + cookie->quiet = 0; + cookie->is_socket = 0; + cookie->want_socket = want_socket; +#ifdef HAVE_W32CE_SYSTEM + cookie->use_writefile = use_writefile; +#endif + if (!name) + cookie->fd = fd; + else if (want_socket) + cookie->fd = -1; + else + { + do + cookie->fd = open (name, O_WRONLY|O_APPEND|O_CREAT, + (S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWGRP|S_IWOTH)); + while (cookie->fd == -1 && errno == EINTR); + } + log_socket = cookie->fd; + + { + es_cookie_io_functions_t io = { NULL }; + io.func_write = fun_writer; + io.func_close = fun_closer; + + fp = _gpgrt_fopencookie (cookie, "w", io); + } + + /* On error default to a stderr based estream. */ + if (!fp) + fp = es_stderr; + + leave: + _gpgrt_setvbuf (fp, NULL, _IOLBF, 0); + + logstream = fp; + + /* We always need to print the prefix and the pid for socket mode, + so that the server reading the socket can do something + meaningful. */ + force_prefixes = want_socket; + + missing_lf = 0; +} + + +/* Set the file to write log to. The special names NULL and "-" may + * be used to select stderr and names formatted like + * "socket:///home/foo/mylogs" may be used to write the logging to the + * socket "/home/foo/mylogs". If the connection to the socket fails + * or a write error is detected, the function writes to stderr and + * tries the next time again to connect the socket. Calling this + * function with (NULL, NULL, -1) sets the default sink. + * Warning: This function is not thread-safe. + */ +void +_gpgrt_log_set_sink (const char *name, estream_t stream, int fd) +{ + if (name && !stream && fd == -1) + set_file_fd (name, -1, NULL); + else if (!name && !stream && fd != -1) + { + if (!_gpgrt_fd_valid_p (fd)) + _gpgrt_log_fatal ("gpgrt_log_set_sink: fd is invalid: %s\n", + strerror (errno)); + set_file_fd (NULL, fd, NULL); + } + else if (!name && stream && fd == -1) + { + set_file_fd (NULL, -1, stream); + } + else /* default */ + set_file_fd ("-", -1, NULL); +} + + +/* Set a function to retrieve the directory name of a socket if + * only "socket://" has been given to log_set_file. + * Warning: This function is not thread-safe. */ +void +_gpgrt_log_set_socket_dir_cb (const char *(*fnc)(void)) +{ + socket_dir_cb = fnc; +} + + +/* Warning: This function is not thread-safe. */ +void +_gpgrt_log_set_pid_suffix_cb (int (*cb)(unsigned long *r_value)) +{ + get_pid_suffix_cb = cb; +} + + +/* Warning: Changing TEXT is not thread-safe. Changing only flags + * might be thread-safe. */ +void +_gpgrt_log_set_prefix (const char *text, unsigned int flags) +{ + if (text) + { + strncpy (prefix_buffer, text, sizeof (prefix_buffer)-1); + prefix_buffer[sizeof (prefix_buffer)-1] = 0; + } + + with_prefix = (flags & GPGRT_LOG_WITH_PREFIX); + with_time = (flags & GPGRT_LOG_WITH_TIME); + with_pid = (flags & GPGRT_LOG_WITH_PID); + running_detached = (flags & GPGRT_LOG_RUN_DETACHED); +#ifdef HAVE_W32_SYSTEM + no_registry = (flags & GPGRT_LOG_NO_REGISTRY); +#endif +} + + +const char * +_gpgrt_log_get_prefix (unsigned int *flags) +{ + if (flags) + { + *flags = 0; + if (with_prefix) + *flags |= GPGRT_LOG_WITH_PREFIX; + if (with_time) + *flags |= GPGRT_LOG_WITH_TIME; + if (with_pid) + *flags |= GPGRT_LOG_WITH_PID; + if (running_detached) + *flags |= GPGRT_LOG_RUN_DETACHED; +#ifdef HAVE_W32_SYSTEM + if (no_registry) + *flags |= GPGRT_LOG_NO_REGISTRY; +#endif + } + return prefix_buffer; +} + +/* This function returns true if the file descriptor FD is in use for + * logging. This is preferable over a test using log_get_fd in that + * it allows the logging code to use more then one file descriptor. */ +int +_gpgrt_log_test_fd (int fd) +{ + if (logstream) + { + int tmp = _gpgrt_fileno (logstream); + if ( tmp != -1 && tmp == fd) + return 1; + } + if (log_socket != -1 && log_socket == fd) + return 1; + return 0; +} + +int +_gpgrt_log_get_fd () +{ + return logstream? _gpgrt_fileno (logstream) : -1; +} + +estream_t +_gpgrt_log_get_stream () +{ + if (!logstream) + { + /* Make sure a log stream has been set. */ + _gpgrt_log_set_sink (NULL, NULL, -1); + if (!logstream) + { + fputs ("gpgrt fatal: failed to init log stream\n", stderr); + _gpgrt_abort (); + } + } + return logstream; +} + + +/* A filter used with the fprintf_sf function to sanitize the args for + * "%s" format specifiers. */ +static char * +fmt_string_filter (const char *string, int no, void *opaque) +{ + struct fmt_string_filter_s *state = opaque; + const unsigned char *p; + size_t buflen; + char *d; + int any; + + if (no == -1) + { + /* The printf engine asked us to release resources. */ + if (state->last_result) + { + _gpgrt_free (state->last_result); + state->last_result = NULL; + } + return NULL; + } + + if (!string) + return NULL; /* Nothing to filter - printf handles NULL nicely. */ + + /* Check whether escaping is needed and count needed length. */ + any = 0; + buflen = 1; + for (p = (const unsigned char *)string; *p; p++) + { + switch (*p) + { + case '\n': + case '\r': + case '\f': + case '\v': + case '\b': + case '\t': + case '\a': + case '\\': + buflen += 2; + any = 1; + break; + default: + if (*p < 0x20 || *p == 0x7f) + { + buflen += 5; + any = 1; + } + else + buflen++; + } + } + if (!any) + return (char*)string; /* Nothing to escape. */ + + /* Create a buffer and escape the input. */ + _gpgrt_free (state->last_result); + state->last_result = _gpgrt_malloc (buflen); + if (!state->last_result) + return "[out_of_core_in_format_string_filter]"; + + d = state->last_result; + for (p = (const unsigned char *)string; *p; p++) + { + switch (*p) + { + case '\n': *d++ = '\\'; *d++ = 'n'; break; + case '\r': *d++ = '\\'; *d++ = 'r'; break; + case '\f': *d++ = '\\'; *d++ = 'f'; break; + case '\v': *d++ = '\\'; *d++ = 'v'; break; + case '\b': *d++ = '\\'; *d++ = 'b'; break; + case '\t': *d++ = '\\'; *d++ = 't'; break; + case '\a': *d++ = '\\'; *d++ = 'a'; break; + case '\\': *d++ = '\\'; *d++ = '\\'; break; + + default: + if (*p < 0x20 || *p == 0x7f) + { + snprintf (d, 5, "\\x%02x", *p); + d += 4; + } + else + *d++ = *p; + } + } + *d = 0; + return state->last_result; +} + + +/* Note: LOGSTREAM is expected to be locked. */ +static int +print_prefix (int level, int leading_backspace) +{ + int rc; + int length = 0; + + if (level != GPGRT_LOGLVL_CONT) + { /* Note this does not work for multiple line logging as we would + * need to print to a buffer first */ + if (with_time && !force_prefixes) + { + struct tm *tp; + time_t atime = time (NULL); + + tp = localtime (&atime); + rc = _gpgrt_fprintf_unlocked (logstream, + "%04d-%02d-%02d %02d:%02d:%02d ", + 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday, + tp->tm_hour, tp->tm_min, tp->tm_sec ); + if (rc > 0) + length += rc; + } + if (with_prefix || force_prefixes) + { + _gpgrt_fputs_unlocked (prefix_buffer, logstream); + length += strlen (prefix_buffer); + } + if (with_pid || force_prefixes) + { + unsigned long pidsuf; + int pidfmt; + + if (get_pid_suffix_cb && (pidfmt=get_pid_suffix_cb (&pidsuf))) + rc = _gpgrt_fprintf_unlocked (logstream, + pidfmt == 1? "[%u.%lu]":"[%u.%lx]", + (unsigned int)getpid (), pidsuf); + else + rc = _gpgrt_fprintf_unlocked (logstream, "[%u]", + (unsigned int)getpid ()); + if (rc > 0) + length += rc; + } + if ((!with_time && (with_prefix || with_pid)) || force_prefixes) + { + _gpgrt_putc_unlocked (':', logstream); + length++; + } + /* A leading backspace suppresses the extra space so that we can + correctly output, programname, filename and linenumber. */ + if (!leading_backspace + && (with_time || with_prefix || with_pid || force_prefixes)) + { + _gpgrt_putc_unlocked (' ', logstream); + length++; + } + } + + switch (level) + { + case GPGRT_LOGLVL_BEGIN: break; + case GPGRT_LOGLVL_CONT: break; + case GPGRT_LOGLVL_INFO: break; + case GPGRT_LOGLVL_WARN: break; + case GPGRT_LOGLVL_ERROR: break; + case GPGRT_LOGLVL_FATAL: + _gpgrt_fputs_unlocked ("Fatal: ", logstream); + length += 7; + break; + case GPGRT_LOGLVL_BUG: + _gpgrt_fputs_unlocked ("Ohhhh jeeee: ", logstream); + length += 13; + break; + case GPGRT_LOGLVL_DEBUG: + _gpgrt_fputs_unlocked ("DBG: ", logstream); + length += 5; + break; + default: + rc = _gpgrt_fprintf_unlocked (logstream, + "[Unknown log level %d]: ", level); + if (rc > 0) + length += rc; + break; + } + + return length; +} + + +/* Internal worker function. Exported so that we can use it in + * visibility.c. Returs the number of characters printed or 0 if the + * line ends in a LF. */ +int +_gpgrt_logv_internal (int level, int ignore_arg_ptr, const char *extrastring, + const char *prefmt, const char *fmt, va_list arg_ptr) +{ + int leading_backspace = (fmt && *fmt == '\b'); + int length; + int rc; + + if (!logstream) + { +#ifdef HAVE_W32_SYSTEM + char *tmp; + + tmp = (no_registry + ? NULL + : _gpgrt_w32_reg_query_string (NULL, "Software\\\\GNU\\\\GnuPG", + "DefaultLogFile")); + _gpgrt_log_set_sink (tmp && *tmp? tmp : NULL, NULL, -1); + _gpgrt_free (tmp); +#else + /* Make sure a log stream has been set. */ + _gpgrt_log_set_sink (NULL, NULL, -1); +#endif + if (!logstream) + { + fputs ("gpgrt fatal: failed to init log stream\n", stderr); + _gpgrt_abort (); + } + } + + _gpgrt_flockfile (logstream); + if (missing_lf && level != GPGRT_LOGLVL_CONT) + _gpgrt_putc_unlocked ('\n', logstream ); + missing_lf = 0; + + length = print_prefix (level, leading_backspace); + if (leading_backspace) + fmt++; + + if (fmt) + { + if (prefmt) + { + _gpgrt_fputs_unlocked (prefmt, logstream); + length += strlen (prefmt); + } + + if (ignore_arg_ptr) + { /* This is used by log_string and comes with the extra + * feature that after a LF the next line is indent at the + * length of the prefix. Note that we do not yet include + * the length of the timestamp and pid in the indent + * computation. */ + const char *p, *pend; + + for (p = fmt; (pend = strchr (p, '\n')); p = pend+1) + { + rc = _gpgrt_fprintf_unlocked (logstream, "%*s%.*s", + (int)((p != fmt + && (with_prefix || force_prefixes)) + ?strlen (prefix_buffer)+2:0), "", + (int)(pend - p)+1, p); + if (rc > 0) + length += rc; + } + _gpgrt_fputs_unlocked (p, logstream); + length += strlen (p); + } + else + { + struct fmt_string_filter_s sf = {NULL}; + + rc = _gpgrt_vfprintf_unlocked (logstream, fmt_string_filter, &sf, + fmt, arg_ptr); + if (rc > 0) + length += rc; + } + + if (*fmt && fmt[strlen(fmt)-1] != '\n') + missing_lf = 1; + } + + /* If we have an EXTRASTRING print it now while we still hold the + * lock on the logstream. */ + if (extrastring) + { + int c; + + if (missing_lf) + { + _gpgrt_putc_unlocked ('\n', logstream); + missing_lf = 0; + length = 0; + } + length += print_prefix (level, leading_backspace); + _gpgrt_fputs_unlocked (">> ", logstream); + length += 3; + missing_lf = 1; + while ((c = *extrastring++)) + { + missing_lf = 1; + if (c == '\\') + { + _gpgrt_fputs_unlocked ("\\\\", logstream); + length += 2; + } + else if (c == '\r') + { + _gpgrt_fputs_unlocked ("\\r", logstream); + length += 2; + } + else if (c == '\n') + { + _gpgrt_fputs_unlocked ("\\n\n", logstream); + length = 0; + if (*extrastring) + { + length += print_prefix (level, leading_backspace); + _gpgrt_fputs_unlocked (">> ", logstream); + length += 3; + } + else + missing_lf = 0; + } + else + { + _gpgrt_putc_unlocked (c, logstream); + length++; + } + } + if (missing_lf) + { + _gpgrt_putc_unlocked ('\n', logstream); + length = 0; + missing_lf = 0; + } + } + + if (level == GPGRT_LOGLVL_FATAL) + { + if (missing_lf) + _gpgrt_putc_unlocked ('\n', logstream); + _gpgrt_funlockfile (logstream); + exit (2); + } + else if (level == GPGRT_LOGLVL_BUG) + { + if (missing_lf) + _gpgrt_putc_unlocked ('\n', logstream ); + _gpgrt_funlockfile (logstream); + /* Using backtrace requires a configure test and to pass + * -rdynamic to gcc. Thus we do not enable it now. */ + /* { */ + /* void *btbuf[20]; */ + /* int btidx, btlen; */ + /* char **btstr; */ + + /* btlen = backtrace (btbuf, DIM (btbuf)); */ + /* btstr = backtrace_symbols (btbuf, btlen); */ + /* if (btstr) */ + /* for (btidx=0; btidx < btlen; btidx++) */ + /* log_debug ("[%d] %s\n", btidx, btstr[btidx]); */ + /* } */ + _gpgrt_abort (); + } + else + _gpgrt_funlockfile (logstream); + + /* Bumb the error counter for log_error. */ + if (level == GPGRT_LOGLVL_ERROR) + _gpgrt_inc_errorcount (); + + return length; +} + + +void +_gpgrt_log (int level, const char *fmt, ...) +{ + va_list arg_ptr ; + + va_start (arg_ptr, fmt) ; + _gpgrt_logv_internal (level, 0, NULL, NULL, fmt, arg_ptr); + va_end (arg_ptr); +} + + +void +_gpgrt_logv (int level, const char *fmt, va_list arg_ptr) +{ + _gpgrt_logv_internal (level, 0, NULL, NULL, fmt, arg_ptr); +} + + +/* Same as log_logv but PREFIX is printed immediately before FMT. + * Note that PREFIX is an additional string and independent of the + * prefix set by gpgrt_log_set_prefix. */ +void +_gpgrt_logv_prefix (int level, const char *prefix, + const char *fmt, va_list arg_ptr) +{ + _gpgrt_logv_internal (level, 0, NULL, prefix, fmt, arg_ptr); +} + + +static void +do_log_ignore_arg (int level, const char *str, ...) +{ + va_list arg_ptr; + va_start (arg_ptr, str); + _gpgrt_logv_internal (level, 1, NULL, NULL, str, arg_ptr); + va_end (arg_ptr); +} + + +/* Log STRING at LEVEL but indent from the second line on by the + * length of the prefix. */ +void +_gpgrt_log_string (int level, const char *string) +{ + /* We need a dummy arg_ptr, but there is no portable way to create + * one. So we call the _gpgrt_logv_internal function through a + * variadic wrapper. */ + do_log_ignore_arg (level, string); +} + + +void +_gpgrt_log_info (const char *fmt, ...) +{ + va_list arg_ptr ; + + va_start (arg_ptr, fmt); + _gpgrt_logv_internal (GPGRT_LOGLVL_INFO, 0, NULL, NULL, fmt, arg_ptr); + va_end (arg_ptr); +} + + +void +_gpgrt_log_error (const char *fmt, ...) +{ + va_list arg_ptr ; + + va_start (arg_ptr, fmt); + _gpgrt_logv_internal (GPGRT_LOGLVL_ERROR, 0, NULL, NULL, fmt, arg_ptr); + va_end (arg_ptr); +} + + +void +_gpgrt_log_fatal (const char *fmt, ...) +{ + va_list arg_ptr ; + + va_start (arg_ptr, fmt); + _gpgrt_logv_internal (GPGRT_LOGLVL_FATAL, 0, NULL, NULL, fmt, arg_ptr); + va_end (arg_ptr); + _gpgrt_abort (); /* Never called; just to make the compiler happy. */ +} + + +void +_gpgrt_log_bug (const char *fmt, ...) +{ + va_list arg_ptr ; + + va_start (arg_ptr, fmt); + _gpgrt_logv_internal (GPGRT_LOGLVL_BUG, 0, NULL, NULL, fmt, arg_ptr); + va_end (arg_ptr); + _gpgrt_abort (); /* Never called; just to make the compiler happy. */ +} + + +void +_gpgrt_log_debug (const char *fmt, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, fmt); + _gpgrt_logv_internal (GPGRT_LOGLVL_DEBUG, 0, NULL, NULL, fmt, arg_ptr); + va_end (arg_ptr); +} + + +/* The same as log_debug but at the end of the output STRING is + * printed with LFs expanded to include the prefix and a final --end-- + * marker. */ +void +_gpgrt_log_debug_string (const char *string, const char *fmt, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, fmt); + _gpgrt_logv_internal (GPGRT_LOGLVL_DEBUG, 0, string, NULL, fmt, arg_ptr); + va_end (arg_ptr); +} + + +void +_gpgrt_log_printf (const char *fmt, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, fmt); + _gpgrt_logv_internal (fmt ? GPGRT_LOGLVL_CONT : GPGRT_LOGLVL_BEGIN, + 0, NULL, NULL, fmt, arg_ptr); + va_end (arg_ptr); +} + + +/* Flush the log - this is useful to make sure that the trailing + linefeed has been printed. */ +void +_gpgrt_log_flush (void) +{ + do_log_ignore_arg (GPGRT_LOGLVL_CONT, NULL); +} + + +/* Print a hexdump of (BUFFER,LENGTH). With FMT passed as NULL print + * just the raw dump (in this case ARG_PTR is not used), with FMT + * being an empty string, print a trailing linefeed, otherwise print + * an entire debug line with the expanded FMT followed by a possible + * wrapped hexdump and a final LF. */ +void +_gpgrt_logv_printhex (const void *buffer, size_t length, + const char *fmt, va_list arg_ptr) +{ + int wrap = 0; + int cnt = 0; + const unsigned char *p; + + /* FIXME: This printing is not yet protected by _gpgrt_flockfile. */ + if (fmt && *fmt) + { + _gpgrt_logv_internal (GPGRT_LOGLVL_DEBUG, 0, NULL, NULL, fmt, arg_ptr); + wrap = 1; + } + + if (length) + { + if (wrap) + _gpgrt_log_printf (" "); + + for (p = buffer; length--; p++) + { + _gpgrt_log_printf ("%02x", *p); + if (wrap && ++cnt == 32 && length) + { + cnt = 0; + /* (we indicate continuations with a backslash) */ + _gpgrt_log_printf (" \\\n"); + _gpgrt_log_debug ("%s", ""); + if (fmt && *fmt) + _gpgrt_log_printf (" "); + } + } + } + + if (fmt) + _gpgrt_log_printf ("\n"); +} + + +/* Print a hexdump of (BUFFER,LENGTH). With FMT passed as NULL print + * just the raw dump, with FMT being an empty string, print a trailing + * linefeed, otherwise print an entire debug line with the expanded + * FMT followed by the hexdump and a final LF. */ +void +_gpgrt_log_printhex (const void *buffer, size_t length, + const char *fmt, ...) +{ + va_list arg_ptr; + + if (fmt) + { + va_start (arg_ptr, fmt); + _gpgrt_logv_printhex (buffer, length, fmt, arg_ptr); + va_end (arg_ptr); + } + else + { + /* va_list is not necessary a pointer and thus we can't use NULL + * because that would conflict with platforms using a straight + * struct for it (e.g. arm64). We use a dummy variable instead; + * the static is a simple way zero it out so to not get + * complains about uninitialized use. */ + static va_list dummy_argptr; + + _gpgrt_logv_printhex (buffer, length, NULL, dummy_argptr); + } +} + + +/* Print a microsecond timestamp followed by FMT. */ +void +_gpgrt_logv_clock (const char *fmt, va_list arg_ptr) +{ +#if ENABLE_LOG_CLOCK + static unsigned long long initial; + struct timespec tv; + unsigned long long now; + char clockbuf[50]; + + if (clock_gettime (CLOCK_REALTIME, &tv)) + { + _gpgrt_log_debug ("error getting the realtime clock value\n"); + return; + } + now = tv.tv_sec * 1000000000ull; + now += tv.tv_nsec; + + if (!initial) + initial = now; + + snprintf (clockbuf, sizeof clockbuf, "[%6llu] ", (now - initial)/1000); + _gpgrt_logv_internal (GPGRT_LOGLVL_DEBUG, 0, NULL, clockbuf, fmt, arg_ptr); + +#else /*!ENABLE_LOG_CLOCK*/ + + /* You may need to link with -ltr to use the above code. */ + + _gpgrt_logv_internal (GPGRT_LOGLVL_DEBUG, + 0, NULL, "[no clock] ", fmt, arg_ptr); + +#endif /*!ENABLE_LOG_CLOCK*/ +} + + +/* Print a microsecond timestamp followed by FMT. */ +void +_gpgrt_log_clock (const char *fmt, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, fmt); + _gpgrt_logv_clock (fmt, arg_ptr); + va_end (arg_ptr); +} + + +void +_gpgrt__log_assert (const char *expr, const char *file, + int line, const char *func) +{ +#ifdef GPGRT_HAVE_MACRO_FUNCTION + _gpgrt_log (GPGRT_LOGLVL_BUG, "Assertion \"%s\" in %s failed (%s:%d)\n", + expr, func, file, line); +#else /*!GPGRT_HAVE_MACRO_FUNCTION*/ + _gpgrt_log (GPGRT_LOGLVL_BUG, "Assertion \"%s\" failed (%s:%d)\n", + expr, file, line); +#endif /*!GPGRT_HAVE_MACRO_FUNCTION*/ + _gpgrt_abort (); /* Never called; just to make the compiler happy. */ +} diff --git a/comm/third_party/libgpg-error/src/mkerrcodes.awk b/comm/third_party/libgpg-error/src/mkerrcodes.awk new file mode 100644 index 0000000000..e9c857c62f --- /dev/null +++ b/comm/third_party/libgpg-error/src/mkerrcodes.awk @@ -0,0 +1,99 @@ +# mkerrcodes.awk +# Copyright (C) 2004, 2005 g10 Code GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +# +# As a special exception, g10 Code GmbH gives unlimited permission to +# copy, distribute and modify the C source files that are the output +# of mkerrcodes.awk. You need not follow the terms of the GNU General +# Public License when using or distributing such scripts, even though +# portions of the text of mkerrcodes.awk appear in them. The GNU +# General Public License (GPL) does govern all other use of the material +# that constitutes the mkerrcodes.awk program. +# +# Certain portions of the mkerrcodes.awk source text are designed to be +# copied (in certain cases, depending on the input) into the output of +# mkerrcodes.awk. We call these the "data" portions. The rest of the +# mkerrcodes.awk source text consists of comments plus executable code +# that decides which of the data portions to output in any given case. +# We call these comments and executable code the "non-data" portions. +# mkerrcodes.h never copies any of the non-data portions into its output. +# +# This special exception to the GPL applies to versions of mkerrcodes.awk +# released by g10 Code GmbH. When you make and distribute a modified version +# of mkerrcodes.awk, you may extend this special exception to the GPL to +# apply to your modified version as well, *unless* your modified version +# has the potential to copy into its output some of the text that was the +# non-data portion of the version that you started with. (In other words, +# unless your change moves or copies text from the non-data portions to the +# data portions.) If your modification has such potential, you must delete +# any notice of this special exception to the GPL from your modified version. + +# This script outputs an intermediate file that contains the following output: +# static struct +# { +# int err; +# const char *err_sym; +# } err_table[] = +# { +# { 7, "GPG_ERR_E2BIG" }, +# [...] +# }; +# +# The input file is a list of possible system errors, followed by a GPG_ERR_* name: +# +# 7 GPG_ERR_E2BIG +# +# Comments (starting with # and ending at the end of the line) are removed, +# as is trailing whitespace. + +BEGIN { + FS="[ \t]+GPG_ERR_"; + print "/* Output of mkerrcodes.awk. DO NOT EDIT. */"; + print ""; + header = 1; +} + +/^#/ { next; } + +header { + if (! /^[ \t]*$/) + { + header = 0; + + print "static struct"; + print " {"; + print " int err;"; + print " const char *err_sym;"; + print " } err_table[] = "; + print "{"; + } + else + print; +} + +!header { + sub (/#.+/, ""); + sub (/[ ]+$/, ""); # Strip trailing space and tab characters. + + if (/^$/) + next; + + print " { " $1 ", \"GPG_ERR_" $2 "\" },"; +} + +END { + print "};"; +} diff --git a/comm/third_party/libgpg-error/src/mkerrcodes.c b/comm/third_party/libgpg-error/src/mkerrcodes.c new file mode 100644 index 0000000000..29c1cc270b --- /dev/null +++ b/comm/third_party/libgpg-error/src/mkerrcodes.c @@ -0,0 +1,78 @@ +/* mkerrcodes.c - Generate list of system error values. + Copyright (C) 2004 g10 Code GmbH + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with libgpg-error; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* This file must not include config.h, as that is for the host + system, while this file will be run on the build system. */ + +#include <stdio.h> + +#include "mkerrcodes.h" + +static const char header[] = +"/* errnos.h - List of system error values.\n" +" Copyright (C) 2004 g10 Code GmbH\n" +" This file is part of libgpg-error.\n" +"\n" +" libgpg-error is free software; you can redistribute it and/or\n" +" modify it under the terms of the GNU Lesser General Public License\n" +" as published by the Free Software Foundation; either version 2.1 of\n" +" the License, or (at your option) any later version.\n" +"\n" +" libgpg-error is distributed in the hope that it will be useful, but\n" +" WITHOUT ANY WARRANTY; without even the implied warranty of\n" +" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" +" Lesser General Public License for more details.\n" +"\n" +" You should have received a copy of the GNU Lesser General Public\n" +" License along with libgpg-error; if not, write to the Free\n" +" Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA\n" +" 02111-1307, USA. */\n" +"\n"; + +int +main (int argc, char **argv) +{ + int sorted; + int i; + + printf ("%s", header); + do + { + sorted = 1; + for (i = 0; i < sizeof (err_table) / sizeof (err_table[0]) - 1; i++) + if (err_table[i].err > err_table[i + 1].err) + { + int err = err_table[i].err; + const char *err_sym = err_table[i].err_sym; + + err_table[i].err = err_table[i + 1].err; + err_table[i].err_sym = err_table[i + 1].err_sym; + err_table[i + 1].err = err; + err_table[i + 1].err_sym = err_sym; + sorted = 0; + } + } + while (!sorted); + + for (i = 0; i < sizeof (err_table) / sizeof (err_table[0]); i++) + printf ("%i\t%s\n", err_table[i].err, err_table[i].err_sym); + + return 0; +} diff --git a/comm/third_party/libgpg-error/src/mkerrcodes1.awk b/comm/third_party/libgpg-error/src/mkerrcodes1.awk new file mode 100644 index 0000000000..4578e290ca --- /dev/null +++ b/comm/third_party/libgpg-error/src/mkerrcodes1.awk @@ -0,0 +1,96 @@ +# mkerrcodes.awk +# Copyright (C) 2003, 2004 g10 Code GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +# +# As a special exception, g10 Code GmbH gives unlimited permission to +# copy, distribute and modify the C source files that are the output +# of mkerrcodes.awk. You need not follow the terms of the GNU General +# Public License when using or distributing such scripts, even though +# portions of the text of mkerrcodes.awk appear in them. The GNU +# General Public License (GPL) does govern all other use of the material +# that constitutes the mkerrcodes.awk program. +# +# Certain portions of the mkerrcodes.awk source text are designed to be +# copied (in certain cases, depending on the input) into the output of +# mkerrcodes.awk. We call these the "data" portions. The rest of the +# mkerrcodes.awk source text consists of comments plus executable code +# that decides which of the data portions to output in any given case. +# We call these comments and executable code the "non-data" portions. +# mkerrcodes.h never copies any of the non-data portions into its output. +# +# This special exception to the GPL applies to versions of mkerrcodes.awk +# released by g10 Code GmbH. When you make and distribute a modified version +# of mkerrcodes.awk, you may extend this special exception to the GPL to +# apply to your modified version as well, *unless* your modified version +# has the potential to copy into its output some of the text that was the +# non-data portion of the version that you started with. (In other words, +# unless your change moves or copies text from the non-data portions to the +# data portions.) If your modification has such potential, you must delete +# any notice of this special exception to the GPL from your modified version. + +# This script outputs an intermediate file that contains the following block +# for each error value symbol in the input file (example for EINVAL): +# +# #ifdef EINVAL +# EINVAL GPG_ERR_EINVAL +# #endif +# +# The input file is a list of possible system errors in the column errnoidx +# (defaults to 2). +# +# Comments (starting with # and ending at the end of the line) are removed, +# as is trailing whitespace. + +BEGIN { + FS="[\t]+"; + header = 1; + if (errnoidx == 0) + errnoidx = 2; + + print "/* Output of mkerrcodes.awk. DO NOT EDIT. */"; + print ""; +} + +/^#/ { next; } + +header { + if ($1 ~ /^[0-9]/) + { + print "#include <errno.h>"; + print "#ifdef _WIN32"; + print "#include <winsock2.h>"; + print "#endif"; + print ""; + header = 0; + } + else + print; +} + +!header { + sub (/#.+/, ""); + sub (/[ ]+$/, ""); # Strip trailing space and tab characters. + + if (/^$/) + next; + + print "#ifdef " $errnoidx; + print $errnoidx "\tGPG_ERR_" $errnoidx; + print "#endif"; + print "#ifdef WSA" $errnoidx; + print "WSA" $errnoidx "\tGPG_ERR_" $errnoidx; + print "#endif"; +} diff --git a/comm/third_party/libgpg-error/src/mkerrcodes2.awk b/comm/third_party/libgpg-error/src/mkerrcodes2.awk new file mode 100644 index 0000000000..188f7a48e3 --- /dev/null +++ b/comm/third_party/libgpg-error/src/mkerrcodes2.awk @@ -0,0 +1,134 @@ +# mkstrtable.awk +# Copyright (C) 2003 g10 Code GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +# +# As a special exception, g10 Code GmbH gives unlimited permission to +# copy, distribute and modify the C source files that are the output +# of mkerrcodes2.awk. You need not follow the terms of the GNU General +# Public License when using or distributing such scripts, even though +# portions of the text of mkerrcodes2.awk appear in them. The GNU +# General Public License (GPL) does govern all other use of the material +# that constitutes the mkerrcodes2.awk program. +# +# Certain portions of the mkerrcodes2.awk source text are designed to be +# copied (in certain cases, depending on the input) into the output of +# mkerrcodes2.awk. We call these the "data" portions. The rest of the +# mkerrcodes2.awk source text consists of comments plus executable code +# that decides which of the data portions to output in any given case. +# We call these comments and executable code the "non-data" portions. +# mkstrtable.h never copies any of the non-data portions into its output. +# +# This special exception to the GPL applies to versions of mkerrcodes2.awk +# released by g10 Code GmbH. When you make and distribute a modified version +# of mkerrcodes2.awk, you may extend this special exception to the GPL to +# apply to your modified version as well, *unless* your modified version +# has the potential to copy into its output some of the text that was the +# non-data portion of the version that you started with. (In other words, +# unless your change moves or copies text from the non-data portions to the +# data portions.) If your modification has such potential, you must delete +# any notice of this special exception to the GPL from your modified version. + +# This script outputs a source file that does define the following +# symbols: +# +# static const char msgstr[]; +# A string containing all messages in the list. +# +# static const int msgidx[]; +# A list of index numbers, one for each message, that points to the +# beginning of the string in msgstr. +# +# msgidxof (code); +# A macro that maps code numbers to idx numbers. If a DEFAULT MESSAGE +# is provided (see below), its index will be returned for unknown codes. +# Otherwise -1 is returned for codes that do not appear in the list. +# You can lookup the message with code CODE with: +# msgstr + msgidx[msgidxof (code)]. +# +# The input file has the following format: +# CODE1 MESSAGE1 (Code number, <tab>, message string) +# CODE2 MESSAGE2 (Code number, <tab>, message string) +# ... +# CODEn MESSAGEn (Code number, <tab>, message string) +# DEFAULT MESSAGE (<tab>, fall-back message string) +# +# Comments (starting with # and ending at the end of the line) are removed, +# as is trailing whitespace. The last line is optional; if no DEFAULT +# MESSAGE is given, msgidxof will return the number -1 for unknown +# index numbers. + +BEGIN { +# msg holds the number of messages. + msg = 0; + print "/* Output of mkerrcodes2.awk. DO NOT EDIT. */"; + print ""; + header = 1; +} + +/^#/ { next; } + +header { + if ($1 ~ /^[0123456789]+$/) + { + print "static const int err_code_from_index[] = {"; + header = 0; + } + else + print; +} + +!header { + sub (/#.+/, ""); + sub (/[ ]+$/, ""); # Strip trailing space and tab characters. + + if (/^$/) + next; + +# Print the string msgstr line by line. We delay output by one line to be able +# to treat the last line differently (see END). + print " " $2 ","; + +# Remember the error value and index of each error code. + code[msg] = $1; + pos[msg] = $2; + msg++; +} +END { + print "};"; + print ""; + print "#define errno_to_idx(code) (0 ? -1 \\"; + +# Gather the ranges. + skip = code[0]; + start = code[0]; + stop = code[0]; + for (i = 1; i < msg; i++) + { + if (code[i] == stop + 1) + stop++; + else + { + print " : ((code >= " start ") && (code <= " stop ")) ? (code - " \ + skip ") \\"; + skip += code[i] - stop - 1; + start = code[i]; + stop = code[i]; + } + } + print " : ((code >= " start ") && (code <= " stop ")) ? (code - " \ + skip ") \\"; + print " : -1)"; +} diff --git a/comm/third_party/libgpg-error/src/mkerrnos.awk b/comm/third_party/libgpg-error/src/mkerrnos.awk new file mode 100644 index 0000000000..15b1aad225 --- /dev/null +++ b/comm/third_party/libgpg-error/src/mkerrnos.awk @@ -0,0 +1,104 @@ +# mkerrnos.awk +# Copyright (C) 2003, 2004 g10 Code GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +# +# As a special exception, g10 Code GmbH gives unlimited permission to +# copy, distribute and modify the C source files that are the output +# of mkerrnos.awk. You need not follow the terms of the GNU General +# Public License when using or distributing such scripts, even though +# portions of the text of mkerrnos.awk appear in them. The GNU +# General Public License (GPL) does govern all other use of the material +# that constitutes the mkerrnos.awk program. +# +# Certain portions of the mkerrnos.awk source text are designed to be +# copied (in certain cases, depending on the input) into the output of +# mkerrnos.awk. We call these the "data" portions. The rest of the +# mkerrnos.awk source text consists of comments plus executable code +# that decides which of the data portions to output in any given case. +# We call these comments and executable code the "non-data" portions. +# mkerrnos.h never copies any of the non-data portions into its output. +# +# This special exception to the GPL applies to versions of mkerrnos.awk +# released by g10 Code GmbH. When you make and distribute a modified version +# of mkerrnos.awk, you may extend this special exception to the GPL to +# apply to your modified version as well, *unless* your modified version +# has the potential to copy into its output some of the text that was the +# non-data portion of the version that you started with. (In other words, +# unless your change moves or copies text from the non-data portions to the +# data portions.) If your modification has such potential, you must delete +# any notice of this special exception to the GPL from your modified version. + +# This script outputs a source file that does define the following +# symbols: +# +# static const int err_code_to_errno[]; +# A mapping of gpg_err_code_t numbers to system errno. The index of an +# error code in the table can be obtained after removing the system error +# code indication bit. +# +# The input file is a list of possible system errors in the column errnoidx +# (defaults to 2). +# +# Comments (starting with # and ending at the end of the line) are removed, +# as is trailing whitespace. + +BEGIN { + FS="[\t]+"; + header = 1; + if (errnoidx == 0) + errnoidx = 2; + + print "/* Output of mkerrnos.awk. DO NOT EDIT. */"; + print ""; +} + +/^#/ { next; } + +header { + if ($1 ~ /^[0-9]/) + { + print "#include <errno.h>"; + print "#ifdef _WIN32"; + print "#include <winsock2.h>"; + print "#endif"; + print ""; + print "static const int err_code_to_errno [] = {"; + header = 0; + } + else + print; +} + +!header { + sub (/#.+/, ""); + sub (/[ ]+$/, ""); # Strip trailing space and tab characters. + + if (/^$/) + next; + + print "#ifdef " $errnoidx; + print " " $errnoidx ","; + print "#else"; + print "#ifdef WSA" $errnoidx; + print " WSA" $errnoidx ","; + print "#else"; + print " 0,"; + print "#endif"; + print "#endif"; +} +END { + print "};"; +} diff --git a/comm/third_party/libgpg-error/src/mkheader.c b/comm/third_party/libgpg-error/src/mkheader.c new file mode 100644 index 0000000000..77826da543 --- /dev/null +++ b/comm/third_party/libgpg-error/src/mkheader.c @@ -0,0 +1,779 @@ +/* mkheader.c - Create a header file for libgpg-error + * Copyright (C) 2010 Free Software Foundation, Inc. + * Copyright (C) 2014 g10 Code GmbH + * + * This file is free software; as a special exception the author gives + * unlimited permission to copy and/or distribute it, with or without + * modifications, as long as this notice is preserved. + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> + +#define PGM "mkheader" + +#define LINESIZE 1024 + +static char *host_triplet; /* malloced. */ +static char *host_os; /* points into host_triplet. */ +static char *srcdir; +static const char *hdr_version; +static const char *hdr_version_number; +static int cross_building; /* Command line flag. */ + +/* Values take from the supplied config.h. */ +static int have_stdint_h; +static int have_sys_types_h; +static int have_w32_system; +static int have_w64_system; +static char *replacement_for_off_type; +static int use_posix_threads; + +/* Various state flags. */ +static int stdint_h_included; +static int sys_types_h_included; + + +/* The usual free wrapper. */ +static void +xfree (void *a) +{ + if (a) + free (a); +} + + +static char * +xmalloc (size_t n) +{ + char *p; + + p = malloc (n); + if (!p) + { + fputs (PGM ": out of core\n", stderr); + exit (1); + } + return p; +} + + +static char * +xstrdup (const char *string) +{ + char *p; + size_t len = strlen (string) + 1; + + p = xmalloc (len); + memcpy (p, string, len); + return p; +} + + +/* Return a malloced string with TRIPLET. If TRIPLET has an alias + * return that instead. In general build-aux/config.sub should do the + * aliasing but some returned triplets are anyway identical and thus + * we use this function to map it to the canonical form. A pointer to + * the OS part of the returned value is stored at R_OS. + * NO_VENDOR_HACK is for internal use; caller must call with 0. */ +static char * +canon_host_triplet (const char *triplet, int no_vendor_hack, char **r_os) +{ + struct { + const char *name; + const char *alias; + } tbl[] = { + {"i486-pc-linux-gnu", "i686-unknown-linux-gnu" }, + {"i586-pc-linux-gnu" }, + {"i686-pc-linux-gnu" }, + {"arc-oe-linux-gnu" }, /* Other CPU but same struct. */ + {"arc-oe-linux-uclibc" }, /* and uclibc is also the same. */ + + {"i486-pc-gnu", "i686-unknown-gnu"}, + {"i586-pc-gnu"}, + {"i686-pc-gnu"}, + + {"i486-pc-kfreebsd-gnu", "i686-unknown-kfreebsd-gnu"}, + {"i586-pc-kfreebsd-gnu"}, + {"i686-pc-kfreebsd-gnu"}, + + {"x86_64-pc-linux-gnuhardened1", "x86_64-unknown-linux-gnu" }, + {"x86_64-pc-linux-gnu" }, + + {"powerpc-unknown-linux-gnuspe", "powerpc-unknown-linux-gnu" }, + + {"arm-unknown-linux-gnueabihf", "arm-unknown-linux-gnueabi" }, + {"armv7-unknown-linux-gnueabihf" }, + {"armv7a-unknown-linux-gnueabihf" }, + {"armv5-unknown-linux-musleabi" }, + {"armv6-unknown-linux-musleabihf" }, + + { NULL } + }; + int i; + const char *lastalias = NULL; + const char *s; + char *p; + char *result; + + for (i=0; tbl[i].name; i++) + { + if (tbl[i].alias) + lastalias = tbl[i].alias; + if (!strcmp (tbl[i].name, triplet)) + { + if (!lastalias) + break; /* Ooops: first entry has no alias. */ + result = xstrdup (lastalias); + goto leave; + } + } + for (i=0, s=triplet; *s; s++) + if (*s == '-') + i++; + if (i > 2 && !no_vendor_hack) + { + /* We have a 4 part "triplet": CPU-VENDOR-KERNEL-SYSTEM where + * the last two parts replace the OS part of a real triplet. + * The VENDOR part is then in general useless because + * KERNEL-SYSTEM is specific enough. We now do a second pass by + * replacing VENDOR with "unknown". */ + char *buf = xmalloc (strlen (triplet) + 7 + 1); + + for (p=buf,s=triplet,i=0; *s; s++) + { + *p++ = *s; + if (*s == '-' && ++i == 1) + { + memcpy (p, "unknown-",8); + p += 8; + for (s++; *s != '-'; s++) + ; + } + } + *p = 0; + result = canon_host_triplet (buf, 1, NULL); + xfree (buf); + goto leave; + } + + result = xstrdup (triplet); + leave: + /* Find the OS part. */ + if (r_os) + { + *r_os = result + strlen (result); /* Default to the empty string. */ + for (i=0, p=result; *p; p++) + if (*p == '-' && ++i == 2) + { + *r_os = p+1; + break; + } + } + + return result; +} + + +/* Parse the supplied config.h file and extract required info. + Returns 0 on success. */ +static int +parse_config_h (const char *fname) +{ + FILE *fp; + char line[LINESIZE]; + int lnr = 0; + char *p1; + + fp = fopen (fname, "r"); + if (!fp) + { + fprintf (stderr, "%s:%d: can't open file: %s\n", + fname, lnr, strerror (errno)); + return 1; + } + + while (fgets (line, LINESIZE, fp)) + { + size_t n = strlen (line); + + lnr++; + if (!n || line[n-1] != '\n') + { + fprintf (stderr, + "%s:%d: trailing linefeed missing, line too long or " + "embedded nul character\n", fname, lnr); + break; + } + line[--n] = 0; + + if (strncmp (line, "#define ", 8)) + continue; /* We are only interested in define lines. */ + p1 = strtok (line + 8, " \t"); + if (!*p1) + continue; /* oops */ + if (!strcmp (p1, "HAVE_STDINT_H")) + have_stdint_h = 1; + else if (!strcmp (p1, "HAVE_SYS_TYPES_H")) + have_sys_types_h = 1; + else if (!strcmp (p1, "HAVE_W32_SYSTEM")) + have_w32_system = 1; + else if (!strcmp (p1, "HAVE_W64_SYSTEM")) + have_w64_system = 1; + else if (!strcmp (p1, "REPLACEMENT_FOR_OFF_T")) + { + p1 = strtok (NULL, "\""); + if (!*p1) + continue; /* oops */ + xfree (replacement_for_off_type); + replacement_for_off_type = xstrdup (p1); + } + else if (!strcmp (p1, "USE_POSIX_THREADS")) + use_posix_threads = 1; + } + + if (ferror (fp)) + { + fprintf (stderr, "%s:%d: error reading file: %s\n", + fname, lnr, strerror (errno)); + return 1; + } + + fclose (fp); + return 0; +} + + +/* Write LINE to stdout. The function is allowed to modify LINE. */ +static void +write_str (char *line) +{ + if (fputs (line, stdout) == EOF) + { + fprintf (stderr, PGM ": error writing to stdout: %s\n", strerror (errno)); + exit (1); + } +} + +static void +write_line (char *line) +{ + if (puts (line) == EOF) + { + fprintf (stderr, PGM ": error writing to stdout: %s\n", strerror (errno)); + exit (1); + } +} + + +/* Write SOURCE or CODES line to stdout. The function is allowed to + modify LINE. Trailing white space is already removed. Passing + NULL resets the internal state. */ +static void +write_sources_or_codes (char *line) +{ + static int in_intro; + char *p1, *p2; + + if (!line) + { + in_intro = 1; + return; + } + + if (!*line) + return; + + if (in_intro) + { + if (!strchr ("0123456789", *line)) + return; + in_intro = 0; + } + + p1 = strtok (line, " \t"); + p2 = p1? strtok (NULL, " \t") : NULL; + + if (p1 && p2 && strchr ("0123456789", *p1) && *p2) + { + write_str (" "); + write_str (p2); + write_str (" = "); + write_str (p1); + write_str (",\n"); + } +} + + +/* Write system errnos to stdout. The function is allowed to + modify LINE. Trailing white space is already removed. Passing + NULL resets the internal state. */ +static void +write_errnos_in (char *line) +{ + static int state; + char *p1, *p2; + + if (!line) + { + state = 0; + return; + } + + if (!*line) + return; + + if (!state && strchr ("0123456789", *line)) + state = 1; + else if (state == 1 && !strchr ("0123456789", *line)) + state = 2; + + if (state != 1) + return; + + p1 = strtok (line, " \t"); + p2 = p1? strtok (NULL, " \t") : NULL; + + if (p1 && p2 && strchr ("0123456789", *p1) && *p2) + { + write_str (" GPG_ERR_"); + write_str (p2); + write_str (" = GPG_ERR_SYSTEM_ERROR | "); + write_str (p1); + write_str (",\n"); + } +} + + +/* Create the full file name for NAME and return a newly allocated + string with it. If name contains a '&' and REPL is not NULL + replace '&' with REPL. */ +static char * +mk_include_name (const char *name, const char *repl) +{ + FILE *fp; + char *incfname, *p; + const char *s; + + incfname = malloc (strlen (srcdir) + strlen (name) + + (repl?strlen (repl):0) + 1); + if (!incfname) + { + fputs (PGM ": out of core\n", stderr); + exit (1); + } + + if (*name == '.' && name[1] == '/') + *incfname = 0; + else + strcpy (incfname, srcdir); + p = incfname + strlen (incfname); + for (s=name; *s; s++) + { + if (*s == '&' && repl) + { + while (*repl) + *p++ = *repl++; + repl = NULL; /* Replace only once. */ + } + else + *p++ = *s; + } + *p = 0; + return incfname; +} + + +/* Include the file NAME from the source directory. The included file + is not further expanded. It may have comments indicated by a + double hash mark at the begin of a line. OUTF is called for each + read line and passed a buffer with the content of line sans line + line endings. If NAME is prefixed with "./" it is included from + the current directory and not from the source directory. */ +static void +include_file (const char *fname, int lnr, const char *name, void (*outf)(char*)) +{ + FILE *fp; + char *incfname; + int inclnr; + char line[LINESIZE]; + int repl_flag; + + repl_flag = !!strchr (name, '&'); + incfname = mk_include_name (name, repl_flag? host_triplet : NULL); + fp = fopen (incfname, "r"); + if (!fp && repl_flag) + { + /* Try again using the OS string. */ + free (incfname); + incfname = mk_include_name (name, host_os); + fp = fopen (incfname, "r"); + } + if (!fp) + { + fprintf (stderr, "%s:%d: error including `%s': %s\n", + fname, lnr, incfname, strerror (errno)); + exit (1); + } + + if (repl_flag) + fprintf (stderr,"%s:%d: note: including '%s'\n", + fname, lnr, incfname); + + inclnr = 0; + while (fgets (line, LINESIZE, fp)) + { + size_t n = strlen (line); + + inclnr++; + if (!n || line[n-1] != '\n') + { + fprintf (stderr, + "%s:%d: trailing linefeed missing, line too long or " + "embedded nul character\n", incfname, inclnr); + fprintf (stderr,"%s:%d: note: file '%s' included from here\n", + fname, lnr, incfname); + exit (1); + } + line[--n] = 0; + while (line[n] == ' ' || line[n] == '\t' || line[n] == '\r') + { + line[n] = 0; + if (!n) + break; + n--; + } + + if (line[0] == '#' && line[1] == '#') + { + if (!strncmp (line+2, "EOF##", 5)) + break; /* Forced EOF. */ + } + else + outf (line); + } + if (ferror (fp)) + { + fprintf (stderr, "%s:%d: error reading `%s': %s\n", + fname, lnr, incfname, strerror (errno)); + exit (1); + } + fclose (fp); + free (incfname); +} + + +/* Try to include the file NAME. Returns true if it does not + exist. */ +static int +try_include_file (const char *fname, int lnr, const char *name, + void (*outf)(char*)) +{ + int rc; + char *incfname; + int repl_flag; + + repl_flag = !!strchr (name, '&'); + incfname = mk_include_name (name, repl_flag? host_triplet : NULL); + rc = access (incfname, R_OK); + if (rc && repl_flag) + { + free (incfname); + incfname = mk_include_name (name, host_os); + rc = access (incfname, R_OK); + } + if (!rc) + include_file (fname, lnr, name, outf); + + free (incfname); + return rc; +} + + +static int +write_special (const char *fname, int lnr, const char *tag) +{ + if (!strcmp (tag, "version")) + { + putchar ('\"'); + fputs (hdr_version, stdout); + putchar ('\"'); + } + else if (!strcmp (tag, "version-number")) + { + fputs (hdr_version_number, stdout); + } + else if (!strcmp (tag, "define:gpgrt_off_t")) + { + if (!replacement_for_off_type) + { + fprintf (stderr, "%s:%d: replacement for off_t not defined\n", + fname, lnr); + exit (1); + } + else + { + if (!strcmp (replacement_for_off_type, "int64_t") + && !stdint_h_included && have_stdint_h) + { + fputs ("#include <stdint.h>\n\n", stdout); + stdint_h_included = 1; + } + printf ("typedef %s gpgrt_off_t;\n", replacement_for_off_type); + } + } + else if (!strcmp (tag, "define:gpgrt_ssize_t")) + { + if (have_w64_system) + { + if (!stdint_h_included && have_stdint_h) + { + fputs ("# include <stdint.h>\n", stdout); + stdint_h_included = 1; + } + fputs ("typedef int64_t gpgrt_ssize_t;\n", stdout); + } + else if (have_w32_system) + { + fputs ("typedef long gpgrt_ssize_t;\n", stdout); + } + else + { + if (!sys_types_h_included) + { + fputs ("#include <sys/types.h>\n", stdout); + sys_types_h_included = 1; + } + fputs ("typedef ssize_t gpgrt_ssize_t;\n", stdout); + } + } + else if (!strcmp (tag, "api_ssize_t")) + { + if (have_w32_system) + fputs ("gpgrt_ssize_t", stdout); + else + fputs ("ssize_t", stdout); + } + else if (!strcmp (tag, "define:pid_t")) + { + if (have_sys_types_h) + { + if (!sys_types_h_included) + { + fputs ("#include <sys/types.h>\n", stdout); + sys_types_h_included = 1; + } + } + else if (have_w64_system) + { + if (!stdint_h_included && have_stdint_h) + { + fputs ("#include <stdint.h>\n", stdout); + stdint_h_included = 1; + } + fputs ("typedef int64_t pid_t\n", stdout); + } + else + { + fputs ("typedef int pid_t\n", stdout); + } + } + else if (!strcmp (tag, "include:err-sources")) + { + write_sources_or_codes (NULL); + include_file (fname, lnr, "err-sources.h.in", write_sources_or_codes); + } + else if (!strcmp (tag, "include:err-codes")) + { + write_sources_or_codes (NULL); + include_file (fname, lnr, "err-codes.h.in", write_sources_or_codes); + } + else if (!strcmp (tag, "include:errnos")) + { + include_file (fname, lnr, "errnos.in", write_errnos_in); + } + else if (!strcmp (tag, "include:os-add")) + { + if (!strcmp (host_os, "mingw32")) + { + include_file (fname, lnr, "w32-add.h", write_line); + } + else if (!strcmp (host_os, "mingw32ce")) + { + include_file (fname, lnr, "w32-add.h", write_line); + include_file (fname, lnr, "w32ce-add.h", write_line); + } + } + else if (!strcmp (tag, "include:lock-obj")) + { + /* If we are not cross compiling and the native file exists we + * prefer that over one from syscfg. */ + if (cross_building + || try_include_file (fname, lnr, + "./lock-obj-pub.native.h", write_line)) + include_file (fname, lnr, "syscfg/lock-obj-pub.&.h", write_line); + } + else + return 0; /* Unknown tag. */ + + return 1; /* Tag processed. */ +} + + +int +main (int argc, char **argv) +{ + FILE *fp = NULL; + char line[LINESIZE]; + int lnr = 0; + const char *fname, *s; + char *p1, *p2; + const char *config_h; + const char *host_triplet_raw; + + if (argc) + { + argc--; argv++; + } + if (argc && !strcmp (argv[0], "--cross")) + { + cross_building = 1; + argc--; argv++; + } + + if (argc == 1) + { + /* Print just the canonicalized host triplet. */ + host_triplet = canon_host_triplet (argv[0], 0, &host_os); + printf ("%s\n", host_triplet); + goto leave; + } + else if (argc == 5) + ; /* Standard operation. */ + else + { + fputs ("usage: " PGM + " host_triplet template.h config.h version version_number\n" + " " PGM + " host_triplet\n", + stderr); + return 1; + } + host_triplet_raw = argv[0]; + fname = argv[1]; + config_h = argv[2]; + hdr_version = argv[3]; + hdr_version_number = argv[4]; + + host_triplet = canon_host_triplet (host_triplet_raw, 0, &host_os); + + srcdir = malloc (strlen (fname) + 2 + 1); + if (!srcdir) + { + fputs (PGM ": out of core\n", stderr); + return 1; + } + strcpy (srcdir, fname); + p1 = strrchr (srcdir, '/'); + if (p1) + p1[1] = 0; + else + strcpy (srcdir, "./"); + + if (parse_config_h (config_h)) + return 1; + + fp = fopen (fname, "r"); + if (!fp) + { + fprintf (stderr, "%s:%d: can't open file: %s\n", + fname, lnr, strerror (errno)); + return 1; + } + + while (fgets (line, LINESIZE, fp)) + { + size_t n = strlen (line); + + lnr++; + if (!n || line[n-1] != '\n') + { + fprintf (stderr, + "%s:%d: trailing linefeed missing, line too long or " + "embedded nul character\n", fname, lnr); + break; + } + line[--n] = 0; + + p1 = strchr (line, '@'); + p2 = p1? strchr (p1+1, '@') : NULL; + if (!p1 || !p2 || p2-p1 == 1) + { + puts (line); + continue; + } + *p1++ = 0; + *p2++ = 0; + fputs (line, stdout); + + if (!strcmp (p1, "configure_input")) + { + s = strrchr (fname, '/'); + printf ("Do not edit. Generated from %s for:\n%*s", + s? s+1 : fname, (int)(p1 - line) + 13, ""); + if (!strcmp (host_triplet, host_triplet_raw)) + printf ("%s", host_triplet); + else + printf ("%s (%s)", host_triplet, host_triplet_raw); + if (!use_posix_threads && !have_w32_system && !have_w64_system) + fputs (" NO-THREADS", stdout); + fputs (p2, stdout); + } + else if (!write_special (fname, lnr, p1)) + { + putchar ('@'); + fputs (p1, stdout); + putchar ('@'); + fputs (p2, stdout); + } + else if (*p2) + { + fputs (p2, stdout); + } + putchar ('\n'); + } + + if (ferror (fp)) + { + fprintf (stderr, "%s:%d: error reading file: %s\n", + fname, lnr, strerror (errno)); + return 1; + } + + fputs ("/*\n" + "Loc" "al Variables:\n" + "buffer-read-only: t\n" + "End:\n" + "*/\n", stdout); + + leave: + if (ferror (stdout)) + { + fprintf (stderr, PGM ": error writing to stdout: %s\n", strerror (errno)); + return 1; + } + + if (fp) + fclose (fp); + + xfree (host_triplet); + return 0; +} diff --git a/comm/third_party/libgpg-error/src/mkstrtable.awk b/comm/third_party/libgpg-error/src/mkstrtable.awk new file mode 100644 index 0000000000..285e45f24c --- /dev/null +++ b/comm/third_party/libgpg-error/src/mkstrtable.awk @@ -0,0 +1,189 @@ +# mkstrtable.awk +# Copyright (C) 2003, 2004, 2008 g10 Code GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +# +# As a special exception, g10 Code GmbH gives unlimited permission to +# copy, distribute and modify the C source files that are the output +# of mkstrtable.awk. You need not follow the terms of the GNU General +# Public License when using or distributing such scripts, even though +# portions of the text of mkstrtable.awk appear in them. The GNU +# General Public License (GPL) does govern all other use of the material +# that constitutes the mkstrtable.awk program. +# +# Certain portions of the mkstrtable.awk source text are designed to be +# copied (in certain cases, depending on the input) into the output of +# mkstrtable.awk. We call these the "data" portions. The rest of the +# mkstrtable.awk source text consists of comments plus executable code +# that decides which of the data portions to output in any given case. +# We call these comments and executable code the "non-data" portions. +# mkstrtable.h never copies any of the non-data portions into its output. +# +# This special exception to the GPL applies to versions of mkstrtable.awk +# released by g10 Code GmbH. When you make and distribute a modified version +# of mkstrtable.awk, you may extend this special exception to the GPL to +# apply to your modified version as well, *unless* your modified version +# has the potential to copy into its output some of the text that was the +# non-data portion of the version that you started with. (In other words, +# unless your change moves or copies text from the non-data portions to the +# data portions.) If your modification has such potential, you must delete +# any notice of this special exception to the GPL from your modified version. + +# This script outputs a source file that does define the following +# symbols: +# +# static const char msgstr[]; +# A string containing all messages in the list. +# +# static const int msgidx[]; +# A list of index numbers, one for each message, that points to the +# beginning of the string in msgstr. +# +# msgidxof (code); +# A macro that maps code numbers to idx numbers. If a DEFAULT MESSAGE +# is provided (see below), its index will be returned for unknown codes. +# Otherwise -1 is returned for codes that do not appear in the list. +# You can lookup the message with code CODE with: +# msgstr + msgidx[msgidxof (code)]. +# +# The input file has the following format: +# CODE1 ... MESSAGE1 (code nr, <tab>, something, <tab>, msg) +# CODE2 ... MESSAGE2 (code nr, <tab>, something, <tab>, msg) +# ... +# CODEn ... MESSAGEn (code nr, <tab>, something, <tab>, msg) +# ... DEFAULT-MESSAGE (<tab>, something, <tab>, fall-back msg) +# +# Comments (starting with # and ending at the end of the line) are removed, +# as is trailing whitespace. The last line is optional; if no DEFAULT +# MESSAGE is given, msgidxof will return the number -1 for unknown +# index numbers. +# +# The field to be used is specified with the variable "textidx" on +# the command line. It defaults to 2. +# +# The variable nogettext can be set to 1 to suppress gettext markers. +# +# The variable prefix can be used to prepend a string to each message. +# +# The variable pkg_namespace can be used to prepend a string to each +# variable and macro name. + +BEGIN { + FS = "[\t]+"; +# cpos holds the current position in the message string. + cpos = 0; +# msg holds the number of messages. + msg = 0; + print "/* Output of mkstrtable.awk. DO NOT EDIT. */"; + print ""; + header = 1; + if (textidx == 0) + textidx = 2; +# nogettext can be set to 1 to suppress gettext noop markers. +} + +/^#/ { next; } + +header { + if ($1 ~ /^[0123456789]+$/) + { + print "/* The purpose of this complex string table is to produce"; + print " optimal code with a minimum of relocations. */"; + print ""; + print "static const char " pkg_namespace "msgstr[] = "; + header = 0; + } + else + print; +} + +!header { + sub (/#.+/, ""); + sub (/[ ]+$/, ""); # Strip trailing space and tab characters. + + if (/^$/) + next; + +# Print the string msgstr line by line. We delay output by one line to be able +# to treat the last line differently (see END). + if (last_msgstr) + { + if (nogettext) + print " \"" last_msgstr "\" \"\\0\""; + else + print " gettext_noop (\"" last_msgstr "\") \"\\0\""; + } + last_msgstr = prefix $textidx; + +# Remember the error code and msgidx of each error message. + code[msg] = $1; + pos[msg] = cpos; + cpos += length (last_msgstr) + 1; + msg++; + + if ($1 == "") + { + has_default = 1; + exit; + } +} +END { + if (has_default) + coded_msgs = msg - 1; + else + coded_msgs = msg; + + if (nogettext) + print " \"" last_msgstr "\";"; + else + print " gettext_noop (\"" last_msgstr "\");"; + print ""; + print "static const int " pkg_namespace "msgidx[] ="; + print " {"; + for (i = 0; i < coded_msgs; i++) + print " " pos[i] ","; + print " " pos[coded_msgs]; + print " };"; + print ""; + print "static GPG_ERR_INLINE int"; + print pkg_namespace "msgidxof (int code)"; + print "{"; + print " return (0 ? 0"; + +# Gather the ranges. + skip = code[0]; + start = code[0]; + stop = code[0]; + for (i = 1; i < coded_msgs; i++) + { + if (code[i] == stop + 1) + stop++; + else + { + print " : ((code >= " start ") && (code <= " stop ")) ? (code - " \ + skip ")"; + skip += code[i] - stop - 1; + start = code[i]; + stop = code[i]; + } + } + print " : ((code >= " start ") && (code <= " stop ")) ? (code - " \ + skip ")"; + if (has_default) + print " : " stop + 1 " - " skip ");"; + else + print " : -1);"; + print "}"; +} diff --git a/comm/third_party/libgpg-error/src/mkw32errmap.c b/comm/third_party/libgpg-error/src/mkw32errmap.c new file mode 100644 index 0000000000..508a51302d --- /dev/null +++ b/comm/third_party/libgpg-error/src/mkw32errmap.c @@ -0,0 +1,178 @@ +/* mkw32errmap.c - Generate mapping sources for Windows. + Copyright (C) 2010 g10 Code GmbH + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, see <https://www.gnu.org/licenses/>. + */ + +#ifdef RESOLVE_MACROS +# include <winerror.h> +#endif +#include <stdio.h> +#include <stdlib.h> + +static const char header_gpg_extra_errno_h[] = + "/* errno.h - WindowsCE errno.h substitute\n" + " Copyright (C) 2010 g10 Code GmbH\n" + "\n" + " This file is free software; as a special exception the author gives\n" + " unlimited permission to copy and/or distribute it, with or without\n" + " modifications, as long as this notice is preserved.\n" + "\n" + " This file is distributed in the hope that it will be useful, but\n" + " WITHOUT ANY WARRANTY, to the extent permitted by law; without even\n" + " the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n" + " PURPOSE.\n" + "\n" + " +++ Do not edit! File has been generated by mkw32errmap.c +++\n" + "\n" + " This file is intended to be used with ming32ce-gcc to implement an\n" + " errno substitute under WindowsCE. It must be included via gcc's\n" + " -idirafter option. The gpg-error-config script emits the\n" + " appropriate option snippet. The actual implementation of the errno\n" + " related functions are part of libgpg-error. A separate header file\n" + " is required because errno.h is often included before gpg-error.h.\n" + " */\n" + "\n" + "#ifndef _GPG_ERROR_EXTRA_ERRNO_H\n" + "#define _GPG_ERROR_EXTRA_ERRNO_H\n" + "\n" + "/* Due to peculiarities in W32 we can't implement ERRNO as an\n" + " writable lvalue. This also allows us to easily find places\n" + " where ERRNO is being written to. See also gpg_err_set_errno. */\n" + "int _gpg_w32ce_get_errno (void);\n" + "#define errno (_gpg_w32ce_get_errno ())\n" + "\n"; +static const char footer_gpg_extra_errno_h[] = + "\n" + "#endif /*_GPG_ERROR_EXTRA_ERRNO_H*/\n"; + + +/* The table below is used in two modes. First we run the host + preprocessor over it to generate a new include file. This include + file has the same content but the Windows error macros are + resolved. This is so that we don't need to include winerror.h into + the generated errno.h. The mkw32errmap_marker variable is only + here to have something to grep for after preprocessing. */ +static int mkw32errmap_marker; +struct table_s +{ + int *dummy; + const char *name; + int w32code; + int w32code2; +}; + +struct table_s table[] = + { +#ifdef RESOLVE_MACROS +#define X(a,b,c) \ + {&mkw32errmap_marker, (a), (b), (c)} + X( "EPERM", ERROR_CANNOT_MAKE , 0 ), + X( "ENOENT", ERROR_FILE_NOT_FOUND , ERROR_PATH_NOT_FOUND ), + X( "EINTR", ERROR_INVALID_AT_INTERRUPT_TIME , 0 ), + X( "EIO", ERROR_IO_DEVICE , 0 ), + X( "ENXIO", ERROR_FILE_INVALID , 0 ), + X( "EBADF", ERROR_INVALID_HANDLE , 0 ), + X( "EAGAIN", ERROR_MORE_DATA , WSAEWOULDBLOCK ), + + X( "ENOMEM", ERROR_NOT_ENOUGH_MEMORY , 0 ), + X( "EACCES", ERROR_ACCESS_DENIED , 0 ), + X( "EFAULT", ERROR_PROCESS_ABORTED , 0 ), + X( "EBUSY", ERROR_BUSY , 0 ), + X( "EEXIST", ERROR_FILE_EXISTS , WSAEADDRINUSE ), + + X( "EXDEV", ERROR_NOT_SAME_DEVICE , 0 ), + X( "ENODEV", ERROR_BAD_DEVICE , ERROR_DEV_NOT_EXIST ), + + X( "ENOTDIR",ERROR_DIRECTORY , 0 ), + X( "EINVAL", ERROR_INVALID_PARAMETER , 0 ), + X( "ENFILE", ERROR_NO_MORE_FILES , 0 ), + X( "EMFILE", ERROR_TOO_MANY_OPEN_FILES , 0 ), + X( "ENOSPC", ERROR_DISK_FULL , 0 ), + X( "EROFS", ERROR_WRITE_PROTECT , 0 ), + X( "EPIPE", ERROR_BROKEN_PIPE , 0 ), + X( "ERANGE", ERROR_ARITHMETIC_OVERFLOW , 0 ), + X( "EDEADLOCK",ERROR_POSSIBLE_DEADLOCK , 0 ), + X( "ENAMETOOLONG", ERROR_FILENAME_EXCED_RANGE, 0 ), + X( "ENOLCK", ERROR_SHARING_BUFFER_EXCEEDED , 0 ), + X( "ENOSYS", ERROR_NOT_SUPPORTED , 0 ), + X( "ENOTEMPTY",ERROR_DIR_NOT_EMPTY , 0 ), + X( "ESPIPE", ERROR_SEEK_ON_DEVICE , 0 ), +#if 0 /* FIXME: Find appropriate mappings. */ + X( "EILSEQ", ), + X( "EDOM", ), + X( "EMLINK", ), + X( "ESRCH", ), /* No such process */ + X( "E2BIG", ), /* Arg list too long */ + X( "ENOEXEC", ), /* Exec format error */ + X( "ECHILD", ), /* No child processes */ + X( "EISDIR", ), /* Is a directory */ + X( "ENOTTY", ), /* Inappropriate I/O control operation */ + X( "EFBIG", ), /* File too large */ +#endif +#undef X +#else /*!RESOLVE_MACROS*/ +# include "mkw32errmap.tab.h" +#endif /*!RESOLVE_MACROS*/ + { NULL, 0 } + }; + + + +static int +compare_table (const void *a_v, const void *b_v) +{ + const struct table_s *a = a_v; + const struct table_s *b = b_v; + + return (a->w32code - b->w32code); +} + + +int +main (int argc, char **argv) +{ + int idx; + + for (idx=0; table[idx].name; idx++) + ; + qsort (table, idx, sizeof *table, compare_table); + + if (argc == 2 && !strcmp (argv[1], "--map")) + { + fputs ("static int\n" + "map_w32codes (int err)\n" + "{\n" + " switch (err)\n" + " {\n", stdout ); + for (idx=0; table[idx].name; idx++) + if (table[idx].w32code2) + printf (" case %d: return %d;\n", + table[idx].w32code2, table[idx].w32code); + fputs (" default: return err;\n" + " }\n" + "}\n", stdout); + } + else + { + fputs (header_gpg_extra_errno_h, stdout); + for (idx=0; table[idx].name; idx++) + printf ("#define %-12s %5d\n", table[idx].name, table[idx].w32code); + fputs (footer_gpg_extra_errno_h, stdout); + } + + return 0; +} diff --git a/comm/third_party/libgpg-error/src/posix-lock-obj.h b/comm/third_party/libgpg-error/src/posix-lock-obj.h new file mode 100644 index 0000000000..08e0bace07 --- /dev/null +++ b/comm/third_party/libgpg-error/src/posix-lock-obj.h @@ -0,0 +1,42 @@ +/* posic-lock-obj.h - Declaration of the POSIX lock object + Copyright (C) 2014 g10 Code GmbH + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef POSIX_LOCK_OBJ_H +#define POSIX_LOCK_OBJ_H + +#define LOCK_ABI_NOT_AVAILABLE (-1) +#if USE_POSIX_THREADS +# define LOCK_ABI_VERSION 1 +#else +# define LOCK_ABI_VERSION LOCK_ABI_NOT_AVAILABLE +#endif + +typedef struct +{ + long vers; +#if USE_POSIX_THREADS + union { + pthread_mutex_t mtx; + long *dummy; + } u; +#endif +} _gpgrt_lock_t; + + +#endif /*POSIX_LOCK_OBJ_H*/ diff --git a/comm/third_party/libgpg-error/src/posix-lock.c b/comm/third_party/libgpg-error/src/posix-lock.c new file mode 100644 index 0000000000..be4cc27559 --- /dev/null +++ b/comm/third_party/libgpg-error/src/posix-lock.c @@ -0,0 +1,263 @@ +/* posix-lock.c - GPGRT lock functions for POSIX systems + Copyright (C) 2005-2009 Free Software Foundation, Inc. + Copyright (C) 2014 g10 Code GmbH + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, see <https://www.gnu.org/licenses/>. + + Parts of the code, in particular use_pthreads_p, are based on code + from gettext, written by Bruno Haible <bruno@clisp.org>, 2005. + */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_W32_SYSTEM +# error This module may not be build for Windows. +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#if USE_POSIX_THREADS +# include <pthread.h> +#endif + +#include "gpgrt-int.h" +#include "lock.h" +#include "posix-lock-obj.h" + + +#if USE_POSIX_THREADS +# if USE_POSIX_THREADS_WEAK + /* On ELF systems it is easy to use pthreads using weak + references. Take care not to test the address of a weak + referenced function we actually use; some GCC versions have a + bug were &foo != NULL is always evaluated to true in PIC mode. */ +# pragma weak pthread_cancel +# pragma weak pthread_mutex_init +# pragma weak pthread_mutex_lock +# pragma weak pthread_mutex_trylock +# pragma weak pthread_mutex_unlock +# pragma weak pthread_mutex_destroy +# if ! PTHREAD_IN_USE_DETECTION_HARD +# define use_pthread_p() (!!pthread_cancel) +# endif +# else /*!USE_POSIX_THREADS_WEAK*/ +# if ! PTHREAD_IN_USE_DETECTION_HARD +# define use_pthread_p() (1) +# endif +# endif /*!USE_POSIX_THREADS_WEAK*/ +# if PTHREAD_IN_USE_DETECTION_HARD +/* The function to be executed by a dummy thread. */ +static void * +dummy_thread_func (void *arg) +{ + return arg; +} + +static int +use_pthread_p (void) +{ + static int tested; + static int result; /* 1: linked with -lpthread, 0: only with libc */ + + if (!tested) + { + pthread_t thread; + + if (pthread_create (&thread, NULL, dummy_thread_func, NULL)) + result = 0; /* Thread creation failed. */ + else + { + /* Thread creation works. */ + void *retval; + if (pthread_join (thread, &retval) != 0) + { + fputs ("gpgrt fatal: pthread_join in use_pthread_p failed\n", + stderr); + _gpgrt_abort (); + } + result = 1; + } + tested = 1; + } + return result; +} +#endif /*PTHREAD_IN_USE_DETECTION_HARD*/ +#endif /*USE_POSIX_THREADS*/ + + +static _gpgrt_lock_t * +get_lock_object (gpgrt_lock_t *lockhd) +{ + _gpgrt_lock_t *lock = (_gpgrt_lock_t*)lockhd; + + if (lock->vers != LOCK_ABI_VERSION) + { + fputs ("gpgrt fatal: lock ABI version mismatch\n", stderr); + _gpgrt_abort (); + } + if (sizeof (gpgrt_lock_t) < sizeof (_gpgrt_lock_t)) + { + fputs ("gpgrt fatal: sizeof lock obj\n", stderr); + _gpgrt_abort (); + } + + return lock; +} + + +gpg_err_code_t +_gpgrt_lock_init (gpgrt_lock_t *lockhd) +{ + _gpgrt_lock_t *lock = (_gpgrt_lock_t*)lockhd; + int rc; + + /* If VERS is zero we assume that no static initialization has been + done, so we setup our ABI version right here. The caller might + have called us to test whether lock support is at all available. */ + if (!lock->vers) + { + if (sizeof (gpgrt_lock_t) < sizeof (_gpgrt_lock_t)) + { + fputs ("gpgrt fatal: sizeof lock obj\n", stderr); + _gpgrt_abort (); + } + lock->vers = LOCK_ABI_VERSION; + } + else /* Run the usual check. */ + lock = get_lock_object (lockhd); + +#if USE_POSIX_THREADS + if (use_pthread_p()) + { + rc = pthread_mutex_init (&lock->u.mtx, NULL); + if (rc) + rc = _gpg_err_code_from_errno (rc); + } + else + rc = 0; /* Threads are not used. */ +#else /* Unknown thread system. */ + rc = lock->vers == LOCK_ABI_NOT_AVAILABLE? 0 : GPG_ERR_NOT_IMPLEMENTED; +#endif /* Unknown thread system. */ + + return rc; +} + + +gpg_err_code_t +_gpgrt_lock_lock (gpgrt_lock_t *lockhd) +{ + _gpgrt_lock_t *lock = get_lock_object (lockhd); + int rc; + +#if USE_POSIX_THREADS + if (use_pthread_p()) + { + _gpgrt_pre_syscall (); + rc = pthread_mutex_lock (&lock->u.mtx); + if (rc) + rc = _gpg_err_code_from_errno (rc); + _gpgrt_post_syscall (); + } + else + rc = 0; /* Threads are not used. */ +#else /* Unknown thread system. */ + rc = lock->vers == LOCK_ABI_NOT_AVAILABLE? 0 : GPG_ERR_NOT_IMPLEMENTED; +#endif /* Unknown thread system. */ + + return rc; +} + + +gpg_err_code_t +_gpgrt_lock_trylock (gpgrt_lock_t *lockhd) +{ + _gpgrt_lock_t *lock = get_lock_object (lockhd); + int rc; + +#if USE_POSIX_THREADS + if (use_pthread_p()) + { + rc = pthread_mutex_trylock (&lock->u.mtx); + if (rc) + rc = _gpg_err_code_from_errno (rc); + } + else + rc = 0; /* Threads are not used. */ +#else /* Unknown thread system. */ + rc = lock->vers == LOCK_ABI_NOT_AVAILABLE? 0 : GPG_ERR_NOT_IMPLEMENTED; +#endif /* Unknown thread system. */ + + return rc; +} + + +gpg_err_code_t +_gpgrt_lock_unlock (gpgrt_lock_t *lockhd) +{ + _gpgrt_lock_t *lock = get_lock_object (lockhd); + int rc; + +#if USE_POSIX_THREADS + if (use_pthread_p()) + { + rc = pthread_mutex_unlock (&lock->u.mtx); + if (rc) + rc = _gpg_err_code_from_errno (rc); + } + else + rc = 0; /* Threads are not used. */ +#else /* Unknown thread system. */ + rc = lock->vers == LOCK_ABI_NOT_AVAILABLE? 0 : GPG_ERR_NOT_IMPLEMENTED; +#endif /* Unknown thread system. */ + + return rc; +} + + +/* Note: Use this function only if no other thread holds or waits for + this lock. */ +gpg_err_code_t +_gpgrt_lock_destroy (gpgrt_lock_t *lockhd) +{ + _gpgrt_lock_t *lock = get_lock_object (lockhd); + int rc; + +#if USE_POSIX_THREADS + if (use_pthread_p()) + { + rc = pthread_mutex_destroy (&lock->u.mtx); + if (rc) + rc = _gpg_err_code_from_errno (rc); + else + { + /* Re-init the mutex so that it can be re-used. */ + gpgrt_lock_t tmp = GPGRT_LOCK_INITIALIZER; + memcpy (lockhd, &tmp, sizeof tmp); + } + } + else + rc = 0; /* Threads are not used. */ +#else /* Unknown thread system. */ + rc = lock->vers == LOCK_ABI_NOT_AVAILABLE? 0 : GPG_ERR_NOT_IMPLEMENTED; +#endif /* Unknown thread system. */ + + return rc; +} diff --git a/comm/third_party/libgpg-error/src/posix-thread.c b/comm/third_party/libgpg-error/src/posix-thread.c new file mode 100644 index 0000000000..36c81ba6f8 --- /dev/null +++ b/comm/third_party/libgpg-error/src/posix-thread.c @@ -0,0 +1,68 @@ +/* posix-thread.c - GPGRT thread functions for POSIX systems + Copyright (C) 2014 g10 Code GmbH + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, see <https://www.gnu.org/licenses/>. + */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_W32_SYSTEM +# error This module may not be build for Windows. +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> /* Get posix option macros. */ + +#if USE_POSIX_THREADS +# ifdef _POSIX_PRIORITY_SCHEDULING +# include <sched.h> +# endif +#elif USE_SOLARIS_THREADS +# include <thread.h> +#endif + +#include "gpgrt-int.h" + +#include "thread.h" + + + +gpg_err_code_t +_gpgrt_yield (void) +{ +#if USE_POSIX_THREADS +# ifdef _POSIX_PRIORITY_SCHEDULING + _gpgrt_pre_syscall (); + sched_yield (); + _gpgrt_post_syscall (); +# else + return GPG_ERR_NOT_SUPPORTED; +# endif +#elif USE_SOLARIS_THREADS + _gpgrt_pre_syscall (); + thr_yield (); + _gpgrt_post_syscall (); +#else + return GPG_ERR_NOT_SUPPORTED; +#endif + + return 0; +} diff --git a/comm/third_party/libgpg-error/src/protos.h b/comm/third_party/libgpg-error/src/protos.h new file mode 100644 index 0000000000..7cc3489e33 --- /dev/null +++ b/comm/third_party/libgpg-error/src/protos.h @@ -0,0 +1,31 @@ +/* protos.h - Miscellaneous prototypes + * Copyright (C) 2020 g10 Code GmbH + * + * This file is part of libgpg-error. + * + * libgpg-error is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * libgpg-error is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <https://www.gnu.org/licenses/>. + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#ifndef _GPGRT_PROTOS_H +#define _GPGRT_PROTOS_H + +/*-- w32-gettext.c --*/ +wchar_t *_gpgrt_utf8_to_wchar (const char *string); +void _gpgrt_free_wchar (wchar_t *wstring); +char *_gpgrt_wchar_to_utf8 (const wchar_t *string, size_t length); +void _gpgrt_w32_set_errno (int ec); + + +#endif /*_GPGRT_PROTOS_H*/ diff --git a/comm/third_party/libgpg-error/src/spawn-posix.c b/comm/third_party/libgpg-error/src/spawn-posix.c new file mode 100644 index 0000000000..ac4c4ce8ae --- /dev/null +++ b/comm/third_party/libgpg-error/src/spawn-posix.c @@ -0,0 +1,886 @@ +/* exechelp.c - Fork and exec helpers for POSIX + * Copyright (C) 2004, 2007-2009, 2010 Free Software Foundation, Inc. + * Copyright (C) 2004, 2006-2012, 2014-2017 g10 Code GmbH + * + * This file is part of Libgpg-error. + * + * Libgpg-error is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgpg-error is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <https://www.gnu.org/licenses/>. + * SPDX-License-Identifier: LGPL-2.1+ + * + * This file was originally a part of GnuPG. + */ + +#include <config.h> + +#if defined(HAVE_W32_SYSTEM) || defined (HAVE_W32CE_SYSTEM) +#error This code is only used on POSIX +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <errno.h> +#ifdef HAVE_SIGNAL_H +# include <signal.h> +#endif +#include <unistd.h> +#include <fcntl.h> + +#include <sys/wait.h> + +#ifdef HAVE_GETRLIMIT +#include <sys/time.h> +#include <sys/resource.h> +#endif /*HAVE_GETRLIMIT*/ + +#ifdef HAVE_STAT +# include <sys/stat.h> +#endif + +#if __linux__ +# include <sys/types.h> +# include <dirent.h> +#endif /*__linux__ */ + +#include "gpgrt-int.h" + + +static void +out_of_core (int line) +{ + _gpgrt_log_fatal ("malloc failed at line %d: %s\n", + line, _gpg_strerror (_gpg_err_code_from_syserror ())); + /*NOTREACHED*/ +} + + +/* Return the maximum number of currently allowed open file + * descriptors. Only useful on POSIX systems but returns a value on + * other systems too. */ +static int +get_max_fds (void) +{ + int max_fds = -1; +#ifdef HAVE_GETRLIMIT + struct rlimit rl; + + /* Under Linux we can figure out the highest used file descriptor by + * reading /proc/PID/fd. This is in the common cases much fast than + * for example doing 4096 close calls where almost all of them will + * fail. On a system with a limit of 4096 files and only 8 files + * open with the highest number being 10, we speedup close_all_fds + * from 125ms to 0.4ms including readdir. + * + * Another option would be to close the file descriptors as returned + * from reading that directory - however then we need to snapshot + * that list before starting to close them. */ +#ifdef __linux__ + { + DIR *dir = NULL; + struct dirent *dir_entry; + const char *s; + int x; + + /* FIXME: Check gpgme on how to do this right on Linux. */ + dir = opendir ("/proc/self/fd"); + if (dir) + { + while ((dir_entry = readdir (dir))) + { + s = dir_entry->d_name; + if ( *s < '0' || *s > '9') + continue; + x = atoi (s); + if (x > max_fds) + max_fds = x; + } + closedir (dir); + } + if (max_fds != -1) + return max_fds + 1; + } +#endif /* __linux__ */ + + +# ifdef RLIMIT_NOFILE + if (!getrlimit (RLIMIT_NOFILE, &rl)) + max_fds = rl.rlim_max; +# endif + +# ifdef RLIMIT_OFILE + if (max_fds == -1 && !getrlimit (RLIMIT_OFILE, &rl)) + max_fds = rl.rlim_max; + +# endif +#endif /*HAVE_GETRLIMIT*/ + +#ifdef _SC_OPEN_MAX + if (max_fds == -1) + { + long int scres = sysconf (_SC_OPEN_MAX); + if (scres >= 0) + max_fds = scres; + } +#endif + +#ifdef _POSIX_OPEN_MAX + if (max_fds == -1) + max_fds = _POSIX_OPEN_MAX; +#endif + +#ifdef OPEN_MAX + if (max_fds == -1) + max_fds = OPEN_MAX; +#endif + + if (max_fds == -1) + max_fds = 256; /* Arbitrary limit. */ + + /* AIX returns INT32_MAX instead of a proper value. We assume that + this is always an error and use an arbitrary limit. */ +#ifdef INT32_MAX + if (max_fds == INT32_MAX) + max_fds = 256; +#endif + + return max_fds; +} + + +/* Close all file descriptors starting with descriptor FIRST. If + * EXCEPT is not NULL, it is expected to be a list of file descriptors + * which shall not be closed. This list shall be sorted in ascending + * order with the end marked by -1. */ +static void +close_all_fds (int first, int *except) +{ + int max_fd = get_max_fds (); + int fd, i, except_start; + + if (except) + { + except_start = 0; + for (fd=first; fd < max_fd; fd++) + { + for (i=except_start; except[i] != -1; i++) + { + if (except[i] == fd) + { + /* If we found the descriptor in the exception list + we can start the next compare run at the next + index because the exception list is ordered. */ + except_start = i + 1; + break; + } + } + if (except[i] == -1) + close (fd); + } + } + else + { + for (fd=first; fd < max_fd; fd++) + close (fd); + } + + _gpg_err_set_errno (0); +} + + +/* Returns an array with all currently open file descriptors. The end + * of the array is marked by -1. The caller needs to release this + * array using the *standard free* and not with xfree. This allow the + * use of this function right at startup even before libgcrypt has + * been initialized. Returns NULL on error and sets ERRNO + * accordingly. + * + * FIXME: Needs to be adjusted for use here. + */ +#if 0 +int * +get_all_open_fds (void) +{ + int *array; + size_t narray; + int fd, max_fd, idx; +#ifndef HAVE_STAT + array = calloc (1, sizeof *array); + if (array) + array[0] = -1; +#else /*HAVE_STAT*/ + struct stat statbuf; + + max_fd = get_max_fds (); + narray = 32; /* If you change this change also t-exechelp.c. */ + array = calloc (narray, sizeof *array); + if (!array) + return NULL; + + /* Note: The list we return is ordered. */ + for (idx=0, fd=0; fd < max_fd; fd++) + if (!(fstat (fd, &statbuf) == -1 && errno == EBADF)) + { + if (idx+1 >= narray) + { + int *tmp; + + narray += (narray < 256)? 32:256; + tmp = realloc (array, narray * sizeof *array); + if (!tmp) + { + free (array); + return NULL; + } + array = tmp; + } + array[idx++] = fd; + } + array[idx] = -1; +#endif /*HAVE_STAT*/ + return array; +} +#endif /*0*/ + + +/* The exec core used right after the fork. This will never return. */ +static void +do_exec (const char *pgmname, const char *argv[], + int fd_in, int fd_out, int fd_err, + int *except, void (*preexec)(void) ) +{ + char **arg_list; + int i, j; + int fds[3]; + + fds[0] = fd_in; + fds[1] = fd_out; + fds[2] = fd_err; + + /* Create the command line argument array. */ + i = 0; + if (argv) + while (argv[i]) + i++; + arg_list = xtrycalloc (i+2, sizeof *arg_list); + if (!arg_list) + out_of_core (__LINE__); + arg_list[0] = strrchr (pgmname, '/'); + if (arg_list[0]) + arg_list[0]++; + else + { + arg_list[0] = xtrystrdup (pgmname); + if (!arg_list[0]) + out_of_core (__LINE__); + } + if (argv) + for (i=0,j=1; argv[i]; i++, j++) + arg_list[j] = (char*)argv[i]; + + /* Assign /dev/null to unused FDs. */ + for (i=0; i <= 2; i++) + { + if (fds[i] == -1 ) + { + fds[i] = open ("/dev/null", i? O_WRONLY : O_RDONLY); + if (fds[i] == -1) + _gpgrt_log_fatal ("failed to open '%s': %s\n", + "/dev/null", strerror (errno)); + } + } + + /* Connect the standard files. */ + for (i=0; i <= 2; i++) + { + if (fds[i] != i && dup2 (fds[i], i) == -1) + _gpgrt_log_fatal ("dup2 std%s failed: %s\n", + i==0?"in":i==1?"out":"err", strerror (errno)); + } + + /* Close all other files. */ + close_all_fds (3, except); + + if (preexec) + preexec (); + execv (pgmname, arg_list); + /* No way to print anything, as we have may have closed all streams. */ + _exit (127); +} + + +/* Helper for _gpgrt_make_pipe. */ +static gpg_err_code_t +do_create_pipe (int filedes[2]) +{ + gpg_error_t err = 0; + + _gpgrt_pre_syscall (); + if (pipe (filedes) == -1) + { + err = _gpg_err_code_from_syserror (); + filedes[0] = filedes[1] = -1; + } + _gpgrt_post_syscall (); + + return err; +} + + +/* Helper for _gpgrt_make_pipe. */ +static gpg_err_code_t +do_create_pipe_and_estream (int filedes[2], estream_t *r_fp, + int outbound, int nonblock) +{ + gpg_err_code_t err; + + _gpgrt_pre_syscall (); + if (pipe (filedes) == -1) + { + err = _gpg_err_code_from_syserror (); + _gpgrt_log_error (_("error creating a pipe: %s\n"), _gpg_strerror (err)); + filedes[0] = filedes[1] = -1; + *r_fp = NULL; + return err; + } + _gpgrt_post_syscall (); + + if (!outbound) + *r_fp = _gpgrt_fdopen (filedes[0], nonblock? "r,nonblock" : "r"); + else + *r_fp = _gpgrt_fdopen (filedes[1], nonblock? "w,nonblock" : "w"); + if (!*r_fp) + { + err = _gpg_err_code_from_syserror (); + _gpgrt_log_error (_("error creating a stream for a pipe: %s\n"), + _gpg_strerror (err)); + close (filedes[0]); + close (filedes[1]); + filedes[0] = filedes[1] = -1; + return err; + } + return 0; +} + + +/* Create a pipe. The DIRECTION parameter gives the type of the created pipe: + * DIRECTION < 0 := Inbound pipe: On Windows the write end is inheritable. + * DIRECTION > 0 := Outbound pipe: On Windows the read end is inheritable. + * If R_FP is NULL a standard pipe and no stream is created, DIRECTION + * should then be 0. */ +gpg_err_code_t +_gpgrt_make_pipe (int filedes[2], estream_t *r_fp, int direction, + int nonblock) +{ + if (r_fp && direction) + return do_create_pipe_and_estream (filedes, r_fp, + (direction > 0), nonblock); + else + return do_create_pipe (filedes); +} + + +/* Fork and exec the PGMNAME, see gpgrt-int.h for details. */ +gpg_err_code_t +_gpgrt_spawn_process (const char *pgmname, const char *argv[], + int *except, void (*preexec)(void), unsigned int flags, + estream_t *r_infp, + estream_t *r_outfp, + estream_t *r_errfp, + pid_t *pid) +{ + gpg_error_t err; + int inpipe[2] = {-1, -1}; + int outpipe[2] = {-1, -1}; + int errpipe[2] = {-1, -1}; + estream_t infp = NULL; + estream_t outfp = NULL; + estream_t errfp = NULL; + int nonblock = !!(flags & GPGRT_SPAWN_NONBLOCK); + + if (r_infp) + *r_infp = NULL; + if (r_outfp) + *r_outfp = NULL; + if (r_errfp) + *r_errfp = NULL; + *pid = (pid_t)(-1); /* Always required. */ + + if (r_infp) + { + err = _gpgrt_create_outbound_pipe (inpipe, &infp, nonblock); + if (err) + return err; + } + + if (r_outfp) + { + err = _gpgrt_create_inbound_pipe (outpipe, &outfp, nonblock); + if (err) + { + if (infp) + _gpgrt_fclose (infp); + else if (inpipe[1] != -1) + close (inpipe[1]); + if (inpipe[0] != -1) + close (inpipe[0]); + + return err; + } + } + + if (r_errfp) + { + err = _gpgrt_create_inbound_pipe (errpipe, &errfp, nonblock); + if (err) + { + if (infp) + _gpgrt_fclose (infp); + else if (inpipe[1] != -1) + close (inpipe[1]); + if (inpipe[0] != -1) + close (inpipe[0]); + + if (outfp) + _gpgrt_fclose (outfp); + else if (outpipe[0] != -1) + close (outpipe[0]); + if (outpipe[1] != -1) + close (outpipe[1]); + + return err; + } + } + + _gpgrt_pre_syscall (); + *pid = fork (); + _gpgrt_post_syscall (); + if (*pid == (pid_t)(-1)) + { + err = _gpg_err_code_from_syserror (); + _gpgrt_log_error (_("error forking process: %s\n"), _gpg_strerror (err)); + + if (infp) + _gpgrt_fclose (infp); + else if (inpipe[1] != -1) + close (inpipe[1]); + if (inpipe[0] != -1) + close (inpipe[0]); + + if (outfp) + _gpgrt_fclose (outfp); + else if (outpipe[0] != -1) + close (outpipe[0]); + if (outpipe[1] != -1) + close (outpipe[1]); + + if (errfp) + _gpgrt_fclose (errfp); + else if (errpipe[0] != -1) + close (errpipe[0]); + if (errpipe[1] != -1) + close (errpipe[1]); + return err; + } + + if (!*pid) + { + /* This is the child. */ + /* FIXME: Needs to be done by preexec: + gcry_control (GCRYCTL_TERM_SECMEM); */ + _gpgrt_fclose (infp); + _gpgrt_fclose (outfp); + _gpgrt_fclose (errfp); + do_exec (pgmname, argv, inpipe[0], outpipe[1], errpipe[1], + except, preexec); + /*NOTREACHED*/ + } + + /* This is the parent. */ + if (inpipe[0] != -1) + close (inpipe[0]); + if (outpipe[1] != -1) + close (outpipe[1]); + if (errpipe[1] != -1) + close (errpipe[1]); + + if (r_infp) + *r_infp = infp; + if (r_outfp) + *r_outfp = outfp; + if (r_errfp) + *r_errfp = errfp; + + return 0; +} + + +/* Fork and exec the PGMNAME using FDs, see gpgrt-int.h for details. */ +gpg_err_code_t +_gpgrt_spawn_process_fd (const char *pgmname, const char *argv[], + int infd, int outfd, int errfd, pid_t *pid) +{ + gpg_error_t err; + + _gpgrt_pre_syscall (); + *pid = fork (); + _gpgrt_post_syscall (); + if (*pid == (pid_t)(-1)) + { + err = _gpg_err_code_from_syserror (); + _gpgrt_log_error (_("error forking process: %s\n"), _gpg_strerror (err)); + return err; + } + + if (!*pid) + { + /* FIXME: We need to add a preexec so that a + gcry_control (GCRYCTL_TERM_SECMEM); + can be done. */ + /* Run child. */ + do_exec (pgmname, argv, infd, outfd, errfd, NULL, NULL); + /*NOTREACHED*/ + } + + return 0; +} + + +/* Waiting for child processes. + * + * waitpid(2) may return information about terminated children that we + * did not yet request, and there is no portable way to wait for a + * specific set of children. + * + * As a workaround, we store the results of children for later use. + * + * XXX: This assumes that PIDs are not reused too quickly. + * FIXME: This is not thread-safe. + */ + +struct terminated_child +{ + pid_t pid; + int exitcode; + struct terminated_child *next; +}; + +static struct terminated_child *terminated_children; + + +static gpg_err_code_t +store_result (pid_t pid, int exitcode) +{ + struct terminated_child *c; + + c = xtrymalloc (sizeof *c); + if (c == NULL) + return _gpg_err_code_from_syserror (); + + c->pid = pid; + c->exitcode = exitcode; + c->next = terminated_children; + terminated_children = c; + + return 0; +} + + +static int +get_result (pid_t pid, int *r_exitcode) +{ + struct terminated_child *c, **prevp; + + for (prevp = &terminated_children, c = terminated_children; + c; + prevp = &c->next, c = c->next) + if (c->pid == pid) + { + *prevp = c->next; + *r_exitcode = c->exitcode; + xfree (c); + return 1; + } + + return 0; +} + + +/* See gpgrt-int.h for a description. */ +gpg_err_code_t +_gpgrt_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode) +{ + gpg_err_code_t ec; + int i, status; + + if (r_exitcode) + *r_exitcode = -1; + + if (pid == (pid_t)(-1)) + return GPG_ERR_INV_VALUE; + + _gpgrt_pre_syscall (); + while ((i=waitpid (pid, &status, hang? 0:WNOHANG)) == (pid_t)(-1) + && errno == EINTR); + _gpgrt_post_syscall (); + + if (i == (pid_t)(-1)) + { + ec = _gpg_err_code_from_syserror (); + _gpgrt_log_error (_("waiting for process %d to terminate failed: %s\n"), + (int)pid, _gpg_strerror (ec)); + } + else if (!i) + { + ec = GPG_ERR_TIMEOUT; /* Still running. */ + } + else if (WIFEXITED (status) && WEXITSTATUS (status) == 127) + { + /* FIXME: This is GnuPG specific. */ + _gpgrt_log_error (_("error running '%s': probably not installed\n"), + pgmname); + ec = GPG_ERR_CONFIGURATION; + } + else if (WIFEXITED (status) && WEXITSTATUS (status)) + { + if (!r_exitcode) + _gpgrt_log_error (_("error running '%s': exit status %d\n"), pgmname, + WEXITSTATUS (status)); + else + *r_exitcode = WEXITSTATUS (status); + ec = GPG_ERR_GENERAL; + } + else if (!WIFEXITED (status)) + { + _gpgrt_log_error (_("error running '%s': terminated\n"), pgmname); + ec = GPG_ERR_GENERAL; + } + else + { + if (r_exitcode) + *r_exitcode = 0; + ec = 0; + } + + return ec; +} + + +/* See gpgrt-int.h for a description. + * + * FIXME: What about using a poll like data structure for the pids and + * their exit codes? The whole thing is anyway problematic in a + * threaded processs because waitpid has no association between PIDS + * and threads. + */ +gpg_err_code_t +_gpgrt_wait_processes (const char **pgmnames, pid_t *pids, size_t count, + int hang, int *r_exitcodes) +{ + gpg_err_code_t ec = 0; + size_t i, left; + int *dummy = NULL; + + if (!r_exitcodes) + { + dummy = r_exitcodes = xtrymalloc (sizeof *r_exitcodes * count); + if (!dummy) + return _gpg_err_code_from_syserror (); + } + + for (i = 0, left = count; i < count; i++) + { + int status = -1; + + if (pids[i] == (pid_t)(-1)) + return GPG_ERR_INV_VALUE; + + /* See if there was a previously stored result for this pid. */ + if (get_result (pids[i], &status)) + left -= 1; + + r_exitcodes[i] = status; + } + + while (left > 0) + { + pid_t pid; + int status; + + _gpgrt_pre_syscall (); + while ((pid = waitpid (-1, &status, hang ? 0 : WNOHANG)) == (pid_t)(-1) + && errno == EINTR); + _gpgrt_post_syscall (); + + if (pid == (pid_t)(-1)) + { + ec = _gpg_err_code_from_syserror (); + _gpgrt_log_error (_("waiting for processes to terminate" + " failed: %s\n"), _gpg_strerror (ec)); + break; + } + else if (!pid) + { + ec = GPG_ERR_TIMEOUT; /* Still running. */ + break; + } + else + { + for (i = 0; i < count; i++) + if (pid == pids[i]) + break; + + if (i == count) + { + /* No match, store this result. */ + ec = store_result (pid, status); + if (ec) + break; + continue; + } + + /* Process PIDS[i] died. */ + if (r_exitcodes[i] != (pid_t) -1) + { + _gpgrt_log_error ("PID %d was reused", (int)pid); + ec = GPG_ERR_GENERAL; + break; + } + + left -= 1; + r_exitcodes[i] = status; + } + } + + for (i = 0; i < count; i++) + { + if (r_exitcodes[i] == -1) + continue; + + if (WIFEXITED (r_exitcodes[i]) && WEXITSTATUS (r_exitcodes[i]) == 127) + { + _gpgrt_log_error (_("error running '%s': probably not installed\n"), + pgmnames[i]); + ec = GPG_ERR_CONFIGURATION; + } + else if (WIFEXITED (r_exitcodes[i]) && WEXITSTATUS (r_exitcodes[i])) + { + if (dummy) + _gpgrt_log_error (_("error running '%s': exit status %d\n"), + pgmnames[i], WEXITSTATUS (r_exitcodes[i])); + else + r_exitcodes[i] = WEXITSTATUS (r_exitcodes[i]); + ec = GPG_ERR_GENERAL; + } + else if (!WIFEXITED (r_exitcodes[i])) + { + _gpgrt_log_error (_("error running '%s': terminated\n"), pgmnames[i]); + ec = GPG_ERR_GENERAL; + } + } + + xfree (dummy); + return ec; +} + + +/* See gpgrt-int.h for a description. FIXME: We should add a prexec + * callback. */ +gpg_err_code_t +_gpgrt_spawn_process_detached (const char *pgmname, const char *argv[], + const char *envp[] ) +{ + gpg_err_code_t ec; + pid_t pid; + int i; + + /* FIXME: Is this GnuPG specific or should we keep it. */ + if (getuid() != geteuid()) + return GPG_ERR_BUG; + + if (access (pgmname, X_OK)) + return _gpg_err_code_from_syserror (); + + _gpgrt_pre_syscall (); + pid = fork (); + _gpgrt_post_syscall (); + if (pid == (pid_t)(-1)) + { + ec = _gpg_err_code_from_syserror (); + _gpgrt_log_error (_("error forking process: %s\n"), _gpg_strerror (ec)); + return ec; + } + + if (!pid) + { + pid_t pid2; + + /* gcry_control (GCRYCTL_TERM_SECMEM); */ + if (setsid() == -1 || chdir ("/")) + _exit (1); + + pid2 = fork (); /* Double fork to let init take over the new child. */ + if (pid2 == (pid_t)(-1)) + _exit (1); + if (pid2) + _exit (0); /* Let the parent exit immediately. */ + + for (i=0; envp && envp[i]; i++) + { + char *p = xtrystrdup (envp[i]); + if (!p) + out_of_core (__LINE__); + putenv (p); + } + + do_exec (pgmname, argv, -1, -1, -1, NULL, NULL); + /*NOTREACHED*/ + } + + _gpgrt_pre_syscall (); + if (waitpid (pid, NULL, 0) == -1) + { + _gpgrt_post_syscall (); + ec = _gpg_err_code_from_syserror (); + _gpgrt_log_error ("waitpid failed in gpgrt_spawn_process_detached: %s", + _gpg_strerror (ec)); + return ec; + } + else + _gpgrt_post_syscall (); + + return 0; +} + + +/* Kill a process; that is send an appropriate signal to the process. + * gnupg_wait_process must be called to actually remove the process + from the system. An invalid PID is ignored. */ +void +_gpgrt_kill_process (pid_t pid) +{ + if (pid != (pid_t)(-1)) + { + _gpgrt_pre_syscall (); + kill (pid, SIGTERM); + _gpgrt_post_syscall (); + } +} + + +void +_gpgrt_release_process (pid_t pid) +{ + (void)pid; +} diff --git a/comm/third_party/libgpg-error/src/spawn-w32.c b/comm/third_party/libgpg-error/src/spawn-w32.c new file mode 100644 index 0000000000..3ede1f2149 --- /dev/null +++ b/comm/third_party/libgpg-error/src/spawn-w32.c @@ -0,0 +1,920 @@ +/* spawn-w32.c - Fork and exec helpers for W32. + * Copyright (C) 2004, 2007-2009, 2010 Free Software Foundation, Inc. + * Copyright (C) 2004, 2006-2012, 2014-2017 g10 Code GmbH + * + * This file is part of Libgpg-error. + * + * Libgpg-error is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgpg-error is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <https://www.gnu.org/licenses/>. + * SPDX-License-Identifier: LGPL-2.1+ + * + * This file was originally a part of GnuPG. + */ + +#include <config.h> + +#if !defined(HAVE_W32_SYSTEM) || defined (HAVE_W32CE_SYSTEM) +#error This code is only used on W32. +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#ifdef HAVE_SIGNAL_H +# include <signal.h> +#endif +#include <unistd.h> +#include <fcntl.h> +#ifdef HAVE_STAT +# include <sys/stat.h> +#endif +#define WIN32_LEAN_AND_MEAN /* We only need the OS core stuff. */ +#include <windows.h> + +#include "gpgrt-int.h" + +/* Define to 1 do enable debugging. */ +#define DEBUG_W32_SPAWN 0 + + +/* It seems Vista doesn't grok X_OK and so fails access() tests. + * Previous versions interpreted X_OK as F_OK anyway, so we'll just + * use F_OK directly. */ +#undef X_OK +#define X_OK F_OK + +/* For HANDLE and the internal file descriptor (fd) of this module: + * HANDLE can be represented by an intptr_t which should be true for + * all systems (HANDLE is defined as void *). Further, we assume that + * -1 denotes an invalid handle. + * + * Note that a C run-time file descriptor (the exposed one to API) is + * always represented by an int. + */ +#define fd_to_handle(a) ((HANDLE)(a)) +#define handle_to_fd(a) ((intptr_t)(a)) + +/* For pid_t and HANDLE: + + * We assume that a HANDLE can be represented by an int which should + * be true for all i386 systems. + * + * On 64-bit machine, it is no longer true, as a type, however, as + * long as the range of the value in the type HANDLE can be + * represented by an int, it works. + * + * FIXME: Breaking ABI for pid_t will be needed when the value won't + * fit within 32-bit range on 64-bit machine. + */ +#define pid_to_handle(a) ((HANDLE)(a)) +#define handle_to_pid(a) ((int)(a)) + + +/* Return the maximum number of currently allowed open file + * descriptors. Only useful on POSIX systems but returns a value on + * other systems too. */ +int +get_max_fds (void) +{ + int max_fds = -1; + +#ifdef OPEN_MAX + if (max_fds == -1) + max_fds = OPEN_MAX; +#endif + + if (max_fds == -1) + max_fds = 256; /* Arbitrary limit. */ + + return max_fds; +} + + +/* Under Windows this is a dummy function. */ +/* static void */ +/* close_all_fds (int first, int *except) */ +/* { */ +/* (void)first; */ +/* (void)except; */ +/* } */ + + +/* Returns an array with all currently open file descriptors. The end + * of the array is marked by -1. The caller needs to release this + * array using the *standard free* and not with xfree. This allow the + * use of this function right at startup even before libgcrypt has + * been initialized. Returns NULL on error and sets ERRNO + * accordingly. Note that fstat prints a warning to DebugView for all + * invalid fds which is a bit annoying. We actually do not need this + * function in real code (close_all_fds is a dummy anyway) but we keep + * it for use by t-exechelp.c. */ +#if 0 +int * +get_all_open_fds (void) +{ + int *array; + size_t narray; + int fd, max_fd, idx; +#ifndef HAVE_STAT + array = calloc (1, sizeof *array); + if (array) + array[0] = -1; +#else /*HAVE_STAT*/ + struct stat statbuf; + + max_fd = get_max_fds (); + narray = 32; /* If you change this change also t-exechelp.c. */ + array = calloc (narray, sizeof *array); + if (!array) + return NULL; + + /* Note: The list we return is ordered. */ + for (idx=0, fd=0; fd < max_fd; fd++) + if (!(fstat (fd, &statbuf) == -1 && errno == EBADF)) + { + if (idx+1 >= narray) + { + int *tmp; + + narray += (narray < 256)? 32:256; + tmp = realloc (array, narray * sizeof *array); + if (!tmp) + { + free (array); + return NULL; + } + array = tmp; + } + array[idx++] = fd; + } + array[idx] = -1; +#endif /*HAVE_STAT*/ + return array; +} +#endif + + +/* Helper function to build_w32_commandline. */ +static char * +build_w32_commandline_copy (char *buffer, const char *string) +{ + char *p = buffer; + const char *s; + + if (!*string) /* Empty string. */ + p = stpcpy (p, "\"\""); + else if (strpbrk (string, " \t\n\v\f\"")) + { + /* Need to do some kind of quoting. */ + p = stpcpy (p, "\""); + for (s=string; *s; s++) + { + *p++ = *s; + if (*s == '\"') + *p++ = *s; + } + *p++ = '\"'; + *p = 0; + } + else + p = stpcpy (p, string); + + return p; +} + + +/* Build a command line for use with W32's CreateProcess. On success + * CMDLINE gets the address of a newly allocated string. */ +static gpg_err_code_t +build_w32_commandline (const char *pgmname, const char * const *argv, + char **cmdline) +{ + int i, n; + const char *s; + char *buf, *p; + + *cmdline = NULL; + n = 0; + s = pgmname; + n += strlen (s) + 1 + 2; /* (1 space, 2 quoting */ + for (; *s; s++) + if (*s == '\"') + n++; /* Need to double inner quotes. */ + for (i=0; (s=argv[i]); i++) + { + n += strlen (s) + 1 + 2; /* (1 space, 2 quoting */ + for (; *s; s++) + if (*s == '\"') + n++; /* Need to double inner quotes. */ + } + n++; + + buf = p = xtrymalloc (n); + if (!buf) + return _gpg_err_code_from_syserror (); + + p = build_w32_commandline_copy (p, pgmname); + for (i=0; argv[i]; i++) + { + *p++ = ' '; + p = build_w32_commandline_copy (p, argv[i]); + } + + *cmdline= buf; + return 0; +} + + +#define INHERIT_READ 1 +#define INHERIT_WRITE 2 +#define INHERIT_BOTH (INHERIT_READ|INHERIT_WRITE) + +/* Create pipe. FLAGS indicates which ends are inheritable. */ +static int +create_inheritable_pipe (HANDLE filedes[2], int flags) +{ + HANDLE r, w; + SECURITY_ATTRIBUTES sec_attr; + + memset (&sec_attr, 0, sizeof sec_attr ); + sec_attr.nLength = sizeof sec_attr; + sec_attr.bInheritHandle = TRUE; + + _gpgrt_pre_syscall (); + if (!CreatePipe (&r, &w, &sec_attr, 0)) + { + _gpgrt_post_syscall (); + return -1; + } + _gpgrt_post_syscall (); + + if ((flags & INHERIT_READ) == 0) + if (! SetHandleInformation (r, HANDLE_FLAG_INHERIT, 0)) + goto fail; + + if ((flags & INHERIT_WRITE) == 0) + if (! SetHandleInformation (w, HANDLE_FLAG_INHERIT, 0)) + goto fail; + + filedes[0] = r; + filedes[1] = w; + return 0; + + fail: + _gpgrt_log_error ("SetHandleInformation failed: ec=%d\n", + (int)GetLastError ()); + CloseHandle (r); + CloseHandle (w); + return -1; +} + + +static HANDLE +w32_open_null (int for_write) +{ + HANDLE hfile; + + hfile = CreateFileW (L"nul", + for_write? GENERIC_WRITE : GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, 0, NULL); + if (hfile == INVALID_HANDLE_VALUE) + _gpgrt_log_debug ("can't open 'nul': ec=%d\n", (int)GetLastError ()); + return hfile; +} + + +static gpg_err_code_t +do_create_pipe_and_estream (int filedes[2], + estream_t *r_fp, int direction, int nonblock) +{ + gpg_err_code_t err = 0; + int flags; + HANDLE fds[2]; + gpgrt_syshd_t syshd; + + if (direction < 0) + flags = INHERIT_WRITE; + else if (direction > 0) + flags = INHERIT_READ; + else + flags = INHERIT_BOTH; + + filedes[0] = filedes[1] = -1; + err = GPG_ERR_GENERAL; + if (!create_inheritable_pipe (fds, flags)) + { + filedes[0] = _open_osfhandle (handle_to_fd (fds[0]), O_RDONLY); + if (filedes[0] == -1) + { + _gpgrt_log_error ("failed to translate osfhandle %p\n", fds[0]); + CloseHandle (fds[1]); + } + else + { + filedes[1] = _open_osfhandle (handle_to_fd (fds[1]), O_APPEND); + if (filedes[1] == -1) + { + _gpgrt_log_error ("failed to translate osfhandle %p\n", fds[1]); + close (filedes[0]); + filedes[0] = -1; + CloseHandle (fds[1]); + } + else + err = 0; + } + } + + if (! err && r_fp) + { + syshd.type = ES_SYSHD_HANDLE; + if (direction < 0) + { + syshd.u.handle = fds[0]; + *r_fp = _gpgrt_sysopen (&syshd, nonblock? "r,nonblock" : "r"); + } + else + { + syshd.u.handle = fds[1]; + *r_fp = _gpgrt_sysopen (&syshd, nonblock? "w,nonblock" : "w"); + } + if (!*r_fp) + { + err = _gpg_err_code_from_syserror (); + _gpgrt_log_error (_("error creating a stream for a pipe: %s\n"), + _gpg_strerror (err)); + close (filedes[0]); + close (filedes[1]); + filedes[0] = filedes[1] = -1; + return err; + } + } + + return err; +} + + +/* Create a pipe. The DIRECTION parameter gives the type of the created pipe: + * DIRECTION < 0 := Inbound pipe: On Windows the write end is inheritable. + * DIRECTION > 0 := Outbound pipe: On Windows the read end is inheritable. + * If R_FP is NULL a standard pipe and no stream is created, DIRECTION + * should then be 0. */ +gpg_err_code_t +_gpgrt_make_pipe (int filedes[2], estream_t *r_fp, int direction, int nonblock) +{ + if (r_fp && direction) + return do_create_pipe_and_estream (filedes, r_fp, direction, nonblock); + else + return do_create_pipe_and_estream (filedes, NULL, 0, 0); +} + + +/* Fork and exec the PGMNAME, see gpgrt-int.h for details. */ +gpg_err_code_t +_gpgrt_spawn_process (const char *pgmname, const char *argv[], + int *except, void (*preexec)(void), unsigned int flags, + estream_t *r_infp, estream_t *r_outfp, estream_t *r_errfp, + pid_t *pid) +{ + gpg_err_code_t err; + SECURITY_ATTRIBUTES sec_attr; + PROCESS_INFORMATION pi = + { + NULL, /* Returns process handle. */ + 0, /* Returns primary thread handle. */ + 0, /* Returns pid. */ + 0 /* Returns tid. */ + }; + STARTUPINFO si; + int cr_flags; + char *cmdline; + HANDLE inpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}; + HANDLE outpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}; + HANDLE errpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}; + estream_t infp = NULL; + estream_t outfp = NULL; + estream_t errfp = NULL; + HANDLE nullhd[3] = {INVALID_HANDLE_VALUE, + INVALID_HANDLE_VALUE, + INVALID_HANDLE_VALUE}; + int i; + es_syshd_t syshd; + int nonblock = !!(flags & GPGRT_SPAWN_NONBLOCK); + int ret; + + (void)except; /* Not yet used. */ + + if (r_infp) + *r_infp = NULL; + if (r_outfp) + *r_outfp = NULL; + if (r_errfp) + *r_errfp = NULL; + *pid = (pid_t)(-1); /* Always required. */ + + if (r_infp) + { + if (create_inheritable_pipe (inpipe, INHERIT_READ)) + { + err = GPG_ERR_GENERAL; + _gpgrt_log_error (_("error creating a pipe: %s\n"), + _gpg_strerror (err)); + return err; + } + + syshd.type = ES_SYSHD_HANDLE; + syshd.u.handle = inpipe[1]; + infp = _gpgrt_sysopen (&syshd, nonblock? "w,nonblock" : "w"); + if (!infp) + { + err = _gpg_err_code_from_syserror (); + _gpgrt_log_error (_("error creating a stream for a pipe: %s\n"), + _gpg_strerror (err)); + CloseHandle (inpipe[0]); + CloseHandle (inpipe[1]); + inpipe[0] = inpipe[1] = INVALID_HANDLE_VALUE; + return err; + } + } + + if (r_outfp) + { + if (create_inheritable_pipe (outpipe, INHERIT_WRITE)) + { + err = GPG_ERR_GENERAL; + _gpgrt_log_error (_("error creating a pipe: %s\n"), + _gpg_strerror (err)); + return err; + } + + syshd.type = ES_SYSHD_HANDLE; + syshd.u.handle = outpipe[0]; + outfp = _gpgrt_sysopen (&syshd, nonblock? "r,nonblock" : "r"); + if (!outfp) + { + err = _gpg_err_code_from_syserror (); + _gpgrt_log_error (_("error creating a stream for a pipe: %s\n"), + _gpg_strerror (err)); + CloseHandle (outpipe[0]); + CloseHandle (outpipe[1]); + outpipe[0] = outpipe[1] = INVALID_HANDLE_VALUE; + if (infp) + _gpgrt_fclose (infp); + else if (inpipe[1] != INVALID_HANDLE_VALUE) + CloseHandle (inpipe[1]); + if (inpipe[0] != INVALID_HANDLE_VALUE) + CloseHandle (inpipe[0]); + return err; + } + } + + if (r_errfp) + { + if (create_inheritable_pipe (errpipe, INHERIT_WRITE)) + { + err = GPG_ERR_GENERAL; + _gpgrt_log_error (_("error creating a pipe: %s\n"), + _gpg_strerror (err)); + return err; + } + + syshd.type = ES_SYSHD_HANDLE; + syshd.u.handle = errpipe[0]; + errfp = _gpgrt_sysopen (&syshd, nonblock? "r,nonblock" : "r"); + if (!errfp) + { + err = _gpg_err_code_from_syserror (); + _gpgrt_log_error (_("error creating a stream for a pipe: %s\n"), + _gpg_strerror (err)); + CloseHandle (errpipe[0]); + CloseHandle (errpipe[1]); + errpipe[0] = errpipe[1] = INVALID_HANDLE_VALUE; + if (outfp) + _gpgrt_fclose (outfp); + else if (outpipe[0] != INVALID_HANDLE_VALUE) + CloseHandle (outpipe[0]); + if (outpipe[1] != INVALID_HANDLE_VALUE) + CloseHandle (outpipe[1]); + if (infp) + _gpgrt_fclose (infp); + else if (inpipe[1] != INVALID_HANDLE_VALUE) + CloseHandle (inpipe[1]); + if (inpipe[0] != INVALID_HANDLE_VALUE) + CloseHandle (inpipe[0]); + return err; + } + } + + /* Prepare security attributes. */ + memset (&sec_attr, 0, sizeof sec_attr ); + sec_attr.nLength = sizeof sec_attr; + sec_attr.bInheritHandle = FALSE; + + /* Build the command line. */ + err = build_w32_commandline (pgmname, argv, &cmdline); + if (err) + return err; + + if (inpipe[0] == INVALID_HANDLE_VALUE) + nullhd[0] = w32_open_null (0); + if (outpipe[1] == INVALID_HANDLE_VALUE) + nullhd[1] = w32_open_null (1); + if (errpipe[1] == INVALID_HANDLE_VALUE) + nullhd[2] = w32_open_null (1); + + /* Start the process. Note that we can't run the PREEXEC function + because this might change our own environment. */ + (void)preexec; + + memset (&si, 0, sizeof si); + si.cb = sizeof (si); + si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; + si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE; + si.hStdInput = inpipe[0] == INVALID_HANDLE_VALUE? nullhd[0] : inpipe[0]; + si.hStdOutput = outpipe[1] == INVALID_HANDLE_VALUE? nullhd[1] : outpipe[1]; + si.hStdError = errpipe[1] == INVALID_HANDLE_VALUE? nullhd[2] : errpipe[1]; + + cr_flags = (CREATE_DEFAULT_ERROR_MODE + | ((flags & GPGRT_SPAWN_DETACHED)? DETACHED_PROCESS : 0) + | GetPriorityClass (GetCurrentProcess ()) + | CREATE_SUSPENDED); + _gpgrt_log_debug ("CreateProcess, path='%s' cmdline='%s'\n", + pgmname, cmdline); + ret = CreateProcess (pgmname, /* Program to start. */ + cmdline, /* Command line arguments. */ + &sec_attr, /* Process security attributes. */ + &sec_attr, /* Thread security attributes. */ + TRUE, /* Inherit handles. */ + cr_flags, /* Creation flags. */ + NULL, /* Environment. */ + NULL, /* Use current drive/directory. */ + &si, /* Startup information. */ + &pi /* Returns process information. */ + ); + if (!ret) + { + _gpgrt_log_error ("CreateProcess failed: ec=%d\n", (int)GetLastError ()); + xfree (cmdline); + if (infp) + _gpgrt_fclose (infp); + else if (inpipe[1] != INVALID_HANDLE_VALUE) + CloseHandle (outpipe[1]); + if (inpipe[0] != INVALID_HANDLE_VALUE) + CloseHandle (inpipe[0]); + if (outfp) + _gpgrt_fclose (outfp); + else if (outpipe[0] != INVALID_HANDLE_VALUE) + CloseHandle (outpipe[0]); + if (outpipe[1] != INVALID_HANDLE_VALUE) + CloseHandle (outpipe[1]); + if (errfp) + _gpgrt_fclose (errfp); + else if (errpipe[0] != INVALID_HANDLE_VALUE) + CloseHandle (errpipe[0]); + if (errpipe[1] != INVALID_HANDLE_VALUE) + CloseHandle (errpipe[1]); + return GPG_ERR_GENERAL; + } + xfree (cmdline); + cmdline = NULL; + + /* Close the inherited handles to /dev/null. */ + for (i=0; i < DIM (nullhd); i++) + if (nullhd[i] != INVALID_HANDLE_VALUE) + CloseHandle (nullhd[i]); + + /* Close the inherited ends of the pipes. */ + if (inpipe[0] != INVALID_HANDLE_VALUE) + CloseHandle (inpipe[0]); + if (outpipe[1] != INVALID_HANDLE_VALUE) + CloseHandle (outpipe[1]); + if (errpipe[1] != INVALID_HANDLE_VALUE) + CloseHandle (errpipe[1]); + + _gpgrt_log_debug ("CreateProcess ready: hProcess=%p hThread=%p" + " dwProcessID=%d dwThreadId=%d\n", + pi.hProcess, pi.hThread, + (int) pi.dwProcessId, (int) pi.dwThreadId); + _gpgrt_log_debug (" outfp=%p errfp=%p\n", outfp, errfp); + + if ((flags & GPGRT_SPAWN_RUN_ASFW)) + { + /* Fixme: For unknown reasons AllowSetForegroundWindow returns + * an invalid argument error if we pass it the correct + * processID. As a workaround we use -1 (ASFW_ANY). */ + if (!AllowSetForegroundWindow (ASFW_ANY /*pi.dwProcessId*/)) + _gpgrt_log_info ("AllowSetForegroundWindow() failed: ec=%d\n", + (int)GetLastError ()); + } + + /* Process has been created suspended; resume it now. */ + _gpgrt_pre_syscall (); + ResumeThread (pi.hThread); + CloseHandle (pi.hThread); + _gpgrt_post_syscall (); + + if (r_infp) + *r_infp = infp; + if (r_outfp) + *r_outfp = outfp; + if (r_errfp) + *r_errfp = errfp; + + *pid = handle_to_pid (pi.hProcess); + return 0; +} + + +/* Fork and exec the PGMNAME using FDs, see gpgrt-int.h for details. */ +gpg_err_code_t +_gpgrt_spawn_process_fd (const char *pgmname, const char *argv[], + int infd, int outfd, int errfd, pid_t *pid) +{ + gpg_err_code_t err; + SECURITY_ATTRIBUTES sec_attr; + PROCESS_INFORMATION pi = { NULL, 0, 0, 0 }; + STARTUPINFO si; + char *cmdline; + int ret, i; + HANDLE stdhd[3]; + + /* Setup return values. */ + *pid = (pid_t)(-1); + + /* Prepare security attributes. */ + memset (&sec_attr, 0, sizeof sec_attr ); + sec_attr.nLength = sizeof sec_attr; + sec_attr.bInheritHandle = FALSE; + + /* Build the command line. */ + err = build_w32_commandline (pgmname, argv, &cmdline); + if (err) + return err; + + memset (&si, 0, sizeof si); + si.cb = sizeof (si); + si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; + si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE; + stdhd[0] = infd == -1? w32_open_null (0) : INVALID_HANDLE_VALUE; + stdhd[1] = outfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE; + stdhd[2] = errfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE; + si.hStdInput = infd == -1? stdhd[0] : (void*)_get_osfhandle (infd); + si.hStdOutput = outfd == -1? stdhd[1] : (void*)_get_osfhandle (outfd); + si.hStdError = errfd == -1? stdhd[2] : (void*)_get_osfhandle (errfd); + + _gpgrt_log_debug ("CreateProcess, path='%s' cmdline='%s'\n", + pgmname, cmdline); + ret = CreateProcess (pgmname, /* Program to start. */ + cmdline, /* Command line arguments. */ + &sec_attr, /* Process security attributes. */ + &sec_attr, /* Thread security attributes. */ + TRUE, /* Inherit handles. */ + (CREATE_DEFAULT_ERROR_MODE + | GetPriorityClass (GetCurrentProcess ()) + | CREATE_SUSPENDED | DETACHED_PROCESS), + NULL, /* Environment. */ + NULL, /* Use current drive/directory. */ + &si, /* Startup information. */ + &pi /* Returns process information. */ + ); + if (!ret) + { + _gpgrt_log_error ("CreateProcess failed: ec=%d\n", (int)GetLastError ()); + err = GPG_ERR_GENERAL; + } + else + err = 0; + + xfree (cmdline); + + for (i=0; i < 3; i++) + if (stdhd[i] != INVALID_HANDLE_VALUE) + CloseHandle (stdhd[i]); + + if (err) + return err; + + _gpgrt_log_debug ("CreateProcess ready: hProcess=%p hThread=%p" + " dwProcessID=%d dwThreadId=%d\n", + pi.hProcess, pi.hThread, + (int) pi.dwProcessId, (int) pi.dwThreadId); + + /* Process has been created suspended; resume it now. */ + ResumeThread (pi.hThread); + CloseHandle (pi.hThread); + + *pid = handle_to_pid (pi.hProcess); + return 0; +} + + +/* See gpgrt-int.h for a description. */ +gpg_err_code_t +_gpgrt_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode) +{ + return _gpgrt_wait_processes (&pgmname, &pid, 1, hang, r_exitcode); +} + + +/* See gpgrt-int.h for a description. */ +gpg_err_code_t +_gpgrt_wait_processes (const char **pgmnames, pid_t *pids, size_t count, + int hang, int *r_exitcodes) +{ + gpg_err_code_t ec = 0; + size_t i; + HANDLE *procs; + int code; + + procs = xtrycalloc (count, sizeof *procs); + if (procs == NULL) + return _gpg_err_code_from_syserror (); + + for (i = 0; i < count; i++) + { + if (r_exitcodes) + r_exitcodes[i] = -1; + + if (pids[i] == (pid_t)(-1)) + return GPG_ERR_INV_VALUE; + + procs[i] = pid_to_handle (pids[i]); + } + + _gpgrt_pre_syscall (); + code = WaitForMultipleObjects (count, procs, TRUE, hang? INFINITE : 0); + _gpgrt_post_syscall (); + switch (code) + { + case WAIT_TIMEOUT: + ec = GPG_ERR_TIMEOUT; + goto leave; + + case WAIT_FAILED: + _gpgrt_log_error (_("waiting for processes to terminate failed: ec=%d\n"), + (int)GetLastError ()); + ec = GPG_ERR_GENERAL; + goto leave; + + case WAIT_OBJECT_0: + for (i = 0; i < count; i++) + { + DWORD exc; + + if (! GetExitCodeProcess (procs[i], &exc)) + { + _gpgrt_log_error (_("error getting exit code of process %d:" + " ec=%d\n"), + (int) pids[i], (int)GetLastError ()); + ec = GPG_ERR_GENERAL; + } + else if (exc) + { + if (!r_exitcodes) + _gpgrt_log_error (_("error running '%s': exit status %d\n"), + pgmnames[i], (int)exc); + else + r_exitcodes[i] = (int)exc; + ec = GPG_ERR_GENERAL; + } + else + { + if (r_exitcodes) + r_exitcodes[i] = 0; + } + } + break; + + default: + _gpgrt_log_debug ("WaitForMultipleObjects returned unexpected code %d\n", + code); + ec = GPG_ERR_GENERAL; + break; + } + + leave: + return ec; +} + + +/* See gpgrt-int.h for a description. */ +gpg_err_code_t +_gpgrt_spawn_process_detached (const char *pgmname, const char *argv[], + const char *envp[] ) +{ + gpg_err_code_t err; + SECURITY_ATTRIBUTES sec_attr; + PROCESS_INFORMATION pi = + { + NULL, /* Returns process handle. */ + 0, /* Returns primary thread handle. */ + 0, /* Returns pid. */ + 0 /* Returns tid. */ + }; + STARTUPINFO si; + int cr_flags; + char *cmdline; + int ret; + gpg_err_code_t ec; + + /* We don't use ENVP. */ + (void)envp; + + ec = _gpgrt_access (pgmname, X_OK); + if (ec) + return ec; + + /* Prepare security attributes. */ + memset (&sec_attr, 0, sizeof sec_attr ); + sec_attr.nLength = sizeof sec_attr; + sec_attr.bInheritHandle = FALSE; + + /* Build the command line. */ + err = build_w32_commandline (pgmname, argv, &cmdline); + if (err) + return err; + + /* Start the process. */ + memset (&si, 0, sizeof si); + si.cb = sizeof (si); + si.dwFlags = STARTF_USESHOWWINDOW; + si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE; + + cr_flags = (CREATE_DEFAULT_ERROR_MODE + | GetPriorityClass (GetCurrentProcess ()) + | CREATE_NEW_PROCESS_GROUP + | DETACHED_PROCESS); + _gpgrt_log_debug ("CreateProcess(detached), path='%s' cmdline='%s'\n", + pgmname, cmdline); + ret = CreateProcess (pgmname, /* Program to start. */ + cmdline, /* Command line arguments. */ + &sec_attr, /* Process security attributes. */ + &sec_attr, /* Thread security attributes. */ + FALSE, /* Inherit handles. */ + cr_flags, /* Creation flags. */ + NULL, /* Environment. */ + NULL, /* Use current drive/directory. */ + &si, /* Startup information. */ + &pi /* Returns process information. */ + ); + if (!ret) + { + _gpgrt_log_error ("CreateProcess(detached) failed: ec=%d\n", + (int)GetLastError ()); + xfree (cmdline); + return GPG_ERR_GENERAL; + } + xfree (cmdline); + cmdline = NULL; + + _gpgrt_log_debug ("CreateProcess(detached) ready: hProcess=%p hThread=%p" + " dwProcessID=%d dwThreadId=%d\n", + pi.hProcess, pi.hThread, + (int) pi.dwProcessId, (int) pi.dwThreadId); + + CloseHandle (pi.hThread); + CloseHandle (pi.hProcess); + + return 0; +} + + +/* Kill a process; that is send an appropriate signal to the process. + gnupg_wait_process must be called to actually remove the process + from the system. An invalid PID is ignored. */ +void +_gpgrt_kill_process (pid_t pid) +{ + if (pid != (pid_t) INVALID_HANDLE_VALUE) + { + HANDLE process = (HANDLE) pid; + + /* Arbitrary error code. */ + _gpgrt_pre_syscall (); + TerminateProcess (process, 1); + _gpgrt_post_syscall (); + } +} + + +void +_gpgrt_release_process (pid_t pid) +{ + if (pid != (pid_t)INVALID_HANDLE_VALUE) + { + HANDLE process = (HANDLE)pid; + + CloseHandle (process); + } +} diff --git a/comm/third_party/libgpg-error/src/strerror-sym.c b/comm/third_party/libgpg-error/src/strerror-sym.c new file mode 100644 index 0000000000..3d79f40bb5 --- /dev/null +++ b/comm/third_party/libgpg-error/src/strerror-sym.c @@ -0,0 +1,56 @@ +/* strerror-sym.c - Describing an error code with its symbol name. + Copyright (C) 2003, 2004 g10 Code GmbH + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with libgpg-error; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stddef.h> + +#include <gpg-error.h> + +#include "err-codes-sym.h" +#include "errnos-sym.h" + +/* Return a pointer to a string containing the name of the symbol of + the error code in the error value ERR. Returns NULL if the error + code is not known. */ +const char * +gpg_strerror_sym (gpg_error_t err) +{ + gpg_err_code_t code = gpg_err_code (err); + + if (code & GPG_ERR_SYSTEM_ERROR) + { + int idx; + + code &= ~GPG_ERR_SYSTEM_ERROR; + idx = errnos_msgidxof (code); + if (idx >= 0) + return errnos_msgstr + errnos_msgidx[idx]; + else + return NULL; + } + + if (msgidxof (code) == msgidxof (GPG_ERR_CODE_DIM)) + return NULL; + + return msgstr + msgidx[msgidxof (code)]; +} diff --git a/comm/third_party/libgpg-error/src/strerror.c b/comm/third_party/libgpg-error/src/strerror.c new file mode 100644 index 0000000000..4cce17f189 --- /dev/null +++ b/comm/third_party/libgpg-error/src/strerror.c @@ -0,0 +1,177 @@ +/* strerror.c - Describing an error code. + Copyright (C) 2003 g10 Code GmbH + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with libgpg-error; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include <gpg-error.h> + +#include "gettext.h" +#include "err-codes.h" + +/* Return a pointer to a string containing a description of the error + code in the error value ERR. This function is not thread-safe. */ +const char * +_gpg_strerror (gpg_error_t err) +{ + gpg_err_code_t code = gpg_err_code (err); + + if (code & GPG_ERR_SYSTEM_ERROR) + { + int no = gpg_err_code_to_errno (code); + if (no) + return strerror (no); + else + code = GPG_ERR_UNKNOWN_ERRNO; + } + return dgettext (PACKAGE, msgstr + msgidx[msgidxof (code)]); +} + + +#ifdef HAVE_STRERROR_R +#ifdef STRERROR_R_CHAR_P +/* The GNU C library and probably some other systems have this weird + variant of strerror_r. */ + +/* Return a dynamically allocated string in *STR describing the system + error NO. If this call succeeds, return 1. If this call fails due + to a resource shortage, set *STR to NULL and return 1. If this + call fails because the error number is not valid, don't set *STR + and return 0. */ +static int +system_strerror_r (int no, char *buf, size_t buflen) +{ + char *errstr; + + errstr = strerror_r (no, buf, buflen); + if (errstr != buf) + { + size_t errstr_len = strlen (errstr) + 1; + size_t cpy_len = errstr_len < buflen ? errstr_len : buflen; + memcpy (buf, errstr, cpy_len); + + return cpy_len == errstr_len ? 0 : ERANGE; + } + else + { + /* We can not tell if the buffer was large enough, but we can + try to make a guess. */ + if (strlen (buf) + 1 >= buflen) + return ERANGE; + + return 0; + } +} + +#else /* STRERROR_R_CHAR_P */ +/* Now the POSIX version. */ + +static int +system_strerror_r (int no, char *buf, size_t buflen) +{ + return strerror_r (no, buf, buflen); +} + +#endif /* STRERROR_R_CHAR_P */ +#elif defined (HAVE_STRERROR_S) +/* Now the Windows version. */ + +static int +system_strerror_r (int no, char *buf, size_t buflen) +{ + return strerror_s (buf, buflen, no); +} + +#else /* ! HAVE_STRERROR_R && ! HAVE_STRERROR_S */ +/* Without strerror_r(), we can still provide a non-thread-safe + version. Maybe we are even lucky and the system's strerror() is + already thread-safe. */ + +static int +system_strerror_r (int no, char *buf, size_t buflen) +{ + char *errstr = strerror (no); + + if (!errstr) + { + int saved_errno = errno; + + if (saved_errno != EINVAL) + snprintf (buf, buflen, "strerror failed: %i\n", errno); + return saved_errno; + } + else + { + size_t errstr_len = strlen (errstr) + 1; + size_t cpy_len = errstr_len < buflen ? errstr_len : buflen; + memcpy (buf, errstr, cpy_len); + return cpy_len == errstr_len ? 0 : ERANGE; + } +} +#endif + + +/* Return the error string for ERR in the user-supplied buffer BUF of + size BUFLEN. This function is, in contrast to gpg_strerror, + thread-safe if a thread-safe strerror_r() function is provided by + the system. If the function succeeds, 0 is returned and BUF + contains the string describing the error. If the buffer was not + large enough, ERANGE is returned and BUF contains as much of the + beginning of the error string as fits into the buffer. */ +int +_gpg_strerror_r (gpg_error_t err, char *buf, size_t buflen) +{ + gpg_err_code_t code = gpg_err_code (err); + const char *errstr; + size_t errstr_len; + size_t cpy_len; + + if (code & GPG_ERR_SYSTEM_ERROR) + { + int no = gpg_err_code_to_errno (code); + if (no) + { + int system_err = system_strerror_r (no, buf, buflen); + + if (system_err != EINVAL) + { + if (buflen) + buf[buflen - 1] = '\0'; + return system_err; + } + } + code = GPG_ERR_UNKNOWN_ERRNO; + } + + errstr = dgettext (PACKAGE, msgstr + msgidx[msgidxof (code)]); + errstr_len = strlen (errstr) + 1; + cpy_len = errstr_len < buflen ? errstr_len : buflen; + memcpy (buf, errstr, cpy_len); + if (buflen) + buf[buflen - 1] = '\0'; + + return cpy_len == errstr_len ? 0 : ERANGE; +} diff --git a/comm/third_party/libgpg-error/src/stringutils.c b/comm/third_party/libgpg-error/src/stringutils.c new file mode 100644 index 0000000000..0be876959c --- /dev/null +++ b/comm/third_party/libgpg-error/src/stringutils.c @@ -0,0 +1,224 @@ +/* stringutils.c - String helper functions. + * Copyright (C) 1997, 2014 Werner Koch + * Copyright (C) 2020 g10 Code GmbH + * + * This file is part of libgpg-error. + * + * libgpg-error is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * libgpg-error is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, see <https://www.gnu.org/licenses/>. + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include <config.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <stdarg.h> +#include <errno.h> +#ifdef HAVE_STAT +# include <sys/stat.h> +#endif +#include <sys/types.h> +#ifdef HAVE_PWD_H +# include <pwd.h> +#endif + +#include "gpgrt-int.h" + + +/* Helper for _gpgrt_fnameconcat. The additional flag WANT_ABS tells + * whether an absolute file name is requested. */ +char * +_gpgrt_vfnameconcat (int want_abs, const char *first_part, va_list arg_ptr) +{ + const char *argv[32]; + int argc; + size_t n; + int skip = 1; /* Characters to skip from FIRST_PART. */ + char *home_buffer = NULL; + char *name, *home, *p; + + /* Put all args into an array because we need to scan them twice. */ + n = strlen (first_part) + 1; + argc = 0; + while ((argv[argc] = va_arg (arg_ptr, const char *))) + { + n += strlen (argv[argc]) + 1; + if (argc >= DIM (argv)-1) + { + _gpg_err_set_errno (EINVAL); + return NULL; + } + argc++; + } + n++; + + home = NULL; + if (*first_part == '~') + { + if (first_part[1] == '/' || !first_part[1]) + { + /* This is the "~/" or "~" case. */ + home_buffer = _gpgrt_getenv ("HOME"); + if (!home_buffer) + home_buffer = _gpgrt_getpwdir (NULL); + home = home_buffer; + if (home && *home) + n += strlen (home); + } + else + { + /* This is the "~username/" or "~username" case. */ + char *user; + + user = _gpgrt_strdup (first_part+1); + if (!user) + return NULL; + + p = strchr (user, '/'); + if (p) + *p = 0; + skip = 1 + strlen (user); + + home = home_buffer = _gpgrt_getpwdir (user); + xfree (user); + if (home) + n += strlen (home); + else + skip = 1; + } + } + + name = xtrymalloc (n); + if (!name) + { + _gpgrt_free (home_buffer); + return NULL; + } + + if (home) + p = stpcpy (stpcpy (name, home), first_part + skip); + else + p = stpcpy (name, first_part); + + xfree (home_buffer); + home_buffer = NULL; + + for (argc=0; argv[argc]; argc++) + { + /* Avoid a leading double slash if the first part was "/". */ + if (!argc && name[0] == '/' && !name[1]) + p = stpcpy (p, argv[argc]); + else + p = stpcpy (stpcpy (p, "/"), argv[argc]); + } + + if (want_abs) + { +#ifdef HAVE_W32_SYSTEM + p = strchr (name, ':'); + if (p) + p++; + else + p = name; +#else + p = name; +#endif + if (*p != '/' +#ifdef HAVE_W32_SYSTEM + && *p != '\\' +#endif + ) + { + home = _gpgrt_getcwd (); + if (!home) + { + xfree (name); + return NULL; + } + + n = strlen (home) + 1 + strlen (name) + 1; + home_buffer = xtrymalloc (n); + if (!home_buffer) + { + xfree (home); + xfree (name); + return NULL; + } + + if (p == name) + p = home_buffer; + else /* Windows case. */ + { + memcpy (home_buffer, p, p - name + 1); + p = home_buffer + (p - name + 1); + } + + /* Avoid a leading double slash if the cwd is "/". */ + if (home[0] == '/' && !home[1]) + strcpy (stpcpy (p, "/"), name); + else + strcpy (stpcpy (stpcpy (p, home), "/"), name); + + xfree (home); + xfree (name); + name = home_buffer; + /* Let's do a simple compression to catch the common case of + * a trailing "/.". */ + n = strlen (name); + if (n > 2 && name[n-2] == '/' && name[n-1] == '.') + name[n-2] = 0; + } + } + +#ifdef HAVE_W32_SYSTEM + for (p=name; *p; p++) + if (*p == '\\') + *p = '/'; +#endif + return name; +} + + +/* Construct a filename from the NULL terminated list of parts. Tilde + * expansion is done for the first argument. The caller must release + * the result using gpgrt_free; on error ERRNO is set and NULL + * returned. */ +char * +_gpgrt_fnameconcat (const char *first_part, ... ) +{ + va_list arg_ptr; + char *result; + + va_start (arg_ptr, first_part); + result = _gpgrt_vfnameconcat (0, first_part, arg_ptr); + va_end (arg_ptr); + return result; +} + + +/* Construct a filename from the NULL terminated list of parts. Tilde + * expansion is done for the first argument. The caller must release + * the result using gpgrt_free; on error ERRNO is set and NULL + * returned. This version returns an absolute filename. */ +char * +_gpgrt_absfnameconcat (const char *first_part, ... ) +{ + va_list arg_ptr; + char *result; + + va_start (arg_ptr, first_part); + result = _gpgrt_vfnameconcat (1, first_part, arg_ptr); + va_end (arg_ptr); + return result; +} diff --git a/comm/third_party/libgpg-error/src/strsource-sym.c b/comm/third_party/libgpg-error/src/strsource-sym.c new file mode 100644 index 0000000000..a191310e95 --- /dev/null +++ b/comm/third_party/libgpg-error/src/strsource-sym.c @@ -0,0 +1,43 @@ +/* strsource-sym.c - Describing an error source with its symbol name. + Copyright (C) 2003, 2004 g10 Code GmbH + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with libgpg-error; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stddef.h> + +#include <gpg-error.h> + +#include "err-sources-sym.h" + +/* Return a pointer to a string containing the name of the symbol of + the error source in the error value ERR. Returns NULL if the error + code is not known. */ +const char * +gpg_strsource_sym (gpg_error_t err) +{ + gpg_err_source_t source = gpg_err_source (err); + + if (msgidxof (source) == msgidxof (GPG_ERR_SOURCE_DIM)) + return NULL; + + return msgstr + msgidx[msgidxof (source)]; +} diff --git a/comm/third_party/libgpg-error/src/strsource.c b/comm/third_party/libgpg-error/src/strsource.c new file mode 100644 index 0000000000..6604eb0a80 --- /dev/null +++ b/comm/third_party/libgpg-error/src/strsource.c @@ -0,0 +1,37 @@ +/* strsource.c - Describing an error source. + Copyright (C) 2003 g10 Code GmbH + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with libgpg-error; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gpg-error.h> + +#include "gettext.h" +#include "err-sources.h" + +/* Return a pointer to a string containing a description of the error + source in the error value ERR. */ +const char * +_gpg_strsource (gpg_error_t err) +{ + gpg_err_source_t source = gpg_err_source (err); + return dgettext (PACKAGE, msgstr + msgidx[msgidxof (source)]); +} diff --git a/comm/third_party/libgpg-error/src/syscall-clamp.c b/comm/third_party/libgpg-error/src/syscall-clamp.c new file mode 100644 index 0000000000..99748f4e4c --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscall-clamp.c @@ -0,0 +1,80 @@ +/* syscall-clamp.c - Syscall clamp related stuff + * Copyright (C) 2016, 2017 g10 Code GmbH + * + * This file is part of Libgpg-error. + * + * Libgpg-error is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgpg-error is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <https://www.gnu.org/licenses/>. + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include <config.h> + +#include "gpgrt-int.h" + +/* + * Functions called before and after blocking syscalls. + * gpgrt_set_syscall_clamp is used to set them. + */ +static void (*pre_syscall_func)(void); +static void (*post_syscall_func)(void); + + +/* + * Register the syscall clamp. These two functions are called + * immediately before and after a possible blocking system call. This + * should be used before any I/O happens. The function is commonly + * used with the nPth library: + * + * gpgrt_set_syscall_clamp (npth_unprotect, npth_protect); + * + * These functions may not modify ERRNO. + * + * Setting the clamp is not thread-safe and should thus be done as + * early as possible. + */ +void +_gpgrt_set_syscall_clamp (void (*pre)(void), void (*post)(void)) +{ + pre_syscall_func = pre; + post_syscall_func = post; +} + +/* + * Return the current sycall clamp functions. This can be used by + * other libraries which have blocking functions. + */ +void +_gpgrt_get_syscall_clamp (void (**r_pre)(void), void (**r_post)(void)) +{ + *r_pre = pre_syscall_func; + *r_post = post_syscall_func; +} + + +/* Call this function before a blocking system or libc call. */ +void +_gpgrt_pre_syscall (void) +{ + if (pre_syscall_func) + pre_syscall_func (); +} + + +/* Call this function after a blocking system or libc call. */ +void +_gpgrt_post_syscall (void) +{ + if (post_syscall_func) + post_syscall_func (); +} diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.aarch64-apple-darwin.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.aarch64-apple-darwin.h new file mode 100644 index 0000000000..3eeadfe2f0 --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.aarch64-apple-darwin.h @@ -0,0 +1,28 @@ +## lock-obj-pub.aarch64-apple-darwin.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[64]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{167,171,170,50,0,0,0,0, \ +0,0,0,0,0,0,0,0, \ +0,0,0,0,0,0,0,0, \ +0,0,0,0,0,0,0,0, \ +0,0,0,0,0,0,0,0, \ +0,0,0,0,0,0,0,0, \ +0,0,0,0,0,0,0,0, \ +0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.aarch64-unknown-linux-gnu.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.aarch64-unknown-linux-gnu.h new file mode 100644 index 0000000000..adf10fc305 --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.aarch64-unknown-linux-gnu.h @@ -0,0 +1,26 @@ +## lock-obj-pub.aarch64-unknown-linux-gnu.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[48]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.aarch64-unknown-linux-gnu_ilp32.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.aarch64-unknown-linux-gnu_ilp32.h new file mode 100644 index 0000000000..61239c36ed --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.aarch64-unknown-linux-gnu_ilp32.h @@ -0,0 +1,24 @@ +## lock-obj-pub.aarch64-unknown-linux-gnu_ilp32.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[32]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.alpha-unknown-linux-gnu.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.alpha-unknown-linux-gnu.h new file mode 100644 index 0000000000..80ddf01ab1 --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.alpha-unknown-linux-gnu.h @@ -0,0 +1,25 @@ +## lock-obj-pub.alpha-unknown-linux-gnu.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[40]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.arm-apple-darwin.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.arm-apple-darwin.h new file mode 100644 index 0000000000..4e9f63028a --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.arm-apple-darwin.h @@ -0,0 +1,26 @@ +## lock-obj-pub.arm-apple-darwin.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[44]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{167,171,170,50,0,0,0,0, \ +0,0,0,0,0,0,0,0, \ +0,0,0,0,0,0,0,0, \ +0,0,0,0,0,0,0,0, \ +0,0,0,0,0,0,0,0, \ +0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.arm-unknown-linux-androideabi.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.arm-unknown-linux-androideabi.h new file mode 100644 index 0000000000..56319f5eba --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.arm-unknown-linux-androideabi.h @@ -0,0 +1,21 @@ +## lock-obj-pub.arm-unknown-linux-androideabi.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[4]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.arm-unknown-linux-gnueabi.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.arm-unknown-linux-gnueabi.h new file mode 100644 index 0000000000..7a92276dc6 --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.arm-unknown-linux-gnueabi.h @@ -0,0 +1,23 @@ +## lock-obj-pub.arm-unknown-linux-gnueabi.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[24]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.hppa-unknown-linux-gnu.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.hppa-unknown-linux-gnu.h new file mode 100644 index 0000000000..b57bb76d5b --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.hppa-unknown-linux-gnu.h @@ -0,0 +1,27 @@ +## lock-obj-pub.hppa-unknown-linux-gnu.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[48]; + int _x16_align __attribute__ ((aligned (16))); + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.i386-apple-darwin.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.i386-apple-darwin.h new file mode 100644 index 0000000000..a5963c48c1 --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.i386-apple-darwin.h @@ -0,0 +1,26 @@ +## lock-obj-pub.i386-apple-darwin.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[44]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{167,171,170,50,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.i686-unknown-gnu.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.i686-unknown-gnu.h new file mode 100644 index 0000000000..0522462a95 --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.i686-unknown-gnu.h @@ -0,0 +1,24 @@ +## lock-obj-pub.i686-pc-gnu.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[32]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.i686-unknown-kfreebsd-gnu.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.i686-unknown-kfreebsd-gnu.h new file mode 100644 index 0000000000..4cf12fcbd6 --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.i686-unknown-kfreebsd-gnu.h @@ -0,0 +1,23 @@ +## lock-obj-pub.i686-pc-kfreebsd-gnu.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[24]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.i686-unknown-linux-gnu.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.i686-unknown-linux-gnu.h new file mode 100644 index 0000000000..b97273b40a --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.i686-unknown-linux-gnu.h @@ -0,0 +1,23 @@ +## lock-obj-pub.i686-pc-linux-gnu.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[24]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.ia64-unknown-linux-gnu.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.ia64-unknown-linux-gnu.h new file mode 100644 index 0000000000..7cf980ab8f --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.ia64-unknown-linux-gnu.h @@ -0,0 +1,25 @@ +## lock-obj-pub.ia64-unknown-linux-gnu.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[40]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.m68k-unknown-linux-gnu.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.m68k-unknown-linux-gnu.h new file mode 100644 index 0000000000..3788797a09 --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.m68k-unknown-linux-gnu.h @@ -0,0 +1,23 @@ +## lock-obj-pub.m68k-unknown-linux-gnu.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[24]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.mingw32.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.mingw32.h new file mode 100644 index 0000000000..f35aee15f6 --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.mingw32.h @@ -0,0 +1,44 @@ +## w32-lock-obj-pub.in - Include fragment for gpg-error.h -*- c-*- +## Copyright (C) 2014 g10 Code GmbH +## +## This file is free software; as a special exception the author gives +## unlimited permission to copy and/or distribute it, with or without +## modifications, as long as this notice is preserved. +## +## This file is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +## implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +## +## +## This file defines the public version of the lock object for 32 bit +## Windows. The actual used version is in w32-lock-obj.h. This file +## is inserted into gpg-error.h by mkheader.c. The tool +## gen-w32-lock-obj.c has been used to construct it. + +#ifdef _WIN64 + +#pragma pack(push, 8) +typedef struct +{ + volatile unsigned char priv[56]; +} gpgrt_lock_t; +#pragma pack(pop) + +#define GPGRT_LOCK_INITIALIZER {{1,0,0,0,0,0,0,0,255,255,255,255, \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0,0,0,0,0}} + +#else + +#pragma pack(push, 8) +typedef struct +{ + volatile unsigned char priv[36]; +} gpgrt_lock_t; +#pragma pack(pop) + +#define GPGRT_LOCK_INITIALIZER {{1,0,0,0,0,0,0,0,255,255,255,255, \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}} +#endif diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.mips-unknown-linux-gnu.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.mips-unknown-linux-gnu.h new file mode 100644 index 0000000000..b31206ea0a --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.mips-unknown-linux-gnu.h @@ -0,0 +1,23 @@ +## lock-obj-pub.mips-unknown-linux-gnu.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[24]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.mips64-unknown-linux-gnuabi64.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.mips64-unknown-linux-gnuabi64.h new file mode 100644 index 0000000000..f571c4bb29 --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.mips64-unknown-linux-gnuabi64.h @@ -0,0 +1,25 @@ +## lock-obj-pub.mips64-unknown-linux-gnuabi64.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[40]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.mips64el-unknown-linux-gnuabi64.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.mips64el-unknown-linux-gnuabi64.h new file mode 100644 index 0000000000..8a81e3faac --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.mips64el-unknown-linux-gnuabi64.h @@ -0,0 +1,25 @@ +## lock-obj-pub.mips64el-unknown-linux-gnuabi64.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[40]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.mipsel-unknown-linux-gnu.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.mipsel-unknown-linux-gnu.h new file mode 100644 index 0000000000..3a24571659 --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.mipsel-unknown-linux-gnu.h @@ -0,0 +1,23 @@ +## lock-obj-pub.mipsel-unknown-linux-gnu.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[24]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.nios2-unknown-linux-gnu.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.nios2-unknown-linux-gnu.h new file mode 100644 index 0000000000..dbd46da792 --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.nios2-unknown-linux-gnu.h @@ -0,0 +1,23 @@ +## lock-obj-pub.nios2-unknown-linux-gnu.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[24]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.or1k-unknown-linux-gnu.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.or1k-unknown-linux-gnu.h new file mode 100644 index 0000000000..60eadab8e7 --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.or1k-unknown-linux-gnu.h @@ -0,0 +1,24 @@ +## lock-obj-pub.or1k-unknown-linux-gnu.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[32]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.powerpc-unknown-linux-gnu.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.powerpc-unknown-linux-gnu.h new file mode 100644 index 0000000000..6601bc9636 --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.powerpc-unknown-linux-gnu.h @@ -0,0 +1,23 @@ +## lock-obj-pub.powerpc-unknown-linux-gnu.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[24]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.powerpc-unknown-linux-gnuspe.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.powerpc-unknown-linux-gnuspe.h new file mode 100644 index 0000000000..c53413bee8 --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.powerpc-unknown-linux-gnuspe.h @@ -0,0 +1,23 @@ +## lock-obj-pub.powerpc-unknown-linux-gnuspe.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[24]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.powerpc64-unknown-linux-gnu.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.powerpc64-unknown-linux-gnu.h new file mode 100644 index 0000000000..635e6eb0c2 --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.powerpc64-unknown-linux-gnu.h @@ -0,0 +1,25 @@ +## lock-obj-pub.powerpc64-unknown-linux-gnu.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[40]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.powerpc64le-unknown-linux-gnu.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.powerpc64le-unknown-linux-gnu.h new file mode 100644 index 0000000000..79073d4c51 --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.powerpc64le-unknown-linux-gnu.h @@ -0,0 +1,25 @@ +## lock-obj-pub.powerpc64le-unknown-linux-gnu.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[40]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.riscv32-unknown-linux-gnu.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.riscv32-unknown-linux-gnu.h new file mode 100644 index 0000000000..b5bdaf57ef --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.riscv32-unknown-linux-gnu.h @@ -0,0 +1,23 @@ +## lock-obj-pub.riscv32-unknown-linux-gnu.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[24]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.riscv64-unknown-linux-gnu.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.riscv64-unknown-linux-gnu.h new file mode 100644 index 0000000000..8aab9d6667 --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.riscv64-unknown-linux-gnu.h @@ -0,0 +1,25 @@ +## lock-obj-pub.riscv64-unknown-linux-gnu.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[40]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.s390x-unknown-linux-gnu.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.s390x-unknown-linux-gnu.h new file mode 100644 index 0000000000..70f6e33d8d --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.s390x-unknown-linux-gnu.h @@ -0,0 +1,25 @@ +## lock-obj-pub.s390x-ibm-linux-gnu.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[40]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.sh3-unknown-linux-gnu.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.sh3-unknown-linux-gnu.h new file mode 100644 index 0000000000..a2ff11f96c --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.sh3-unknown-linux-gnu.h @@ -0,0 +1,23 @@ +## lock-obj-pub.sh3-unknown-linux-gnu.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[24]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.sh4-unknown-linux-gnu.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.sh4-unknown-linux-gnu.h new file mode 100644 index 0000000000..eb62ba3d8b --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.sh4-unknown-linux-gnu.h @@ -0,0 +1,23 @@ +## lock-obj-pub.sh4-unknown-linux-gnu.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[24]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.sparc-unknown-linux-gnu.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.sparc-unknown-linux-gnu.h new file mode 100644 index 0000000000..2748b26881 --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.sparc-unknown-linux-gnu.h @@ -0,0 +1,23 @@ +## lock-obj-pub.sparc-unknown-linux-gnu.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[24]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.sparc64-unknown-linux-gnu.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.sparc64-unknown-linux-gnu.h new file mode 100644 index 0000000000..ee309a9f49 --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.sparc64-unknown-linux-gnu.h @@ -0,0 +1,25 @@ +## lock-obj-pub.sparc64-unknown-linux-gnu.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[40]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.tilegx-unknown-linux-gnu.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.tilegx-unknown-linux-gnu.h new file mode 100644 index 0000000000..b99ea32003 --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.tilegx-unknown-linux-gnu.h @@ -0,0 +1,25 @@ +## lock-obj-pub.tilegx-unknown-linux-gnu.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[40]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.x86_64-apple-darwin.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.x86_64-apple-darwin.h new file mode 100644 index 0000000000..eaf8689f98 --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.x86_64-apple-darwin.h @@ -0,0 +1,28 @@ +## lock-obj-pub.x86_64-apple-darwin.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[64]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{167,171,170,50,0,0,0,0, \ +0,0,0,0,0,0,0,0, \ +0,0,0,0,0,0,0,0, \ +0,0,0,0,0,0,0,0, \ +0,0,0,0,0,0,0,0, \ +0,0,0,0,0,0,0,0, \ +0,0,0,0,0,0,0,0, \ +0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.x86_64-unknown-kfreebsd-gnu.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.x86_64-unknown-kfreebsd-gnu.h new file mode 100644 index 0000000000..7fb596c4a9 --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.x86_64-unknown-kfreebsd-gnu.h @@ -0,0 +1,25 @@ +## lock-obj-pub.x86_64-pc-kfreebsd-gnu.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[40]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.x86_64-unknown-linux-gnu.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.x86_64-unknown-linux-gnu.h new file mode 100644 index 0000000000..0dd6431d28 --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.x86_64-unknown-linux-gnu.h @@ -0,0 +1,25 @@ +## lock-obj-pub.x86_64-pc-linux-gnu.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[40]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.x86_64-unknown-linux-gnux32.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.x86_64-unknown-linux-gnux32.h new file mode 100644 index 0000000000..e85bd308b0 --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.x86_64-unknown-linux-gnux32.h @@ -0,0 +1,24 @@ +## lock-obj-pub.x86_64-pc-linux-gnux32.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[32]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.x86_64-unknown-linux-musl.h b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.x86_64-unknown-linux-musl.h new file mode 100644 index 0000000000..1b059f4260 --- /dev/null +++ b/comm/third_party/libgpg-error/src/syscfg/lock-obj-pub.x86_64-unknown-linux-musl.h @@ -0,0 +1,25 @@ +## lock-obj-pub.x86_64-pc-linux-musl.h +## File created by gen-posix-lock-obj - DO NOT EDIT +## To be included by mkheader into gpg-error.h + +typedef struct +{ + long _vers; + union { + volatile char _priv[40]; + long _x_align; + long *_xp_align; + } u; +} gpgrt_lock_t; + +#define GPGRT_LOCK_INITIALIZER {1,{{0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0, \ + 0,0,0,0,0,0,0,0}}} +## +## Local Variables: +## mode: c +## buffer-read-only: t +## End: +## diff --git a/comm/third_party/libgpg-error/src/sysutils.c b/comm/third_party/libgpg-error/src/sysutils.c new file mode 100644 index 0000000000..8f70a6694e --- /dev/null +++ b/comm/third_party/libgpg-error/src/sysutils.c @@ -0,0 +1,524 @@ +/* sysutils.c - Platform specific helper functions + * Copyright (C) 2017 g10 Code GmbH + * + * This file is part of libgpg-error. + * + * libgpg-error is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * libgpg-error is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <https://www.gnu.org/licenses/>. + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include <config.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#ifdef HAVE_W32_SYSTEM +# include <windows.h> +#endif +#ifdef HAVE_STAT +# include <sys/stat.h> +#endif +#include <sys/types.h> +#include <fcntl.h> +#ifdef HAVE_PWD_H +# include <pwd.h> +#endif + +#include "gpgrt-int.h" + + +#ifdef HAVE_W32_SYSTEM +/* Return true if STRING has any 8 bit character. */ +static int +any8bitchar (const char *string) +{ + if (string) + for ( ; *string; string++) + if ((*string & 0x80)) + return 1; + return 0; +} +#endif /*HAVE_W32_SYSTEM*/ + + +/* Return true if FD is valid. */ +int +_gpgrt_fd_valid_p (int fd) +{ + int d = dup (fd); + if (d < 0) + return 0; + close (d); + return 1; +} + + +/* Our variant of getenv. The returned string must be freed. If the + * environment variable does not exists NULL is returned and ERRNO set + * to 0. */ +char * +_gpgrt_getenv (const char *name) +{ + if (!name || !*name || strchr (name, '=')) + { + _gpg_err_set_errno (EINVAL); + return NULL; + } + +#ifdef HAVE_W32_SYSTEM + { + int len, size; + char *result; + + len = GetEnvironmentVariable (name, NULL, 0); + if (!len && GetLastError () == ERROR_ENVVAR_NOT_FOUND) + { + _gpg_err_set_errno (0); + return NULL; + } + again: + size = len; + result = _gpgrt_malloc (size); + if (!result) + return NULL; + len = GetEnvironmentVariable (name, result, size); + if (len >= size) + { + /* Changed in the meantime - retry. */ + _gpgrt_free (result); + goto again; + } + if (!len && GetLastError () == ERROR_ENVVAR_NOT_FOUND) + { + /* Deleted in the meantime. */ + _gpgrt_free (result); + _gpg_err_set_errno (0); + return NULL; + } + if (!len) + { + /* Other error. FIXME: We need mapping fucntion. */ + _gpgrt_free (result); + _gpg_err_set_errno (EIO); + return NULL; + } + + return result; + } +#else /*!HAVE_W32_SYSTEM*/ + { + const char *s = getenv (name); + if (!s) + { + _gpg_err_set_errno (0); + return NULL; + } + return _gpgrt_strdup (s); + } +#endif /*!HAVE_W32_SYSTEM*/ +} + + +/* Wrapper around setenv so that we can have the same function in + * Windows and Unix. In contrast to the standard setenv passing a + * VALUE as NULL and setting OVERWRITE will remove the envvar. */ +gpg_err_code_t +_gpgrt_setenv (const char *name, const char *value, int overwrite) +{ + if (!name || !*name || strchr (name, '=')) + return GPG_ERR_EINVAL; + +#ifdef HAVE_W32_SYSTEM + /* Windows maintains (at least) two sets of environment variables. + * One set can be accessed by GetEnvironmentVariable and + * SetEnvironmentVariable. This set is inherited by the children. + * The other set is maintained in the C runtime, and is accessed + * using getenv and putenv. We try to keep them in sync by + * modifying both sets. Note that gpgrt_getenv ignores the libc + * values - however, too much existing code still uses getenv. */ + { + int exists; + char tmpbuf[10]; + char *buf; + + if (!value && overwrite) + { + if (!SetEnvironmentVariable (name, NULL)) + return GPG_ERR_EINVAL; + if (getenv (name)) + { + /* Ugly: Leaking memory. */ + buf = _gpgrt_strdup (name); + if (!buf) + return _gpg_err_code_from_syserror (); + if (putenv (buf)) + return _gpg_err_code_from_syserror (); + } + return 0; + } + + exists = GetEnvironmentVariable (name, tmpbuf, sizeof tmpbuf); + if ((! exists || overwrite) && !SetEnvironmentVariable (name, value)) + return GPG_ERR_EINVAL; /* (Might also be ENOMEM.) */ + if (overwrite || !getenv (name)) + { + /* Ugly: Leaking memory. */ + buf = _gpgrt_strconcat (name, "=", value, NULL); + if (!buf) + return _gpg_err_code_from_syserror (); + if (putenv (buf)) + return _gpg_err_code_from_syserror (); + } + return 0; + } + +#else /*!HAVE_W32_SYSTEM*/ + +# ifdef HAVE_SETENV + + { + if (!value && overwrite) + { + if (unsetenv (name)) + return _gpg_err_code_from_syserror (); + } + else + { + if (setenv (name, value ? value : "", overwrite)) + return _gpg_err_code_from_syserror (); + } + + return 0; + } + +# else /*!HAVE_SETENV*/ + +# if __GNUC__ +# warning no setenv - using putenv but leaking memory. +# endif + { + char *buf; + + if (!value && overwrite) + { + if (getenv (name)) + { + buf = _gpgrt_strdup (name); + if (!buf) + return _gpg_err_code_from_syserror (); + if (putenv (buf)) + return -1; + } + } + else if (overwrite || !getenv (name)) + { + buf = _gpgrt_strconcat (name, "=", value, NULL); + if (!buf) + return _gpg_err_code_from_syserror (); + if (putenv (buf)) + return _gpg_err_code_from_syserror (); + } + + return 0; + } +# endif /*!HAVE_SETENV*/ +#endif /*!HAVE_W32_SYSTEM*/ +} + + +#ifndef HAVE_W32_SYSTEM +static mode_t +modestr_to_mode (const char *modestr) +{ + mode_t mode = 0; + + if (modestr && *modestr) + { + modestr++; + if (*modestr && *modestr++ == 'r') + mode |= S_IRUSR; + if (*modestr && *modestr++ == 'w') + mode |= S_IWUSR; + if (*modestr && *modestr++ == 'x') + mode |= S_IXUSR; + if (*modestr && *modestr++ == 'r') + mode |= S_IRGRP; + if (*modestr && *modestr++ == 'w') + mode |= S_IWGRP; + if (*modestr && *modestr++ == 'x') + mode |= S_IXGRP; + if (*modestr && *modestr++ == 'r') + mode |= S_IROTH; + if (*modestr && *modestr++ == 'w') + mode |= S_IWOTH; + if (*modestr && *modestr++ == 'x') + mode |= S_IXOTH; + } + + return mode; +} +#endif + + +/* A wrapper around mkdir which takes a string for the mode argument. + * This makes it easier to handle the mode argument which is not + * defined on all systems. The format of the modestring is + * + * "-rwxrwxrwx" + * + * '-' is a don't care or not set. 'r', 'w', 'x' are read allowed, + * write allowed, execution allowed with the first group for the user, + * the second for the group and the third for all others. If the + * string is shorter than above the missing mode characters are meant + * to be not set. + * + * Note that in addition to returning an gpg-error error code ERRNO is + * also set by this function. + */ +gpg_err_code_t +_gpgrt_mkdir (const char *name, const char *modestr) +{ +#ifdef HAVE_W32_SYSTEM + wchar_t *wname; + gpg_err_code_t ec; + (void)modestr; + + /* Note: Fixme: We should set appropriate permissions. */ + wname = _gpgrt_utf8_to_wchar (name); + if (!wname) + return _gpg_err_code_from_syserror (); + if (!CreateDirectoryW (wname, NULL)) + { + _gpgrt_w32_set_errno (-1); + ec = _gpg_err_code_from_syserror (); + } + else + ec = 0; + _gpgrt_free_wchar (wname); + return ec; +#elif MKDIR_TAKES_ONE_ARG + (void)modestr; + if (mkdir (name)) + return _gpg_err_code_from_syserror (); + return 0; +#else + if (mkdir (name, modestr_to_mode (modestr))) + return _gpg_err_code_from_syserror (); + return 0; +#endif +} + + +/* A simple wrapper around chdir. NAME is expected to be utf8 + * encoded. + * Note that in addition to returning an gpg-error error code ERRNO is + * also set by this function. */ +gpg_err_code_t +_gpgrt_chdir (const char *name) +{ +#ifdef HAVE_W32_SYSTEM + wchar_t *wname; + gpg_err_code_t ec; + + wname = _gpgrt_utf8_to_wchar (name); + if (!wname) + return _gpg_err_code_from_syserror (); + if (!SetCurrentDirectoryW (wname)) + { + _gpgrt_w32_set_errno (-1); + ec = _gpg_err_code_from_syserror (); + } + else + ec = 0; + _gpgrt_free_wchar (wname); + return ec; + +#else /*!HAVE_W32_SYSTEM*/ + if (chdir (name)) + return _gpg_err_code_from_syserror (); + return 0; +#endif /*!HAVE_W32_SYSTEM*/ +} + + +/* Return the current working directory as a malloced string. Return + * NULL and sets ERRNO on error. */ +char * +_gpgrt_getcwd (void) +{ +#ifdef HAVE_W32CE_SYSTEM + + return xtrystrdup ("/"); + +#elif defined(HAVE_W32_SYSTEM) + wchar_t wbuffer[MAX_PATH + sizeof(wchar_t)]; + DWORD wlen; + char *buf, *p; + + wlen = GetCurrentDirectoryW (MAX_PATH, wbuffer); + if (!wlen) + { + _gpgrt_w32_set_errno (-1); + return NULL; + + } + else if (wlen > MAX_PATH) + { + _gpg_err_set_errno (ENAMETOOLONG); + return NULL; + } + buf = _gpgrt_wchar_to_utf8 (wbuffer, wlen); + if (buf) + { + for (p=buf; *p; p++) + if (*p == '\\') + *p = '/'; + } + return buf; + +#else /*Unix*/ + char *buffer; + size_t size = 100; + + for (;;) + { + buffer = xtrymalloc (size+1); + if (!buffer) + return NULL; + if (getcwd (buffer, size) == buffer) + return buffer; + xfree (buffer); + if (errno != ERANGE) + return NULL; + size *= 2; + } +#endif /*Unix*/ +} + + +/* Wrapper around access to handle file name encoding under Windows. + * Returns 0 if FNAME can be accessed in MODE or an error code. ERRNO + * is also set on error. */ +gpg_err_code_t +_gpgrt_access (const char *fname, int mode) +{ + gpg_err_code_t ec; + +#ifdef HAVE_W32_SYSTEM + if (any8bitchar (fname)) + { + wchar_t *wfname; + + wfname = _gpgrt_utf8_to_wchar (fname); + if (!wfname) + ec = _gpg_err_code_from_syserror (); + else + { + ec = _waccess (wfname, mode)? _gpg_err_code_from_syserror () : 0; + _gpgrt_free_wchar (wfname); + } + } + else +#endif /*HAVE_W32_SYSTEM*/ + ec = access (fname, mode)? _gpg_err_code_from_syserror () : 0; + + return ec; +} + + + +/* Get the standard home directory for user NAME. If NAME is NULL the + * directory for the current user is returned. Caller must release + * the returned string. */ +char * +_gpgrt_getpwdir (const char *name) +{ + char *result = NULL; +#ifdef HAVE_PWD_H + struct passwd *pwd = NULL; + + if (name) + { +#ifdef HAVE_GETPWNAM + /* Fixme: We should use getpwnam_r if available. */ + pwd = getpwnam (name); +#endif + } + else + { +#ifdef HAVE_GETPWUID + /* Fixme: We should use getpwuid_r if available. */ + pwd = getpwuid (getuid()); +#endif + } + if (pwd) + { + result = _gpgrt_strdup (pwd->pw_dir); + } +#else /*!HAVE_PWD_H*/ + /* No support at all. */ + (void)name; +#endif /*HAVE_PWD_H*/ + return result; +} + + +/* Return a malloced copy of the current user's account name; this may + * return NULL on memory failure. */ +char * +_gpgrt_getusername (void) +{ + char *result = NULL; + +#ifdef HAVE_W32_SYSTEM + wchar_t wtmp[1]; + wchar_t *wbuf; + DWORD wsize = 1; + char *buf; + + GetUserNameW (wtmp, &wsize); + wbuf = _gpgrt_malloc (wsize * sizeof *wbuf); + if (!wbuf) + { + _gpgrt_w32_set_errno (-1); + return NULL; + } + if (!GetUserNameW (wbuf, &wsize)) + { + _gpgrt_w32_set_errno (-1); + xfree (wbuf); + return NULL; + } + buf = _gpgrt_wchar_to_utf8 (wbuf, wsize); + xfree (wbuf); + return buf; + +#else /* !HAVE_W32_SYSTEM */ + +# if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID) + struct passwd *pwd; + + pwd = getpwuid (getuid()); + if (pwd) + { + result = _gpgrt_strdup (pwd->pw_name); + } + +# endif /*HAVE_PWD_H*/ + +#endif /* !HAVE_W32_SYSTEM */ + + return result; +} diff --git a/comm/third_party/libgpg-error/src/thread.h b/comm/third_party/libgpg-error/src/thread.h new file mode 100644 index 0000000000..c650a991f3 --- /dev/null +++ b/comm/third_party/libgpg-error/src/thread.h @@ -0,0 +1,24 @@ +/* thread.h - Declarations for *-thread.c + Copyright (C) 2014 g10 Code GmbH + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef THREAD_H +#define THREAD_H + + +#endif /*THREAD_H*/ diff --git a/comm/third_party/libgpg-error/src/version.c b/comm/third_party/libgpg-error/src/version.c new file mode 100644 index 0000000000..276ee04447 --- /dev/null +++ b/comm/third_party/libgpg-error/src/version.c @@ -0,0 +1,246 @@ +/* version.c - Version checking + * Copyright (C) 2001, 2002, 2012, 2013, 2014 g10 Code GmbH + * + * This file is part of libgpg-error. + * + * libgpg-error is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * libgpg-error is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <https://www.gnu.org/licenses/>. + */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <gpg-error.h> + + +#define digitp(a) ((a) >= '0' && (a) <= '9') + + +/* This is actually a dummy function to make sure that is module is + not empty. Some compilers barf on empty modules. */ +static const char * +cright_blurb (void) +{ + static const char blurb[] = + "\n\n" + "This is Libgpg-error " PACKAGE_VERSION " - A runtime library\n" + "Copyright 2001-2020 g10 Code GmbH\n" + "\n" + "(" BUILD_REVISION " " BUILD_TIMESTAMP ")\n" + "\n\n"; + return blurb; +} + + +/* This function parses the first portion of the version number S and + * stores it at NUMBER. On success, this function returns a pointer + * into S starting with the first character, which is not part of the + * initial number portion; on failure, NULL is returned. */ +static const char* +parse_version_number (const char *s, int *number) +{ + int val = 0; + + if (*s == '0' && digitp (s[1])) + return NULL; /* Leading zeros are not allowed. */ + for (; digitp (*s); s++) + { + val *= 10; + val += *s - '0'; + } + *number = val; + return val < 0 ? NULL : s; +} + + +/* This function breaks up the complete string-representation of the + * version number S, which is of the following struture: <major + * number>.<minor number>.<micro number><patch level>. The major, + * minor and micro number components will be stored in *MAJOR, *MINOR + * and *MICRO. If MINOR or MICRO is NULL the version number is + * assumed to have just 1 respective 2 parts. + * + * On success, the last component, the patch level, will be returned; + * in failure, NULL will be returned. */ +static const char * +parse_version_string (const char *s, int *major, int *minor, int *micro) +{ + s = parse_version_number (s, major); + if (!s) + return NULL; + if (!minor) + { + if (*s == '.') + s++; + } + else + { + if (*s != '.') + return NULL; + s++; + s = parse_version_number (s, minor); + if (!s) + return NULL; + if (!micro) + { + if (*s == '.') + s++; + } + else + { + if (*s != '.') + return NULL; + s++; + s = parse_version_number (s, micro); + if (!s) + return NULL; + } + } + return s; /* patchlevel */ +} + + +/* Helper for _gpgrt_cmp_version. */ +static int +do_cmp_version (const char *a, const char *b, int level) +{ + int a_major, a_minor, a_micro; + int b_major, b_minor, b_micro; + const char *a_plvl, *b_plvl; + int r; + int ignore_plvl; + int positive, negative; + + if (level < 0) + { + positive = -1; + negative = 1; + level = 0 - level; + } + else + { + positive = 1; + negative = -1; + } + if ((ignore_plvl = (level > 9))) + level %= 10; + + a_major = a_minor = a_micro = 0; + a_plvl = parse_version_string (a, &a_major, + level > 1? &a_minor : NULL, + level > 2? &a_micro : NULL); + if (!a_plvl) + a_major = a_minor = a_micro = 0; /* Error. */ + + b_major = b_minor = b_micro = 0; + b_plvl = parse_version_string (b, &b_major, + level > 1? &b_minor : NULL, + level > 2? &b_micro : NULL); + if (!b_plvl) + b_major = b_minor = b_micro = 0; + + if (!ignore_plvl) + { + if (!a_plvl && !b_plvl) + return negative; /* Put invalid strings at the end. */ + if (a_plvl && !b_plvl) + return positive; + if (!a_plvl && b_plvl) + return negative; + } + + if (a_major > b_major) + return positive; + if (a_major < b_major) + return negative; + + if (a_minor > b_minor) + return positive; + if (a_minor < b_minor) + return negative; + + if (a_micro > b_micro) + return positive; + if (a_micro < b_micro) + return negative; + + if (ignore_plvl) + return 0; + + for (; *a_plvl && *b_plvl; a_plvl++, b_plvl++) + { + if (*a_plvl == '.' && *b_plvl == '.') + { + r = strcmp (a_plvl, b_plvl); + if (!r) + return 0; + else if ( r > 0 ) + return positive; + else + return negative; + } + else if (*a_plvl == '.') + return negative; /* B is larger. */ + else if (*b_plvl == '.') + return positive; /* A is larger. */ + else if (*a_plvl != *b_plvl) + break; + } + if (*a_plvl == *b_plvl) + return 0; + else if ((*(signed char *)a_plvl - *(signed char *)b_plvl) > 0) + return positive; + else + return negative; +} + + +/* Compare function for version strings. The return value is + * like strcmp(). LEVEL may be + * 0 - reserved + * 1 - format is "<major><patchlevel>". + * 2 - format is "<major>.<minor><patchlevel>". + * 3 - format is "<major>.<minor>.<micro><patchlevel>". + * To ignore the patchlevel in the comparison add 10 to LEVEL. To get + * a reverse sorting order use a negative number. + */ +int +_gpgrt_cmp_version (const char *a, const char *b, int level) +{ + return do_cmp_version (a, b, level); +} + + +/* + * Check that the the version of the library is at minimum REQ_VERSION + * and return the actual version string; return NULL if the condition + * is not met. If NULL is passed to this function, no check is done + * and the version string is simply returned. + */ +const char * +_gpg_error_check_version (const char *req_version) +{ + const char *my_version = PACKAGE_VERSION; + + if (req_version && req_version[0] == 1 && req_version[1] == 1) + return cright_blurb (); + if (!req_version) + return my_version; + return _gpgrt_cmp_version + (my_version, req_version, 12) >= 0 ? my_version : NULL; +} diff --git a/comm/third_party/libgpg-error/src/versioninfo.rc.in b/comm/third_party/libgpg-error/src/versioninfo.rc.in new file mode 100644 index 0000000000..d42d8fe3e5 --- /dev/null +++ b/comm/third_party/libgpg-error/src/versioninfo.rc.in @@ -0,0 +1,54 @@ +/* versioninfo.rc.in - for libgpg-error + * Copyright (C) 2005 g10 Code GmbH + * + * This file is free software; as a special exception the author gives + * unlimited permission to copy and/or distribute it, with or without + * modifications, as long as this notice is preserved. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * SPDX-License-Identifier: FSFULLR + */ + +/* This file is processed by configure to create versioninfo.rc */ + +#line __LINE__ "versioninfo.rc.in" + +#include <afxres.h> + + +VS_VERSION_INFO VERSIONINFO + FILEVERSION @BUILD_FILEVERSION@ + PRODUCTVERSION @BUILD_FILEVERSION@ + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x21L +#else + FILEFLAGS 0x20L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "Provided under the terms of the GNU Lesser General Public License.\0" + VALUE "CompanyName", "g10 Code GmbH\0" + VALUE "FileDescription", "libgpg-error - Common error codes\0" + VALUE "FileVersion", "@LIBGPG_ERROR_LT_CURRENT@.@LIBGPG_ERROR_LT_AGE@.@LIBGPG_ERROR_LT_REVISION@.@BUILD_REVISION@\0" + VALUE "InternalName", "libgpg-error\0" + VALUE "LegalCopyright", "Copyright © 2020 g10 Code GmbH\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "libgpg-error.dll\0" + VALUE "PrivateBuild", "\0" + VALUE "ProductName", "libgpg-error\0" + VALUE "ProductVersion", "@PACKAGE_VERSION@\0" + VALUE "SpecialBuild", "@BUILD_TIMESTAMP@\0" + END + END +END + +1 RT_MANIFEST "gpg-error.w32-manifest" diff --git a/comm/third_party/libgpg-error/src/visibility.c b/comm/third_party/libgpg-error/src/visibility.c new file mode 100644 index 0000000000..03a6c45b07 --- /dev/null +++ b/comm/third_party/libgpg-error/src/visibility.c @@ -0,0 +1,1250 @@ +/* visibility.c - Wrapper for all public functions. + * Copyright (C) 2014 g10 Code GmbH + * + * This file is part of libgpg-error. + * + * libgpg-error is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * libgpg-error is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <https://www.gnu.org/licenses/>. + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include <config.h> +#include <stdarg.h> +#include <stdlib.h> /* For abort(). */ + +#define _GPGRT_INCL_BY_VISIBILITY_C 1 +#include "gpgrt-int.h" + +const char * +gpg_strerror (gpg_error_t err) +{ + return _gpg_strerror (err); +} + +int +gpg_strerror_r (gpg_error_t err, char *buf, size_t buflen) +{ + return _gpg_strerror_r (err, buf, buflen); +} + +const char * +gpg_strsource (gpg_error_t err) +{ + return _gpg_strsource (err); +} + +gpg_err_code_t +gpg_err_code_from_errno (int err) +{ + return _gpg_err_code_from_errno (err); +} + +int +gpg_err_code_to_errno (gpg_err_code_t code) +{ + return _gpg_err_code_to_errno (code); +} + +gpg_err_code_t +gpg_err_code_from_syserror (void) +{ + return _gpg_err_code_from_syserror (); +} + +void +gpg_err_set_errno (int err) +{ + _gpg_err_set_errno (err); +} + + +gpg_error_t +gpg_err_init (void) +{ + return _gpg_err_init (); +} + +void +gpg_err_deinit (int mode) +{ + _gpg_err_deinit (mode); +} + +void +gpgrt_add_emergency_cleanup (void (*f)(void)) +{ + _gpgrt_add_emergency_cleanup (f); +} + +void +gpgrt_abort (void) +{ + _gpgrt_abort (); +} + +const char * +gpg_error_check_version (const char *req_version) +{ + return _gpg_error_check_version (req_version); +} + +const char * +gpgrt_check_version (const char *req_version) +{ + return _gpg_error_check_version (req_version); +} + +void +gpgrt_set_syscall_clamp (void (*pre)(void), void (*post)(void)) +{ + _gpgrt_set_syscall_clamp (pre, post); +} + +void +gpgrt_get_syscall_clamp (void (**r_pre)(void), void (**r_post)(void)) +{ + _gpgrt_get_syscall_clamp (r_pre, r_post); +} + +void +gpgrt_set_alloc_func (void *(*f)(void *a, size_t n)) +{ + _gpgrt_set_alloc_func (f); +} + + +gpg_err_code_t +gpgrt_lock_init (gpgrt_lock_t *lockhd) +{ + return _gpgrt_lock_init (lockhd); +} + +gpg_err_code_t +gpgrt_lock_lock (gpgrt_lock_t *lockhd) +{ + return _gpgrt_lock_lock (lockhd); +} + +gpg_err_code_t +gpgrt_lock_trylock (gpgrt_lock_t *lockhd) +{ + return _gpgrt_lock_trylock (lockhd); +} + +gpg_err_code_t +gpgrt_lock_unlock (gpgrt_lock_t *lockhd) +{ + return _gpgrt_lock_unlock (lockhd); +} + +gpg_err_code_t +gpgrt_lock_destroy (gpgrt_lock_t *lockhd) +{ + return _gpgrt_lock_destroy (lockhd); +} + +gpg_err_code_t +gpgrt_yield (void) +{ + return _gpgrt_yield (); +} + + + +estream_t +gpgrt_fopen (const char *_GPGRT__RESTRICT path, + const char *_GPGRT__RESTRICT mode) +{ + return _gpgrt_fopen (path, mode); +} + +estream_t +gpgrt_mopen (void *_GPGRT__RESTRICT data, size_t data_n, size_t data_len, + unsigned int grow, + void *(*func_realloc) (void *mem, size_t size), + void (*func_free) (void *mem), + const char *_GPGRT__RESTRICT mode) +{ + return _gpgrt_mopen (data, data_n, data_len, grow, func_realloc, func_free, + mode); +} + +estream_t +gpgrt_fopenmem (size_t memlimit, const char *_GPGRT__RESTRICT mode) +{ + return _gpgrt_fopenmem (memlimit, mode); +} + +estream_t +gpgrt_fopenmem_init (size_t memlimit, const char *_GPGRT__RESTRICT mode, + const void *data, size_t datalen) +{ + return _gpgrt_fopenmem_init (memlimit, mode, data, datalen); +} + +estream_t +gpgrt_fdopen (int filedes, const char *mode) +{ + return _gpgrt_fdopen (filedes, mode); +} + +estream_t +gpgrt_fdopen_nc (int filedes, const char *mode) +{ + return _gpgrt_fdopen_nc (filedes, mode); +} + +estream_t +gpgrt_sysopen (es_syshd_t *syshd, const char *mode) +{ + return _gpgrt_sysopen (syshd, mode); +} + +estream_t +gpgrt_sysopen_nc (es_syshd_t *syshd, const char *mode) +{ + return _gpgrt_sysopen_nc (syshd, mode); +} + +estream_t +gpgrt_fpopen (FILE *fp, const char *mode) +{ + return _gpgrt_fpopen (fp, mode); +} + +estream_t +gpgrt_fpopen_nc (FILE *fp, const char *mode) +{ + return _gpgrt_fpopen_nc (fp, mode); +} + +estream_t +gpgrt_freopen (const char *_GPGRT__RESTRICT path, + const char *_GPGRT__RESTRICT mode, + estream_t _GPGRT__RESTRICT stream) +{ + return _gpgrt_freopen (path, mode, stream); +} + +estream_t +gpgrt_fopencookie (void *_GPGRT__RESTRICT cookie, + const char *_GPGRT__RESTRICT mode, + gpgrt_cookie_io_functions_t functions) +{ + return _gpgrt_fopencookie (cookie, mode, functions); +} + +int +gpgrt_fclose (estream_t stream) +{ + return _gpgrt_fclose (stream); +} + +int +gpgrt_fcancel (estream_t stream) +{ + return _gpgrt_fcancel (stream); +} + +int +gpgrt_fclose_snatch (estream_t stream, void **r_buffer, size_t *r_buflen) +{ + return _gpgrt_fclose_snatch (stream, r_buffer, r_buflen); +} + +int +gpgrt_onclose (estream_t stream, int mode, + void (*fnc) (estream_t, void*), void *fnc_value) +{ + return _gpgrt_onclose (stream, mode, fnc, fnc_value); +} + +int +gpgrt_fileno (estream_t stream) +{ + return _gpgrt_fileno (stream); +} + +int +gpgrt_fileno_unlocked (estream_t stream) +{ + return _gpgrt_fileno_unlocked (stream); +} + +int +gpgrt_syshd (estream_t stream, es_syshd_t *syshd) +{ + return _gpgrt_syshd (stream, syshd); +} + +int +gpgrt_syshd_unlocked (estream_t stream, es_syshd_t *syshd) +{ + return _gpgrt_syshd_unlocked (stream, syshd); +} + +void +_gpgrt_set_std_fd (int no, int fd) +{ + _gpgrt__set_std_fd (no, fd); /* (double dash in name) */ +} + +estream_t +_gpgrt_get_std_stream (int fd) +{ + return _gpgrt__get_std_stream (fd); /* (double dash in name) */ +} + +void +gpgrt_flockfile (estream_t stream) +{ + _gpgrt_flockfile (stream); +} + +int +gpgrt_ftrylockfile (estream_t stream) +{ + return _gpgrt_ftrylockfile (stream); +} + +void +gpgrt_funlockfile (estream_t stream) +{ + _gpgrt_funlockfile (stream); +} + +int +_gpgrt_pending (estream_t stream) +{ + return _gpgrt__pending (stream); +} + +int +_gpgrt_pending_unlocked (estream_t stream) +{ + return _gpgrt__pending_unlocked (stream); +} + +int +gpgrt_feof (estream_t stream) +{ + return _gpgrt_feof (stream); +} + +int +gpgrt_feof_unlocked (estream_t stream) +{ + return _gpgrt_feof_unlocked (stream); +} + +int +gpgrt_ferror (estream_t stream) +{ + return _gpgrt_ferror (stream); +} + +int +gpgrt_ferror_unlocked (estream_t stream) +{ + return _gpgrt_ferror_unlocked (stream); +} + +void +gpgrt_clearerr (estream_t stream) +{ + _gpgrt_clearerr (stream); +} + +void +gpgrt_clearerr_unlocked (estream_t stream) +{ + _gpgrt_clearerr_unlocked (stream); +} + +int +gpgrt_fflush (estream_t stream) +{ + return _gpgrt_fflush (stream); +} + +int +gpgrt_fseek (estream_t stream, long int offset, int whence) +{ + return _gpgrt_fseek (stream, offset, whence); +} + +int +gpgrt_fseeko (estream_t stream, gpgrt_off_t offset, int whence) +{ + return _gpgrt_fseeko (stream, offset, whence); +} + +long int +gpgrt_ftell (estream_t stream) +{ + return _gpgrt_ftell (stream); +} + +gpgrt_off_t +gpgrt_ftello (estream_t stream) +{ + return _gpgrt_ftello (stream); +} + +void +gpgrt_rewind (estream_t stream) +{ + _gpgrt_rewind (stream); +} + +int +gpgrt_ftruncate (estream_t stream, gpgrt_off_t length) +{ + return _gpgrt_ftruncate (stream, length); +} + +int +gpgrt_fgetc (estream_t stream) +{ + return _gpgrt_fgetc (stream); +} + +int +_gpgrt_getc_underflow (estream_t stream) +{ + return _gpgrt__getc_underflow (stream); +} + +int +gpgrt_fputc (int c, estream_t stream) +{ + return _gpgrt_fputc (c, stream); +} + +int +_gpgrt_putc_overflow (int c, estream_t stream) +{ + return _gpgrt__putc_overflow (c, stream); +} + +int +gpgrt_ungetc (int c, estream_t stream) +{ + return _gpgrt_ungetc (c, stream); +} + +int +gpgrt_read (estream_t _GPGRT__RESTRICT stream, + void *_GPGRT__RESTRICT buffer, size_t bytes_to_read, + size_t *_GPGRT__RESTRICT bytes_read) +{ + return _gpgrt_read (stream, buffer, bytes_to_read, bytes_read); +} + +int +gpgrt_write (estream_t _GPGRT__RESTRICT stream, + const void *_GPGRT__RESTRICT buffer, size_t bytes_to_write, + size_t *_GPGRT__RESTRICT bytes_written) +{ + return _gpgrt_write (stream, buffer, bytes_to_write, bytes_written); +} + +int +gpgrt_write_sanitized (estream_t _GPGRT__RESTRICT stream, + const void * _GPGRT__RESTRICT buffer, size_t length, + const char * delimiters, + size_t * _GPGRT__RESTRICT bytes_written) +{ + return _gpgrt_write_sanitized (stream, buffer, length, delimiters, + bytes_written); +} + +int +gpgrt_write_hexstring (estream_t _GPGRT__RESTRICT stream, + const void *_GPGRT__RESTRICT buffer, size_t length, + int reserved, size_t *_GPGRT__RESTRICT bytes_written ) +{ + return _gpgrt_write_hexstring (stream, buffer, length, reserved, + bytes_written); +} + +size_t +gpgrt_fread (void *_GPGRT__RESTRICT ptr, size_t size, size_t nitems, + estream_t _GPGRT__RESTRICT stream) +{ + return _gpgrt_fread (ptr, size, nitems, stream); +} + +size_t +gpgrt_fwrite (const void *_GPGRT__RESTRICT ptr, size_t size, size_t nitems, + estream_t _GPGRT__RESTRICT stream) +{ + return _gpgrt_fwrite (ptr, size, nitems, stream); +} + +char * +gpgrt_fgets (char *_GPGRT__RESTRICT buffer, int length, + estream_t _GPGRT__RESTRICT stream) +{ + return _gpgrt_fgets (buffer, length, stream); +} + +int +gpgrt_fputs (const char *_GPGRT__RESTRICT s, estream_t _GPGRT__RESTRICT stream) +{ + return _gpgrt_fputs (s, stream); +} + +int +gpgrt_fputs_unlocked (const char *_GPGRT__RESTRICT s, + estream_t _GPGRT__RESTRICT stream) +{ + return _gpgrt_fputs_unlocked (s, stream); +} + +gpgrt_ssize_t +gpgrt_getline (char *_GPGRT__RESTRICT *_GPGRT__RESTRICT lineptr, + size_t *_GPGRT__RESTRICT n, estream_t _GPGRT__RESTRICT stream) +{ + return _gpgrt_getline (lineptr, n, stream); +} + +gpgrt_ssize_t +gpgrt_read_line (estream_t stream, + char **addr_of_buffer, size_t *length_of_buffer, + size_t *max_length) +{ + return _gpgrt_read_line (stream, addr_of_buffer, length_of_buffer, + max_length); +} + +int +gpgrt_vfprintf (estream_t _GPGRT__RESTRICT stream, + const char *_GPGRT__RESTRICT format, + va_list ap) +{ + return _gpgrt_vfprintf (stream, NULL, NULL, format, ap); +} + +int +gpgrt_vfprintf_unlocked (estream_t _GPGRT__RESTRICT stream, + const char *_GPGRT__RESTRICT format, + va_list ap) +{ + return _gpgrt_vfprintf_unlocked (stream, NULL, NULL, format, ap); +} + +int +gpgrt_printf (const char *_GPGRT__RESTRICT format, ...) +{ + va_list ap; + int rc; + + va_start (ap, format); + rc = _gpgrt_vfprintf (es_stdout, NULL, NULL, format, ap); + va_end (ap); + + return rc; +} + +int +gpgrt_printf_unlocked (const char *_GPGRT__RESTRICT format, ...) +{ + va_list ap; + int rc; + + va_start (ap, format); + rc = _gpgrt_vfprintf_unlocked (es_stdout, NULL, NULL, format, ap); + va_end (ap); + + return rc; +} + +int +gpgrt_fprintf (estream_t _GPGRT__RESTRICT stream, + const char *_GPGRT__RESTRICT format, ...) +{ + va_list ap; + int rc; + + va_start (ap, format); + rc = _gpgrt_vfprintf (stream, NULL, NULL, format, ap); + va_end (ap); + + return rc; +} + +int +gpgrt_fprintf_unlocked (estream_t _GPGRT__RESTRICT stream, + const char *_GPGRT__RESTRICT format, ...) +{ + va_list ap; + int rc; + + va_start (ap, format); + rc = _gpgrt_vfprintf_unlocked (stream, NULL, NULL, format, ap); + va_end (ap); + + return rc; +} + +int +gpgrt_fprintf_sf (estream_t _GPGRT__RESTRICT stream, + gpgrt_string_filter_t sf, void *sfvalue, + const char *_GPGRT__RESTRICT format, ...) +{ + va_list ap; + int rc; + + va_start (ap, format); + rc = _gpgrt_vfprintf (stream, sf, sfvalue, format, ap); + va_end (ap); + + return rc; +} + +int +gpgrt_fprintf_sf_unlocked (estream_t _GPGRT__RESTRICT stream, + gpgrt_string_filter_t sf, void *sfvalue, + const char *_GPGRT__RESTRICT format, ...) +{ + va_list ap; + int rc; + + va_start (ap, format); + rc = _gpgrt_vfprintf_unlocked (stream, sf, sfvalue, format, ap); + va_end (ap); + + return rc; +} + +int +gpgrt_setvbuf (estream_t _GPGRT__RESTRICT stream, + char *_GPGRT__RESTRICT buf, int type, size_t size) +{ + return _gpgrt_setvbuf (stream, buf, type, size); +} + +void +gpgrt_setbuf (estream_t _GPGRT__RESTRICT stream, char *_GPGRT__RESTRICT buf) +{ + _gpgrt_setvbuf (stream, buf, buf? _IOFBF : _IONBF, BUFSIZ); +} + +void +gpgrt_set_binary (estream_t stream) +{ + _gpgrt_set_binary (stream); +} + +int +gpgrt_set_nonblock (estream_t stream, int onoff) +{ + return _gpgrt_set_nonblock (stream, onoff); +} + +int +gpgrt_get_nonblock (estream_t stream) +{ + return _gpgrt_get_nonblock (stream); +} + +int +gpgrt_poll (gpgrt_poll_t *fds, unsigned int nfds, int timeout) +{ + return _gpgrt_poll (fds, nfds, timeout); +} + +estream_t +gpgrt_tmpfile (void) +{ + return _gpgrt_tmpfile (); +} + +void +gpgrt_opaque_set (estream_t stream, void *opaque) +{ + _gpgrt_opaque_set (stream, opaque); +} + +void * +gpgrt_opaque_get (estream_t stream) +{ + return _gpgrt_opaque_get (stream); +} + +void +gpgrt_fname_set (estream_t stream, const char *fname) +{ + _gpgrt_fname_set (stream, fname); +} + +const char * +gpgrt_fname_get (estream_t stream) +{ + return _gpgrt_fname_get (stream); +} + +int +gpgrt_asprintf (char **r_buf, const char *_GPGRT__RESTRICT format, ...) +{ + va_list ap; + int rc; + + va_start (ap, format); + rc = _gpgrt_estream_vasprintf (r_buf, format, ap); + va_end (ap); + + return rc; +} + +int +gpgrt_vasprintf (char **r_buf, const char *_GPGRT__RESTRICT format, va_list ap) +{ + return _gpgrt_estream_vasprintf (r_buf, format, ap); +} + +char * +gpgrt_bsprintf (const char *_GPGRT__RESTRICT format, ...) +{ + int rc; + va_list ap; + char *buf; + + va_start (ap, format); + rc = _gpgrt_estream_vasprintf (&buf, format, ap); + va_end (ap); + if (rc < 0) + return NULL; + return buf; +} + +char * +gpgrt_vbsprintf (const char *_GPGRT__RESTRICT format, va_list ap) +{ + int rc; + char *buf; + + rc = _gpgrt_estream_vasprintf (&buf, format, ap); + if (rc < 0) + return NULL; + return buf; +} + +int +gpgrt_snprintf (char *buf, size_t bufsize, const char *format, ...) +{ + int rc; + va_list arg_ptr; + + va_start (arg_ptr, format); + rc = _gpgrt_estream_vsnprintf (buf, bufsize, format, arg_ptr); + va_end (arg_ptr); + + return rc; +} + +int +gpgrt_vsnprintf (char *buf, size_t bufsize, + const char *format, va_list arg_ptr) +{ + return _gpgrt_estream_vsnprintf (buf, bufsize, format, arg_ptr); +} + + + +void * +gpgrt_realloc (void *a, size_t n) +{ + return _gpgrt_realloc (a, n); +} + +void * +gpgrt_reallocarray (void *a, size_t oldnmemb, size_t nmemb, size_t size) +{ + return _gpgrt_reallocarray (a, oldnmemb, nmemb, size); +} + +void * +gpgrt_malloc (size_t n) +{ + return _gpgrt_malloc (n); +} + +void * +gpgrt_calloc (size_t n, size_t m) +{ + return _gpgrt_calloc (n, m); +} + +char * +gpgrt_strdup (const char *string) +{ + return _gpgrt_strdup (string); +} + +char * +gpgrt_strconcat (const char *s1, ...) +{ + va_list arg_ptr; + char *result; + + if (!s1) + result = _gpgrt_strdup (""); + else + { + va_start (arg_ptr, s1); + result = _gpgrt_strconcat_core (s1, arg_ptr); + va_end (arg_ptr); + } + return result; +} + +void +gpgrt_free (void *a) +{ + if (a) + _gpgrt_free (a); +} + +char * +gpgrt_getenv (const char *name) +{ + return _gpgrt_getenv (name); +} + +gpg_err_code_t +gpgrt_setenv (const char *name, const char *value, int overwrite) +{ + return _gpgrt_setenv (name, value, overwrite); +} + +gpg_err_code_t +gpgrt_mkdir (const char *name, const char *modestr) +{ + return _gpgrt_mkdir (name, modestr); +} + +gpg_err_code_t +gpgrt_chdir (const char *name) +{ + return _gpgrt_chdir (name); +} + +char * +gpgrt_getcwd (void) +{ + return _gpgrt_getcwd (); +} + +gpg_err_code_t +gpgrt_access (const char *fname, int mode) +{ + return _gpgrt_access (fname, mode); +} + + + +gpgrt_b64state_t +gpgrt_b64enc_start (estream_t stream, const char *title) +{ + return _gpgrt_b64enc_start (stream, title); +} + +gpg_err_code_t +gpgrt_b64enc_write (gpgrt_b64state_t state, const void *buffer, size_t nbytes) +{ + return _gpgrt_b64enc_write (state, buffer, nbytes); +} + +gpg_err_code_t +gpgrt_b64enc_finish (gpgrt_b64state_t state) +{ + return _gpgrt_b64enc_finish (state); +} + +gpgrt_b64state_t +gpgrt_b64dec_start (const char *title) +{ + return _gpgrt_b64dec_start (title); +} + +gpg_error_t +gpgrt_b64dec_proc (gpgrt_b64state_t state, void *buffer, + size_t length, size_t *r_nbytes) +{ + return _gpgrt_b64dec_proc (state, buffer, length, r_nbytes); +} + +gpg_error_t +gpgrt_b64dec_finish (gpgrt_b64state_t state) +{ + return _gpgrt_b64dec_finish (state); +} + + + +int +gpgrt_get_errorcount (int clear) +{ + return _gpgrt_get_errorcount (clear); +} + +void +gpgrt_inc_errorcount (void) +{ + _gpgrt_inc_errorcount (); +} + +void +gpgrt_log_set_sink (const char *name, estream_t stream, int fd) +{ + _gpgrt_log_set_sink (name, stream, fd); +} + +void +gpgrt_log_set_socket_dir_cb (const char *(*fnc)(void)) +{ + _gpgrt_log_set_socket_dir_cb (fnc); +} + +void +gpgrt_log_set_pid_suffix_cb (int (*cb)(unsigned long *r_value)) +{ + _gpgrt_log_set_pid_suffix_cb (cb); +} + +void +gpgrt_log_set_prefix (const char *text, unsigned int flags) +{ + _gpgrt_log_set_prefix (text, flags); +} + +const char * +gpgrt_log_get_prefix (unsigned int *flags) +{ + return _gpgrt_log_get_prefix (flags); +} + +int +gpgrt_log_test_fd (int fd) +{ + return _gpgrt_log_test_fd (fd); +} + +int +gpgrt_log_get_fd (void) +{ + return _gpgrt_log_get_fd (); +} + +estream_t +gpgrt_log_get_stream (void) +{ + return _gpgrt_log_get_stream (); +} + +void +gpgrt_log (int level, const char *fmt, ...) +{ + va_list arg_ptr ; + + va_start (arg_ptr, fmt) ; + _gpgrt_logv (level, fmt, arg_ptr); + va_end (arg_ptr); +} + +void +gpgrt_logv (int level, const char *fmt, va_list arg_ptr) +{ + _gpgrt_logv (level, fmt, arg_ptr); +} + +void +gpgrt_logv_prefix (int level, const char *prefix, + const char *fmt, va_list arg_ptr) +{ + _gpgrt_logv_prefix (level, prefix, fmt, arg_ptr); +} + +void +gpgrt_log_string (int level, const char *string) +{ + _gpgrt_log_string (level, string); +} + +void +gpgrt_log_info (const char *fmt, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, fmt); + _gpgrt_logv (GPGRT_LOGLVL_INFO, fmt, arg_ptr); + va_end (arg_ptr); +} + +void +gpgrt_log_error (const char *fmt, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, fmt); + _gpgrt_logv (GPGRT_LOGLVL_ERROR, fmt, arg_ptr); + va_end (arg_ptr); +} + +void +gpgrt_log_fatal (const char *fmt, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, fmt); + _gpgrt_logv (GPGRT_LOGLVL_FATAL, fmt, arg_ptr); + va_end (arg_ptr); + _gpgrt_abort (); /* Never called; just to make the compiler happy. */ +} + +void +gpgrt_log_bug (const char *fmt, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, fmt); + _gpgrt_logv (GPGRT_LOGLVL_BUG, fmt, arg_ptr); + va_end (arg_ptr); + _gpgrt_abort (); /* Never called; just to make the compiler happy. */ +} + +void +gpgrt_log_debug (const char *fmt, ...) +{ + va_list arg_ptr ; + + va_start (arg_ptr, fmt); + _gpgrt_logv (GPGRT_LOGLVL_DEBUG, fmt, arg_ptr); + va_end (arg_ptr); +} + +void +gpgrt_log_debug_string (const char *string, const char *fmt, ...) +{ + va_list arg_ptr ; + + va_start (arg_ptr, fmt); + _gpgrt_logv_internal (GPGRT_LOGLVL_DEBUG, 0, string, NULL, fmt, arg_ptr); + va_end (arg_ptr); +} + +void +gpgrt_log_printf (const char *fmt, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, fmt); + _gpgrt_logv (fmt ? GPGRT_LOGLVL_CONT : GPGRT_LOGLVL_BEGIN, fmt, arg_ptr); + va_end (arg_ptr); +} + +void +gpgrt_log_flush (void) +{ + _gpgrt_log_flush (); +} + +void +gpgrt_log_printhex (const void *buffer, size_t length, const char *fmt, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, fmt); + _gpgrt_logv_printhex (buffer, length, fmt, arg_ptr); + va_end (arg_ptr); +} + +void +gpgrt_log_clock (const char *fmt, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, fmt); + _gpgrt_logv_clock (fmt, arg_ptr); + va_end (arg_ptr); +} + +void +_gpgrt_log_assert (const char *expr, const char *file, + int line, const char *func) +{ +#ifdef GPGRT_HAVE_MACRO_FUNCTION + _gpgrt__log_assert (expr, file, line, func); +#else + _gpgrt__log_assert (expr, file, line); +#endif +} + + +#if 0 +gpg_err_code_t +gpgrt_make_pipe (int filedes[2], estream_t *r_fp, int direction, int nonblock) +{ + return _gpgrt_make_pipe (filedes, r_fp, direction, nonblock); +} + +gpg_err_code_t +gpgrt_spawn_process (const char *pgmname, const char *argv[], + int *except, void (*preexec)(void), unsigned int flags, + estream_t *r_infp, estream_t *r_outfp, estream_t *r_errfp, + pid_t *pid) +{ + return _gpgrt_spawn_process (pgmname, argv, except, preexec, flags, + r_infp, r_outfp, r_errfp, pid); +} + +gpg_err_code_t +gpgrt_spawn_process_fd (const char *pgmname, const char *argv[], + int infd, int outfd, int errfd, pid_t *pid) +{ + return _gpgrt_spawn_process_fd (pgmname, argv, infd, outfd, errfd, pid); +} + +gpg_err_code_t +gpgrt_spawn_process_detached (const char *pgmname, const char *argv[], + const char *envp[]) +{ + return _gpgrt_spawn_process_detached (pgmname, argv, envp); +} + +gpg_err_code_t +gpgrt_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode) +{ + return _gpgrt_wait_process (pgmname, pid, hang, r_exitcode); +} + +gpg_err_code_t +gpgrt_wait_processes (const char **pgmnames, pid_t *pids, + size_t count, int hang, int *r_exitcodes) +{ + return _gpgrt_wait_processes (pgmnames, pids, count, hang, r_exitcodes); +} + +void +gpgrt_kill_process (pid_t pid) +{ + _gpgrt_kill_process (pid); +} + +void +gpgrt_release_process (pid_t pid) +{ + _gpgrt_release_process (pid); +} +#endif /*0*/ + + +int +gpgrt_argparse (estream_t fp, gpgrt_argparse_t *arg, gpgrt_opt_t *opts) +{ + return _gpgrt_argparse (fp, arg, opts); +} + +int +gpgrt_argparser (gpgrt_argparse_t *arg, gpgrt_opt_t *opts, const char *name) +{ + return _gpgrt_argparser (arg, opts, name); +} + +void +gpgrt_usage (int level) +{ + _gpgrt_usage (level); +} + +const char * +gpgrt_strusage (int level) +{ + return _gpgrt_strusage (level); +} + +void +gpgrt_set_strusage (const char *(*f)(int)) +{ + _gpgrt_set_strusage (f); +} + +void +gpgrt_set_usage_outfnc (int (*f)(int, const char *)) +{ + _gpgrt_set_usage_outfnc (f); +} + +void +gpgrt_set_fixed_string_mapper (const char *(*f)(const char*)) +{ + _gpgrt_set_fixed_string_mapper (f); +} + +void +gpgrt_set_confdir (int what, const char *name) +{ + _gpgrt_set_confdir (what, name); +} + + + +/* Compare program versions. */ +int +gpgrt_cmp_version (const char *a, const char *b, int level) +{ + return _gpgrt_cmp_version (a, b, level); +} + + + +/* String utilities. */ +char * +gpgrt_fnameconcat (const char *first, ... ) +{ + va_list arg_ptr; + char *result; + + va_start (arg_ptr, first); + result = _gpgrt_vfnameconcat (0, first, arg_ptr); + va_end (arg_ptr); + return result; +} + +char * +gpgrt_absfnameconcat (const char *first, ... ) +{ + va_list arg_ptr; + char *result; + + va_start (arg_ptr, first); + result = _gpgrt_vfnameconcat (1, first, arg_ptr); + va_end (arg_ptr); + return result; +} + + + +/* For consistency reasons we use function wrappers also for Windows + * specific function despite that they are technically not needed. */ +#ifdef HAVE_W32_SYSTEM + +char * +gpgrt_w32_reg_query_string (const char *root, const char *dir, const char *name) +{ + return _gpgrt_w32_reg_query_string (root, dir, name); +} + +#endif /*HAVE_W32_SYSTEM*/ diff --git a/comm/third_party/libgpg-error/src/visibility.h b/comm/third_party/libgpg-error/src/visibility.h new file mode 100644 index 0000000000..f9218b5558 --- /dev/null +++ b/comm/third_party/libgpg-error/src/visibility.h @@ -0,0 +1,419 @@ +/* visibility.h - Set visibility attribute + * Copyright (C) 2014 g10 Code GmbH + * + * This file is part of libgpg-error. + * + * libgpg-error is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * libgpg-error is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <https://www.gnu.org/licenses/>. + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#ifndef _GPGRT_VISIBILITY_H +#define _GPGRT_VISIBILITY_H + +/* Include the main header here so that public symbols are mapped to + the internal underscored ones. */ +#ifdef _GPGRT_INCL_BY_VISIBILITY_C +# include "gpgrt-int.h" +#endif + + +/* Our use of the ELF visibility feature works by passing + -fvisibiliy=hidden on the command line and by explicitly marking + all exported functions as visible. + + NOTE: When adding new functions, please make sure to add them to + gpg-error.vers and gpg-error.def.in as well. */ + +#ifdef _GPGRT_INCL_BY_VISIBILITY_C + +# ifdef GPGRT_USE_VISIBILITY +# define MARK_VISIBLE(name) \ + extern __typeof__ (name) name __attribute__ ((visibility("default"))); +# else +# define MARK_VISIBLE(name) /* */ +# endif + +MARK_VISIBLE (gpg_strerror) +MARK_VISIBLE (gpg_strerror_r) +MARK_VISIBLE (gpg_strsource) +MARK_VISIBLE (gpg_err_code_from_errno) +MARK_VISIBLE (gpg_err_code_to_errno) +MARK_VISIBLE (gpg_err_code_from_syserror) +MARK_VISIBLE (gpg_err_set_errno) + +MARK_VISIBLE (gpg_err_init) +MARK_VISIBLE (gpg_err_deinit) +MARK_VISIBLE (gpgrt_add_emergency_cleanup) +MARK_VISIBLE (gpgrt_abort) +MARK_VISIBLE (gpg_error_check_version) +MARK_VISIBLE (gpgrt_check_version) + +MARK_VISIBLE (gpgrt_lock_init) +MARK_VISIBLE (gpgrt_lock_lock) +MARK_VISIBLE (gpgrt_lock_unlock) +MARK_VISIBLE (gpgrt_lock_destroy) +MARK_VISIBLE (gpgrt_yield) +MARK_VISIBLE (gpgrt_lock_trylock) + +MARK_VISIBLE (gpgrt_fopen) +MARK_VISIBLE (gpgrt_mopen) +MARK_VISIBLE (gpgrt_fopenmem) +MARK_VISIBLE (gpgrt_fopenmem_init) +MARK_VISIBLE (gpgrt_fdopen) +MARK_VISIBLE (gpgrt_fdopen_nc) +MARK_VISIBLE (gpgrt_sysopen) +MARK_VISIBLE (gpgrt_sysopen_nc) +MARK_VISIBLE (gpgrt_fpopen) +MARK_VISIBLE (gpgrt_fpopen_nc) +MARK_VISIBLE (gpgrt_freopen) +MARK_VISIBLE (gpgrt_fopencookie) +MARK_VISIBLE (gpgrt_fclose) +MARK_VISIBLE (gpgrt_fcancel) +MARK_VISIBLE (gpgrt_fclose_snatch) +MARK_VISIBLE (gpgrt_onclose) +MARK_VISIBLE (gpgrt_fileno) +MARK_VISIBLE (gpgrt_fileno_unlocked) +MARK_VISIBLE (gpgrt_syshd) +MARK_VISIBLE (gpgrt_syshd_unlocked) +MARK_VISIBLE (_gpgrt_set_std_fd) +MARK_VISIBLE (_gpgrt_get_std_stream) +MARK_VISIBLE (gpgrt_flockfile) +MARK_VISIBLE (gpgrt_ftrylockfile) +MARK_VISIBLE (gpgrt_funlockfile) +MARK_VISIBLE (_gpgrt_pending) +MARK_VISIBLE (_gpgrt_pending_unlocked) +MARK_VISIBLE (gpgrt_feof) +MARK_VISIBLE (gpgrt_feof_unlocked) +MARK_VISIBLE (gpgrt_ferror) +MARK_VISIBLE (gpgrt_ferror_unlocked) +MARK_VISIBLE (gpgrt_clearerr) +MARK_VISIBLE (gpgrt_clearerr_unlocked) +MARK_VISIBLE (gpgrt_fflush) +MARK_VISIBLE (gpgrt_fseek) +MARK_VISIBLE (gpgrt_fseeko) +MARK_VISIBLE (gpgrt_ftell) +MARK_VISIBLE (gpgrt_ftello) +MARK_VISIBLE (gpgrt_rewind) +MARK_VISIBLE (gpgrt_ftruncate) +MARK_VISIBLE (gpgrt_fgetc) +MARK_VISIBLE (_gpgrt_getc_underflow) +MARK_VISIBLE (gpgrt_fputc) +MARK_VISIBLE (_gpgrt_putc_overflow) +MARK_VISIBLE (gpgrt_ungetc) +MARK_VISIBLE (gpgrt_read) +MARK_VISIBLE (gpgrt_write) +MARK_VISIBLE (gpgrt_write_sanitized) +MARK_VISIBLE (gpgrt_write_hexstring) +MARK_VISIBLE (gpgrt_fread) +MARK_VISIBLE (gpgrt_fwrite) +MARK_VISIBLE (gpgrt_fgets) +MARK_VISIBLE (gpgrt_fputs) +MARK_VISIBLE (gpgrt_fputs_unlocked) +MARK_VISIBLE (gpgrt_getline) +MARK_VISIBLE (gpgrt_read_line) +MARK_VISIBLE (gpgrt_fprintf) +MARK_VISIBLE (gpgrt_fprintf_unlocked) +MARK_VISIBLE (gpgrt_fprintf_sf) +MARK_VISIBLE (gpgrt_fprintf_sf_unlocked) +MARK_VISIBLE (gpgrt_printf) +MARK_VISIBLE (gpgrt_printf_unlocked) +MARK_VISIBLE (gpgrt_vfprintf) +MARK_VISIBLE (gpgrt_vfprintf_unlocked) +MARK_VISIBLE (gpgrt_setvbuf) +MARK_VISIBLE (gpgrt_setbuf) +MARK_VISIBLE (gpgrt_set_binary) +MARK_VISIBLE (gpgrt_set_nonblock) +MARK_VISIBLE (gpgrt_get_nonblock) +MARK_VISIBLE (gpgrt_poll) +MARK_VISIBLE (gpgrt_tmpfile) +MARK_VISIBLE (gpgrt_opaque_set) +MARK_VISIBLE (gpgrt_opaque_get) +MARK_VISIBLE (gpgrt_fname_set) +MARK_VISIBLE (gpgrt_fname_get) +MARK_VISIBLE (gpgrt_asprintf) +MARK_VISIBLE (gpgrt_vasprintf) +MARK_VISIBLE (gpgrt_bsprintf) +MARK_VISIBLE (gpgrt_vbsprintf) +MARK_VISIBLE (gpgrt_snprintf) +MARK_VISIBLE (gpgrt_vsnprintf) + +MARK_VISIBLE (gpgrt_set_syscall_clamp) +MARK_VISIBLE (gpgrt_get_syscall_clamp) +MARK_VISIBLE (gpgrt_set_alloc_func) + +MARK_VISIBLE (gpgrt_realloc) +MARK_VISIBLE (gpgrt_reallocarray) +MARK_VISIBLE (gpgrt_malloc) +MARK_VISIBLE (gpgrt_calloc) +MARK_VISIBLE (gpgrt_strdup) +MARK_VISIBLE (gpgrt_strconcat) +MARK_VISIBLE (gpgrt_free) +MARK_VISIBLE (gpgrt_getenv) +MARK_VISIBLE (gpgrt_setenv) +MARK_VISIBLE (gpgrt_mkdir) +MARK_VISIBLE (gpgrt_chdir) +MARK_VISIBLE (gpgrt_getcwd) +MARK_VISIBLE (gpgrt_access); + +MARK_VISIBLE (gpgrt_b64dec_start) +MARK_VISIBLE (gpgrt_b64dec_proc) +MARK_VISIBLE (gpgrt_b64dec_finish) +MARK_VISIBLE (gpgrt_b64enc_start) +MARK_VISIBLE (gpgrt_b64enc_write) +MARK_VISIBLE (gpgrt_b64enc_finish) + +MARK_VISIBLE (gpgrt_get_errorcount) +MARK_VISIBLE (gpgrt_inc_errorcount) +MARK_VISIBLE (gpgrt_log_set_sink) +MARK_VISIBLE (gpgrt_log_set_socket_dir_cb) +MARK_VISIBLE (gpgrt_log_set_pid_suffix_cb) +MARK_VISIBLE (gpgrt_log_set_prefix) +MARK_VISIBLE (gpgrt_log_get_prefix) +MARK_VISIBLE (gpgrt_log_test_fd) +MARK_VISIBLE (gpgrt_log_get_fd) +MARK_VISIBLE (gpgrt_log_get_stream) +MARK_VISIBLE (gpgrt_log) +MARK_VISIBLE (gpgrt_logv) +MARK_VISIBLE (gpgrt_logv_prefix) +MARK_VISIBLE (gpgrt_log_string) +MARK_VISIBLE (gpgrt_log_bug) +MARK_VISIBLE (gpgrt_log_fatal) +MARK_VISIBLE (gpgrt_log_error) +MARK_VISIBLE (gpgrt_log_info) +MARK_VISIBLE (gpgrt_log_debug) +MARK_VISIBLE (gpgrt_log_debug_string) +MARK_VISIBLE (gpgrt_log_printf) +MARK_VISIBLE (gpgrt_log_printhex) +MARK_VISIBLE (gpgrt_log_clock) +MARK_VISIBLE (gpgrt_log_flush) +MARK_VISIBLE (_gpgrt_log_assert) + +#if 0 +MARK_VISIBLE (gpgrt_make_pipe) +MARK_VISIBLE (gpgrt_spawn_process) +MARK_VISIBLE (gpgrt_spawn_process_fd) +MARK_VISIBLE (gpgrt_spawn_process_detached) +MARK_VISIBLE (gpgrt_wait_process) +MARK_VISIBLE (gpgrt_wait_processes) +MARK_VISIBLE (gpgrt_kill_process) +MARK_VISIBLE (gpgrt_release_process) +#endif + +MARK_VISIBLE (gpgrt_argparse) +MARK_VISIBLE (gpgrt_argparser) +MARK_VISIBLE (gpgrt_usage) +MARK_VISIBLE (gpgrt_strusage) +MARK_VISIBLE (gpgrt_set_strusage) +MARK_VISIBLE (gpgrt_set_fixed_string_mapper); +MARK_VISIBLE (gpgrt_set_usage_outfnc); +MARK_VISIBLE (gpgrt_set_confdir); + +MARK_VISIBLE (gpgrt_cmp_version); + +MARK_VISIBLE (gpgrt_fnameconcat); +MARK_VISIBLE (gpgrt_absfnameconcat); + + + +#undef MARK_VISIBLE + +#else /*!_GPGRT_INCL_BY_VISIBILITY_C*/ + +/* To avoid accidental use of the public functions inside Libgpg-error, + we redefine them to catch such errors. */ + +#define gpg_strerror _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpg_strerror_r _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpg_strsource _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpg_err_code_from_errno _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpg_err_code_to_errno _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpg_err_code_from_syserror _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpg_err_set_errno _gpgrt_USE_UNDERSCORED_FUNCTION + +#define gpg_err_init _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpg_err_deinit _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_add_emergency_cleanup _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_abort _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpg_error_check_version _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_check_version _gpgrt_USE_OTHER_FUNCTION + +#define gpgrt_lock_init _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_lock_lock _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_lock_unlock _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_lock_destroy _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_yield _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_lock_trylock _gpgrt_USE_UNDERSCORED_FUNCTION + +#define gpgrt_fopen _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_mopen _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fopenmem _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fopenmem_init _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fdopen _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fdopen_nc _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_sysopen _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_sysopen_nc _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fpopen _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fpopen_nc _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_freopen _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fopencookie _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fclose _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fcancel _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fclose_snatch _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_onclose _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fileno _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fileno_unlocked _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_syshd _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_syshd_unlocked _gpgrt_USE_UNDERSCORED_FUNCTION +#define _gpgrt_set_std_fd _gpgrt_USE_UNDERSCORED_FUNCTION +#define _gpgrt_get_std_stream _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_flockfile _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_ftrylockfile _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_funlockfile _gpgrt_USE_UNDERSCORED_FUNCTION +#define _gpgrt_pending _gpgrt_USE_UNDERSCORED_FUNCTION +#define _gpgrt_pending_unlocked _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_feof _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_feof_unlocked _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_ferror _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_ferror_unlocked _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_clearerr _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_clearerr_unlocked _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fflush _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fseek _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fseeko _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_ftell _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_ftello _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_rewind _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_ftruncate _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fgetc _gpgrt_USE_UNDERSCORED_FUNCTION +#define _gpgrt_getc_underflow _gpgrt_USE_DBLUNDERSCO_FUNCTION +#define gpgrt_fputc _gpgrt_USE_UNDERSCORED_FUNCTION +#define _gpgrt_putc_overflow _gpgrt_USE_DBLUNDERSCO_FUNCTION +#define gpgrt_ungetc _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_read _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_write _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_write_sanitized _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_write_hexstring _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fread _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fwrite _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fgets _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fputs _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fputs_unlocked _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_getline _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_read_line _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fprintf _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fprintf_unlocked _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fprintf_sf _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fprintf_sf_unlocked _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_printf _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_printf_unlocked _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_vfprintf _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_vfprintf_unlocked _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_setvbuf _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_setbuf _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_set_binary _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_set_nonblock _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_get_nonblock _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_poll _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_tmpfile _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_opaque_set _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_opaque_get _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fname_set _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fname_get _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_asprintf _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_vasprintf _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_bsprintf _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_vbsprintf _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_snprintf _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_vsnprintf _gpgrt_USE_UNDERSCORED_FUNCTION + +#define gpgrt_realloc _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_reallocarray _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_malloc _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_calloc _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_strdup _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_strconcat _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_free _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_getenv _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_setenv _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_mkdir _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_chdir _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_getcwd _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_access _gpgrt_USE_UNDERSCORED_FUNCTION + +#define gpgrt_set_syscall_clamp _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_get_syscall_clamp _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_set_alloc_func _gpgrt_USE_UNDERSCORED_FUNCTION + +#define gpgrt_b64enc_start _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_b64enc_write _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_b64enc_finish _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_b64dec_start _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_b64dec_proc _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_b64dec_finish _gpgrt_USE_UNDERSCORED_FUNCTION + +#define gpgrt_get_errorcount _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_inc_errorcount _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_log_set_sink _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_log_set_socket_dir_cb _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_log_set_pid_suffix_cb _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_log_set_prefix _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_log_get_prefix _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_log_test_fd _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_log_get_fd _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_log_get_stream _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_log _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_logv _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_logv_prefix _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_log_string _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_log_bug _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_log_fatal _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_log_error _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_log_info _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_log_debug _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_log_debug_string _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_log_printf _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_log_printhex _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_log_clock _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_log_flush _gpgrt_USE_UNDERSCORED_FUNCTION +#define _gpgrt_log_assert _gpgrt_USE_UNDERSCORED_FUNCTION + +#define gpgrt_make_pipe _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_spawn_process _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_spawn_process_fd _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_spawn_process_detached _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_wait_process _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_wait_processes _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_kill_process _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_release_process _gpgrt_USE_UNDERSCORED_FUNCTION + +#define gpgrt_argparse _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_argparser _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_usage _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_set_strusage _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_strusage _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_set_usage_outfnc _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_set_fixed_string_mapper _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_set_confdir _gpgrt_USE_UNDERSCORED_FUNCTION + +#define gpgrt_cmp_version _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_fnameconcat _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_absfnameconcat _gpgrt_USE_UNDERSCORED_FUNCTION + +/* Windows specific functions. */ +#define gpgrt_w32_reg_query_string _gpgrt_USE_UNDERSCORED_FUNCTION + + +#endif /*!_GPGRT_INCL_BY_VISIBILITY_C*/ + +#endif /*_GPGRT_VISIBILITY_H*/ diff --git a/comm/third_party/libgpg-error/src/w32-add.h b/comm/third_party/libgpg-error/src/w32-add.h new file mode 100644 index 0000000000..34289615f4 --- /dev/null +++ b/comm/third_party/libgpg-error/src/w32-add.h @@ -0,0 +1,67 @@ +## w32-add.h - Snippet to be be included into gpg-error.h. +## Comments are indicated by a double hash mark. Due to a +## peculiarity of the script the first used line must not +## start with a hash mark. + +/* Decide whether to use the format_arg attribute. */ +#if _GPG_ERR_GCC_VERSION > 20800 +# define _GPG_ERR_ATTR_FORMAT_ARG(a) __attribute__ ((__format_arg__ (a))) +#else +# define _GPG_ERR_ATTR_FORMAT_ARG(a) +#endif + +/* A lean gettext implementation based on GNU style mo files which are + required to be encoded in UTF-8. There is a limit on 65534 entries + to save some RAM. Only Germanic plural rules are supported. */ +const char *_gpg_w32_bindtextdomain (const char *domainname, + const char *dirname); +const char *_gpg_w32_textdomain (const char *domainname); +const char *_gpg_w32_gettext (const char *msgid) + _GPG_ERR_ATTR_FORMAT_ARG (1); +const char *_gpg_w32_dgettext (const char *domainname, const char *msgid) + _GPG_ERR_ATTR_FORMAT_ARG (2); +const char *_gpg_w32_dngettext (const char *domainname, const char *msgid1, + const char *msgid2, unsigned long int n) + _GPG_ERR_ATTR_FORMAT_ARG (2) _GPG_ERR_ATTR_FORMAT_ARG (3); +const char *_gpg_w32_gettext_localename (void); +int _gpg_w32_gettext_use_utf8 (int value); + +#ifdef GPG_ERR_ENABLE_GETTEXT_MACROS +# define bindtextdomain(a,b) _gpg_w32_bindtextdomain ((a), (b)) +# define textdomain(a) _gpg_w32_textdomain ((a)) +# define gettext(a) _gpg_w32_gettext ((a)) +# define dgettext(a,b) _gpg_w32_dgettext ((a), (b)) +# define ngettext(a,b,c) _gpg_w32_dngettext (NULL, (a), (b), (c)) +# define dngettext(a,b,c,d) _gpg_w32_dngettext ((a), (b), (c), (d)) +# define gettext_localename() _gpg_w32_gettext_localename () +# define gettext_use_utf8(a) _gpg_w32_gettext_use_utf8 (a) +#endif /*GPG_ERR_ENABLE_GETTEXT_MACROS*/ + +/* Force the use of the locale NAME or if NAME is NULL the one derived + * from LANGID. This function must be used early and is not thread-safe. */ +void gpgrt_w32_override_locale (const char *name, unsigned short langid); + + +/* A simple iconv implementation w/o the need for an extra DLL. */ +struct _gpgrt_w32_iconv_s; +typedef struct _gpgrt_w32_iconv_s *gpgrt_w32_iconv_t; + +gpgrt_w32_iconv_t gpgrt_w32_iconv_open (const char *tocode, + const char *fromcode); +int gpgrt_w32_iconv_close (gpgrt_w32_iconv_t cd); +size_t gpgrt_w32_iconv (gpgrt_w32_iconv_t cd, + const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft); + +#ifdef GPGRT_ENABLE_W32_ICONV_MACROS +# define ICONV_CONST const +# define iconv_t gpgrt_w32_iconv_t +# define iconv_open(a,b) gpgrt_w32_iconv_open ((a), (b)) +# define iconv_close(a) gpgrt_w32_iconv_close ((a)) +# define iconv(a,b,c,d,e) gpgrt_w32_iconv ((a),(b),(c),(d),(e)) +#endif /*GPGRT_ENABLE_W32_ICONV_MACROS*/ + +/* Query a string in the registry. */ +char *gpgrt_w32_reg_query_string (const char *root, + const char *dir, + const char *name); diff --git a/comm/third_party/libgpg-error/src/w32-estream.c b/comm/third_party/libgpg-error/src/w32-estream.c new file mode 100644 index 0000000000..5bb1bcf56c --- /dev/null +++ b/comm/third_party/libgpg-error/src/w32-estream.c @@ -0,0 +1,1078 @@ +/* w32-estream.c - es_poll support on W32. + * Copyright (C) 2000 Werner Koch (dd9jn) + * Copyright (C) 2001, 2002, 2003, 2004, 2007, 2010, 2016 g10 Code GmbH + * + * This file is part of libgpg-error. + * + * libgpg-error is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * libgpg-error is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <https://www.gnu.org/licenses/>. + */ + +/* + * This file is based on GPGME's w32-io.c started in 2001. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#ifdef HAVE_SYS_TIME_H +# include <sys/time.h> +#endif +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif +#include <io.h> +#include <windows.h> + +/* Enable tracing. The value is the module name to be printed. */ +/*#define ENABLE_TRACING "estream" */ + +#include "gpgrt-int.h" + +/* + * In order to support es_poll on Windows, we create a proxy shim that + * we use as the estream I/O functions. This shim creates reader and + * writer threads that use the original I/O functions. + */ + + +/* Calculate array dimension. */ +#ifndef DIM +#define DIM(array) (sizeof (array) / sizeof (*array)) +#endif + +#define READBUF_SIZE 8192 +#define WRITEBUF_SIZE 8192 + + +typedef struct estream_cookie_w32_pollable *estream_cookie_w32_pollable_t; + +struct reader_context_s +{ + estream_cookie_w32_pollable_t pcookie; + HANDLE thread_hd; + + CRITICAL_SECTION mutex; + + int stop_me; + int eof; + int eof_shortcut; + int error; + int error_code; + + /* This is manually reset. */ + HANDLE have_data_ev; + /* This is automatically reset. */ + HANDLE have_space_ev; + /* This is manually reset but actually only triggered once. */ + HANDLE close_ev; + + size_t readpos, writepos; + char buffer[READBUF_SIZE]; +}; + +struct writer_context_s +{ + estream_cookie_w32_pollable_t pcookie; + HANDLE thread_hd; + + CRITICAL_SECTION mutex; + + int stop_me; + int error; + int error_code; + + /* This is manually reset. */ + HANDLE have_data; + HANDLE is_empty; + HANDLE close_ev; + size_t nbytes; + char buffer[WRITEBUF_SIZE]; +}; + +/* Cookie for pollable objects. */ +struct estream_cookie_w32_pollable +{ + unsigned int modeflags; + + struct cookie_io_functions_s next_functions; + void *next_cookie; + + struct reader_context_s *reader; + struct writer_context_s *writer; +}; + + +static DWORD CALLBACK +reader (void *arg) +{ + struct reader_context_s *ctx = arg; + int nbytes; + ssize_t nread; + + trace (("%p: reader starting", ctx)); + + for (;;) + { + EnterCriticalSection (&ctx->mutex); + /* Leave a 1 byte gap so that we can see whether it is empty or + full. */ + while ((ctx->writepos + 1) % READBUF_SIZE == ctx->readpos) + { + /* Wait for space. */ + if (!ResetEvent (ctx->have_space_ev)) + trace (("%p: ResetEvent failed: ec=%d", ctx, (int)GetLastError())); + LeaveCriticalSection (&ctx->mutex); + trace (("%p: waiting for space", ctx)); + WaitForSingleObject (ctx->have_space_ev, INFINITE); + trace (("%p: got space", ctx)); + EnterCriticalSection (&ctx->mutex); + } + gpgrt_assert (((ctx->writepos + 1) % READBUF_SIZE != ctx->readpos)); + if (ctx->stop_me) + { + LeaveCriticalSection (&ctx->mutex); + break; + } + nbytes = (ctx->readpos + READBUF_SIZE + - ctx->writepos - 1) % READBUF_SIZE; + gpgrt_assert (nbytes); + if (nbytes > READBUF_SIZE - ctx->writepos) + nbytes = READBUF_SIZE - ctx->writepos; + LeaveCriticalSection (&ctx->mutex); + + trace (("%p: reading up to %d bytes", ctx, nbytes)); + + nread = ctx->pcookie->next_functions.public.func_read + (ctx->pcookie->next_cookie, ctx->buffer + ctx->writepos, nbytes); + trace (("%p: got %d bytes", ctx, nread)); + if (nread < 0) + { + ctx->error_code = (int) errno; + /* NOTE (W32CE): Do not ignore ERROR_BUSY! Check at + least stop_me if that happens. */ + if (ctx->error_code == ERROR_BROKEN_PIPE) + { + ctx->eof = 1; + trace (("%p: got EOF (broken pipe)", ctx)); + } + else + { + ctx->error = 1; + trace (("%p: read error: ec=%d", ctx, ctx->error_code)); + } + break; + } + + EnterCriticalSection (&ctx->mutex); + if (ctx->stop_me) + { + LeaveCriticalSection (&ctx->mutex); + break; + } + if (!nread) + { + ctx->eof = 1; + trace (("%p: got eof", ctx)); + LeaveCriticalSection (&ctx->mutex); + break; + } + + ctx->writepos = (ctx->writepos + nread) % READBUF_SIZE; + if (!SetEvent (ctx->have_data_ev)) + trace (("%p: SetEvent (%p) failed: ec=%d", + ctx, ctx->have_data_ev, (int)GetLastError ())); + LeaveCriticalSection (&ctx->mutex); + } + /* Indicate that we have an error or EOF. */ + if (!SetEvent (ctx->have_data_ev)) + trace (("%p: SetEvent (%p) failed: ec=%d", + ctx, ctx->have_data_ev, (int)GetLastError ())); + + trace (("%p: waiting for close", ctx)); + WaitForSingleObject (ctx->close_ev, INFINITE); + + CloseHandle (ctx->close_ev); + CloseHandle (ctx->have_data_ev); + CloseHandle (ctx->have_space_ev); + CloseHandle (ctx->thread_hd); + DeleteCriticalSection (&ctx->mutex); + free (ctx); /* Standard free! See comment in create_reader. */ + + return 0; +} + + +static struct reader_context_s * +create_reader (estream_cookie_w32_pollable_t pcookie) +{ + struct reader_context_s *ctx; + SECURITY_ATTRIBUTES sec_attr; + DWORD tid; + + memset (&sec_attr, 0, sizeof sec_attr); + sec_attr.nLength = sizeof sec_attr; + sec_attr.bInheritHandle = FALSE; + + /* The CTX must be allocated in standard system memory so that we + * won't use any custom allocation handler which may use our lock + * primitives for its implementation. The problem here is that the + * syscall clamp mechanism (e.g. nPth) would be called recursively: + * 1. For example by the caller of _gpgrt_w32_poll and 2. by + * gpgrt_lock_lock on behalf of the the custom allocation and free + * functions. */ + ctx = calloc (1, sizeof *ctx); + if (!ctx) + { + return NULL; + } + + ctx->pcookie = pcookie; + + ctx->have_data_ev = CreateEvent (&sec_attr, TRUE, FALSE, NULL); + if (ctx->have_data_ev) + ctx->have_space_ev = CreateEvent (&sec_attr, FALSE, TRUE, NULL); + if (ctx->have_space_ev) + ctx->close_ev = CreateEvent (&sec_attr, TRUE, FALSE, NULL); + if (!ctx->have_data_ev || !ctx->have_space_ev || !ctx->close_ev) + { + trace (("%p: CreateEvent failed: ec=%d", ctx, (int)GetLastError ())); + if (ctx->have_data_ev) + CloseHandle (ctx->have_data_ev); + if (ctx->have_space_ev) + CloseHandle (ctx->have_space_ev); + if (ctx->close_ev) + CloseHandle (ctx->close_ev); + _gpgrt_free (ctx); + return NULL; + } + + InitializeCriticalSection (&ctx->mutex); + +#ifdef HAVE_W32CE_SYSTEM + ctx->thread_hd = CreateThread (&sec_attr, 64 * 1024, reader, ctx, + STACK_SIZE_PARAM_IS_A_RESERVATION, &tid); +#else + ctx->thread_hd = CreateThread (&sec_attr, 0, reader, ctx, 0, &tid); +#endif + + if (!ctx->thread_hd) + { + trace (("%p: CreateThread failed: ec=%d", ctx, (int)GetLastError ())); + DeleteCriticalSection (&ctx->mutex); + if (ctx->have_data_ev) + CloseHandle (ctx->have_data_ev); + if (ctx->have_space_ev) + CloseHandle (ctx->have_space_ev); + if (ctx->close_ev) + CloseHandle (ctx->close_ev); + _gpgrt_free (ctx); + return NULL; + } + else + { +#if 0 + /* We set the priority of the thread higher because we know that + it only runs for a short time. This greatly helps to + increase the performance of the I/O. */ + SetThreadPriority (ctx->thread_hd, get_desired_thread_priority ()); +#endif + } + + return ctx; +} + + +/* Prepare destruction of the reader thread for CTX. Returns 0 if a + call to this function is sufficient and destroy_reader_finish shall + not be called. */ +static void +destroy_reader (struct reader_context_s *ctx) +{ + EnterCriticalSection (&ctx->mutex); + ctx->stop_me = 1; + if (ctx->have_space_ev) + SetEvent (ctx->have_space_ev); + LeaveCriticalSection (&ctx->mutex); + +#ifdef HAVE_W32CE_SYSTEM + /* Scenario: We never create a full pipe, but already started + reading. Then we need to unblock the reader in the pipe driver + to make our reader thread notice that we want it to go away. */ + + if (ctx->file_hd != INVALID_HANDLE_VALUE) + { + if (!DeviceIoControl (ctx->file_hd, GPGCEDEV_IOCTL_UNBLOCK, + NULL, 0, NULL, 0, NULL, NULL)) + { + trace (("%p: unblock control call failed: ec=%d", + ctx, (int)GetLastError ())); + } + } +#endif + + /* XXX is it feasible to unblock the thread? */ + + /* After setting this event CTX is void. */ + SetEvent (ctx->close_ev); +} + + +/* + * Read function for pollable objects. + */ +static gpgrt_ssize_t +func_w32_pollable_read (void *cookie, void *buffer, size_t count) +{ + estream_cookie_w32_pollable_t pcookie = cookie; + gpgrt_ssize_t nread; + struct reader_context_s *ctx; + + trace (("%p: enter buffer=%p count=%u", cookie, buffer, count)); + + /* FIXME: implement pending check if COUNT==0 */ + + ctx = pcookie->reader; + if (ctx == NULL) + { + pcookie->reader = ctx = create_reader (pcookie); + if (!ctx) + { + _gpg_err_set_errno (EBADF); + nread = -1; + goto leave; + } + trace (("%p: new reader %p", cookie, pcookie->reader)); + } + + if (ctx->eof_shortcut) + { + nread = 0; + goto leave; + } + + EnterCriticalSection (&ctx->mutex); + trace (("%p: readpos: %d, writepos %d", cookie, ctx->readpos, ctx->writepos)); + if (ctx->readpos == ctx->writepos && !ctx->error) + { + /* No data available. */ + int eof = ctx->eof; + + LeaveCriticalSection (&ctx->mutex); + + if (pcookie->modeflags & O_NONBLOCK && ! eof) + { + _gpg_err_set_errno (EAGAIN); + nread = -1; + goto leave; + } + + trace (("%p: waiting for data", cookie)); + WaitForSingleObject (ctx->have_data_ev, INFINITE); + trace (("%p: data available", cookie)); + EnterCriticalSection (&ctx->mutex); + } + + if (ctx->readpos == ctx->writepos || ctx->error) + { + LeaveCriticalSection (&ctx->mutex); + ctx->eof_shortcut = 1; + if (ctx->eof) + return 0; + if (!ctx->error) + { + trace (("%p: EOF but ctx->eof flag not set", cookie)); + nread = 0; + goto leave; + } + _gpg_err_set_errno (ctx->error_code); + return -1; + } + + nread = ctx->readpos < ctx->writepos + ? ctx->writepos - ctx->readpos + : READBUF_SIZE - ctx->readpos; + if (nread > count) + nread = count; + memcpy (buffer, ctx->buffer + ctx->readpos, nread); + ctx->readpos = (ctx->readpos + nread) % READBUF_SIZE; + if (ctx->readpos == ctx->writepos && !ctx->eof) + { + if (!ResetEvent (ctx->have_data_ev)) + { + trace (("%p: ResetEvent failed: ec=%d", + cookie, (int)GetLastError ())); + LeaveCriticalSection (&ctx->mutex); + /* FIXME: Should translate the error code. */ + _gpg_err_set_errno (EIO); + nread = -1; + goto leave; + } + } + if (!SetEvent (ctx->have_space_ev)) + { + trace (("%p: SetEvent (%p) failed: ec=%d", + cookie, ctx->have_space_ev, (int)GetLastError ())); + LeaveCriticalSection (&ctx->mutex); + /* FIXME: Should translate the error code. */ + _gpg_err_set_errno (EIO); + nread = -1; + goto leave; + } + LeaveCriticalSection (&ctx->mutex); + + leave: + trace_errno (nread==-1,("%p: leave nread=%d", cookie, (int)nread)); + return nread; +} + + +/* The writer does use a simple buffering strategy so that we are + informed about write errors as soon as possible (i. e. with the the + next call to the write function. */ +static DWORD CALLBACK +writer (void *arg) +{ + struct writer_context_s *ctx = arg; + ssize_t nwritten; + + trace (("%p: writer starting", ctx)); + + for (;;) + { + EnterCriticalSection (&ctx->mutex); + if (ctx->stop_me && !ctx->nbytes) + { + LeaveCriticalSection (&ctx->mutex); + break; + } + if (!ctx->nbytes) + { + if (!SetEvent (ctx->is_empty)) + trace (("%p: SetEvent failed: ec=%d", ctx, (int)GetLastError ())); + if (!ResetEvent (ctx->have_data)) + trace (("%p: ResetEvent failed: ec=%d", ctx, (int)GetLastError ())); + LeaveCriticalSection (&ctx->mutex); + trace (("%p: idle", ctx)); + WaitForSingleObject (ctx->have_data, INFINITE); + trace (("%p: got data to write", ctx)); + EnterCriticalSection (&ctx->mutex); + } + if (ctx->stop_me && !ctx->nbytes) + { + LeaveCriticalSection (&ctx->mutex); + break; + } + LeaveCriticalSection (&ctx->mutex); + + trace (("%p: writing up to %d bytes", ctx, ctx->nbytes)); + + nwritten = ctx->pcookie->next_functions.public.func_write + (ctx->pcookie->next_cookie, ctx->buffer, ctx->nbytes); + trace (("%p: wrote %d bytes", ctx, nwritten)); + if (nwritten < 1) + { + /* XXX */ + if (errno == ERROR_BUSY) + { + /* Probably stop_me is set now. */ + trace (("%p: pipe busy (unblocked?)", ctx)); + continue; + } + + ctx->error_code = errno; + ctx->error = 1; + trace (("%p: write error: ec=%d", ctx, ctx->error_code)); + break; + } + + EnterCriticalSection (&ctx->mutex); + ctx->nbytes -= nwritten; + LeaveCriticalSection (&ctx->mutex); + } + /* Indicate that we have an error. */ + if (!SetEvent (ctx->is_empty)) + trace (("%p: SetEvent failed: ec=%d", ctx, (int)GetLastError ())); + + trace (("%p: waiting for close", ctx)); + WaitForSingleObject (ctx->close_ev, INFINITE); + + if (ctx->nbytes) + trace (("%p: still %d bytes in buffer at close time", ctx, ctx->nbytes)); + + CloseHandle (ctx->close_ev); + CloseHandle (ctx->have_data); + CloseHandle (ctx->is_empty); + CloseHandle (ctx->thread_hd); + DeleteCriticalSection (&ctx->mutex); + trace (("%p: writer is destroyed", ctx)); + free (ctx); /* Standard free! See comment in create_writer. */ + + return 0; +} + + +static struct writer_context_s * +create_writer (estream_cookie_w32_pollable_t pcookie) +{ + struct writer_context_s *ctx; + SECURITY_ATTRIBUTES sec_attr; + DWORD tid; + + memset (&sec_attr, 0, sizeof sec_attr); + sec_attr.nLength = sizeof sec_attr; + sec_attr.bInheritHandle = FALSE; + + /* See comment at create_reader. */ + ctx = calloc (1, sizeof *ctx); + if (!ctx) + { + return NULL; + } + + ctx->pcookie = pcookie; + + ctx->have_data = CreateEvent (&sec_attr, TRUE, FALSE, NULL); + if (ctx->have_data) + ctx->is_empty = CreateEvent (&sec_attr, TRUE, TRUE, NULL); + if (ctx->is_empty) + ctx->close_ev = CreateEvent (&sec_attr, TRUE, FALSE, NULL); + if (!ctx->have_data || !ctx->is_empty || !ctx->close_ev) + { + trace (("%p: CreateEvent failed: ec=%d", ctx, (int)GetLastError ())); + if (ctx->have_data) + CloseHandle (ctx->have_data); + if (ctx->is_empty) + CloseHandle (ctx->is_empty); + if (ctx->close_ev) + CloseHandle (ctx->close_ev); + _gpgrt_free (ctx); + return NULL; + } + + InitializeCriticalSection (&ctx->mutex); + +#ifdef HAVE_W32CE_SYSTEM + ctx->thread_hd = CreateThread (&sec_attr, 64 * 1024, writer, ctx, + STACK_SIZE_PARAM_IS_A_RESERVATION, &tid); +#else + ctx->thread_hd = CreateThread (&sec_attr, 0, writer, ctx, 0, &tid ); +#endif + + if (!ctx->thread_hd) + { + trace (("%p: CreateThread failed: ec=%d", ctx, (int)GetLastError ())); + DeleteCriticalSection (&ctx->mutex); + if (ctx->have_data) + CloseHandle (ctx->have_data); + if (ctx->is_empty) + CloseHandle (ctx->is_empty); + if (ctx->close_ev) + CloseHandle (ctx->close_ev); + _gpgrt_free (ctx); + return NULL; + } + else + { +#if 0 + /* We set the priority of the thread higher because we know + that it only runs for a short time. This greatly helps to + increase the performance of the I/O. */ + SetThreadPriority (ctx->thread_hd, get_desired_thread_priority ()); +#endif + } + + return ctx; +} + + +static void +destroy_writer (struct writer_context_s *ctx) +{ + trace (("%p: enter pollable_destroy_writer", ctx)); + EnterCriticalSection (&ctx->mutex); + trace (("%p: setting stopme", ctx)); + ctx->stop_me = 1; + if (ctx->have_data) + SetEvent (ctx->have_data); + LeaveCriticalSection (&ctx->mutex); + + trace (("%p: waiting for empty", ctx)); + + /* Give the writer a chance to flush the buffer. */ + WaitForSingleObject (ctx->is_empty, INFINITE); + +#ifdef HAVE_W32CE_SYSTEM + /* Scenario: We never create a full pipe, but already started + writing more than the pipe buffer. Then we need to unblock the + writer in the pipe driver to make our writer thread notice that + we want it to go away. */ + + if (!DeviceIoControl (ctx->file_hd, GPGCEDEV_IOCTL_UNBLOCK, + NULL, 0, NULL, 0, NULL, NULL)) + { + trace (("%p: unblock control call failed: ec=%d", + ctx, (int)GetLastError ())); + } +#endif + + /* After setting this event CTX is void. */ + trace (("%p: set close_ev", ctx)); + SetEvent (ctx->close_ev); + trace (("%p: leave pollable_destroy_writer", ctx)); +} + + +/* + * Write function for pollable objects. + */ +static gpgrt_ssize_t +func_w32_pollable_write (void *cookie, const void *buffer, size_t count) +{ + estream_cookie_w32_pollable_t pcookie = cookie; + struct writer_context_s *ctx = pcookie->writer; + int nwritten; + + trace (("%p: enter buffer: %p count: %d", cookie, buffer, count)); + if (count == 0) + { + nwritten = 0; + goto leave; + } + + if (ctx == NULL) + { + pcookie->writer = ctx = create_writer (pcookie); + if (!ctx) + { + nwritten = -1; + goto leave; + } + trace (("%p: new writer %p", cookie, pcookie->writer)); + } + + EnterCriticalSection (&ctx->mutex); + trace (("%p: buffer: %p, count: %d, nbytes: %d", + cookie, buffer, count, ctx->nbytes)); + if (!ctx->error && ctx->nbytes) + { + /* Bytes are pending for send. */ + + /* Reset the is_empty event. Better safe than sorry. */ + if (!ResetEvent (ctx->is_empty)) + { + trace (("%p: ResetEvent failed: ec=%d", + cookie, (int)GetLastError ())); + LeaveCriticalSection (&ctx->mutex); + /* FIXME: Should translate the error code. */ + _gpg_err_set_errno (EIO); + nwritten = -1; + goto leave; + } + LeaveCriticalSection (&ctx->mutex); + + if (pcookie->modeflags & O_NONBLOCK) + { + trace (("%p: would block", cookie)); + _gpg_err_set_errno (EAGAIN); + nwritten = -1; + goto leave; + } + + trace (("%p: waiting for empty buffer", cookie)); + WaitForSingleObject (ctx->is_empty, INFINITE); + trace (("%p: buffer is empty", cookie)); + EnterCriticalSection (&ctx->mutex); + } + + if (ctx->error) + { + LeaveCriticalSection (&ctx->mutex); + if (ctx->error_code == ERROR_NO_DATA) + _gpg_err_set_errno (EPIPE); + else + _gpg_err_set_errno (EIO); + nwritten = -1; + goto leave; + } + + /* If no error occurred, the number of bytes in the buffer must be + zero. */ + gpgrt_assert (!ctx->nbytes); + + if (count > WRITEBUF_SIZE) + count = WRITEBUF_SIZE; + memcpy (ctx->buffer, buffer, count); + ctx->nbytes = count; + + /* We have to reset the is_empty event early, because it is also + used by the select() implementation to probe the channel. */ + if (!ResetEvent (ctx->is_empty)) + { + trace (("%p: ResetEvent failed: ec=%d", cookie, (int)GetLastError ())); + LeaveCriticalSection (&ctx->mutex); + /* FIXME: Should translate the error code. */ + _gpg_err_set_errno (EIO); + nwritten = -1; + goto leave; + } + if (!SetEvent (ctx->have_data)) + { + trace (("%p: SetEvent failed: ec=%d", cookie, (int)GetLastError ())); + LeaveCriticalSection (&ctx->mutex); + /* FIXME: Should translate the error code. */ + _gpg_err_set_errno (EIO); + nwritten = -1; + goto leave; + } + LeaveCriticalSection (&ctx->mutex); + + nwritten = count; + + leave: + trace_errno (nwritten==-1,("%p: leave nwritten=%d", cookie, nwritten)); + return nwritten; +} + + +/* This is the core of _gpgrt_poll. The caller needs to make sure that + * the syscall clamp has been engaged. */ +int +_gpgrt_w32_poll (gpgrt_poll_t *fds, size_t nfds, int timeout) +{ + HANDLE waitbuf[MAXIMUM_WAIT_OBJECTS]; + int waitidx[MAXIMUM_WAIT_OBJECTS]; +#ifdef ENABLE_TRACING + char waitinfo[MAXIMUM_WAIT_OBJECTS]; +#endif + unsigned int code; + int nwait; + int i; + int any; + int count; + +#if 0 + restart: +#endif + + any = 0; + nwait = 0; + count = 0; + for (i = 0; i < nfds; i++) + { + struct estream_cookie_w32_pollable *pcookie; + + if (fds[i].ignore) + continue; + + if (fds[i].stream->intern->kind != BACKEND_W32_POLLABLE) + { + /* This stream does not support polling. */ + fds[i].got_err = 1; + continue; + } + + pcookie = fds[i].stream->intern->cookie; + + if (fds[i].want_read || fds[i].want_write) + { + /* XXX: What if one wants read and write, is that supported? */ + if (fds[i].want_read) + { + struct reader_context_s *ctx = pcookie->reader; + if (ctx == NULL) + { + pcookie->reader = ctx = create_reader (pcookie); + if (!ctx) + { + /* FIXME: Is the error code appropriate? */ + _gpg_err_set_errno (EBADF); + return -1; + } + trace (("%p: new reader %p", pcookie, pcookie->reader)); + } + trace (("%p: using reader %p", pcookie, pcookie->reader)); + + if (nwait >= DIM (waitbuf)) + { + trace (("oops: too many objects for WFMO")); + /* FIXME: Should translate the error code. */ + _gpg_err_set_errno (EIO); + return -1; + } + waitidx[nwait] = i; +#ifdef ENABLE_TRACING + waitinfo[nwait] = 'r'; +#endif /*ENABLE_TRACING*/ + waitbuf[nwait++] = ctx->have_data_ev; + any = 1; + } + else if (fds[i].want_write) + { + struct writer_context_s *ctx = pcookie->writer; + if (ctx == NULL) + { + pcookie->writer = ctx = create_writer (pcookie); + if (!ctx) + { + trace (("oops: create writer failed")); + /* FIXME: Is the error code appropriate? */ + _gpg_err_set_errno (EBADF); + return -1; + } + trace (("%p: new writer %p", pcookie, pcookie->writer)); + } + trace (("%p: using writer %p", pcookie, pcookie->writer)); + + if (nwait >= DIM (waitbuf)) + { + trace (("oops: Too many objects for WFMO")); + /* FIXME: Should translate the error code. */ + _gpg_err_set_errno (EIO); + return -1; + } + waitidx[nwait] = i; +#ifdef ENABLE_TRACING + waitinfo[nwait] = 'w'; +#endif /*ENABLE_TRACING*/ + waitbuf[nwait++] = ctx->is_empty; + any = 1; + } + } + } +#ifdef ENABLE_TRACING + trace_start (("poll on [ ")); + for (i = 0; i < nwait; i++) + trace_append (("%d/%c ", waitidx[i], waitinfo[i])); + trace_finish (("]")); +#endif /*ENABLE_TRACING*/ + + if (!any) + { + /* WFMO needs at least one object, thus we use use sleep here. + * INFINITE wait does not make any sense in this case, so we + * error out. */ + if (timeout == -1) + { + _gpg_err_set_errno (EINVAL); + return -1; + } + if (timeout) + Sleep (timeout); + code = WAIT_TIMEOUT; + } + else + code = WaitForMultipleObjects (nwait, waitbuf, 0, + timeout == -1 ? INFINITE : timeout); + + if (code < WAIT_OBJECT_0 + nwait) + { + /* This WFMO is a really silly function: It does return either + the index of the signaled object or if 2 objects have been + signalled at the same time, the index of the object with the + lowest object is returned - so and how do we find out how + many objects have been signaled???. The only solution I can + imagine is to test each object starting with the returned + index individually - how dull. */ + any = 0; + for (i = code - WAIT_OBJECT_0; i < nwait; i++) + { + if (WaitForSingleObject (waitbuf[i], 0) == WAIT_OBJECT_0) + { + gpgrt_assert (waitidx[i] >=0 && waitidx[i] < nfds); + /* XXX: What if one wants read and write, is that + supported? */ + if (fds[waitidx[i]].want_read) + fds[waitidx[i]].got_read = 1; + else if (fds[waitidx[i]].want_write) + fds[waitidx[i]].got_write = 1; + any = 1; + count++; + } + } + if (!any) + { + trace (("no signaled objects found after WFMO")); + count = -1; + } + } + else if (code == WAIT_TIMEOUT) + trace (("WFMO timed out")); + else if (code == WAIT_FAILED) + { + trace (("WFMO failed: ec=%d", (int)GetLastError ())); +#if 0 + if (GetLastError () == ERROR_INVALID_HANDLE) + { + int k; + int j = handle_to_fd (waitbuf[i]); + + trace (("WFMO invalid handle %d removed", j)); + for (k = 0 ; k < nfds; k++) + { + if (fds[k].fd == j) + { + fds[k].want_read = fds[k].want_write = 0; + goto restart; + } + } + trace ((" oops, or not???")); + } +#endif + count = -1; + } + else + { + trace (("WFMO returned %u", code)); + count = -1; + } + + if (count > 0) + { + trace_start (("poll OK [ ")); + for (i = 0; i < nfds; i++) + { + if (fds[i].ignore) + continue; + if (fds[i].got_read || fds[i].got_write) + trace_append (("%c%d ", fds[i].want_read ? 'r' : 'w', i)); + } + trace_finish (("]")); + } + + if (count < 0) + { + /* FIXME: Should determine a proper error code. */ + _gpg_err_set_errno (EIO); + } + + return count; +} + + + +/* + * Implementation of pollable I/O on Windows. + */ + +/* + * Constructor for pollable objects. + */ +int +_gpgrt_w32_pollable_create (void *_GPGRT__RESTRICT *_GPGRT__RESTRICT cookie, + unsigned int modeflags, + struct cookie_io_functions_s next_functions, + void *next_cookie) +{ + estream_cookie_w32_pollable_t pcookie; + int err; + + pcookie = _gpgrt_malloc (sizeof *pcookie); + if (!pcookie) + err = -1; + else + { + pcookie->modeflags = modeflags; + pcookie->next_functions = next_functions; + pcookie->next_cookie = next_cookie; + pcookie->reader = NULL; + pcookie->writer = NULL; + *cookie = pcookie; + err = 0; + } + + trace_errno (err,("cookie=%p", *cookie)); + return err; +} + + +/* + * Seek function for pollable objects. + */ +static int +func_w32_pollable_seek (void *cookie, gpgrt_off_t *offset, int whence) +{ + estream_cookie_w32_pollable_t pcookie = cookie; + (void) pcookie; + (void) offset; + (void) whence; + /* XXX */ + _gpg_err_set_errno (EOPNOTSUPP); + return -1; +} + + +/* + * The IOCTL function for pollable objects. + */ +static int +func_w32_pollable_ioctl (void *cookie, int cmd, void *ptr, size_t *len) +{ + estream_cookie_w32_pollable_t pcookie = cookie; + cookie_ioctl_function_t func_ioctl = pcookie->next_functions.func_ioctl; + + if (cmd == COOKIE_IOCTL_NONBLOCK) + { + if (ptr) + pcookie->modeflags |= O_NONBLOCK; + else + pcookie->modeflags &= ~O_NONBLOCK; + return 0; + } + + if (func_ioctl) + return func_ioctl (pcookie->next_cookie, cmd, ptr, len); + + _gpg_err_set_errno (EOPNOTSUPP); + return -1; +} + + +/* + * The destroy function for pollable objects. + */ +static int +func_w32_pollable_destroy (void *cookie) +{ + estream_cookie_w32_pollable_t pcookie = cookie; + + if (cookie) + { + if (pcookie->reader) + destroy_reader (pcookie->reader); + if (pcookie->writer) + destroy_writer (pcookie->writer); + pcookie->next_functions.public.func_close (pcookie->next_cookie); + _gpgrt_free (pcookie); + } + return 0; +} + +/* + * Access object for the pollable functions. + */ +struct cookie_io_functions_s _gpgrt_functions_w32_pollable = + { + { + func_w32_pollable_read, + func_w32_pollable_write, + func_w32_pollable_seek, + func_w32_pollable_destroy, + }, + func_w32_pollable_ioctl, + }; diff --git a/comm/third_party/libgpg-error/src/w32-gettext.c b/comm/third_party/libgpg-error/src/w32-gettext.c new file mode 100644 index 0000000000..7c4c9b058d --- /dev/null +++ b/comm/third_party/libgpg-error/src/w32-gettext.c @@ -0,0 +1,2016 @@ +/* w32-gettext.h - A simple gettext implementation for Windows targets. + Copyright (C) 1995, 1996, 1997, 1999, 2005, 2007, + 2008, 2010 Free Software Foundation, Inc. + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, see <https://www.gnu.org/licenses/>. + */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif +#if !defined (_WIN32) && !defined (__CYGWIN32__) +# error This module may only be build for Windows or Cygwin32 +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#include <stdint.h> +#include <locale.h> +#include <windows.h> + +#ifdef JNLIB_IN_JNLIB +#include "libjnlib-config.h" +#endif + +#ifndef jnlib_malloc +# define jnlib_malloc(a) malloc ((a)) +# define jnlib_calloc(a,b) calloc ((a), (b)) +# define jnlib_free(a) free ((a)) +# define jnlib_xstrdup(a) not_used +#endif /*!jnlib_malloc*/ + +#include "init.h" +#include "gpgrt-int.h" +#include "protos.h" + +/* Override values initialized by gpgrt_w32_override_locale. If NAME + * is not the empty string LANGID will be used. */ +static struct +{ + unsigned short active; /* If not zero this override is active. */ + unsigned short langid; + char name[28]; +} override_locale; + + + + +/* localname.c from gettext BEGIN. */ + +/* Determine the current selected locale. + Copyright (C) 1995-1999, 2000-2003 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +/* Written by Ulrich Drepper <drepper@gnu.org>, 1995. */ +/* Win32 code written by Tor Lillqvist <tml@iki.fi>. */ +/* Renamed _nl_locale_name, removed unused args, removed include files, + non-W32 code and changed comments <wk@gnupg.org>. */ + +/* Mingw headers don't have latest language and sublanguage codes. */ +#ifndef LANG_AFRIKAANS +#define LANG_AFRIKAANS 0x36 +#endif +#ifndef LANG_ALBANIAN +#define LANG_ALBANIAN 0x1c +#endif +#ifndef LANG_AMHARIC +#define LANG_AMHARIC 0x5e +#endif +#ifndef LANG_ARABIC +#define LANG_ARABIC 0x01 +#endif +#ifndef LANG_ARMENIAN +#define LANG_ARMENIAN 0x2b +#endif +#ifndef LANG_ASSAMESE +#define LANG_ASSAMESE 0x4d +#endif +#ifndef LANG_AZERI +#define LANG_AZERI 0x2c +#endif +#ifndef LANG_BASQUE +#define LANG_BASQUE 0x2d +#endif +#ifndef LANG_BELARUSIAN +#define LANG_BELARUSIAN 0x23 +#endif +#ifndef LANG_BENGALI +#define LANG_BENGALI 0x45 +#endif +#ifndef LANG_BURMESE +#define LANG_BURMESE 0x55 +#endif +#ifndef LANG_CAMBODIAN +#define LANG_CAMBODIAN 0x53 +#endif +#ifndef LANG_CATALAN +#define LANG_CATALAN 0x03 +#endif +#ifndef LANG_CHEROKEE +#define LANG_CHEROKEE 0x5c +#endif +#ifndef LANG_DIVEHI +#define LANG_DIVEHI 0x65 +#endif +#ifndef LANG_EDO +#define LANG_EDO 0x66 +#endif +#ifndef LANG_ESTONIAN +#define LANG_ESTONIAN 0x25 +#endif +#ifndef LANG_FAEROESE +#define LANG_FAEROESE 0x38 +#endif +#ifndef LANG_FARSI +#define LANG_FARSI 0x29 +#endif +#ifndef LANG_FRISIAN +#define LANG_FRISIAN 0x62 +#endif +#ifndef LANG_FULFULDE +#define LANG_FULFULDE 0x67 +#endif +#ifndef LANG_GAELIC +#define LANG_GAELIC 0x3c +#endif +#ifndef LANG_GALICIAN +#define LANG_GALICIAN 0x56 +#endif +#ifndef LANG_GEORGIAN +#define LANG_GEORGIAN 0x37 +#endif +#ifndef LANG_GUARANI +#define LANG_GUARANI 0x74 +#endif +#ifndef LANG_GUJARATI +#define LANG_GUJARATI 0x47 +#endif +#ifndef LANG_HAUSA +#define LANG_HAUSA 0x68 +#endif +#ifndef LANG_HAWAIIAN +#define LANG_HAWAIIAN 0x75 +#endif +#ifndef LANG_HEBREW +#define LANG_HEBREW 0x0d +#endif +#ifndef LANG_HINDI +#define LANG_HINDI 0x39 +#endif +#ifndef LANG_IBIBIO +#define LANG_IBIBIO 0x69 +#endif +#ifndef LANG_IGBO +#define LANG_IGBO 0x70 +#endif +#ifndef LANG_INDONESIAN +#define LANG_INDONESIAN 0x21 +#endif +#ifndef LANG_INUKTITUT +#define LANG_INUKTITUT 0x5d +#endif +#ifndef LANG_KANNADA +#define LANG_KANNADA 0x4b +#endif +#ifndef LANG_KANURI +#define LANG_KANURI 0x71 +#endif +#ifndef LANG_KASHMIRI +#define LANG_KASHMIRI 0x60 +#endif +#ifndef LANG_KAZAK +#define LANG_KAZAK 0x3f +#endif +#ifndef LANG_KONKANI +#define LANG_KONKANI 0x57 +#endif +#ifndef LANG_KYRGYZ +#define LANG_KYRGYZ 0x40 +#endif +#ifndef LANG_LAO +#define LANG_LAO 0x54 +#endif +#ifndef LANG_LATIN +#define LANG_LATIN 0x76 +#endif +#ifndef LANG_LATVIAN +#define LANG_LATVIAN 0x26 +#endif +#ifndef LANG_LITHUANIAN +#define LANG_LITHUANIAN 0x27 +#endif +#ifndef LANG_MACEDONIAN +#define LANG_MACEDONIAN 0x2f +#endif +#ifndef LANG_MALAY +#define LANG_MALAY 0x3e +#endif +#ifndef LANG_MALAYALAM +#define LANG_MALAYALAM 0x4c +#endif +#ifndef LANG_MALTESE +#define LANG_MALTESE 0x3a +#endif +#ifndef LANG_MANIPURI +#define LANG_MANIPURI 0x58 +#endif +#ifndef LANG_MARATHI +#define LANG_MARATHI 0x4e +#endif +#ifndef LANG_MONGOLIAN +#define LANG_MONGOLIAN 0x50 +#endif +#ifndef LANG_NEPALI +#define LANG_NEPALI 0x61 +#endif +#ifndef LANG_ORIYA +#define LANG_ORIYA 0x48 +#endif +#ifndef LANG_OROMO +#define LANG_OROMO 0x72 +#endif +#ifndef LANG_PAPIAMENTU +#define LANG_PAPIAMENTU 0x79 +#endif +#ifndef LANG_PASHTO +#define LANG_PASHTO 0x63 +#endif +#ifndef LANG_PUNJABI +#define LANG_PUNJABI 0x46 +#endif +#ifndef LANG_RHAETO_ROMANCE +#define LANG_RHAETO_ROMANCE 0x17 +#endif +#ifndef LANG_SAAMI +#define LANG_SAAMI 0x3b +#endif +#ifndef LANG_SANSKRIT +#define LANG_SANSKRIT 0x4f +#endif +#ifndef LANG_SERBIAN +#define LANG_SERBIAN 0x1a +#endif +#ifndef LANG_SINDHI +#define LANG_SINDHI 0x59 +#endif +#ifndef LANG_SINHALESE +#define LANG_SINHALESE 0x5b +#endif +#ifndef LANG_SLOVAK +#define LANG_SLOVAK 0x1b +#endif +#ifndef LANG_SOMALI +#define LANG_SOMALI 0x77 +#endif +#ifndef LANG_SORBIAN +#define LANG_SORBIAN 0x2e +#endif +#ifndef LANG_SUTU +#define LANG_SUTU 0x30 +#endif +#ifndef LANG_SWAHILI +#define LANG_SWAHILI 0x41 +#endif +#ifndef LANG_SYRIAC +#define LANG_SYRIAC 0x5a +#endif +#ifndef LANG_TAGALOG +#define LANG_TAGALOG 0x64 +#endif +#ifndef LANG_TAJIK +#define LANG_TAJIK 0x28 +#endif +#ifndef LANG_TAMAZIGHT +#define LANG_TAMAZIGHT 0x5f +#endif +#ifndef LANG_TAMIL +#define LANG_TAMIL 0x49 +#endif +#ifndef LANG_TATAR +#define LANG_TATAR 0x44 +#endif +#ifndef LANG_TELUGU +#define LANG_TELUGU 0x4a +#endif +#ifndef LANG_THAI +#define LANG_THAI 0x1e +#endif +#ifndef LANG_TIBETAN +#define LANG_TIBETAN 0x51 +#endif +#ifndef LANG_TIGRINYA +#define LANG_TIGRINYA 0x73 +#endif +#ifndef LANG_TSONGA +#define LANG_TSONGA 0x31 +#endif +#ifndef LANG_TSWANA +#define LANG_TSWANA 0x32 +#endif +#ifndef LANG_TURKMEN +#define LANG_TURKMEN 0x42 +#endif +#ifndef LANG_UKRAINIAN +#define LANG_UKRAINIAN 0x22 +#endif +#ifndef LANG_URDU +#define LANG_URDU 0x20 +#endif +#ifndef LANG_UZBEK +#define LANG_UZBEK 0x43 +#endif +#ifndef LANG_VENDA +#define LANG_VENDA 0x33 +#endif +#ifndef LANG_VIETNAMESE +#define LANG_VIETNAMESE 0x2a +#endif +#ifndef LANG_WELSH +#define LANG_WELSH 0x52 +#endif +#ifndef LANG_XHOSA +#define LANG_XHOSA 0x34 +#endif +#ifndef LANG_YI +#define LANG_YI 0x78 +#endif +#ifndef LANG_YIDDISH +#define LANG_YIDDISH 0x3d +#endif +#ifndef LANG_YORUBA +#define LANG_YORUBA 0x6a +#endif +#ifndef LANG_ZULU +#define LANG_ZULU 0x35 +#endif +#ifndef SUBLANG_ARABIC_SAUDI_ARABIA +#define SUBLANG_ARABIC_SAUDI_ARABIA 0x01 +#endif +#ifndef SUBLANG_ARABIC_IRAQ +#define SUBLANG_ARABIC_IRAQ 0x02 +#endif +#ifndef SUBLANG_ARABIC_EGYPT +#define SUBLANG_ARABIC_EGYPT 0x03 +#endif +#ifndef SUBLANG_ARABIC_LIBYA +#define SUBLANG_ARABIC_LIBYA 0x04 +#endif +#ifndef SUBLANG_ARABIC_ALGERIA +#define SUBLANG_ARABIC_ALGERIA 0x05 +#endif +#ifndef SUBLANG_ARABIC_MOROCCO +#define SUBLANG_ARABIC_MOROCCO 0x06 +#endif +#ifndef SUBLANG_ARABIC_TUNISIA +#define SUBLANG_ARABIC_TUNISIA 0x07 +#endif +#ifndef SUBLANG_ARABIC_OMAN +#define SUBLANG_ARABIC_OMAN 0x08 +#endif +#ifndef SUBLANG_ARABIC_YEMEN +#define SUBLANG_ARABIC_YEMEN 0x09 +#endif +#ifndef SUBLANG_ARABIC_SYRIA +#define SUBLANG_ARABIC_SYRIA 0x0a +#endif +#ifndef SUBLANG_ARABIC_JORDAN +#define SUBLANG_ARABIC_JORDAN 0x0b +#endif +#ifndef SUBLANG_ARABIC_LEBANON +#define SUBLANG_ARABIC_LEBANON 0x0c +#endif +#ifndef SUBLANG_ARABIC_KUWAIT +#define SUBLANG_ARABIC_KUWAIT 0x0d +#endif +#ifndef SUBLANG_ARABIC_UAE +#define SUBLANG_ARABIC_UAE 0x0e +#endif +#ifndef SUBLANG_ARABIC_BAHRAIN +#define SUBLANG_ARABIC_BAHRAIN 0x0f +#endif +#ifndef SUBLANG_ARABIC_QATAR +#define SUBLANG_ARABIC_QATAR 0x10 +#endif +#ifndef SUBLANG_AZERI_LATIN +#define SUBLANG_AZERI_LATIN 0x01 +#endif +#ifndef SUBLANG_AZERI_CYRILLIC +#define SUBLANG_AZERI_CYRILLIC 0x02 +#endif +#ifndef SUBLANG_BENGALI_INDIA +#define SUBLANG_BENGALI_INDIA 0x01 +#endif +#ifndef SUBLANG_BENGALI_BANGLADESH +#define SUBLANG_BENGALI_BANGLADESH 0x02 +#endif +#ifndef SUBLANG_CHINESE_MACAU +#define SUBLANG_CHINESE_MACAU 0x05 +#endif +#ifndef SUBLANG_ENGLISH_SOUTH_AFRICA +#define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07 +#endif +#ifndef SUBLANG_ENGLISH_JAMAICA +#define SUBLANG_ENGLISH_JAMAICA 0x08 +#endif +#ifndef SUBLANG_ENGLISH_CARIBBEAN +#define SUBLANG_ENGLISH_CARIBBEAN 0x09 +#endif +#ifndef SUBLANG_ENGLISH_BELIZE +#define SUBLANG_ENGLISH_BELIZE 0x0a +#endif +#ifndef SUBLANG_ENGLISH_TRINIDAD +#define SUBLANG_ENGLISH_TRINIDAD 0x0b +#endif +#ifndef SUBLANG_ENGLISH_ZIMBABWE +#define SUBLANG_ENGLISH_ZIMBABWE 0x0c +#endif +#ifndef SUBLANG_ENGLISH_PHILIPPINES +#define SUBLANG_ENGLISH_PHILIPPINES 0x0d +#endif +#ifndef SUBLANG_ENGLISH_INDONESIA +#define SUBLANG_ENGLISH_INDONESIA 0x0e +#endif +#ifndef SUBLANG_ENGLISH_HONGKONG +#define SUBLANG_ENGLISH_HONGKONG 0x0f +#endif +#ifndef SUBLANG_ENGLISH_INDIA +#define SUBLANG_ENGLISH_INDIA 0x10 +#endif +#ifndef SUBLANG_ENGLISH_MALAYSIA +#define SUBLANG_ENGLISH_MALAYSIA 0x11 +#endif +#ifndef SUBLANG_ENGLISH_SINGAPORE +#define SUBLANG_ENGLISH_SINGAPORE 0x12 +#endif +#ifndef SUBLANG_FRENCH_LUXEMBOURG +#define SUBLANG_FRENCH_LUXEMBOURG 0x05 +#endif +#ifndef SUBLANG_FRENCH_MONACO +#define SUBLANG_FRENCH_MONACO 0x06 +#endif +#ifndef SUBLANG_FRENCH_WESTINDIES +#define SUBLANG_FRENCH_WESTINDIES 0x07 +#endif +#ifndef SUBLANG_FRENCH_REUNION +#define SUBLANG_FRENCH_REUNION 0x08 +#endif +#ifndef SUBLANG_FRENCH_CONGO +#define SUBLANG_FRENCH_CONGO 0x09 +#endif +#ifndef SUBLANG_FRENCH_SENEGAL +#define SUBLANG_FRENCH_SENEGAL 0x0a +#endif +#ifndef SUBLANG_FRENCH_CAMEROON +#define SUBLANG_FRENCH_CAMEROON 0x0b +#endif +#ifndef SUBLANG_FRENCH_COTEDIVOIRE +#define SUBLANG_FRENCH_COTEDIVOIRE 0x0c +#endif +#ifndef SUBLANG_FRENCH_MALI +#define SUBLANG_FRENCH_MALI 0x0d +#endif +#ifndef SUBLANG_FRENCH_MOROCCO +#define SUBLANG_FRENCH_MOROCCO 0x0e +#endif +#ifndef SUBLANG_FRENCH_HAITI +#define SUBLANG_FRENCH_HAITI 0x0f +#endif +#ifndef SUBLANG_GERMAN_LUXEMBOURG +#define SUBLANG_GERMAN_LUXEMBOURG 0x04 +#endif +#ifndef SUBLANG_GERMAN_LIECHTENSTEIN +#define SUBLANG_GERMAN_LIECHTENSTEIN 0x05 +#endif +#ifndef SUBLANG_KASHMIRI_INDIA +#define SUBLANG_KASHMIRI_INDIA 0x02 +#endif +#ifndef SUBLANG_MALAY_MALAYSIA +#define SUBLANG_MALAY_MALAYSIA 0x01 +#endif +#ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM +#define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02 +#endif +#ifndef SUBLANG_NEPALI_INDIA +#define SUBLANG_NEPALI_INDIA 0x02 +#endif +#ifndef SUBLANG_PUNJABI_INDIA +#define SUBLANG_PUNJABI_INDIA 0x01 +#endif +#ifndef SUBLANG_ROMANIAN_ROMANIA +#define SUBLANG_ROMANIAN_ROMANIA 0x01 +#endif +#ifndef SUBLANG_SERBIAN_LATIN +#define SUBLANG_SERBIAN_LATIN 0x02 +#endif +#ifndef SUBLANG_SERBIAN_CYRILLIC +#define SUBLANG_SERBIAN_CYRILLIC 0x03 +#endif +#ifndef SUBLANG_SINDHI_INDIA +#define SUBLANG_SINDHI_INDIA 0x00 +#endif +#ifndef SUBLANG_SINDHI_PAKISTAN +#define SUBLANG_SINDHI_PAKISTAN 0x01 +#endif +#ifndef SUBLANG_SPANISH_GUATEMALA +#define SUBLANG_SPANISH_GUATEMALA 0x04 +#endif +#ifndef SUBLANG_SPANISH_COSTA_RICA +#define SUBLANG_SPANISH_COSTA_RICA 0x05 +#endif +#ifndef SUBLANG_SPANISH_PANAMA +#define SUBLANG_SPANISH_PANAMA 0x06 +#endif +#ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC +#define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07 +#endif +#ifndef SUBLANG_SPANISH_VENEZUELA +#define SUBLANG_SPANISH_VENEZUELA 0x08 +#endif +#ifndef SUBLANG_SPANISH_COLOMBIA +#define SUBLANG_SPANISH_COLOMBIA 0x09 +#endif +#ifndef SUBLANG_SPANISH_PERU +#define SUBLANG_SPANISH_PERU 0x0a +#endif +#ifndef SUBLANG_SPANISH_ARGENTINA +#define SUBLANG_SPANISH_ARGENTINA 0x0b +#endif +#ifndef SUBLANG_SPANISH_ECUADOR +#define SUBLANG_SPANISH_ECUADOR 0x0c +#endif +#ifndef SUBLANG_SPANISH_CHILE +#define SUBLANG_SPANISH_CHILE 0x0d +#endif +#ifndef SUBLANG_SPANISH_URUGUAY +#define SUBLANG_SPANISH_URUGUAY 0x0e +#endif +#ifndef SUBLANG_SPANISH_PARAGUAY +#define SUBLANG_SPANISH_PARAGUAY 0x0f +#endif +#ifndef SUBLANG_SPANISH_BOLIVIA +#define SUBLANG_SPANISH_BOLIVIA 0x10 +#endif +#ifndef SUBLANG_SPANISH_EL_SALVADOR +#define SUBLANG_SPANISH_EL_SALVADOR 0x11 +#endif +#ifndef SUBLANG_SPANISH_HONDURAS +#define SUBLANG_SPANISH_HONDURAS 0x12 +#endif +#ifndef SUBLANG_SPANISH_NICARAGUA +#define SUBLANG_SPANISH_NICARAGUA 0x13 +#endif +#ifndef SUBLANG_SPANISH_PUERTO_RICO +#define SUBLANG_SPANISH_PUERTO_RICO 0x14 +#endif +#ifndef SUBLANG_SWEDISH_FINLAND +#define SUBLANG_SWEDISH_FINLAND 0x02 +#endif +#ifndef SUBLANG_TAMAZIGHT_ARABIC +#define SUBLANG_TAMAZIGHT_ARABIC 0x01 +#endif +#ifndef SUBLANG_TAMAZIGHT_LATIN +#define SUBLANG_TAMAZIGHT_LATIN 0x02 +#endif +#ifndef SUBLANG_TIGRINYA_ETHIOPIA +#define SUBLANG_TIGRINYA_ETHIOPIA 0x00 +#endif +#ifndef SUBLANG_TIGRINYA_ERITREA +#define SUBLANG_TIGRINYA_ERITREA 0x01 +#endif +#ifndef SUBLANG_URDU_PAKISTAN +#define SUBLANG_URDU_PAKISTAN 0x01 +#endif +#ifndef SUBLANG_URDU_INDIA +#define SUBLANG_URDU_INDIA 0x02 +#endif +#ifndef SUBLANG_UZBEK_LATIN +#define SUBLANG_UZBEK_LATIN 0x01 +#endif +#ifndef SUBLANG_UZBEK_CYRILLIC +#define SUBLANG_UZBEK_CYRILLIC 0x02 +#endif + +/* Return an XPG style locale name + language[_territory[.codeset]][@modifier]. + Don't even bother determining the codeset; it's not useful in this + context, because message catalogs are not specific to a single + codeset. The result must not be freed; it is statically + allocated. */ +static const char * +my_nl_locale_name (const char *categoryname) +{ + const char *retval; + LANGID langid; + int primary, sub; + + if (override_locale.active) + { + if (*override_locale.name) + return override_locale.name; + langid = override_locale.langid; + } + else + { + LCID lcid; + + /* Let the user override the system settings through environment + * variables, as on POSIX systems. */ + retval = getenv ("LC_ALL"); + if (retval != NULL && retval[0] != '\0') + return retval; + retval = getenv (categoryname); + if (retval != NULL && retval[0] != '\0') + return retval; + retval = getenv ("LANG"); + if (retval != NULL && retval[0] != '\0') + return retval; + + /* Use native Win32 API locale ID. */ + lcid = GetThreadLocale (); + /* Strip off the sorting rules, keep only the language part. */ + langid = LANGIDFROMLCID (lcid); + } + + /* Split into language and territory part. */ + primary = PRIMARYLANGID (langid); + sub = SUBLANGID (langid); + + /* Dispatch on language. + For details about languages, see https://www.ethnologue.com/ . */ + switch (primary) + { + case LANG_AFRIKAANS: return "af_ZA"; + case LANG_ALBANIAN: return "sq_AL"; + case LANG_AMHARIC: return "am_ET"; + case LANG_ARABIC: + switch (sub) + { + case SUBLANG_ARABIC_SAUDI_ARABIA: return "ar_SA"; + case SUBLANG_ARABIC_IRAQ: return "ar_IQ"; + case SUBLANG_ARABIC_EGYPT: return "ar_EG"; + case SUBLANG_ARABIC_LIBYA: return "ar_LY"; + case SUBLANG_ARABIC_ALGERIA: return "ar_DZ"; + case SUBLANG_ARABIC_MOROCCO: return "ar_MA"; + case SUBLANG_ARABIC_TUNISIA: return "ar_TN"; + case SUBLANG_ARABIC_OMAN: return "ar_OM"; + case SUBLANG_ARABIC_YEMEN: return "ar_YE"; + case SUBLANG_ARABIC_SYRIA: return "ar_SY"; + case SUBLANG_ARABIC_JORDAN: return "ar_JO"; + case SUBLANG_ARABIC_LEBANON: return "ar_LB"; + case SUBLANG_ARABIC_KUWAIT: return "ar_KW"; + case SUBLANG_ARABIC_UAE: return "ar_AE"; + case SUBLANG_ARABIC_BAHRAIN: return "ar_BH"; + case SUBLANG_ARABIC_QATAR: return "ar_QA"; + } + return "ar"; + case LANG_ARMENIAN: return "hy_AM"; + case LANG_ASSAMESE: return "as_IN"; + case LANG_AZERI: + switch (sub) + { + /* FIXME: Adjust this when Azerbaijani locales appear on Unix. */ + case SUBLANG_AZERI_LATIN: return "az_AZ@latin"; + case SUBLANG_AZERI_CYRILLIC: return "az_AZ@cyrillic"; + } + return "az"; + case LANG_BASQUE: + return "eu"; /* Ambiguous: could be "eu_ES" or "eu_FR". */ + case LANG_BELARUSIAN: return "be_BY"; + case LANG_BENGALI: + switch (sub) + { + case SUBLANG_BENGALI_INDIA: return "bn_IN"; + case SUBLANG_BENGALI_BANGLADESH: return "bn_BD"; + } + return "bn"; + case LANG_BULGARIAN: return "bg_BG"; + case LANG_BURMESE: return "my_MM"; + case LANG_CAMBODIAN: return "km_KH"; + case LANG_CATALAN: return "ca_ES"; + case LANG_CHEROKEE: return "chr_US"; + case LANG_CHINESE: + switch (sub) + { + case SUBLANG_CHINESE_TRADITIONAL: return "zh_TW"; + case SUBLANG_CHINESE_SIMPLIFIED: return "zh_CN"; + case SUBLANG_CHINESE_HONGKONG: return "zh_HK"; + case SUBLANG_CHINESE_SINGAPORE: return "zh_SG"; + case SUBLANG_CHINESE_MACAU: return "zh_MO"; + } + return "zh"; + case LANG_CROATIAN: /* LANG_CROATIAN == LANG_SERBIAN + * What used to be called Serbo-Croatian + * should really now be two separate + * languages because of political reasons. + * (Says tml, who knows nothing about Serbian + * or Croatian.) + * (I can feel those flames coming already.) + */ + switch (sub) + { + case SUBLANG_DEFAULT: return "hr_HR"; + case SUBLANG_SERBIAN_LATIN: return "sr_CS"; + case SUBLANG_SERBIAN_CYRILLIC: return "sr_CS@cyrillic"; + } + return "hr"; + case LANG_CZECH: return "cs_CZ"; + case LANG_DANISH: return "da_DK"; + case LANG_DIVEHI: return "div_MV"; + case LANG_DUTCH: + switch (sub) + { + case SUBLANG_DUTCH: return "nl_NL"; + case SUBLANG_DUTCH_BELGIAN: /* FLEMISH, VLAAMS */ return "nl_BE"; + } + return "nl"; + case LANG_EDO: return "bin_NG"; + case LANG_ENGLISH: + switch (sub) + { + /* SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. Heh. I thought + * English was the language spoken in England. + * Oh well. + */ + case SUBLANG_ENGLISH_US: return "en_US"; + case SUBLANG_ENGLISH_UK: return "en_GB"; + case SUBLANG_ENGLISH_AUS: return "en_AU"; + case SUBLANG_ENGLISH_CAN: return "en_CA"; + case SUBLANG_ENGLISH_NZ: return "en_NZ"; + case SUBLANG_ENGLISH_EIRE: return "en_IE"; + case SUBLANG_ENGLISH_SOUTH_AFRICA: return "en_ZA"; + case SUBLANG_ENGLISH_JAMAICA: return "en_JM"; + case SUBLANG_ENGLISH_CARIBBEAN: return "en_GD"; /* Grenada? */ + case SUBLANG_ENGLISH_BELIZE: return "en_BZ"; + case SUBLANG_ENGLISH_TRINIDAD: return "en_TT"; + case SUBLANG_ENGLISH_ZIMBABWE: return "en_ZW"; + case SUBLANG_ENGLISH_PHILIPPINES: return "en_PH"; + case SUBLANG_ENGLISH_INDONESIA: return "en_ID"; + case SUBLANG_ENGLISH_HONGKONG: return "en_HK"; + case SUBLANG_ENGLISH_INDIA: return "en_IN"; + case SUBLANG_ENGLISH_MALAYSIA: return "en_MY"; + case SUBLANG_ENGLISH_SINGAPORE: return "en_SG"; + } + return "en"; + case LANG_ESTONIAN: return "et_EE"; + case LANG_FAEROESE: return "fo_FO"; + case LANG_FARSI: return "fa_IR"; + case LANG_FINNISH: return "fi_FI"; + case LANG_FRENCH: + switch (sub) + { + case SUBLANG_FRENCH: return "fr_FR"; + case SUBLANG_FRENCH_BELGIAN: /* WALLOON */ return "fr_BE"; + case SUBLANG_FRENCH_CANADIAN: return "fr_CA"; + case SUBLANG_FRENCH_SWISS: return "fr_CH"; + case SUBLANG_FRENCH_LUXEMBOURG: return "fr_LU"; + case SUBLANG_FRENCH_MONACO: return "fr_MC"; + case SUBLANG_FRENCH_WESTINDIES: return "fr"; /* Caribbean? */ + case SUBLANG_FRENCH_REUNION: return "fr_RE"; + case SUBLANG_FRENCH_CONGO: return "fr_CG"; + case SUBLANG_FRENCH_SENEGAL: return "fr_SN"; + case SUBLANG_FRENCH_CAMEROON: return "fr_CM"; + case SUBLANG_FRENCH_COTEDIVOIRE: return "fr_CI"; + case SUBLANG_FRENCH_MALI: return "fr_ML"; + case SUBLANG_FRENCH_MOROCCO: return "fr_MA"; + case SUBLANG_FRENCH_HAITI: return "fr_HT"; + } + return "fr"; + case LANG_FRISIAN: return "fy_NL"; + case LANG_FULFULDE: return "ful_NG"; + case LANG_GAELIC: + switch (sub) + { + case 0x01: /* SCOTTISH */ return "gd_GB"; + case 0x02: /* IRISH */ return "ga_IE"; + } + return "C"; + case LANG_GALICIAN: return "gl_ES"; + case LANG_GEORGIAN: return "ka_GE"; + case LANG_GERMAN: + switch (sub) + { + case SUBLANG_GERMAN: return "de_DE"; + case SUBLANG_GERMAN_SWISS: return "de_CH"; + case SUBLANG_GERMAN_AUSTRIAN: return "de_AT"; + case SUBLANG_GERMAN_LUXEMBOURG: return "de_LU"; + case SUBLANG_GERMAN_LIECHTENSTEIN: return "de_LI"; + } + return "de"; + case LANG_GREEK: return "el_GR"; + case LANG_GUARANI: return "gn_PY"; + case LANG_GUJARATI: return "gu_IN"; + case LANG_HAUSA: return "ha_NG"; + case LANG_HAWAIIAN: + /* FIXME: Do they mean Hawaiian ("haw_US", 1000 speakers) + or Hawaii Creole English ("cpe_US", 600000 speakers)? */ + return "cpe_US"; + case LANG_HEBREW: return "he_IL"; + case LANG_HINDI: return "hi_IN"; + case LANG_HUNGARIAN: return "hu_HU"; + case LANG_IBIBIO: return "nic_NG"; + case LANG_ICELANDIC: return "is_IS"; + case LANG_IGBO: return "ibo_NG"; + case LANG_INDONESIAN: return "id_ID"; + case LANG_INUKTITUT: return "iu_CA"; + case LANG_ITALIAN: + switch (sub) + { + case SUBLANG_ITALIAN: return "it_IT"; + case SUBLANG_ITALIAN_SWISS: return "it_CH"; + } + return "it"; + case LANG_JAPANESE: return "ja_JP"; + case LANG_KANNADA: return "kn_IN"; + case LANG_KANURI: return "kau_NG"; + case LANG_KASHMIRI: + switch (sub) + { + case SUBLANG_DEFAULT: return "ks_PK"; + case SUBLANG_KASHMIRI_INDIA: return "ks_IN"; + } + return "ks"; + case LANG_KAZAK: return "kk_KZ"; + case LANG_KONKANI: + /* FIXME: Adjust this when such locales appear on Unix. */ + return "kok_IN"; + case LANG_KOREAN: return "ko_KR"; + case LANG_KYRGYZ: return "ky_KG"; + case LANG_LAO: return "lo_LA"; + case LANG_LATIN: return "la_VA"; + case LANG_LATVIAN: return "lv_LV"; + case LANG_LITHUANIAN: return "lt_LT"; + case LANG_MACEDONIAN: return "mk_MK"; + case LANG_MALAY: + switch (sub) + { + case SUBLANG_MALAY_MALAYSIA: return "ms_MY"; + case SUBLANG_MALAY_BRUNEI_DARUSSALAM: return "ms_BN"; + } + return "ms"; + case LANG_MALAYALAM: return "ml_IN"; + case LANG_MALTESE: return "mt_MT"; + case LANG_MANIPURI: + /* FIXME: Adjust this when such locales appear on Unix. */ + return "mni_IN"; + case LANG_MARATHI: return "mr_IN"; + case LANG_MONGOLIAN: + return "mn"; /* Ambiguous: could be "mn_CN" or "mn_MN". */ + case LANG_NEPALI: + switch (sub) + { + case SUBLANG_DEFAULT: return "ne_NP"; + case SUBLANG_NEPALI_INDIA: return "ne_IN"; + } + return "ne"; + case LANG_NORWEGIAN: + switch (sub) + { + case SUBLANG_NORWEGIAN_BOKMAL: return "no_NO"; + case SUBLANG_NORWEGIAN_NYNORSK: return "nn_NO"; + } + return "no"; + case LANG_ORIYA: return "or_IN"; + case LANG_OROMO: return "om_ET"; + case LANG_PAPIAMENTU: return "pap_AN"; + case LANG_PASHTO: + return "ps"; /* Ambiguous: could be "ps_PK" or "ps_AF". */ + case LANG_POLISH: return "pl_PL"; + case LANG_PORTUGUESE: + switch (sub) + { + case SUBLANG_PORTUGUESE: return "pt_PT"; + /* Hmm. SUBLANG_PORTUGUESE_BRAZILIAN == SUBLANG_DEFAULT. + Same phenomenon as SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. */ + case SUBLANG_PORTUGUESE_BRAZILIAN: return "pt_BR"; + } + return "pt"; + case LANG_PUNJABI: + switch (sub) + { + case SUBLANG_PUNJABI_INDIA: return "pa_IN"; /* Gurmukhi script */ + } + return "pa"; + case LANG_RHAETO_ROMANCE: return "rm_CH"; + case LANG_ROMANIAN: + switch (sub) + { + case SUBLANG_ROMANIAN_ROMANIA: return "ro_RO"; + } + return "ro"; + case LANG_RUSSIAN: + return "ru"; /* Ambiguous: could be "ru_RU" or "ru_UA" or "ru_MD". */ + case LANG_SAAMI: /* actually Northern Sami */ return "se_NO"; + case LANG_SANSKRIT: return "sa_IN"; + case LANG_SINDHI: + switch (sub) + { + case SUBLANG_SINDHI_INDIA: return "sd_IN"; + case SUBLANG_SINDHI_PAKISTAN: return "sd_PK"; + } + return "sd"; + case LANG_SINHALESE: return "si_LK"; + case LANG_SLOVAK: return "sk_SK"; + case LANG_SLOVENIAN: return "sl_SI"; + case LANG_SOMALI: return "so_SO"; + case LANG_SORBIAN: + /* FIXME: Adjust this when such locales appear on Unix. */ + return "wen_DE"; + case LANG_SPANISH: + switch (sub) + { + case SUBLANG_SPANISH: return "es_ES"; + case SUBLANG_SPANISH_MEXICAN: return "es_MX"; + case SUBLANG_SPANISH_MODERN: + return "es_ES@modern"; /* not seen on Unix */ + case SUBLANG_SPANISH_GUATEMALA: return "es_GT"; + case SUBLANG_SPANISH_COSTA_RICA: return "es_CR"; + case SUBLANG_SPANISH_PANAMA: return "es_PA"; + case SUBLANG_SPANISH_DOMINICAN_REPUBLIC: return "es_DO"; + case SUBLANG_SPANISH_VENEZUELA: return "es_VE"; + case SUBLANG_SPANISH_COLOMBIA: return "es_CO"; + case SUBLANG_SPANISH_PERU: return "es_PE"; + case SUBLANG_SPANISH_ARGENTINA: return "es_AR"; + case SUBLANG_SPANISH_ECUADOR: return "es_EC"; + case SUBLANG_SPANISH_CHILE: return "es_CL"; + case SUBLANG_SPANISH_URUGUAY: return "es_UY"; + case SUBLANG_SPANISH_PARAGUAY: return "es_PY"; + case SUBLANG_SPANISH_BOLIVIA: return "es_BO"; + case SUBLANG_SPANISH_EL_SALVADOR: return "es_SV"; + case SUBLANG_SPANISH_HONDURAS: return "es_HN"; + case SUBLANG_SPANISH_NICARAGUA: return "es_NI"; + case SUBLANG_SPANISH_PUERTO_RICO: return "es_PR"; + } + return "es"; + case LANG_SUTU: return "bnt_TZ"; /* or "st_LS" or "nso_ZA"? */ + case LANG_SWAHILI: return "sw_KE"; + case LANG_SWEDISH: + switch (sub) + { + case SUBLANG_DEFAULT: return "sv_SE"; + case SUBLANG_SWEDISH_FINLAND: return "sv_FI"; + } + return "sv"; + case LANG_SYRIAC: return "syr_TR"; /* An extinct language. */ + case LANG_TAGALOG: return "tl_PH"; + case LANG_TAJIK: return "tg_TJ"; + case LANG_TAMAZIGHT: + switch (sub) + { + /* FIXME: Adjust this when Tamazight locales appear on Unix. */ + case SUBLANG_TAMAZIGHT_ARABIC: return "ber_MA@arabic"; + case SUBLANG_TAMAZIGHT_LATIN: return "ber_MA@latin"; + } + return "ber_MA"; + case LANG_TAMIL: + return "ta"; /* Ambiguous: could be "ta_IN" or "ta_LK" or "ta_SG". */ + case LANG_TATAR: return "tt_RU"; + case LANG_TELUGU: return "te_IN"; + case LANG_THAI: return "th_TH"; + case LANG_TIBETAN: return "bo_CN"; + case LANG_TIGRINYA: + switch (sub) + { + case SUBLANG_TIGRINYA_ETHIOPIA: return "ti_ET"; + case SUBLANG_TIGRINYA_ERITREA: return "ti_ER"; + } + return "ti"; + case LANG_TSONGA: return "ts_ZA"; + case LANG_TSWANA: return "tn_BW"; + case LANG_TURKISH: return "tr_TR"; + case LANG_TURKMEN: return "tk_TM"; + case LANG_UKRAINIAN: return "uk_UA"; + case LANG_URDU: + switch (sub) + { + case SUBLANG_URDU_PAKISTAN: return "ur_PK"; + case SUBLANG_URDU_INDIA: return "ur_IN"; + } + return "ur"; + case LANG_UZBEK: + switch (sub) + { + case SUBLANG_UZBEK_LATIN: return "uz_UZ"; + case SUBLANG_UZBEK_CYRILLIC: return "uz_UZ@cyrillic"; + } + return "uz"; + case LANG_VENDA: + return "ve_ZA"; + case LANG_VIETNAMESE: return "vi_VN"; + case LANG_WELSH: return "cy_GB"; + case LANG_XHOSA: return "xh_ZA"; + case LANG_YI: return "sit_CN"; + case LANG_YIDDISH: return "yi_IL"; + case LANG_YORUBA: return "yo_NG"; + case LANG_ZULU: return "zu_ZA"; + default: return "C"; + } +} + +/* localname.c from gettext END. */ + + + +/* Support functions. */ + +static GPG_ERR_INLINE uint32_t +do_swap_u32 (uint32_t i) +{ + return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24); +} + +#define SWAPIT(flag, data) ((flag) ? do_swap_u32(data) : (data)) + + +/* We assume to have `unsigned long int' value with at least 32 bits. */ +#define HASHWORDBITS 32 + +/* The so called `hashpjw' function by P.J. Weinberger + [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools, + 1986, 1987 Bell Telephone Laboratories, Inc.] */ +static GPG_ERR_INLINE unsigned long +hash_string (const char *str_param) +{ + unsigned long int hval, g; + const char *str = str_param; + + hval = 0; + while (*str != '\0') + { + hval <<= 4; + hval += (unsigned long int) *str++; + g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4)); + if (g != 0) + { + hval ^= g >> (HASHWORDBITS - 8); + hval ^= g; + } + } + return hval; +} + + +/* Generic message catalog and gettext stuff. */ + +/* The magic number of the GNU message catalog format. */ +#define MAGIC 0x950412de +#define MAGIC_SWAPPED 0xde120495 + +/* Revision number of the currently used .mo (binary) file format. */ +#define MO_REVISION_NUMBER 0 + + +/* Header for binary .mo file format. */ +struct mo_file_header +{ + /* The magic number. */ + uint32_t magic; + /* The revision number of the file format. */ + uint32_t revision; + /* The number of strings pairs. */ + uint32_t nstrings; + /* Offset of table with start offsets of original strings. */ + uint32_t orig_tab_offset; + /* Offset of table with start offsets of translation strings. */ + uint32_t trans_tab_offset; + /* Size of hashing table. */ + uint32_t hash_tab_size; + /* Offset of first hashing entry. */ + uint32_t hash_tab_offset; +}; + + +struct string_desc +{ + /* Length of addressed string. */ + uint32_t length; + /* Offset of string in file. */ + uint32_t offset; +}; + + +struct overflow_space_s +{ + struct overflow_space_s *next; + uint32_t idx; + uint32_t length; + char d[1]; +}; + +struct loaded_domain +{ + char *data; + char *data_native; /* Data mapped to the native version of the + string. (Allocated along with DATA). */ + int must_swap; + uint16_t nstrings; /* Number of strings. */ + uint16_t *mapped; /* Array of mapping indicators: + 0 := Not mapped (original utf8). + 1 := Mapped to native encoding in overflow space. + >=2 := Mapped to native encoding. The value + gives the length of the mapped string. + Because the terminating nul is included + in the length and an empty string is + not allowed, values are always > 1. */ + struct overflow_space_s *overflow_space; + struct string_desc *orig_tab; + struct string_desc *trans_tab; + uint32_t hash_size; + uint32_t *hash_tab; +}; + + +/* The list of domains we we are aware of. This list is protected by + the criticla section DOMAINLIST_ACCESS_CS. */ +static struct domainlist_s *domainlist; + +/* A critical section to guard access to the domainlist. */ +static CRITICAL_SECTION domainlist_access_cs; + +/* The name of the current domain. This is a malloced string. This + is a gobal variable which is not thread-safe. */ +static char *current_domainname; + + + +/* Constructor for this module. This can only be used if we are a + DLL. If used as a static lib we can't control the process set; for + example it might be used with a main module which is not build with + mingw and thus does not know how to call the constructors. */ +#ifdef DLL_EXPORT +static void module_init (void) _GPG_ERR_CONSTRUCTOR; +#endif +static void +module_init (void) +{ + static int init_done; + + if (!init_done) + { + InitializeCriticalSection (&domainlist_access_cs); + init_done = 1; + } +} + +#if !defined(DLL_EXPORT) || !defined(_GPG_ERR_HAVE_CONSTRUCTOR) +void +_gpg_w32__init_gettext_module (void) +{ + module_init (); +} +#endif + + +/* Free the domain data. */ +static void +free_domain (struct loaded_domain *domain) +{ + struct overflow_space_s *os, *os2; + + jnlib_free (domain->data); + jnlib_free (domain->mapped); + for (os = domain->overflow_space; os; os = os2) + { + os2 = os->next; + jnlib_free (os); + } + jnlib_free (domain); +} + + +static struct loaded_domain * +load_domain (const char *filename) +{ + HANDLE fh; + DWORD size; + struct mo_file_header *data = NULL; + struct loaded_domain *domain = NULL; + size_t to_read; + char *read_ptr; + + { + wchar_t *wfilename = _gpgrt_utf8_to_wchar (filename); + + if (!wfilename) + fh = INVALID_HANDLE_VALUE; + else + fh = CreateFileW (wfilename, GENERIC_READ, FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, 0, NULL); + xfree (wfilename); + } + if (fh == INVALID_HANDLE_VALUE) + return NULL; + + size = GetFileSize (fh, NULL); + if (size == INVALID_FILE_SIZE) + { + CloseHandle (fh); + return NULL; + } + + data = (2*size <= size)? NULL : jnlib_malloc (2*size); + if (!data) + { + CloseHandle (fh); + return NULL; + } + + to_read = size; + read_ptr = (char *) data; + do + { + BOOL res; + DWORD nb; + + res = ReadFile (fh, read_ptr, to_read, &nb, NULL); + if (! res || nb < to_read) + { + CloseHandle (fh); + jnlib_free (data); + return NULL; + } + read_ptr += nb; + to_read -= nb; + } + while (to_read > 0); + CloseHandle (fh); + + /* Using the magic number we can test whether it really is a message + catalog file. */ + if (data->magic != MAGIC && data->magic != MAGIC_SWAPPED) + { + /* The magic number is wrong: not a message catalog file. */ + jnlib_free (data); + return NULL; + } + + domain = jnlib_calloc (1, sizeof *domain); + if (!domain) + { + jnlib_free (data); + return NULL; + } + domain->data = (char *) data; + domain->data_native = (char *) data + size; + domain->must_swap = data->magic != MAGIC; + + /* Fill in the information about the available tables. */ + switch (SWAPIT (domain->must_swap, data->revision)) + { + case MO_REVISION_NUMBER: + { + uint32_t nstrings; + + /* Because we use 16 bit values for the mapping array, we + can't support more that 65534 strings (65535 would be okay, + but it is often used as a special value). A PO file with + that many translations is very unlikely given that GnuPG + with its very large number of strings has only about 1600 + strings + variants. */ + nstrings = SWAPIT (domain->must_swap, data->nstrings); + if (nstrings > 65534) + goto bailout; + domain->nstrings = nstrings; + domain->orig_tab = (struct string_desc *) + ((char *) data + SWAPIT (domain->must_swap, data->orig_tab_offset)); + domain->trans_tab = (struct string_desc *) + ((char *) data + SWAPIT (domain->must_swap, data->trans_tab_offset)); + domain->hash_size = SWAPIT (domain->must_swap, data->hash_tab_size); + domain->hash_tab = (uint32_t *) + ((char *) data + SWAPIT (domain->must_swap, data->hash_tab_offset)); + } + break; + + default: /* This is an invalid revision. */ + goto bailout; + } + + /* Allocate an array to keep track of code page mappings. */ + domain->mapped = jnlib_calloc (domain->nstrings, sizeof *domain->mapped); + if (domain->mapped) + return domain; /* Okay. */ + + bailout: + jnlib_free (data); + jnlib_free (domain); + return NULL; +} + + +/* Return a malloced wide char string from an UTF-8 encoded input + string STRING. Caller must free this value. On failure returns + NULL. The result of calling this function with STRING set to NULL + is not defined. If LENGTH is zero and RETLEN NULL the fucntion + assumes that STRING is a nul-terminated string and returns a + (wchar_t)0-terminated string. */ +static wchar_t * +utf8_to_wchar (const char *string, size_t length, size_t *retlen) +{ + int n; + wchar_t *result; + size_t nbytes; + int cbmultibyte; + + if (!length && !retlen) + cbmultibyte = -1; + else + cbmultibyte = length; + + n = MultiByteToWideChar (CP_UTF8, 0, string, cbmultibyte, NULL, 0); + if (n < 0 || (n+1) <= 0) + return NULL; + + nbytes = (size_t)(n+1) * sizeof(*result); + if (nbytes / sizeof(*result) != (n+1)) + { + _gpg_err_set_errno (ENOMEM); + return NULL; + } + result = jnlib_malloc (nbytes); + if (!result) + return NULL; + + n = MultiByteToWideChar (CP_UTF8, 0, string, cbmultibyte, result, n); + if (n < 0) + { + jnlib_free (result); + return NULL; + } + if (retlen) + *retlen = n; + return result; +} + + +/* Convert an UTF8 string to a WCHAR string. Caller should use + * _gpgrt_free_wchar to release the result. */ +wchar_t * +_gpgrt_utf8_to_wchar (const char *string) +{ + return utf8_to_wchar (string, 0, NULL); +} + + +/* We provide a dedicated release function to be sure that we don't + * use a somehow mapped free function but the one which matches the + * used alloc. */ +void +_gpgrt_free_wchar (wchar_t *wstring) +{ + if (wstring) + jnlib_free (wstring); +} + + +/* Helper for wchar_to_native and wchar_to_utf8. */ +static char * +wchar_to_cp (const wchar_t *string, size_t length, size_t *retlen, + unsigned int cpno) +{ + int n; + char *result; + + n = WideCharToMultiByte (cpno, 0, string, length, NULL, 0, NULL, NULL); + if (n < 0 || (n+1) <= 0) + { + _gpgrt_w32_set_errno (-1); + return NULL; + } + + result = jnlib_malloc (n+1); + if (!result) + return NULL; + + n = WideCharToMultiByte (cpno, 0, string, length, result, n, NULL, NULL); + if (n < 0) + { + _gpgrt_w32_set_errno (-1); + jnlib_free (result); + return NULL; + } + result[n] = 0; + if (retlen) + *retlen = n; + return result; +} + + +/* Return a malloced string encoded in the native console codepage + from the wide char input string STRING. + Caller must free this value. On failure returns NULL. + The result of calling this function with STRING set to NULL + is not defined. */ +static char * +wchar_to_native (const wchar_t *string, size_t length, size_t *retlen) +{ + unsigned int cpno = GetConsoleOutputCP (); + + /* GetConsoleOutputCP returns the 8-Bit codepage that should be used + for console output. If the codepage is not returned we fall back + to the codepage GUI programs should use (CP_ACP). */ + if (!cpno) + cpno = GetACP (); + + return wchar_to_cp (string, length, retlen, cpno); +} + + +/* Convert a WCHAR string to UTF-8. Caller should use xfree to + * release the result. Returns NULL on error and sets ERRNO. */ +char * +_gpgrt_wchar_to_utf8 (const wchar_t *string, size_t length) +{ + return wchar_to_cp (string, length, NULL, CP_UTF8); +} + + +/* Convert UTF8 to the native codepage. Caller must free the return value. */ +static char * +utf8_to_native (const char *string, size_t length, size_t *retlen) +{ + wchar_t *wstring; + char *result; + size_t newlen; + + wstring = utf8_to_wchar (string, length, &newlen); + if (wstring) + { + result = wchar_to_native (wstring, newlen, &newlen); + jnlib_free (wstring); + } + else + result = NULL; + *retlen = result? newlen : 0; + return result; +} + + + +/* Specify that the DOMAINNAME message catalog will be found + in DIRNAME rather than in the system locale data base. */ +const char * +_gpg_w32_bindtextdomain (const char *domainname, const char *dirname) +{ + const char *catval_full; + char *catval; + char *fname; + const char *retvalue; + + if (!dirname) + { + struct domainlist_s *dl; + + retvalue = NULL; + EnterCriticalSection (&domainlist_access_cs); + { + for (dl = domainlist; dl; dl = dl->next) + if (!strcmp (dl->name, domainname)) + { + retvalue = dl->dname; + break; + } + } + LeaveCriticalSection (&domainlist_access_cs); + return retvalue; + } + + /* DIRNAME is "$INSTALLDIR\share\locale". */ + + /* First find out the category value. */ + catval = NULL; + catval_full = my_nl_locale_name ("LC_MESSAGES"); + + /* Normally we would have to loop over all returned locales and + search for the right file. See gettext intl/dcigettext.c for all + the gory details. Here, we only support the basic category, and + ignore everything else. */ + if (catval_full) + { + char *p; + + catval = jnlib_malloc (strlen (catval_full) + 1); + if (catval) + { + strcpy (catval, catval_full); + p = strchr (catval, '_'); + if (p) + *p = '\0'; + } + } + if (!catval) + return NULL; + + /* Now build the filename string. The complete filename is this: + DIRNAME + \ + CATVAL + \LC_MESSAGES\ + DOMAINNAME + .mo */ + { + int len = (strlen (dirname) + 1 + strlen (catval) + 13 + + strlen (domainname) + 3 + 1); + char *p; + + fname = jnlib_malloc (len); + if (!fname) + { + jnlib_free (catval); + return NULL; + } + + p = fname; + strcpy (p, dirname); + p += strlen (dirname); + *(p++) = '\\'; + strcpy (p, catval); + p += strlen (catval); + strcpy (p, "\\LC_MESSAGES\\"); + p += 13; + strcpy (p, domainname); + p += strlen (domainname); + strcpy (p, ".mo"); + } + + jnlib_free (catval); + + /* Store the domain information in the domainlist. */ + { + struct domainlist_s *item, *dl; + char *rel_ptr1 = NULL; + char *rel_ptr2 = NULL; + + item = jnlib_calloc (1, sizeof *dl + strlen (domainname)); + if (!item) + { + jnlib_free (fname); + return NULL; + } + strcpy (item->name, domainname); + item->dname = jnlib_malloc (strlen (dirname) +1); + if(!item->dname) + { + jnlib_free (item); + jnlib_free (fname); + return NULL; + } + strcpy (item->dname, dirname); + retvalue = item->dname; + + EnterCriticalSection (&domainlist_access_cs); + { + for (dl = domainlist; dl; dl = dl->next) + if (!strcmp (dl->name, domainname)) + break; + if (!dl) /* First time called for this domainname. */ + { + item->fname = fname; + fname = NULL; + item->next = domainlist; + domainlist = item; + item = NULL; + } + else /* Update only. */ + { + rel_ptr1 = dl->fname; + dl->fname = fname; + fname = NULL; + rel_ptr2 = dl->dname; + dl->dname = item->dname; + item->dname = NULL; + } + } + LeaveCriticalSection (&domainlist_access_cs); + + jnlib_free (item); + jnlib_free (rel_ptr1); + jnlib_free (rel_ptr2); + } + + return retvalue; +} + + + + +static const char * +get_plural (const char *data, size_t datalen, unsigned long nplural) +{ + const char *p; + int idx; + + /* We only support the Germanic rule. */ + idx = (nplural == 1? 0 : 1); + + for (; idx; idx--) + { + p = strchr (data, 0) + 1; + if (p >= data+datalen) + return "ERROR in GETTEXT (bad plural entry)"; + datalen -= (p-data); + data = p; + } + return data; +} + + +static const char* +get_string (struct loaded_domain *domain, uint32_t idx, + int use_plural, unsigned long nplural) +{ + struct tls_space_s *tls = get_tls (); + struct overflow_space_s *os; + const char *trans; /* Pointer to the translated entry. */ + size_t translen; /* Length of that entry. */ + + if (idx > 65534) + return "ERROR in GETTEXT (too many strings)"; + + if (tls->gt_use_utf8) + { + trans = (domain->data + + SWAPIT(domain->must_swap, domain->trans_tab[idx].offset)); + translen = SWAPIT(domain->must_swap, domain->trans_tab[idx].length); + } + else if (!domain->mapped[idx]) + { + /* Not yet mapped. Map from utf-8 to native encoding now. */ + const char *p_utf8; + size_t plen_utf8, buflen; + char *buf; + + p_utf8 = (domain->data + + SWAPIT(domain->must_swap, domain->trans_tab[idx].offset)); + plen_utf8 = SWAPIT(domain->must_swap, domain->trans_tab[idx].length); + + /* We need to include the nul, so that the utf8->wchar->native + conversion chain works correctly and the nul is stored after + the conversion. */ + if (p_utf8[plen_utf8]) + { + trans = "ERROR in MO file"; /* Terminating zero is missing. */ + translen = 0; + goto leave; + } + plen_utf8++; + + buf = utf8_to_native (p_utf8, plen_utf8, &buflen); + if (!buf) + { + trans = "ERROR in GETTEXT MALLOC"; + translen = 0; + } + else if (buflen <= plen_utf8 && buflen > 1) + { + /* Copy into the DATA_NATIVE area. */ + char *p_tmp; + + p_tmp = (domain->data_native + + SWAPIT(domain->must_swap, domain->trans_tab[idx].offset)); + memcpy (p_tmp, buf, buflen); + domain->mapped[idx] = buflen; + trans = p_tmp; + translen = buflen; + } + else + { + /* There is not enough space for the translation (or for + whatever reason an empty string is used): Store it in the + overflow_space and mark that in the mapped array. + Because UTF-8 strings are in general longer than the + Windows native encoding, we expect that this won't happen + too often and thus we use a linked list to manage this + space. */ + os = jnlib_malloc (sizeof *os + buflen); + if (os) + { + os->idx = idx; + memcpy (os->d, buf, buflen); + os->length = buflen; + os->next = domain->overflow_space; + domain->overflow_space = os; + domain->mapped[idx] = 1; + trans = os->d; + translen = os->length; + } + else + { + trans = "ERROR in GETTEXT MALLOC"; + translen = 0; + } + } + if (translen) + translen--; /* TRANSLEN shall be the size without the nul. */ + jnlib_free (buf); + } + else if (domain->mapped[idx] == 1) + { + /* The translated string is in the overflow_space. */ + for (os=domain->overflow_space; os; os = os->next) + if (os->idx == idx) + break; + if (os) + { + trans = os->d; + translen = os->length; + } + else + { + trans = "ERROR in GETTEXT (overflow space)\n"; + translen = 0; + } + } + else + { + trans = (domain->data_native + + SWAPIT(domain->must_swap, domain->trans_tab[idx].offset)); + translen = domain->mapped[idx]; + } + + leave: + if (use_plural && translen) + return get_plural (trans, translen, nplural); + else + return trans; +} + + +static const char * +do_gettext (const char *domainname, + const char *msgid, const char *msgid2, unsigned long nplural) +{ + struct domainlist_s *dl; + struct loaded_domain *domain; + int load_failed; + uint32_t top, bottom, nstr; + char *filename; + + if (!domainname) + domainname = current_domainname? current_domainname : ""; + + /* FIXME: The whole locking stuff is a bit questionable because + gettext does not claim to be thread-safe. We need to investigate + this further. */ + + load_failed = 0; + domain = NULL; + filename = NULL; + EnterCriticalSection (&domainlist_access_cs); + { + for (dl = domainlist; dl; dl = dl->next) + if (!strcmp (dl->name, domainname)) + { + load_failed = dl->load_failed; + domain = dl->domain; + break; + } + if (dl && !domain && !load_failed && dl->fname) + { + filename = jnlib_malloc (strlen (dl->fname) + 1); + if (filename) + strcpy (filename, dl->fname); + } + } + LeaveCriticalSection (&domainlist_access_cs); + if (!dl) + goto not_found; /* DOMAINNAME not bound. */ + if (filename) + { + /* No attempt so far to load the MO file. Try now. */ + int updated = 0; + + domain = load_domain (filename); + jnlib_free (filename); + filename = NULL; + EnterCriticalSection (&domainlist_access_cs); + { + for (dl = domainlist; dl; dl = dl->next) + if (!strcmp (dl->name, domainname)) + { + if (domain) + dl->domain = domain; + else + dl->load_failed = 1; + updated = 1; + break; + } + } + LeaveCriticalSection (&domainlist_access_cs); + if (!updated) + { + /* Ooops - lost the domain. */ + free_domain (domain); + domain = NULL; + } + } + + if (!domain) + goto not_found; /* No MO file. */ + + /* First try to use the hash table. */ + if (domain->hash_size > 2 && domain->hash_tab) + { + /* Use the hashing table. */ + uint32_t len = strlen (msgid); + uint32_t hash_val = hash_string (msgid); + uint32_t idx = hash_val % domain->hash_size; + uint32_t incr = 1 + (hash_val % (domain->hash_size - 2)); + + while ( (nstr = SWAPIT (domain->must_swap, domain->hash_tab[idx])) ) + { + nstr--; + if (nstr < domain->nstrings + && SWAPIT(domain->must_swap, + domain->orig_tab[nstr].length) >= len + && !strcmp (msgid, (domain->data + + SWAPIT(domain->must_swap, + domain->orig_tab[nstr].offset)))) + { + return get_string (domain, nstr, !!msgid2, nplural); + } + + if (idx >= domain->hash_size - incr) + idx -= domain->hash_size - incr; + else + idx += incr; + } + } + + /* Now we try the default method: binary search in the sorted array + of messages. */ + bottom = 0; + top = domain->nstrings; + while (bottom < top) + { + int cmp_val; + + nstr = (bottom + top) / 2; + cmp_val = strcmp (msgid, (domain->data + + SWAPIT(domain->must_swap, + domain->orig_tab[nstr].offset))); + if (cmp_val < 0) + top = nstr; + else if (cmp_val > 0) + bottom = nstr + 1; + else + { + return get_string (domain, nstr, !!msgid2, nplural); + } + } + + not_found: + /* We use the standard Germanic rule if plural has been requested. */ + return msgid2? (nplural == 1? msgid : msgid2) : msgid; +} + + +const char * +_gpg_w32_textdomain (const char *domainname) +{ + char *string; + + if (!domainname) + { + if (!current_domainname) + _gpg_err_set_errno (0); + } + else + { + string = malloc (strlen (domainname) + 1); + if (!string) + return NULL; + strcpy (string, domainname); + current_domainname = string; + } + return current_domainname; +} + + +/* A direct implementation of gettext instead of a macro calling + dngettext. This is so that the caller does not need to push dummy + values on the stack. The used domain is the first one registered + with bindtextdomain. */ +const char * +_gpg_w32_gettext (const char *msgid) +{ + return do_gettext (NULL, msgid, NULL, 0); +} + + +/* A direct implementation of dgettext instead of a macro calling + dngettext. This is so that the caller does not need to push dummy + values on the stack. */ +const char * +_gpg_w32_dgettext (const char *domainname, const char *msgid) +{ + return do_gettext (domainname, msgid, NULL, 0); +} + + +/* Our implementation of dngettext. This is the most genereic + function we have; a macro implements ngettext. */ +const char * +_gpg_w32_dngettext (const char *domainname, const char *msgid1, + const char *msgid2, unsigned long int n) +{ + /* We use the simple Germanic plural rule. */ + return do_gettext (domainname, msgid1, msgid2, n); +} + + +/* Return the locale name as used by gettext. The return value will + never be NULL. */ +const char * +_gpg_w32_gettext_localename (void) +{ + const char *s; + + s = my_nl_locale_name ("LC_MESSAGES"); + return s? s:""; +} + + +/* With a VALUE of 1 switch the gettext functions into utf8 mode. + That is the strings are returned without translation to the native + charset. A VALUE of 0 switches back to translated strings. A VALUE + of -1 returns the current value. */ +int +_gpg_w32_gettext_use_utf8 (int value) +{ + struct tls_space_s *tls = get_tls (); + int last = tls->gt_use_utf8; + if (value != -1) + tls->gt_use_utf8 = value; + return last; +} + + +/* Force the use of the locale NAME or if NAME is NULL the locale + * derived from LANGID will be used. This function is not thread-safe + * and must be used early - even before gpgrt_check_version. */ +void +gpgrt_w32_override_locale (const char *name, unsigned short langid) +{ + if (name) + { + strncpy (override_locale.name, name, sizeof (override_locale.name) - 1); + override_locale.name[sizeof (override_locale.name) - 1] = 0; + } + else + *override_locale.name = 0; + override_locale.langid = langid; + override_locale.active = 1; +} + + +#ifdef TEST +int +main (int argc, char **argv) +{ + const char atext1[] = + "Warning: You have entered an insecure passphrase.%%0A" + "A passphrase should be at least %u character long."; + const char atext2[] = + "Warning: You have entered an insecure passphrase.%%0A" + "A passphrase should be at least %u characters long."; + + if (argc) + { + argc--; + argv++; + } + + _gpg_err_w32_bindtextdomain ("gnupg2", "c:/programme/gnu/gnupg/share/locale"); + + printf ("locale is `%s'\n", _gpg_err_w32_gettext_localename ()); + fputs ("text with N=1:\n", stdout); + fputs (_gpg_err_w32_ngettext (atext1, atext2, 1), stdout); + fputs ("\n\ntext with N=2:\n", stdout); + fputs (_gpg_err_w32_ngettext (atext1, atext2, 2), stdout); + fputs ("\nready\n", stdout); + + return 0; +} +/* + *No-Local Variables: + * compile-command: "i586-mingw32msvc-gcc -DTEST -Wall -g w32-gettext.c" + * End: + */ +#endif /*TEST*/ diff --git a/comm/third_party/libgpg-error/src/w32-iconv.c b/comm/third_party/libgpg-error/src/w32-iconv.c new file mode 100644 index 0000000000..888b72209c --- /dev/null +++ b/comm/third_party/libgpg-error/src/w32-iconv.c @@ -0,0 +1,1795 @@ +/* w32-iconv.c - iconv implementation for Windows. + * Copyright (C) 2016 g10 Code GmbH + * + * This file is part of libgpg-error. + * + * libgpg-error is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * libgpg-error is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <https://www.gnu.org/licenses/>. + * + ************************************************************** + * This code code is based on the file win_iconv.c as found + * at https://github.com/win-iconv/win-iconv with the commit id + * 8c23784e35327c9d85d22810b9e4a2cbd06ffe90, dated 2016-03-18. + * Yukihiro Nakadaira <yukihiro.nakadaira@gmail.com> is the + * original author. The file win_iconv.c carried this notice: + *-------------------------------------------------------------- + * iconv implementation using Win32 API to convert. + * + * This file is placed in the public domain. + *--------------------------------------------------- + */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif +#if !defined (_WIN32) && !defined (__CYGWIN32__) +# error This module may only be build for Windows or Cygwin32 +#endif + +/* for WC_NO_BEST_FIT_CHARS */ +#ifndef WINVER +# define WINVER 0x0500 +#endif + +#include <windows.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> + +#include "gpgrt-int.h" + +#undef USE_MLANG_DLL + +#define MB_CHAR_MAX 16 + +#define UNICODE_MODE_BOM_DONE 1 +#define UNICODE_MODE_SWAPPED 2 + +#define FLAG_USE_BOM 1 +#define FLAG_TRANSLIT 2 /* //TRANSLIT */ +#define FLAG_IGNORE 4 /* //IGNORE */ + +typedef unsigned char uchar; +typedef unsigned short ushort; +typedef unsigned int uint; + +typedef struct compat_t compat_t; +typedef struct csconv_t csconv_t; + +typedef int* (*f_errno)(void); +typedef int (*f_mbtowc)(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize); +typedef int (*f_wctomb)(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize); +typedef int (*f_mblen)(csconv_t *cv, const uchar *buf, int bufsize); +typedef int (*f_flush)(csconv_t *cv, uchar *buf, int bufsize); + +#define COMPAT_IN 1 +#define COMPAT_OUT 2 + +/* unicode mapping for compatibility with other conversion table. */ +struct compat_t { + uint in; + uint out; + uint flag; +}; + +struct csconv_t { + int codepage; + int flags; + f_mbtowc mbtowc; + f_wctomb wctomb; + f_mblen mblen; + f_flush flush; + DWORD mode; + compat_t *compat; +}; + +struct _gpgrt_w32_iconv_s { + f_errno _errno; + csconv_t from; + csconv_t to; +}; + +#if USE_MLANG_DLL +static int load_mlang(void); +#endif /*USE_MLANG_DLL*/ + +static int make_csconv(const char *name, csconv_t *cv); +static int name_to_codepage(const char *name); +static uint utf16_to_ucs4(const ushort *wbuf); +static void ucs4_to_utf16(uint wc, ushort *wbuf, int *wbufsize); +static int mbtowc_flags(int codepage); +static int must_use_null_useddefaultchar(int codepage); +static char *strrstr(const char *str, const char *token); +static char *xstrndup(const char *s, size_t n); +static int seterror(int err); + +static int sbcs_mblen(csconv_t *cv, const uchar *buf, int bufsize); +static int dbcs_mblen(csconv_t *cv, const uchar *buf, int bufsize); +static int mbcs_mblen(csconv_t *cv, const uchar *buf, int bufsize); +static int utf8_mblen(csconv_t *cv, const uchar *buf, int bufsize); +#if USE_MLANG_DLL +static int eucjp_mblen(csconv_t *cv, const uchar *buf, int bufsize); +#endif /*USE_MLANG_DLL*/ + +static int kernel_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize); +static int kernel_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize); + +#if USE_MLANG_DLL +static int mlang_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize); +static int mlang_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize); +#endif /*USE_MLANG_DLL*/ + +static int utf16_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize); +static int utf16_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize); +static int utf32_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize); +static int utf32_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize); + +#if USE_MLANG_DLL +static int iso2022jp_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize); +static int iso2022jp_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize); +static int iso2022jp_flush(csconv_t *cv, uchar *buf, int bufsize); +#endif /*USE_MLANG_DLL*/ + +static struct { + int codepage; + const char *name; +} codepage_alias[] = { + {65001, "CP65001"}, + {65001, "UTF8"}, + {65001, "UTF-8"}, + + {1200, "CP1200"}, + {1200, "UTF16LE"}, + {1200, "UTF-16LE"}, + {1200, "UCS2LE"}, + {1200, "UCS-2LE"}, + {1200, "UCS-2-INTERNAL"}, + + {1201, "CP1201"}, + {1201, "UTF16BE"}, + {1201, "UTF-16BE"}, + {1201, "UCS2BE"}, + {1201, "UCS-2BE"}, + {1201, "unicodeFFFE"}, + + {12000, "CP12000"}, + {12000, "UTF32LE"}, + {12000, "UTF-32LE"}, + {12000, "UCS4LE"}, + {12000, "UCS-4LE"}, + + {12001, "CP12001"}, + {12001, "UTF32BE"}, + {12001, "UTF-32BE"}, + {12001, "UCS4BE"}, + {12001, "UCS-4BE"}, + + /* + * Default is big endian. + * See rfc2781 4.3 Interpreting text labelled as UTF-16. + */ + {1201, "UTF16"}, + {1201, "UTF-16"}, + {1201, "UCS2"}, + {1201, "UCS-2"}, + {12001, "UTF32"}, + {12001, "UTF-32"}, + {12001, "UCS-4"}, + {12001, "UCS4"}, + + /* copy from libiconv `iconv -l` */ + /* !IsValidCodePage(367) */ + {20127, "ANSI_X3.4-1968"}, + {20127, "ANSI_X3.4-1986"}, + {20127, "ASCII"}, + {20127, "CP367"}, + {20127, "IBM367"}, + {20127, "ISO-IR-6"}, + {20127, "ISO646-US"}, + {20127, "ISO_646.IRV:1991"}, + {20127, "US"}, + {20127, "US-ASCII"}, + {20127, "CSASCII"}, + + /* !IsValidCodePage(819) */ + {1252, "CP819"}, + {1252, "IBM819"}, + {28591, "ISO-8859-1"}, + {28591, "ISO-IR-100"}, + {28591, "ISO8859-1"}, + {28591, "ISO_8859-1"}, + {28591, "ISO_8859-1:1987"}, + {28591, "L1"}, + {28591, "LATIN1"}, + {28591, "CSISOLATIN1"}, + + {1250, "CP1250"}, + {1250, "MS-EE"}, + {1250, "WINDOWS-1250"}, + + {1251, "CP1251"}, + {1251, "MS-CYRL"}, + {1251, "WINDOWS-1251"}, + + {1252, "CP1252"}, + {1252, "MS-ANSI"}, + {1252, "WINDOWS-1252"}, + + {1253, "CP1253"}, + {1253, "MS-GREEK"}, + {1253, "WINDOWS-1253"}, + + {1254, "CP1254"}, + {1254, "MS-TURK"}, + {1254, "WINDOWS-1254"}, + + {1255, "CP1255"}, + {1255, "MS-HEBR"}, + {1255, "WINDOWS-1255"}, + + {1256, "CP1256"}, + {1256, "MS-ARAB"}, + {1256, "WINDOWS-1256"}, + + {1257, "CP1257"}, + {1257, "WINBALTRIM"}, + {1257, "WINDOWS-1257"}, + + {1258, "CP1258"}, + {1258, "WINDOWS-1258"}, + + {850, "850"}, + {850, "CP850"}, + {850, "IBM850"}, + {850, "CSPC850MULTILINGUAL"}, + + /* !IsValidCodePage(862) */ + {862, "862"}, + {862, "CP862"}, + {862, "IBM862"}, + {862, "CSPC862LATINHEBREW"}, + + {866, "866"}, + {866, "CP866"}, + {866, "IBM866"}, + {866, "CSIBM866"}, + + /* !IsValidCodePage(154) */ + {154, "CP154"}, + {154, "CYRILLIC-ASIAN"}, + {154, "PT154"}, + {154, "PTCP154"}, + {154, "CSPTCP154"}, + + /* !IsValidCodePage(1133) */ + {1133, "CP1133"}, + {1133, "IBM-CP1133"}, + + {874, "CP874"}, + {874, "WINDOWS-874"}, + + /* !IsValidCodePage(51932) */ + {51932, "CP51932"}, + {51932, "MS51932"}, + {51932, "WINDOWS-51932"}, + {51932, "EUC-JP"}, + + {932, "CP932"}, + {932, "MS932"}, + {932, "SHIFFT_JIS"}, + {932, "SHIFFT_JIS-MS"}, + {932, "SJIS"}, + {932, "SJIS-MS"}, + {932, "SJIS-OPEN"}, + {932, "SJIS-WIN"}, + {932, "WINDOWS-31J"}, + {932, "WINDOWS-932"}, + {932, "CSWINDOWS31J"}, + + {50221, "CP50221"}, + {50221, "ISO-2022-JP"}, + {50221, "ISO-2022-JP-MS"}, + {50221, "ISO2022-JP"}, + {50221, "ISO2022-JP-MS"}, + {50221, "MS50221"}, + {50221, "WINDOWS-50221"}, + + {936, "CP936"}, + {936, "GBK"}, + {936, "MS936"}, + {936, "WINDOWS-936"}, + + {950, "CP950"}, + {950, "BIG5"}, + {950, "BIG5HKSCS"}, + {950, "BIG5-HKSCS"}, + + {949, "CP949"}, + {949, "UHC"}, + {949, "EUC-KR"}, + + {1361, "CP1361"}, + {1361, "JOHAB"}, + + {437, "437"}, + {437, "CP437"}, + {437, "IBM437"}, + {437, "CSPC8CODEPAGE437"}, + + {737, "CP737"}, + + {775, "CP775"}, + {775, "IBM775"}, + {775, "CSPC775BALTIC"}, + + {852, "852"}, + {852, "CP852"}, + {852, "IBM852"}, + {852, "CSPCP852"}, + + /* !IsValidCodePage(853) */ + {853, "CP853"}, + + {855, "855"}, + {855, "CP855"}, + {855, "IBM855"}, + {855, "CSIBM855"}, + + {857, "857"}, + {857, "CP857"}, + {857, "IBM857"}, + {857, "CSIBM857"}, + + /* !IsValidCodePage(858) */ + {858, "CP858"}, + + {860, "860"}, + {860, "CP860"}, + {860, "IBM860"}, + {860, "CSIBM860"}, + + {861, "861"}, + {861, "CP-IS"}, + {861, "CP861"}, + {861, "IBM861"}, + {861, "CSIBM861"}, + + {863, "863"}, + {863, "CP863"}, + {863, "IBM863"}, + {863, "CSIBM863"}, + + {864, "CP864"}, + {864, "IBM864"}, + {864, "CSIBM864"}, + + {865, "865"}, + {865, "CP865"}, + {865, "IBM865"}, + {865, "CSIBM865"}, + + {869, "869"}, + {869, "CP-GR"}, + {869, "CP869"}, + {869, "IBM869"}, + {869, "CSIBM869"}, + + /* !IsValidCodePage(1152) */ + {1125, "CP1125"}, + + /* + * Code Page Identifiers + * https://msdn.microsoft.com/en-us/library/dd317756.aspx + */ + {37, "IBM037"}, /* IBM EBCDIC US-Canada */ + {437, "IBM437"}, /* OEM United States */ + {500, "IBM500"}, /* IBM EBCDIC International */ + {708, "ASMO-708"}, /* Arabic (ASMO 708) */ + /* 709 Arabic (ASMO-449+, BCON V4) */ + /* 710 Arabic - Transparent Arabic */ + {720, "DOS-720"}, /* Arabic (Transparent ASMO); Arabic (DOS) */ + {737, "ibm737"}, /* OEM Greek (formerly 437G); Greek (DOS) */ + {775, "ibm775"}, /* OEM Baltic; Baltic (DOS) */ + {850, "ibm850"}, /* OEM Multilingual Latin 1; Western European (DOS) */ + {852, "ibm852"}, /* OEM Latin 2; Central European (DOS) */ + {855, "IBM855"}, /* OEM Cyrillic (primarily Russian) */ + {857, "ibm857"}, /* OEM Turkish; Turkish (DOS) */ + {858, "IBM00858"}, /* OEM Multilingual Latin 1 + Euro symbol */ + {860, "IBM860"}, /* OEM Portuguese; Portuguese (DOS) */ + {861, "ibm861"}, /* OEM Icelandic; Icelandic (DOS) */ + {862, "DOS-862"}, /* OEM Hebrew; Hebrew (DOS) */ + {863, "IBM863"}, /* OEM French Canadian; French Canadian (DOS) */ + {864, "IBM864"}, /* OEM Arabic; Arabic (864) */ + {865, "IBM865"}, /* OEM Nordic; Nordic (DOS) */ + {866, "cp866"}, /* OEM Russian; Cyrillic (DOS) */ + {869, "ibm869"}, /* OEM Modern Greek; Greek, Modern (DOS) */ + {870, "IBM870"}, /* IBM EBCDIC Multilingual/ROECE (Latin 2); IBM EBCDIC Multilingual Latin 2 */ + {874, "windows-874"}, /* ANSI/OEM Thai (same as 28605, ISO 8859-15); Thai (Windows) */ + {875, "cp875"}, /* IBM EBCDIC Greek Modern */ + {932, "shift_jis"}, /* ANSI/OEM Japanese; Japanese (Shift-JIS) */ + {932, "shift-jis"}, /* alternative name for it */ + {936, "gb2312"}, /* ANSI/OEM Simplified Chinese (PRC, Singapore); Chinese Simplified (GB2312) */ + {949, "ks_c_5601-1987"}, /* ANSI/OEM Korean (Unified Hangul Code) */ + {950, "big5"}, /* ANSI/OEM Traditional Chinese (Taiwan; Hong Kong SAR, PRC); Chinese Traditional (Big5) */ + {950, "big5hkscs"}, /* ANSI/OEM Traditional Chinese (Hong Kong SAR); Chinese Traditional (Big5-HKSCS) */ + {950, "big5-hkscs"}, /* alternative name for it */ + {1026, "IBM1026"}, /* IBM EBCDIC Turkish (Latin 5) */ + {1047, "IBM01047"}, /* IBM EBCDIC Latin 1/Open System */ + {1140, "IBM01140"}, /* IBM EBCDIC US-Canada (037 + Euro symbol); IBM EBCDIC (US-Canada-Euro) */ + {1141, "IBM01141"}, /* IBM EBCDIC Germany (20273 + Euro symbol); IBM EBCDIC (Germany-Euro) */ + {1142, "IBM01142"}, /* IBM EBCDIC Denmark-Norway (20277 + Euro symbol); IBM EBCDIC (Denmark-Norway-Euro) */ + {1143, "IBM01143"}, /* IBM EBCDIC Finland-Sweden (20278 + Euro symbol); IBM EBCDIC (Finland-Sweden-Euro) */ + {1144, "IBM01144"}, /* IBM EBCDIC Italy (20280 + Euro symbol); IBM EBCDIC (Italy-Euro) */ + {1145, "IBM01145"}, /* IBM EBCDIC Latin America-Spain (20284 + Euro symbol); IBM EBCDIC (Spain-Euro) */ + {1146, "IBM01146"}, /* IBM EBCDIC United Kingdom (20285 + Euro symbol); IBM EBCDIC (UK-Euro) */ + {1147, "IBM01147"}, /* IBM EBCDIC France (20297 + Euro symbol); IBM EBCDIC (France-Euro) */ + {1148, "IBM01148"}, /* IBM EBCDIC International (500 + Euro symbol); IBM EBCDIC (International-Euro) */ + {1149, "IBM01149"}, /* IBM EBCDIC Icelandic (20871 + Euro symbol); IBM EBCDIC (Icelandic-Euro) */ + {1250, "windows-1250"}, /* ANSI Central European; Central European (Windows) */ + {1251, "windows-1251"}, /* ANSI Cyrillic; Cyrillic (Windows) */ + {1252, "windows-1252"}, /* ANSI Latin 1; Western European (Windows) */ + {1253, "windows-1253"}, /* ANSI Greek; Greek (Windows) */ + {1254, "windows-1254"}, /* ANSI Turkish; Turkish (Windows) */ + {1255, "windows-1255"}, /* ANSI Hebrew; Hebrew (Windows) */ + {1256, "windows-1256"}, /* ANSI Arabic; Arabic (Windows) */ + {1257, "windows-1257"}, /* ANSI Baltic; Baltic (Windows) */ + {1258, "windows-1258"}, /* ANSI/OEM Vietnamese; Vietnamese (Windows) */ + {1361, "Johab"}, /* Korean (Johab) */ + {10000, "macintosh"}, /* MAC Roman; Western European (Mac) */ + {10001, "x-mac-japanese"}, /* Japanese (Mac) */ + {10002, "x-mac-chinesetrad"}, /* MAC Traditional Chinese (Big5); Chinese Traditional (Mac) */ + {10003, "x-mac-korean"}, /* Korean (Mac) */ + {10004, "x-mac-arabic"}, /* Arabic (Mac) */ + {10005, "x-mac-hebrew"}, /* Hebrew (Mac) */ + {10006, "x-mac-greek"}, /* Greek (Mac) */ + {10007, "x-mac-cyrillic"}, /* Cyrillic (Mac) */ + {10008, "x-mac-chinesesimp"}, /* MAC Simplified Chinese (GB 2312); Chinese Simplified (Mac) */ + {10010, "x-mac-romanian"}, /* Romanian (Mac) */ + {10017, "x-mac-ukrainian"}, /* Ukrainian (Mac) */ + {10021, "x-mac-thai"}, /* Thai (Mac) */ + {10029, "x-mac-ce"}, /* MAC Latin 2; Central European (Mac) */ + {10079, "x-mac-icelandic"}, /* Icelandic (Mac) */ + {10081, "x-mac-turkish"}, /* Turkish (Mac) */ + {10082, "x-mac-croatian"}, /* Croatian (Mac) */ + {20000, "x-Chinese_CNS"}, /* CNS Taiwan; Chinese Traditional (CNS) */ + {20001, "x-cp20001"}, /* TCA Taiwan */ + {20002, "x_Chinese-Eten"}, /* Eten Taiwan; Chinese Traditional (Eten) */ + {20003, "x-cp20003"}, /* IBM5550 Taiwan */ + {20004, "x-cp20004"}, /* TeleText Taiwan */ + {20005, "x-cp20005"}, /* Wang Taiwan */ + {20105, "x-IA5"}, /* IA5 (IRV International Alphabet No. 5, 7-bit); Western European (IA5) */ + {20106, "x-IA5-German"}, /* IA5 German (7-bit) */ + {20107, "x-IA5-Swedish"}, /* IA5 Swedish (7-bit) */ + {20108, "x-IA5-Norwegian"}, /* IA5 Norwegian (7-bit) */ + {20127, "us-ascii"}, /* US-ASCII (7-bit) */ + {20261, "x-cp20261"}, /* T.61 */ + {20269, "x-cp20269"}, /* ISO 6937 Non-Spacing Accent */ + {20273, "IBM273"}, /* IBM EBCDIC Germany */ + {20277, "IBM277"}, /* IBM EBCDIC Denmark-Norway */ + {20278, "IBM278"}, /* IBM EBCDIC Finland-Sweden */ + {20280, "IBM280"}, /* IBM EBCDIC Italy */ + {20284, "IBM284"}, /* IBM EBCDIC Latin America-Spain */ + {20285, "IBM285"}, /* IBM EBCDIC United Kingdom */ + {20290, "IBM290"}, /* IBM EBCDIC Japanese Katakana Extended */ + {20297, "IBM297"}, /* IBM EBCDIC France */ + {20420, "IBM420"}, /* IBM EBCDIC Arabic */ + {20423, "IBM423"}, /* IBM EBCDIC Greek */ + {20424, "IBM424"}, /* IBM EBCDIC Hebrew */ + {20833, "x-EBCDIC-KoreanExtended"}, /* IBM EBCDIC Korean Extended */ + {20838, "IBM-Thai"}, /* IBM EBCDIC Thai */ + {20866, "koi8-r"}, /* Russian (KOI8-R); Cyrillic (KOI8-R) */ + {20871, "IBM871"}, /* IBM EBCDIC Icelandic */ + {20880, "IBM880"}, /* IBM EBCDIC Cyrillic Russian */ + {20905, "IBM905"}, /* IBM EBCDIC Turkish */ + {20924, "IBM00924"}, /* IBM EBCDIC Latin 1/Open System (1047 + Euro symbol) */ + {20932, "EUC-JP"}, /* Japanese (JIS 0208-1990 and 0121-1990) */ + {20936, "x-cp20936"}, /* Simplified Chinese (GB2312); Chinese Simplified (GB2312-80) */ + {20949, "x-cp20949"}, /* Korean Wansung */ + {21025, "cp1025"}, /* IBM EBCDIC Cyrillic Serbian-Bulgarian */ + /* 21027 (deprecated) */ + {21866, "koi8-u"}, /* Ukrainian (KOI8-U); Cyrillic (KOI8-U) */ + {28591, "iso-8859-1"}, /* ISO 8859-1 Latin 1; Western European (ISO) */ + {28591, "iso8859-1"}, /* ISO 8859-1 Latin 1; Western European (ISO) */ + {28591, "iso_8859-1"}, + {28591, "iso_8859_1"}, + {28592, "iso-8859-2"}, /* ISO 8859-2 Central European; Central European (ISO) */ + {28592, "iso8859-2"}, /* ISO 8859-2 Central European; Central European (ISO) */ + {28592, "iso_8859-2"}, + {28592, "iso_8859_2"}, + {28593, "iso-8859-3"}, /* ISO 8859-3 Latin 3 */ + {28593, "iso8859-3"}, /* ISO 8859-3 Latin 3 */ + {28593, "iso_8859-3"}, + {28593, "iso_8859_3"}, + {28594, "iso-8859-4"}, /* ISO 8859-4 Baltic */ + {28594, "iso8859-4"}, /* ISO 8859-4 Baltic */ + {28594, "iso_8859-4"}, + {28594, "iso_8859_4"}, + {28595, "iso-8859-5"}, /* ISO 8859-5 Cyrillic */ + {28595, "iso8859-5"}, /* ISO 8859-5 Cyrillic */ + {28595, "iso_8859-5"}, + {28595, "iso_8859_5"}, + {28596, "iso-8859-6"}, /* ISO 8859-6 Arabic */ + {28596, "iso8859-6"}, /* ISO 8859-6 Arabic */ + {28596, "iso_8859-6"}, + {28596, "iso_8859_6"}, + {28597, "iso-8859-7"}, /* ISO 8859-7 Greek */ + {28597, "iso8859-7"}, /* ISO 8859-7 Greek */ + {28597, "iso_8859-7"}, + {28597, "iso_8859_7"}, + {28598, "iso-8859-8"}, /* ISO 8859-8 Hebrew; Hebrew (ISO-Visual) */ + {28598, "iso8859-8"}, /* ISO 8859-8 Hebrew; Hebrew (ISO-Visual) */ + {28598, "iso_8859-8"}, + {28598, "iso_8859_8"}, + {28599, "iso-8859-9"}, /* ISO 8859-9 Turkish */ + {28599, "iso8859-9"}, /* ISO 8859-9 Turkish */ + {28599, "iso_8859-9"}, + {28599, "iso_8859_9"}, + {28603, "iso-8859-13"}, /* ISO 8859-13 Estonian */ + {28603, "iso8859-13"}, /* ISO 8859-13 Estonian */ + {28603, "iso_8859-13"}, + {28603, "iso_8859_13"}, + {28605, "iso-8859-15"}, /* ISO 8859-15 Latin 9 */ + {28605, "iso8859-15"}, /* ISO 8859-15 Latin 9 */ + {28605, "iso_8859-15"}, + {28605, "iso_8859_15"}, + {29001, "x-Europa"}, /* Europa 3 */ + {38598, "iso-8859-8-i"}, /* ISO 8859-8 Hebrew; Hebrew (ISO-Logical) */ + {38598, "iso8859-8-i"}, /* ISO 8859-8 Hebrew; Hebrew (ISO-Logical) */ + {38598, "iso_8859-8-i"}, + {38598, "iso_8859_8-i"}, + {50220, "iso-2022-jp"}, /* ISO 2022 Japanese with no halfwidth Katakana; Japanese (JIS) */ + {50221, "csISO2022JP"}, /* ISO 2022 Japanese with halfwidth Katakana; Japanese (JIS-Allow 1 byte Kana) */ + {50222, "iso-2022-jp"}, /* ISO 2022 Japanese JIS X 0201-1989; Japanese (JIS-Allow 1 byte Kana - SO/SI) */ + {50225, "iso-2022-kr"}, /* ISO 2022 Korean */ + {50225, "iso2022-kr"}, /* ISO 2022 Korean */ + {50227, "x-cp50227"}, /* ISO 2022 Simplified Chinese; Chinese Simplified (ISO 2022) */ + /* 50229 ISO 2022 Traditional Chinese */ + /* 50930 EBCDIC Japanese (Katakana) Extended */ + /* 50931 EBCDIC US-Canada and Japanese */ + /* 50933 EBCDIC Korean Extended and Korean */ + /* 50935 EBCDIC Simplified Chinese Extended and Simplified Chinese */ + /* 50936 EBCDIC Simplified Chinese */ + /* 50937 EBCDIC US-Canada and Traditional Chinese */ + /* 50939 EBCDIC Japanese (Latin) Extended and Japanese */ + {51932, "euc-jp"}, /* EUC Japanese */ + {51936, "EUC-CN"}, /* EUC Simplified Chinese; Chinese Simplified (EUC) */ + {51949, "euc-kr"}, /* EUC Korean */ + /* 51950 EUC Traditional Chinese */ + {52936, "hz-gb-2312"}, /* HZ-GB2312 Simplified Chinese; Chinese Simplified (HZ) */ + {54936, "GB18030"}, /* Windows XP and later: GB18030 Simplified Chinese (4 byte); Chinese Simplified (GB18030) */ + {57002, "x-iscii-de"}, /* ISCII Devanagari */ + {57003, "x-iscii-be"}, /* ISCII Bengali */ + {57004, "x-iscii-ta"}, /* ISCII Tamil */ + {57005, "x-iscii-te"}, /* ISCII Telugu */ + {57006, "x-iscii-as"}, /* ISCII Assamese */ + {57007, "x-iscii-or"}, /* ISCII Oriya */ + {57008, "x-iscii-ka"}, /* ISCII Kannada */ + {57009, "x-iscii-ma"}, /* ISCII Malayalam */ + {57010, "x-iscii-gu"}, /* ISCII Gujarati */ + {57011, "x-iscii-pa"}, /* ISCII Punjabi */ + + {0, NULL} +}; + +/* + * SJIS SHIFTJIS table CP932 table + * ---- --------------------------- -------------------------------- + * 5C U+00A5 YEN SIGN U+005C REVERSE SOLIDUS + * 7E U+203E OVERLINE U+007E TILDE + * 815C U+2014 EM DASH U+2015 HORIZONTAL BAR + * 815F U+005C REVERSE SOLIDUS U+FF3C FULLWIDTH REVERSE SOLIDUS + * 8160 U+301C WAVE DASH U+FF5E FULLWIDTH TILDE + * 8161 U+2016 DOUBLE VERTICAL LINE U+2225 PARALLEL TO + * 817C U+2212 MINUS SIGN U+FF0D FULLWIDTH HYPHEN-MINUS + * 8191 U+00A2 CENT SIGN U+FFE0 FULLWIDTH CENT SIGN + * 8192 U+00A3 POUND SIGN U+FFE1 FULLWIDTH POUND SIGN + * 81CA U+00AC NOT SIGN U+FFE2 FULLWIDTH NOT SIGN + * + * EUC-JP and ISO-2022-JP should be compatible with CP932. + * + * Kernel and MLang have different Unicode mapping table. Make sure + * which API is used. + */ +static compat_t cp932_compat[] = { + {0x00A5, 0x005C, COMPAT_OUT}, + {0x203E, 0x007E, COMPAT_OUT}, + {0x2014, 0x2015, COMPAT_OUT}, + {0x301C, 0xFF5E, COMPAT_OUT}, + {0x2016, 0x2225, COMPAT_OUT}, + {0x2212, 0xFF0D, COMPAT_OUT}, + {0x00A2, 0xFFE0, COMPAT_OUT}, + {0x00A3, 0xFFE1, COMPAT_OUT}, + {0x00AC, 0xFFE2, COMPAT_OUT}, + {0, 0, 0} +}; + +static compat_t cp20932_compat[] = { + {0x00A5, 0x005C, COMPAT_OUT}, + {0x203E, 0x007E, COMPAT_OUT}, + {0x2014, 0x2015, COMPAT_OUT}, + {0xFF5E, 0x301C, COMPAT_OUT|COMPAT_IN}, + {0x2225, 0x2016, COMPAT_OUT|COMPAT_IN}, + {0xFF0D, 0x2212, COMPAT_OUT|COMPAT_IN}, + {0xFFE0, 0x00A2, COMPAT_OUT|COMPAT_IN}, + {0xFFE1, 0x00A3, COMPAT_OUT|COMPAT_IN}, + {0xFFE2, 0x00AC, COMPAT_OUT|COMPAT_IN}, + {0, 0, 0} +}; + +static compat_t *cp51932_compat = cp932_compat; + +/* cp20932_compat for kernel. cp932_compat for mlang. */ +static compat_t *cp5022x_compat = cp932_compat; + +#if USE_MLANG_DLL +typedef HRESULT (WINAPI *CONVERTINETSTRING)( + LPDWORD lpdwMode, + DWORD dwSrcEncoding, + DWORD dwDstEncoding, + LPCSTR lpSrcStr, + LPINT lpnSrcSize, + LPBYTE lpDstStr, + LPINT lpnDstSize +); +typedef HRESULT (WINAPI *CONVERTINETMULTIBYTETOUNICODE)( + LPDWORD lpdwMode, + DWORD dwSrcEncoding, + LPCSTR lpSrcStr, + LPINT lpnMultiCharCount, + LPWSTR lpDstStr, + LPINT lpnWideCharCount +); +typedef HRESULT (WINAPI *CONVERTINETUNICODETOMULTIBYTE)( + LPDWORD lpdwMode, + DWORD dwEncoding, + LPCWSTR lpSrcStr, + LPINT lpnWideCharCount, + LPSTR lpDstStr, + LPINT lpnMultiCharCount +); +typedef HRESULT (WINAPI *ISCONVERTINETSTRINGAVAILABLE)( + DWORD dwSrcEncoding, + DWORD dwDstEncoding +); +typedef HRESULT (WINAPI *LCIDTORFC1766A)( + LCID Locale, + LPSTR pszRfc1766, + int nChar +); +typedef HRESULT (WINAPI *LCIDTORFC1766W)( + LCID Locale, + LPWSTR pszRfc1766, + int nChar +); +typedef HRESULT (WINAPI *RFC1766TOLCIDA)( + LCID *pLocale, + LPSTR pszRfc1766 +); +typedef HRESULT (WINAPI *RFC1766TOLCIDW)( + LCID *pLocale, + LPWSTR pszRfc1766 +); +static CONVERTINETSTRING ConvertINetString; +static CONVERTINETMULTIBYTETOUNICODE ConvertINetMultiByteToUnicode; +static CONVERTINETUNICODETOMULTIBYTE ConvertINetUnicodeToMultiByte; +static ISCONVERTINETSTRINGAVAILABLE IsConvertINetStringAvailable; +static LCIDTORFC1766A LcidToRfc1766A; +static RFC1766TOLCIDA Rfc1766ToLcidA; +#endif /*USE_MLANG_DLL*/ + +#if USE_MLANG_DLL +static int +load_mlang(void) +{ + HMODULE h; + if (ConvertINetString != NULL) + return TRUE; + h = LoadLibrary(TEXT("mlang.dll")); + if (!h) + return FALSE; + ConvertINetString = (CONVERTINETSTRING)GetProcAddressA(h, "ConvertINetString"); + ConvertINetMultiByteToUnicode = (CONVERTINETMULTIBYTETOUNICODE)GetProcAddressA(h, "ConvertINetMultiByteToUnicode"); + ConvertINetUnicodeToMultiByte = (CONVERTINETUNICODETOMULTIBYTE)GetProcAddressA(h, "ConvertINetUnicodeToMultiByte"); + IsConvertINetStringAvailable = (ISCONVERTINETSTRINGAVAILABLE)GetProcAddressA(h, "IsConvertINetStringAvailable"); + LcidToRfc1766A = (LCIDTORFC1766A)GetProcAddressA(h, "LcidToRfc1766A"); + Rfc1766ToLcidA = (RFC1766TOLCIDA)GetProcAddressA(h, "Rfc1766ToLcidA"); + return TRUE; +} +#endif + + +static int +win_iconv_open(gpgrt_w32_iconv_t cd, const char *tocode, const char *fromcode) +{ + if (!make_csconv(fromcode, &cd->from) || !make_csconv(tocode, &cd->to)) + return FALSE; + cd->_errno = _errno; + return TRUE; +} + +static size_t +win_iconv (gpgrt_w32_iconv_t cd, + const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + ushort wbuf[MB_CHAR_MAX]; /* enough room for one character */ + int insize; + int outsize; + int wsize; + DWORD frommode; + DWORD tomode; + uint wc; + compat_t *cp; + int i; + + if (inbuf == NULL || *inbuf == NULL) + { + if (outbuf != NULL && *outbuf != NULL && cd->to.flush != NULL) + { + tomode = cd->to.mode; + outsize = cd->to.flush(&cd->to, (uchar *)*outbuf, *outbytesleft); + if (outsize == -1) + { + if ((cd->to.flags & FLAG_IGNORE) && errno != E2BIG) + { + outsize = 0; + } + else + { + cd->to.mode = tomode; + return (size_t)(-1); + } + } + *outbuf += outsize; + *outbytesleft -= outsize; + } + cd->from.mode = 0; + cd->to.mode = 0; + return 0; + } + + while (*inbytesleft != 0) + { + frommode = cd->from.mode; + tomode = cd->to.mode; + wsize = MB_CHAR_MAX; + + insize = cd->from.mbtowc(&cd->from, (const uchar *)*inbuf, *inbytesleft, wbuf, &wsize); + if (insize == -1) + { + if (cd->to.flags & FLAG_IGNORE) + { + cd->from.mode = frommode; + insize = 1; + wsize = 0; + } + else + { + cd->from.mode = frommode; + return (size_t)(-1); + } + } + + if (wsize == 0) + { + *inbuf += insize; + *inbytesleft -= insize; + continue; + } + + if (cd->from.compat != NULL) + { + wc = utf16_to_ucs4(wbuf); + cp = cd->from.compat; + for (i = 0; cp[i].in != 0; ++i) + { + if ((cp[i].flag & COMPAT_IN) && cp[i].out == wc) + { + ucs4_to_utf16(cp[i].in, wbuf, &wsize); + break; + } + } + } + + if (cd->to.compat != NULL) + { + wc = utf16_to_ucs4(wbuf); + cp = cd->to.compat; + for (i = 0; cp[i].in != 0; ++i) + { + if ((cp[i].flag & COMPAT_OUT) && cp[i].in == wc) + { + ucs4_to_utf16(cp[i].out, wbuf, &wsize); + break; + } + } + } + + outsize = cd->to.wctomb(&cd->to, wbuf, wsize, (uchar *)*outbuf, *outbytesleft); + if (outsize == -1) + { + if ((cd->to.flags & FLAG_IGNORE) && errno != E2BIG) + { + cd->to.mode = tomode; + outsize = 0; + } + else + { + cd->from.mode = frommode; + cd->to.mode = tomode; + return (size_t)(-1); + } + } + + *inbuf += insize; + *outbuf += outsize; + *inbytesleft -= insize; + *outbytesleft -= outsize; + } + + return 0; +} + +static int +make_csconv(const char *_name, csconv_t *cv) +{ + CPINFO cpinfo; + int use_compat = TRUE; + int flag = 0; + char *name; + char *p; + + name = xstrndup(_name, strlen(_name)); + if (name == NULL) + return FALSE; + + /* check for option "enc_name//opt1//opt2" */ + while ((p = strrstr(name, "//")) != NULL) + { + if (_stricmp(p + 2, "nocompat") == 0) + use_compat = FALSE; + else if (_stricmp(p + 2, "translit") == 0) + flag |= FLAG_TRANSLIT; + else if (_stricmp(p + 2, "ignore") == 0) + flag |= FLAG_IGNORE; + *p = 0; + } + + cv->mode = 0; + cv->flags = flag; + cv->mblen = NULL; + cv->flush = NULL; + cv->compat = NULL; + cv->codepage = name_to_codepage(name); + if (cv->codepage == 1200 || cv->codepage == 1201) + { + cv->mbtowc = utf16_mbtowc; + cv->wctomb = utf16_wctomb; + if (_stricmp(name, "UTF-16") == 0 || _stricmp(name, "UTF16") == 0 || + _stricmp(name, "UCS-2") == 0 || _stricmp(name, "UCS2") == 0 || + _stricmp(name,"UCS-2-INTERNAL") == 0) + cv->flags |= FLAG_USE_BOM; + } + else if (cv->codepage == 12000 || cv->codepage == 12001) + { + cv->mbtowc = utf32_mbtowc; + cv->wctomb = utf32_wctomb; + if (_stricmp(name, "UTF-32") == 0 || _stricmp(name, "UTF32") == 0 || + _stricmp(name, "UCS-4") == 0 || _stricmp(name, "UCS4") == 0) + cv->flags |= FLAG_USE_BOM; + } + else if (cv->codepage == 65001) + { + cv->mbtowc = kernel_mbtowc; + cv->wctomb = kernel_wctomb; + cv->mblen = utf8_mblen; + } +#if USE_MLANG_DLL + else if ((cv->codepage == 50220 || cv->codepage == 50221 || cv->codepage == 50222) && load_mlang()) + { + cv->mbtowc = iso2022jp_mbtowc; + cv->wctomb = iso2022jp_wctomb; + cv->flush = iso2022jp_flush; + } + else if (cv->codepage == 51932 && load_mlang()) + { + cv->mbtowc = mlang_mbtowc; + cv->wctomb = mlang_wctomb; + cv->mblen = eucjp_mblen; + } +#endif /*USE_MLANG_DLL*/ + else if (IsValidCodePage(cv->codepage) + && GetCPInfo(cv->codepage, &cpinfo) != 0) + { + cv->mbtowc = kernel_mbtowc; + cv->wctomb = kernel_wctomb; + if (cpinfo.MaxCharSize == 1) + cv->mblen = sbcs_mblen; + else if (cpinfo.MaxCharSize == 2) + cv->mblen = dbcs_mblen; + else + cv->mblen = mbcs_mblen; + } + else + { + /* not supported */ + free(name); + errno = EINVAL; + return FALSE; + } + + if (use_compat) + { + switch (cv->codepage) + { + case 932: cv->compat = cp932_compat; break; + case 20932: cv->compat = cp20932_compat; break; + case 51932: cv->compat = cp51932_compat; break; + case 50220: case 50221: case 50222: cv->compat = cp5022x_compat; break; + } + } + + free(name); + + return TRUE; +} + +static int +name_to_codepage(const char *name) +{ + int i; + + if (*name == '\0' || + strcmp(name, "char") == 0) + return GetACP(); + else if (strcmp(name, "wchar_t") == 0) + return 1200; + else if (_strnicmp(name, "cp", 2) == 0) + return atoi(name + 2); /* CP123 */ + else if ('0' <= name[0] && name[0] <= '9') + return atoi(name); /* 123 */ + else if (_strnicmp(name, "xx", 2) == 0) + return atoi(name + 2); /* XX123 for debug */ + + for (i = 0; codepage_alias[i].name != NULL; ++i) + if (_stricmp(name, codepage_alias[i].name) == 0) + return codepage_alias[i].codepage; + return -1; +} + +/* + * https://tools.ietf.org/html/rfc2781 + */ +static uint +utf16_to_ucs4(const ushort *wbuf) +{ + uint wc = wbuf[0]; + if (0xD800 <= wbuf[0] && wbuf[0] <= 0xDBFF) + wc = ((wbuf[0] & 0x3FF) << 10) + (wbuf[1] & 0x3FF) + 0x10000; + return wc; +} + +static void +ucs4_to_utf16(uint wc, ushort *wbuf, int *wbufsize) +{ + if (wc < 0x10000) + { + wbuf[0] = wc; + *wbufsize = 1; + } + else + { + wc -= 0x10000; + wbuf[0] = 0xD800 | ((wc >> 10) & 0x3FF); + wbuf[1] = 0xDC00 | (wc & 0x3FF); + *wbufsize = 2; + } +} + +/* + * Check if codepage is one of those for which the dwFlags parameter + * to MultiByteToWideChar() must be zero. Return zero or + * MB_ERR_INVALID_CHARS. The docs in Platform SDK for Windows + * Server 2003 R2 claims that also codepage 65001 is one of these, but + * that doesn't seem to be the case. The MSDN docs for MSVS2008 leave + * out 65001 (UTF-8), and that indeed seems to be the case on XP, it + * works fine to pass MB_ERR_INVALID_CHARS in dwFlags when converting + * from UTF-8. + */ +static int +mbtowc_flags(int codepage) +{ + return (codepage == 50220 || codepage == 50221 || + codepage == 50222 || codepage == 50225 || + codepage == 50227 || codepage == 50229 || + codepage == 52936 || codepage == 54936 || + (codepage >= 57002 && codepage <= 57011) || + codepage == 65000 || codepage == 42) ? 0 : MB_ERR_INVALID_CHARS; +} + +/* + * Check if codepage is one those for which the lpUsedDefaultChar + * parameter to WideCharToMultiByte() must be NULL. The docs in + * Platform SDK for Windows Server 2003 R2 claims that this is the + * list below, while the MSDN docs for MSVS2008 claim that it is only + * for 65000 (UTF-7) and 65001 (UTF-8). This time the earlier Platform + * SDK seems to be correct, at least for XP. + */ +static int +must_use_null_useddefaultchar(int codepage) +{ + return (codepage == 65000 || codepage == 65001 || + codepage == 50220 || codepage == 50221 || + codepage == 50222 || codepage == 50225 || + codepage == 50227 || codepage == 50229 || + codepage == 52936 || codepage == 54936 || + (codepage >= 57002 && codepage <= 57011) || + codepage == 42); +} + +static char * +strrstr(const char *str, const char *token) +{ + int len = strlen(token); + const char *p = str + strlen(str); + + while (str <= --p) + if (p[0] == token[0] && strncmp(p, token, len) == 0) + return (char *)p; + return NULL; +} + +static char * +xstrndup(const char *s, size_t n) +{ + char *p; + + p = (char *)malloc(n + 1); + if (p == NULL) + return NULL; + memcpy(p, s, n); + p[n] = '\0'; + return p; +} + +static int +seterror(int err) +{ + _gpg_err_set_errno (err); + return -1; +} + + +static int +sbcs_mblen(csconv_t *cv, const uchar *buf, int bufsize) +{ + (void)cv; + (void)buf; + (void)bufsize; + return 1; +} + +static int +dbcs_mblen(csconv_t *cv, const uchar *buf, int bufsize) +{ + int len = IsDBCSLeadByteEx(cv->codepage, buf[0]) ? 2 : 1; + if (bufsize < len) + return seterror(EINVAL); + return len; +} + +static int +mbcs_mblen(csconv_t *cv, const uchar *buf, int bufsize) +{ + int len = 0; + + if (cv->codepage == 54936) { + if (buf[0] <= 0x7F) len = 1; + else if (buf[0] >= 0x81 && buf[0] <= 0xFE && + bufsize >= 2 && + ((buf[1] >= 0x40 && buf[1] <= 0x7E) || + (buf[1] >= 0x80 && buf[1] <= 0xFE))) len = 2; + else if (buf[0] >= 0x81 && buf[0] <= 0xFE && + bufsize >= 4 && + buf[1] >= 0x30 && buf[1] <= 0x39) len = 4; + else + return seterror(EINVAL); + return len; + } + else + return seterror(EINVAL); +} + +static int +utf8_mblen(csconv_t *cv, const uchar *buf, int bufsize) +{ + int len = 0; + + (void) cv; + + if (buf[0] < 0x80) len = 1; + else if ((buf[0] & 0xE0) == 0xC0) len = 2; + else if ((buf[0] & 0xF0) == 0xE0) len = 3; + else if ((buf[0] & 0xF8) == 0xF0) len = 4; + else if ((buf[0] & 0xFC) == 0xF8) len = 5; + else if ((buf[0] & 0xFE) == 0xFC) len = 6; + + if (len == 0) + return seterror(EILSEQ); + else if (bufsize < len) + return seterror(EINVAL); + return len; +} + +#if USE_MLANG_DLL +static int +eucjp_mblen(csconv_t *cv, const uchar *buf, int bufsize) +{ + (void) cv; + + if (buf[0] < 0x80) /* ASCII */ + return 1; + else if (buf[0] == 0x8E) /* JIS X 0201 */ + { + if (bufsize < 2) + return seterror(EINVAL); + else if (!(0xA1 <= buf[1] && buf[1] <= 0xDF)) + return seterror(EILSEQ); + return 2; + } + else if (buf[0] == 0x8F) /* JIS X 0212 */ + { + if (bufsize < 3) + return seterror(EINVAL); + else if (!(0xA1 <= buf[1] && buf[1] <= 0xFE) + || !(0xA1 <= buf[2] && buf[2] <= 0xFE)) + return seterror(EILSEQ); + return 3; + } + else /* JIS X 0208 */ + { + if (bufsize < 2) + return seterror(EINVAL); + else if (!(0xA1 <= buf[0] && buf[0] <= 0xFE) + || !(0xA1 <= buf[1] && buf[1] <= 0xFE)) + return seterror(EILSEQ); + return 2; + } +} +#endif /*USE_MLANG_DLL*/ + +static int +kernel_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize) +{ + int len; + + len = cv->mblen(cv, buf, bufsize); + if (len == -1) + return -1; + /* If converting from ASCII, reject 8bit + * chars. MultiByteToWideChar() doesn't. Note that for ASCII we + * know that the mblen function is sbcs_mblen() so len is 1. + */ + if (cv->codepage == 20127 && buf[0] >= 0x80) + return seterror(EILSEQ); + *wbufsize = MultiByteToWideChar(cv->codepage, mbtowc_flags (cv->codepage), + (const char *)buf, len, (wchar_t *)wbuf, *wbufsize); + if (*wbufsize == 0) + return seterror(EILSEQ); + return len; +} + +static int +kernel_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize) +{ + BOOL usedDefaultChar = 0; + BOOL *p = NULL; + int flags = 0; + int len; + + if (bufsize == 0) + return seterror(E2BIG); + if (!must_use_null_useddefaultchar(cv->codepage)) + { + p = &usedDefaultChar; +#ifdef WC_NO_BEST_FIT_CHARS + if (!(cv->flags & FLAG_TRANSLIT)) + flags |= WC_NO_BEST_FIT_CHARS; +#endif + } + len = WideCharToMultiByte(cv->codepage, flags, + (const wchar_t *)wbuf, wbufsize, (char *)buf, bufsize, NULL, p); + if (len == 0) + { + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) + return seterror(E2BIG); + return seterror(EILSEQ); + } + else if (usedDefaultChar && !(cv->flags & FLAG_TRANSLIT)) + return seterror(EILSEQ); + else if (cv->mblen(cv, buf, len) != len) /* validate result */ + return seterror(EILSEQ); + return len; +} + +/* + * It seems that the mode (cv->mode) is fixnum. + * For example, when converting iso-2022-jp(cp50221) to unicode: + * in ascii sequence: mode=0xC42C0000 + * in jisx0208 sequence: mode=0xC42C0001 + * "C42C" is same for each convert session. + * It should be: ((codepage-1)<<16)|state + */ +#if USE_MLANG_DLL +static int +mlang_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize) +{ + int len; + int insize; + HRESULT hr; + + len = cv->mblen(cv, buf, bufsize); + if (len == -1) + return -1; + insize = len; + hr = ConvertINetMultiByteToUnicode(&cv->mode, cv->codepage, + (const char *)buf, &insize, (wchar_t *)wbuf, wbufsize); + if (hr != S_OK || insize != len) + return seterror(EILSEQ); + return len; +} + +static int +mlang_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize) +{ + char tmpbuf[MB_CHAR_MAX]; /* enough room for one character */ + int tmpsize = MB_CHAR_MAX; + int insize = wbufsize; + HRESULT hr; + + hr = ConvertINetUnicodeToMultiByte(&cv->mode, cv->codepage, + (const wchar_t *)wbuf, &wbufsize, tmpbuf, &tmpsize); + if (hr != S_OK || insize != wbufsize) + return seterror(EILSEQ); + else if (bufsize < tmpsize) + return seterror(E2BIG); + else if (cv->mblen(cv, (uchar *)tmpbuf, tmpsize) != tmpsize) + return seterror(EILSEQ); + memcpy(buf, tmpbuf, tmpsize); + return tmpsize; +} +#endif /*USE_MLANG_DLL*/ + +static int +utf16_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize) +{ + int codepage = cv->codepage; + + /* swap endian: 1200 <-> 1201 */ + if (cv->mode & UNICODE_MODE_SWAPPED) + codepage ^= 1; + + if (bufsize < 2) + return seterror(EINVAL); + if (codepage == 1200) /* little endian */ + wbuf[0] = (buf[1] << 8) | buf[0]; + else if (codepage == 1201) /* big endian */ + wbuf[0] = (buf[0] << 8) | buf[1]; + + if ((cv->flags & FLAG_USE_BOM) && !(cv->mode & UNICODE_MODE_BOM_DONE)) + { + cv->mode |= UNICODE_MODE_BOM_DONE; + if (wbuf[0] == 0xFFFE) + { + cv->mode |= UNICODE_MODE_SWAPPED; + *wbufsize = 0; + return 2; + } + else if (wbuf[0] == 0xFEFF) + { + *wbufsize = 0; + return 2; + } + } + + if (0xDC00 <= wbuf[0] && wbuf[0] <= 0xDFFF) + return seterror(EILSEQ); + if (0xD800 <= wbuf[0] && wbuf[0] <= 0xDBFF) + { + if (bufsize < 4) + return seterror(EINVAL); + if (codepage == 1200) /* little endian */ + wbuf[1] = (buf[3] << 8) | buf[2]; + else if (codepage == 1201) /* big endian */ + wbuf[1] = (buf[2] << 8) | buf[3]; + if (!(0xDC00 <= wbuf[1] && wbuf[1] <= 0xDFFF)) + return seterror(EILSEQ); + *wbufsize = 2; + return 4; + } + *wbufsize = 1; + return 2; +} + +static int +utf16_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize) +{ + if ((cv->flags & FLAG_USE_BOM) && !(cv->mode & UNICODE_MODE_BOM_DONE)) + { + int r; + + cv->mode |= UNICODE_MODE_BOM_DONE; + if (bufsize < 2) + return seterror(E2BIG); + if (cv->codepage == 1200) /* little endian */ + memcpy(buf, "\xFF\xFE", 2); + else if (cv->codepage == 1201) /* big endian */ + memcpy(buf, "\xFE\xFF", 2); + + r = utf16_wctomb(cv, wbuf, wbufsize, buf + 2, bufsize - 2); + if (r == -1) + return -1; + return r + 2; + } + + if (bufsize < 2) + return seterror(E2BIG); + if (cv->codepage == 1200) /* little endian */ + { + buf[0] = (wbuf[0] & 0x00FF); + buf[1] = (wbuf[0] & 0xFF00) >> 8; + } + else if (cv->codepage == 1201) /* big endian */ + { + buf[0] = (wbuf[0] & 0xFF00) >> 8; + buf[1] = (wbuf[0] & 0x00FF); + } + if (0xD800 <= wbuf[0] && wbuf[0] <= 0xDBFF) + { + if (bufsize < 4) + return seterror(E2BIG); + if (cv->codepage == 1200) /* little endian */ + { + buf[2] = (wbuf[1] & 0x00FF); + buf[3] = (wbuf[1] & 0xFF00) >> 8; + } + else if (cv->codepage == 1201) /* big endian */ + { + buf[2] = (wbuf[1] & 0xFF00) >> 8; + buf[3] = (wbuf[1] & 0x00FF); + } + return 4; + } + return 2; +} + +static int +utf32_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize) +{ + int codepage = cv->codepage; + uint wc = 0xD800; + + /* swap endian: 12000 <-> 12001 */ + if (cv->mode & UNICODE_MODE_SWAPPED) + codepage ^= 1; + + if (bufsize < 4) + return seterror(EINVAL); + if (codepage == 12000) /* little endian */ + wc = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + else if (codepage == 12001) /* big endian */ + wc = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; + + if ((cv->flags & FLAG_USE_BOM) && !(cv->mode & UNICODE_MODE_BOM_DONE)) + { + cv->mode |= UNICODE_MODE_BOM_DONE; + if (wc == 0xFFFE0000) + { + cv->mode |= UNICODE_MODE_SWAPPED; + *wbufsize = 0; + return 4; + } + else if (wc == 0x0000FEFF) + { + *wbufsize = 0; + return 4; + } + } + + if ((0xD800 <= wc && wc <= 0xDFFF) || 0x10FFFF < wc) + return seterror(EILSEQ); + ucs4_to_utf16(wc, wbuf, wbufsize); + return 4; +} + +static int +utf32_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize) +{ + uint wc; + + if ((cv->flags & FLAG_USE_BOM) && !(cv->mode & UNICODE_MODE_BOM_DONE)) + { + int r; + + cv->mode |= UNICODE_MODE_BOM_DONE; + if (bufsize < 4) + return seterror(E2BIG); + if (cv->codepage == 12000) /* little endian */ + memcpy(buf, "\xFF\xFE\x00\x00", 4); + else if (cv->codepage == 12001) /* big endian */ + memcpy(buf, "\x00\x00\xFE\xFF", 4); + + r = utf32_wctomb(cv, wbuf, wbufsize, buf + 4, bufsize - 4); + if (r == -1) + return -1; + return r + 4; + } + + if (bufsize < 4) + return seterror(E2BIG); + wc = utf16_to_ucs4(wbuf); + if (cv->codepage == 12000) /* little endian */ + { + buf[0] = wc & 0x000000FF; + buf[1] = (wc & 0x0000FF00) >> 8; + buf[2] = (wc & 0x00FF0000) >> 16; + buf[3] = (wc & 0xFF000000) >> 24; + } + else if (cv->codepage == 12001) /* big endian */ + { + buf[0] = (wc & 0xFF000000) >> 24; + buf[1] = (wc & 0x00FF0000) >> 16; + buf[2] = (wc & 0x0000FF00) >> 8; + buf[3] = wc & 0x000000FF; + } + return 4; +} + +/* + * 50220: ISO 2022 Japanese with no halfwidth Katakana; Japanese (JIS) + * 50221: ISO 2022 Japanese with halfwidth Katakana; Japanese (JIS-Allow + * 1 byte Kana) + * 50222: ISO 2022 Japanese JIS X 0201-1989; Japanese (JIS-Allow 1 byte + * Kana - SO/SI) + * + * MultiByteToWideChar() and WideCharToMultiByte() behave differently + * depending on Windows version. On XP, WideCharToMultiByte() doesn't + * terminate result sequence with ascii escape. But Vista does. + * Use MLang instead. + */ + +#define ISO2022_MODE(cs, shift) (((cs) << 8) | (shift)) +#define ISO2022_MODE_CS(mode) (((mode) >> 8) & 0xFF) +#define ISO2022_MODE_SHIFT(mode) ((mode) & 0xFF) + +#define ISO2022_SI 0 +#define ISO2022_SO 1 + +#if USE_MLANG_DLL +/* shift in */ +static const char iso2022_SI_seq[] = "\x0F"; +/* shift out */ +static const char iso2022_SO_seq[] = "\x0E"; + +typedef struct iso2022_esc_t iso2022_esc_t; +struct iso2022_esc_t { + const char *esc; + int esc_len; + int len; + int cs; +}; +#endif + +#define ISO2022JP_CS_ASCII 0 +#define ISO2022JP_CS_JISX0201_ROMAN 1 +#define ISO2022JP_CS_JISX0201_KANA 2 +#define ISO2022JP_CS_JISX0208_1978 3 +#define ISO2022JP_CS_JISX0208_1983 4 +#define ISO2022JP_CS_JISX0212 5 + +#if USE_MLANG_DLL +static iso2022_esc_t iso2022jp_esc[] = { + {"\x1B\x28\x42", 3, 1, ISO2022JP_CS_ASCII}, + {"\x1B\x28\x4A", 3, 1, ISO2022JP_CS_JISX0201_ROMAN}, + {"\x1B\x28\x49", 3, 1, ISO2022JP_CS_JISX0201_KANA}, + {"\x1B\x24\x40", 3, 2, ISO2022JP_CS_JISX0208_1983}, /* unify 1978 with 1983 */ + {"\x1B\x24\x42", 3, 2, ISO2022JP_CS_JISX0208_1983}, + {"\x1B\x24\x28\x44", 4, 2, ISO2022JP_CS_JISX0212}, + {NULL, 0, 0, 0} +}; +#endif /*USE_MLANG_DLL*/ + +#if USE_MLANG_DLL +static int +iso2022jp_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, + ushort *wbuf, int *wbufsize) +{ + iso2022_esc_t *iesc = iso2022jp_esc; + char tmp[MB_CHAR_MAX]; + int insize; + HRESULT hr; + DWORD dummy = 0; + int len; + int esc_len; + int cs; + int shift; + int i; + + if (buf[0] == 0x1B) + { + for (i = 0; iesc[i].esc != NULL; ++i) + { + esc_len = iesc[i].esc_len; + if (bufsize < esc_len) + { + if (strncmp((char *)buf, iesc[i].esc, bufsize) == 0) + return seterror(EINVAL); + } + else + { + if (strncmp((char *)buf, iesc[i].esc, esc_len) == 0) + { + cv->mode = ISO2022_MODE(iesc[i].cs, ISO2022_SI); + *wbufsize = 0; + return esc_len; + } + } + } + /* not supported escape sequence */ + return seterror(EILSEQ); + } + else if (buf[0] == iso2022_SO_seq[0]) + { + cv->mode = ISO2022_MODE(ISO2022_MODE_CS(cv->mode), ISO2022_SO); + *wbufsize = 0; + return 1; + } + else if (buf[0] == iso2022_SI_seq[0]) + { + cv->mode = ISO2022_MODE(ISO2022_MODE_CS(cv->mode), ISO2022_SI); + *wbufsize = 0; + return 1; + } + + cs = ISO2022_MODE_CS(cv->mode); + shift = ISO2022_MODE_SHIFT(cv->mode); + + /* reset the mode for informal sequence */ + if (buf[0] < 0x20) + { + cs = ISO2022JP_CS_ASCII; + shift = ISO2022_SI; + } + + len = iesc[cs].len; + if (bufsize < len) + return seterror(EINVAL); + for (i = 0; i < len; ++i) + if (!(buf[i] < 0x80)) + return seterror(EILSEQ); + esc_len = iesc[cs].esc_len; + memcpy(tmp, iesc[cs].esc, esc_len); + if (shift == ISO2022_SO) + { + memcpy(tmp + esc_len, iso2022_SO_seq, 1); + esc_len += 1; + } + memcpy(tmp + esc_len, buf, len); + + if ((cv->codepage == 50220 || cv->codepage == 50221 + || cv->codepage == 50222) && shift == ISO2022_SO) + { + /* XXX: shift-out cannot be used for mbtowc (both kernel and + * mlang) */ + esc_len = iesc[ISO2022JP_CS_JISX0201_KANA].esc_len; + memcpy(tmp, iesc[ISO2022JP_CS_JISX0201_KANA].esc, esc_len); + memcpy(tmp + esc_len, buf, len); + } + + insize = len + esc_len; + hr = ConvertINetMultiByteToUnicode(&dummy, cv->codepage, + (const char *)tmp, &insize, (wchar_t *)wbuf, wbufsize); + if (hr != S_OK || insize != len + esc_len) + return seterror(EILSEQ); + + /* Check for conversion error. Assuming defaultChar is 0x3F. */ + /* ascii should be converted from ascii */ + if (wbuf[0] == buf[0] + && cv->mode != ISO2022_MODE(ISO2022JP_CS_ASCII, ISO2022_SI)) + return seterror(EILSEQ); + + /* reset the mode for informal sequence */ + if (cv->mode != ISO2022_MODE(cs, shift)) + cv->mode = ISO2022_MODE(cs, shift); + + return len; +} +#endif /*USE_MLANG_DLL*/ + + +#if USE_MLANG_DLL +static int +iso2022jp_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize) +{ + iso2022_esc_t *iesc = iso2022jp_esc; + char tmp[MB_CHAR_MAX]; + int tmpsize = MB_CHAR_MAX; + int insize = wbufsize; + HRESULT hr; + DWORD dummy = 0; + int len; + int esc_len; + int cs; + int shift; + int i; + + /* + * MultiByte = [escape sequence] + character + [escape sequence] + * + * Whether trailing escape sequence is added depends on which API is + * used (kernel or MLang, and its version). + */ + hr = ConvertINetUnicodeToMultiByte(&dummy, cv->codepage, + (const wchar_t *)wbuf, &wbufsize, tmp, &tmpsize); + if (hr != S_OK || insize != wbufsize) + return seterror(EILSEQ); + else if (bufsize < tmpsize) + return seterror(E2BIG); + + if (tmpsize == 1) + { + cs = ISO2022JP_CS_ASCII; + esc_len = 0; + } + else + { + for (i = 1; iesc[i].esc != NULL; ++i) + { + esc_len = iesc[i].esc_len; + if (strncmp(tmp, iesc[i].esc, esc_len) == 0) + { + cs = iesc[i].cs; + break; + } + } + if (iesc[i].esc == NULL) + /* not supported escape sequence */ + return seterror(EILSEQ); + } + + shift = ISO2022_SI; + if (tmp[esc_len] == iso2022_SO_seq[0]) + { + shift = ISO2022_SO; + esc_len += 1; + } + + len = iesc[cs].len; + + /* Check for converting error. Assuming defaultChar is 0x3F. */ + /* ascii should be converted from ascii */ + if (cs == ISO2022JP_CS_ASCII && !(wbuf[0] < 0x80)) + return seterror(EILSEQ); + else if (tmpsize < esc_len + len) + return seterror(EILSEQ); + + if (cv->mode == ISO2022_MODE(cs, shift)) + { + /* remove escape sequence */ + if (esc_len != 0) + memmove(tmp, tmp + esc_len, len); + esc_len = 0; + } + else + { + if (cs == ISO2022JP_CS_ASCII) + { + esc_len = iesc[ISO2022JP_CS_ASCII].esc_len; + memmove(tmp + esc_len, tmp, len); + memcpy(tmp, iesc[ISO2022JP_CS_ASCII].esc, esc_len); + } + if (ISO2022_MODE_SHIFT(cv->mode) == ISO2022_SO) + { + /* shift-in before changing to other mode */ + memmove(tmp + 1, tmp, len + esc_len); + memcpy(tmp, iso2022_SI_seq, 1); + esc_len += 1; + } + } + + if (bufsize < len + esc_len) + return seterror(E2BIG); + memcpy(buf, tmp, len + esc_len); + cv->mode = ISO2022_MODE(cs, shift); + return len + esc_len; +} +#endif /*USE_MLANG_DLL*/ + +#if USE_MLANG_DLL +static int +iso2022jp_flush(csconv_t *cv, uchar *buf, int bufsize) +{ + iso2022_esc_t *iesc = iso2022jp_esc; + int esc_len; + + if (cv->mode != ISO2022_MODE(ISO2022JP_CS_ASCII, ISO2022_SI)) + { + esc_len = 0; + if (ISO2022_MODE_SHIFT(cv->mode) != ISO2022_SI) + esc_len += 1; + if (ISO2022_MODE_CS(cv->mode) != ISO2022JP_CS_ASCII) + esc_len += iesc[ISO2022JP_CS_ASCII].esc_len; + if (bufsize < esc_len) + return seterror(E2BIG); + + esc_len = 0; + if (ISO2022_MODE_SHIFT(cv->mode) != ISO2022_SI) + { + memcpy(buf, iso2022_SI_seq, 1); + esc_len += 1; + } + if (ISO2022_MODE_CS(cv->mode) != ISO2022JP_CS_ASCII) + { + memcpy(buf + esc_len, iesc[ISO2022JP_CS_ASCII].esc, + iesc[ISO2022JP_CS_ASCII].esc_len); + esc_len += iesc[ISO2022JP_CS_ASCII].esc_len; + } + return esc_len; + } + return 0; +} +#endif /*USE_MLANG_DLL*/ + + +gpgrt_w32_iconv_t +gpgrt_w32_iconv_open (const char *tocode, const char *fromcode) +{ + gpgrt_w32_iconv_t cd; + + cd = calloc(1, sizeof *cd); + if (!cd) + return (gpgrt_w32_iconv_t)(-1); + + /* reset the errno to prevent reporting wrong error code. + * 0 for unsorted error. */ + _gpg_err_set_errno (0); + if (win_iconv_open(cd, tocode, fromcode)) + return cd; + + free(cd); + + return (gpgrt_w32_iconv_t)(-1); +} + +int +gpgrt_w32_iconv_close (gpgrt_w32_iconv_t cd) +{ + if (cd) + { + free (cd); + } + + return 0; +} + +size_t +gpgrt_w32_iconv (gpgrt_w32_iconv_t cd, + const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + size_t r; + + r = win_iconv (cd, inbuf, inbytesleft, outbuf, outbytesleft); + _gpg_err_set_errno (*(cd->_errno())); + return r; +} diff --git a/comm/third_party/libgpg-error/src/w32-lock-obj.h b/comm/third_party/libgpg-error/src/w32-lock-obj.h new file mode 100644 index 0000000000..8ed3084054 --- /dev/null +++ b/comm/third_party/libgpg-error/src/w32-lock-obj.h @@ -0,0 +1,38 @@ +/* w32-lock-obj.h - Declaration of the Windows lock object + Copyright (C) 2014 g10 Code GmbH + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef W32_LOCK_OBJ_H +#define W32_LOCK_OBJ_H + +#define LOCK_ABI_VERSION 1 + +/* The real definition of our lock object. The public definition is + named gpgrt_lock_t and hides this internal structure. */ +#pragma pack(push, 8) +typedef struct +{ + long vers; + volatile long initdone; + volatile long started; + CRITICAL_SECTION csec; +} _gpgrt_lock_t; +#pragma pack(pop) + + +#endif /*W32_LOCK_OBJ_H*/ diff --git a/comm/third_party/libgpg-error/src/w32-lock.c b/comm/third_party/libgpg-error/src/w32-lock.c new file mode 100644 index 0000000000..feed1e6338 --- /dev/null +++ b/comm/third_party/libgpg-error/src/w32-lock.c @@ -0,0 +1,161 @@ +/* w32-lock.c - GPGRT lock functions for Windows + Copyright (C) 2014 g10 Code GmbH + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, see <https://www.gnu.org/licenses/>. + */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#ifndef HAVE_W32_SYSTEM +# error This module may only be build for Windows. +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#include "gpgrt-int.h" +#include "lock.h" +#include "w32-lock-obj.h" + + + +static _gpgrt_lock_t * +get_lock_object (gpgrt_lock_t *lockhd) +{ + _gpgrt_lock_t *lock = (_gpgrt_lock_t*)lockhd; + + if (lock->vers != LOCK_ABI_VERSION) + _gpgrt_abort (); + + return lock; +} + + +gpg_err_code_t +_gpgrt_lock_init (gpgrt_lock_t *lockhd) +{ + _gpgrt_lock_t *lock = (_gpgrt_lock_t*)lockhd; + + /* If VERS is zero we assume that no static initialization has been + done, so we setup our ABI version right here. The caller might + have called us to test whether lock support is at all available. */ + if (!lock->vers) + { + if (sizeof (gpgrt_lock_t) < sizeof (_gpgrt_lock_t)) + _gpgrt_abort (); + lock->vers = LOCK_ABI_VERSION; + } + else /* Run the usual check. */ + { + lock = get_lock_object (lockhd); + if (sizeof (gpgrt_lock_t) < sizeof (_gpgrt_lock_t)) + _gpgrt_abort (); + } + + InitializeCriticalSection (&lock->csec); + lock->initdone = 1; + return 0; +} + + +gpg_err_code_t +_gpgrt_lock_lock (gpgrt_lock_t *lockhd) +{ + _gpgrt_lock_t *lock = get_lock_object (lockhd); + + if (!lock->initdone) + { + if (!InterlockedIncrement (&lock->started)) + { + /* The new value of started is 0. Because the initial value + if the variable was -1 we known that this thread is the + first who needs this lock. Thus we initialize now. All + other threads won't get 0 back from InterlockedIncrement + and thus fall into the wait loop below. We ignore that + STARTED may in theory overflow if this thread starves for + too long. */ + _gpgrt_lock_init (lockhd); + } + else + { + while (!lock->initdone) + Sleep (0); + } + } + + _gpgrt_pre_syscall (); + EnterCriticalSection (&lock->csec); + _gpgrt_post_syscall (); + return 0; +} + + +gpg_err_code_t +_gpgrt_lock_trylock (gpgrt_lock_t *lockhd) +{ + _gpgrt_lock_t *lock = get_lock_object (lockhd); + + if (!lock->initdone) + { + if (!InterlockedIncrement (&lock->started)) + { + _gpgrt_lock_init (lockhd); + } + else + { + while (!lock->initdone) + Sleep (0); + } + } + + if (!TryEnterCriticalSection (&lock->csec)) + return GPG_ERR_EBUSY; + return 0; +} + + +gpg_err_code_t +_gpgrt_lock_unlock (gpgrt_lock_t *lockhd) +{ + _gpgrt_lock_t *lock = get_lock_object (lockhd); + + if (!lock->initdone) + return GPG_ERR_INV_LOCK_OBJ; + LeaveCriticalSection (&lock->csec); + return 0; +} + + +/* Note: Use this function only if no other thread holds or waits for + this lock. */ +gpg_err_code_t +_gpgrt_lock_destroy (gpgrt_lock_t *lockhd) +{ + _gpgrt_lock_t *lock = get_lock_object (lockhd); + + if (!lock->initdone) + return GPG_ERR_INV_LOCK_OBJ; + DeleteCriticalSection (&lock->csec); + lock->initdone = 0; + lock->started = -1; + return 0; +} diff --git a/comm/third_party/libgpg-error/src/w32-reg.c b/comm/third_party/libgpg-error/src/w32-reg.c new file mode 100644 index 0000000000..8b1bf8a6aa --- /dev/null +++ b/comm/third_party/libgpg-error/src/w32-reg.c @@ -0,0 +1,154 @@ +/* w32-reg.c - Windows registry support + * Copyright (C) 2002, 2005, 2010, 2012, 2017 g10 Code GmbH + * + * This file is part of Libgpg-error. + * + * Libgpg-error is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgpg-error is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <https://www.gnu.org/licenses/>. + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#ifndef HAVE_W32_SYSTEM +# error This module may only be build for Windows. +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <gpg-error.h> +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#include "gpgrt-int.h" + + +/* Return a string from the W32 Registry or NULL in case of error. + * Caller must release the return value. A NULL for root is an alias + * for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn. The returned + * string is UTF-8 encoded; ROOT, DIR, and NAME must be plain + * ASCII. */ +char * +_gpgrt_w32_reg_query_string (const char *root, const char *dir, + const char *name) +{ + HKEY root_key, key_handle; + DWORD n1, nbytes, type; + char *result = NULL; + + if (!root) + root_key = HKEY_CURRENT_USER; + else if (!strcmp( root, "HKEY_CLASSES_ROOT")) + root_key = HKEY_CLASSES_ROOT; + else if (!strcmp( root, "HKEY_CURRENT_USER")) + root_key = HKEY_CURRENT_USER; + else if (!strcmp( root, "HKEY_LOCAL_MACHINE")) + root_key = HKEY_LOCAL_MACHINE; + else if (!strcmp( root, "HKEY_USERS")) + root_key = HKEY_USERS; + else if (!strcmp( root, "HKEY_PERFORMANCE_DATA")) + root_key = HKEY_PERFORMANCE_DATA; + else if (!strcmp( root, "HKEY_CURRENT_CONFIG")) + root_key = HKEY_CURRENT_CONFIG; + else + return NULL; + + if (RegOpenKeyExA (root_key, dir, 0, KEY_READ, &key_handle)) + { + if (root) + return NULL; /* No need for a RegClose, so return direct. */ + /* It seems to be common practise to fall back to HKLM. */ + if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle)) + return NULL; /* still no need for a RegClose, so return direct */ + } + + + /* FIXME: Use wide functions and convert to utf-8. */ + nbytes = 1; + if (RegQueryValueExA (key_handle, name, 0, NULL, NULL, &nbytes)) + { + if (root) + goto leave; + /* Try to fallback to HKLM also for a missing value. */ + RegCloseKey (key_handle); + if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle)) + return NULL; /* Nope. */ + if (RegQueryValueExA (key_handle, name, 0, NULL, NULL, &nbytes)) + goto leave; + } + n1 = nbytes + 1; + result = xtrymalloc (n1); + if (!result) + goto leave; + if (RegQueryValueExA (key_handle, name, 0, &type, (LPBYTE) result, &n1)) + { + xfree (result); + result = NULL; + goto leave; + } + result[nbytes] = 0; /* Make sure it is really a string. */ + +#ifndef HAVE_W32CE_SYSTEM /* (Windows CE has no environment.) */ + if (type == REG_EXPAND_SZ && strchr (result, '%')) + { + char *tmp; + + n1 += 1000; + tmp = xtrymalloc (n1 + 1); + if (!tmp) + goto leave; + nbytes = ExpandEnvironmentStrings (result, tmp, n1); + if (nbytes && nbytes > n1) + { + xfree (tmp); + n1 = nbytes; + tmp = xtrymalloc (n1 + 1); + if (!tmp) + goto leave; + nbytes = ExpandEnvironmentStrings (result, tmp, n1); + if (nbytes && nbytes > n1) { + xfree (tmp); /* Oops - truncated, better don't expand at all. */ + goto leave; + } + tmp[nbytes] = 0; + xfree (result); + result = tmp; + } + else if (nbytes) /* Okay, reduce the length. */ + { + tmp[nbytes] = 0; + xfree (result); + result = xtrymalloc (strlen (tmp)+1); + if (!result) + result = tmp; + else + { + strcpy (result, tmp); + xfree (tmp); + } + } + else /* Error - don't expand. */ + { + xfree (tmp); + } + } +#endif + + leave: + RegCloseKey (key_handle); + return result; +} diff --git a/comm/third_party/libgpg-error/src/w32-thread.c b/comm/third_party/libgpg-error/src/w32-thread.c new file mode 100644 index 0000000000..c389635493 --- /dev/null +++ b/comm/third_party/libgpg-error/src/w32-thread.c @@ -0,0 +1,46 @@ +/* w32-thread.c - GPGRT thread functions for Windows + Copyright (C) 2014 g10 Code GmbH + + This file is part of libgpg-error. + + libgpg-error is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + libgpg-error is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, see <https://www.gnu.org/licenses/>. + */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#ifndef HAVE_W32_SYSTEM +# error This module may only be build for Windows. +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#include "gpgrt-int.h" +#include "thread.h" + + +gpg_err_code_t +_gpgrt_yield (void) +{ + _gpgrt_pre_syscall (); + Sleep (0); + _gpgrt_post_syscall (); + return 0; +} diff --git a/comm/third_party/libgpg-error/src/w32ce-add.h b/comm/third_party/libgpg-error/src/w32ce-add.h new file mode 100644 index 0000000000..c6207bb2bb --- /dev/null +++ b/comm/third_party/libgpg-error/src/w32ce-add.h @@ -0,0 +1,8 @@ +## w32ce-add.h - Snippet to be be included into gpg-error.h. +## (Comments are indicated by a double hash mark) + +/* Substitute for strerror - this one is thread safe. */ +char *_gpg_w32ce_strerror (int err); +#ifdef GPG_ERR_ENABLE_ERRNO_MACROS +# define strerror(a) _gpg_w32ce_strerror (a) +#endif |