Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F18825823
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
213 KB
Subscribers
None
View Options
diff --git a/configure.ac b/configure.ac
index 5c3e47a..1779f7e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,756 +1,759 @@
# configure.ac for libgpg-error
# Copyright (C) 2003, 2004, 2006, 2010, 2013-2022 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 General Public License
# along with this program; if not, see <https://www.gnu.org/licenses/>.
# SPDX-License-Identifier: LGPL-2.1+
# (Process this file with autoconf to produce a configure script.)
# The following lines are used by ./autogen.sh.
AC_PREREQ([2.69])
min_automake_version="1.14"
# To build a release you need to create a tag with the version number
# (git tag -s libgpg-error-n.m) and run "./autogen.sh --force".
# Please bump the version number immediately after the release, do
# another commit, and a push so that the git magic is able to work.
# See below for the LT versions.
m4_define([mym4_package],[libgpg-error])
m4_define([mym4_major], [1])
m4_define([mym4_minor], [47])
# Below is m4 magic to extract and compute the revision number, the
# decimalized short revision number, a beta version string, and a flag
# indicating a development version (mym4_isgit). Note that the m4
# processing is done by autoconf and not during the configure run.
m4_define([mym4_verslist], m4_split(m4_esyscmd([./autogen.sh --find-version] \
mym4_package mym4_major mym4_minor),[:]))
m4_define([mym4_isbeta], m4_argn(2, mym4_verslist))
m4_define([mym4_version], m4_argn(4, mym4_verslist))
m4_define([mym4_revision], m4_argn(7, mym4_verslist))
m4_define([mym4_revision_dec], m4_argn(8, mym4_verslist))
m4_esyscmd([echo ]mym4_version[>VERSION])
AC_INIT([mym4_package],[mym4_version],[https://bugs.gnupg.org])
# LT Version numbers, remember to change them just *before* a release.
# (Code changed: REVISION++)
# (Interfaces added/removed/changed: CURRENT++, REVISION=0)
# (Interfaces added: AGE++)
# (Interfaces removed: AGE=0)
# Note that added error codes don't constitute an interface change.
LIBGPG_ERROR_LT_CURRENT=33
LIBGPG_ERROR_LT_AGE=33
LIBGPG_ERROR_LT_REVISION=1
################################################
AC_SUBST(LIBGPG_ERROR_LT_CURRENT)
AC_SUBST(LIBGPG_ERROR_LT_AGE)
AC_SUBST(LIBGPG_ERROR_LT_REVISION)
VERSION_NUMBER=m4_esyscmd(printf "0x%02x%02x00" mym4_major mym4_minor)
AC_SUBST(VERSION_NUMBER)
AC_CONFIG_AUX_DIR([build-aux])
AM_INIT_AUTOMAKE([serial-tests dist-bzip2])
AM_MAINTAINER_MODE
AC_CONFIG_SRCDIR([src/err-sources.h.in])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
AM_SILENT_RULES
# We need to know about the host architecture to avoid spurious
# warnings.
AC_CANONICAL_HOST
AB_INIT
# Checks for programs.
AC_PROG_CC
AM_PROG_CC_C_O
AC_PROG_CPP
AC_PROG_AWK
AC_CHECK_TOOL(AR, ar, :)
AC_USE_SYSTEM_EXTENSIONS
AM_LANGINFO_CODESET
# Taken from mpfr-4.0.1, then modified for LDADD_FOR_TESTS_KLUDGE
dnl Under Linux, make sure that the old dtags are used if LD_LIBRARY_PATH
dnl is defined. The issue is that with the new dtags, LD_LIBRARY_PATH has
dnl the precedence over the run path, so that if a compatible MPFR library
dnl is installed in some directory from $LD_LIBRARY_PATH, then the tested
dnl MPFR library will be this library instead of the MPFR library from the
dnl build tree. Other OS with the same issue might be added later.
dnl
dnl References:
dnl https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=859732
dnl http://lists.gnu.org/archive/html/libtool/2017-05/msg00000.html
dnl
dnl We need to check whether --disable-new-dtags is supported as alternate
dnl linkers may be used (e.g., with tcc: CC=tcc LD=tcc).
dnl
case $host in
*-*-linux*)
if test -n "$LD_LIBRARY_PATH"; then
saved_LDFLAGS="$LDFLAGS"
LDADD_FOR_TESTS_KLUDGE="-Wl,--disable-new-dtags"
LDFLAGS="$LDFLAGS $LDADD_FOR_TESTS_KLUDGE"
AC_MSG_CHECKING(whether --disable-new-dtags is supported by the linker)
AC_LINK_IFELSE([AC_LANG_SOURCE([[
int main (void) { return 0; }
]])],
[AC_MSG_RESULT(yes (use it since LD_LIBRARY_PATH is set))],
[AC_MSG_RESULT(no)
LDADD_FOR_TESTS_KLUDGE=""
])
LDFLAGS="$saved_LDFLAGS"
fi
;;
esac
AC_SUBST([LDADD_FOR_TESTS_KLUDGE])
# Set some variables depending on the platform for later use.
have_w32_system=no
have_w64_system=no
case "${host}" in
x86_64-*mingw32*)
have_w32_system=yes
have_w64_system=yes
;;
*-mingw32*)
have_w32_system=yes
;;
*-apple-darwin*)
# This is the equivalent of the _GNU_SOURCE feature-test-macro
# on GNU libc systems.
AC_DEFINE(_DARWIN_C_SOURCE, 1,
Expose all libc features (__DARWIN_C_FULL).)
;;
*)
;;
esac
if test "$have_w32_system" != yes; then
gl_THREADLIB_EARLY
fi
# We build libgpg-error with large file support so that we have a 64
# bit off_t. Our external interface uses the gpgrt_off_t which is
# anyway specified as 64 bit. Thus the same libgpg-error can be used
# by software which is not build with large file support.
AC_SYS_LARGEFILE
LT_PREREQ([2.2.6])
LT_INIT([win32-dll disable-static])
LT_LANG([Windows Resource])
# We need to compile and run a program on the build machine.
AX_CC_FOR_BUILD
AH_BOTTOM([
/* Force using of NLS for W32 even if no libintl has been found. This is
okay because we have our own gettext implementation for W32. */
#if defined(HAVE_W32_SYSTEM) && !defined(ENABLE_NLS)
#define ENABLE_NLS 1
#endif
/* Connect the generic estream-printf.c to our framework. */
#define _ESTREAM_PRINTF_REALLOC _gpgrt_realloc
#define _ESTREAM_PRINTF_EXTRA_INCLUDE "gpgrt-int.h"
/* For building we need to define these macro. */
#define GPG_ERR_ENABLE_GETTEXT_MACROS 1
#define GPG_ERR_ENABLE_ERRNO_MACROS 1
#define GPGRT_ENABLE_ES_MACROS 1
#define GPGRT_ENABLE_LOG_MACROS 1
#define GPGRT_ENABLE_ARGPARSE_MACROS 1
])
# We used to provide gpg-error-config command always. Now, it's
# gpgrt-config command with gpg-error.pc configuration file, which
# does same thing. gpg-error-config command is deprecated.
AC_ARG_ENABLE(install-gpg-error-config,
AS_HELP_STRING([--enable-install-gpg-error-config],
[install gpg-error-config command]),
install_gpg_error_config=$enableval)
AM_CONDITIONAL(INSTALL_GPG_ERROR_CONFIG,
test "$install_gpg_error_config" = "yes")
# Note, that autogen.sh greps for the next line.
AM_GNU_GETTEXT_VERSION([0.19.3])
AM_GNU_GETTEXT([external])
# Checks for header files.
AC_CHECK_HEADERS([locale.h stdint.h sys/select.h sys/time.h \
signal.h poll.h pwd.h])
AC_FUNC_STRERROR_R
case "${host_os}" in
mingw32*)
INSTALLSHELLPATH=/bin/sh
AC_CHECK_FUNC([strerror_s])
;;
solaris*)
INSTALLSHELLPATH=/usr/xpg4/bin/sh
# All versions of Solaris from 2.4 have a thread-safe strerror().
# Since Solaris 10, in addition strerror_r() exists.
;;
*)
INSTALLSHELLPATH=/bin/sh
AC_CHECK_FUNC([strerror_r], [],
AC_MSG_WARN([[Without strerror_r, gpg_strerror_r might not be thread-safe]]))
;;
esac
AC_SUBST(INSTALLSHELLPATH)
-AC_FUNC_FORK
+# We don't check 'fork' by configure script. Use of fork is inferred from by
+# the target system (POSIX or Windows).
+# AC_FUNC_FORK
+
AC_CHECK_FUNCS([flockfile vasprintf mmap rand strlwr stpcpy setenv stat \
getrlimit getpwnam getpwuid getpwnam_r getpwuid_r inet_pton])
#
# Checks for typedefs, structures, and compiler characteristics.
#
AC_C_CONST
AC_CHECK_SIZEOF(int)
AC_CHECK_SIZEOF(long)
AC_CHECK_SIZEOF(long long)
GNUPG_FUNC_MKDIR_TAKES_ONE_ARG
# Find a 64 bit integer type to be used instead of off_t. We prefer
# the standard integer types over int64_t and finally try long long.
if test "$ac_cv_sizeof_int" = "8"; then
replacement_for_off_t="int"
elif test "$ac_cv_sizeof_long" = "8"; then
replacement_for_off_t="long"
elif test "$ac_cv_header_stdint_h" = yes; then
replacement_for_off_t="int64_t"
elif test "$ac_cv_sizeof_long_long" = "8"; then
replacement_for_off_t="long long"
else
AC_MSG_ERROR([[
***
*** No 64 bit signed integer type found. Can't build this library.
***]])
fi
AC_DEFINE_UNQUOTED(REPLACEMENT_FOR_OFF_T, "$replacement_for_off_t",
[Used by mkheader to insert the replacement type.])
#
# Setup gcc specific options
#
AC_MSG_NOTICE([checking for cc features])
if test "$GCC" = yes; then
# Check whether gcc does not emit a diagnostic for unknown -Wno-*
# options. This is the case for gcc >= 4.6
AC_MSG_CHECKING([if gcc ignores unknown -Wno-* options])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6 )
#kickerror
#endif]],[])],[_gcc_silent_wno=yes],[_gcc_silent_wno=no])
AC_MSG_RESULT($_gcc_silent_wno)
# Note that it is okay to use CFLAGS here because these are just
# warning options and the user should have a chance of overriding
# them.
if test "$USE_MAINTAINER_MODE" = "yes"; then
M_CFLAGS="-O3 -Wall -Wcast-align -Wshadow -Wstrict-prototypes"
M_CFLAGS="$M_CFLAGS -Wformat -Wno-format-y2k -Wformat-security"
if test x"$_gcc_silent_wno" = xyes ; then
_gcc_wopt=yes
else
AC_MSG_CHECKING([if gcc supports -Wno-missing-field-initializers])
_gcc_cflags_save=$CFLAGS
CFLAGS="-Wno-missing-field-initializers"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],
[_gcc_wopt=yes],[_gcc_wopt=no])
AC_MSG_RESULT($_gcc_wopt)
CFLAGS=$_gcc_cflags_save;
fi
if test x"$_gcc_wopt" = xyes ; then
M_CFLAGS="$M_CFLAGS -W -Wno-sign-compare -Wno-missing-field-initializers"
fi
AC_MSG_CHECKING([if gcc supports -Wdeclaration-after-statement])
_gcc_cflags_save=$CFLAGS
CFLAGS="-Wdeclaration-after-statement"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],_gcc_wopt=yes,_gcc_wopt=no)
AC_MSG_RESULT($_gcc_wopt)
CFLAGS=$_gcc_cflags_save;
if test x"$_gcc_wopt" = xyes ; then
M_CFLAGS="$M_CFLAGS -Wdeclaration-after-statement"
fi
# Prepend the maintainer-cflags so that the user can override
# them, e.g. to override the optimization flags for debugging.
CFLAGS="$M_CFLAGS $CFLAGS"
else
CFLAGS="$CFLAGS -Wall"
fi
AC_MSG_CHECKING([if gcc supports -Wpointer-arith])
_gcc_cflags_save=$CFLAGS
CFLAGS="-Wpointer-arith"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],_gcc_psign=yes,_gcc_psign=no)
AC_MSG_RESULT($_gcc_psign)
CFLAGS=$_gcc_cflags_save;
if test x"$_gcc_psign" = xyes ; then
CFLAGS="$CFLAGS -Wpointer-arith"
fi
# The undocumented option -Wno-psabi suppresses the annoying
# "the ABI of passing union with long double has changed in GCC 4.4"
# which is emitted in estream-printf.c but entirely irrelvant
# because that union is local to the file.
if test x"$_gcc_silent_wno" = xyes ; then
CFLAGS="$CFLAGS -Wno-psabi"
fi
fi
#
# Check whether the compiler supports the GCC style aligned attribute
#
AC_CACHE_CHECK([whether the GCC style aligned attribute is supported],
[gcry_cv_gcc_attribute_aligned],
[gcry_cv_gcc_attribute_aligned=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[struct { int a; } foo __attribute__ ((aligned (16)));]])],
[gcry_cv_gcc_attribute_aligned=yes])])
if test "$gcry_cv_gcc_attribute_aligned" = "yes" ; then
AC_DEFINE(HAVE_GCC_ATTRIBUTE_ALIGNED,1,
[Defined if a GCC style "__attribute__ ((aligned (n))" is supported])
fi
#
# Check for ELF visibility support.
#
AC_CACHE_CHECK(whether the visibility attribute is supported,
gcry_cv_visibility_attribute,
[gcry_cv_visibility_attribute=no
AC_LANG_CONFTEST([AC_LANG_SOURCE(
[[int foo __attribute__ ((visibility ("hidden"))) = 1;
int bar __attribute__ ((visibility ("protected"))) = 1;
]])])
if ${CC-cc} -Werror -S conftest.c -o conftest.s \
1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ; then
if grep '\.hidden.*foo' conftest.s >/dev/null 2>&1 ; then
if grep '\.protected.*bar' conftest.s >/dev/null 2>&1; then
gcry_cv_visibility_attribute=yes
fi
fi
fi
])
if test "$gcry_cv_visibility_attribute" = "yes"; then
AC_CACHE_CHECK(for broken visibility attribute,
gcry_cv_broken_visibility_attribute,
[gcry_cv_broken_visibility_attribute=yes
AC_LANG_CONFTEST([AC_LANG_SOURCE(
[[int foo (int x);
int bar (int x) __asm__ ("foo")
__attribute__ ((visibility ("hidden")));
int bar (int x) { return x; }
]])])
if ${CC-cc} -Werror -S conftest.c -o conftest.s \
1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ; then
if grep '\.hidden@<:@ _@:>@foo' conftest.s >/dev/null 2>&1;
then
gcry_cv_broken_visibility_attribute=no
fi
fi
])
fi
if test "$gcry_cv_visibility_attribute" = "yes"; then
AC_CACHE_CHECK(for broken alias attribute,
gcry_cv_broken_alias_attribute,
[gcry_cv_broken_alias_attribute=yes
AC_LANG_CONFTEST([AC_LANG_SOURCE(
[[extern int foo (int x) __asm ("xyzzy");
int bar (int x) { return x; }
extern __typeof (bar) foo __attribute ((weak, alias ("bar")));
extern int dfoo;
extern __typeof (dfoo) dfoo __asm ("abccb");
int dfoo = 1;
]])])
if ${CC-cc} -Werror -S conftest.c -o conftest.s \
1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ; then
if grep 'xyzzy' conftest.s >/dev/null 2>&1 && \
grep 'abccb' conftest.s >/dev/null 2>&1; then
gcry_cv_broken_alias_attribute=no
fi
fi
])
fi
if test "$gcry_cv_visibility_attribute" = "yes"; then
AC_CACHE_CHECK(if gcc supports -fvisibility=hidden,
gcry_cv_gcc_has_f_visibility,
[gcry_cv_gcc_has_f_visibility=no
_gcc_cflags_save=$CFLAGS
CFLAGS="-fvisibility=hidden"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],
gcry_cv_gcc_has_f_visibility=yes)
CFLAGS=$_gcc_cflags_save;
])
fi
if test "$gcry_cv_visibility_attribute" = "yes" \
&& test "$gcry_cv_broken_visibility_attribute" != "yes" \
&& test "$gcry_cv_broken_alias_attribute" != "yes" \
&& test "$gcry_cv_gcc_has_f_visibility" = "yes"
then
AC_DEFINE(GPGRT_USE_VISIBILITY, 1,
[Define to use the GNU C visibility attribute.])
CFLAGS="$CFLAGS -fvisibility=hidden"
fi
#
# Check whether ld supports a version script.
# (Actually not a check but a list of systems which are known to support it.)
#
have_ld_version_script=no
case "${host}" in
*-*-linux*)
have_ld_version_script=yes
;;
*-*-gnu*)
have_ld_version_script=yes
;;
esac
AC_ARG_ENABLE([ld-version-script],
AS_HELP_STRING([--enable-ld-version-script],
[enable/disable use of linker version script.
(default is system dependent)]),
[have_ld_version_script=$enableval],
[ : ] )
AM_CONDITIONAL(HAVE_LD_VERSION_SCRIPT, test "$have_ld_version_script" = "yes")
#
# Check for thread library.
#
# Windows has always thread support; thus we don't bother to test for
# it as it may lead to false results when cross building.
if test "$have_w32_system" = yes; then
GPG_ERROR_CONFIG_LIBS_PRIVATE=-lws2_32
AC_DEFINE([USE_WINDOWS_THREADS], [1])
LIBTHREAD=
LTLIBTHREAD=
LIBMULTITHREAD=
LTLIBMULTITHREAD=
THREADLIB_CPPFLAGS=""
AC_SUBST([LIBTHREAD])
AC_SUBST([LTLIBTHREAD])
AC_SUBST([LIBMULTITHREAD])
AC_SUBST([LTLIBMULTITHREAD])
else
GPG_ERROR_CONFIG_LIBS_PRIVATE=""
gl_LOCK
if test "$gl_threads_api" = posix; then
AC_CHECK_SIZEOF(pthread_mutex_t,,[AC_INCLUDES_DEFAULT
#include <pthread.h>])
AC_CHECK_HEADERS([sys/single_threaded.h])
fi
fi
# Default value for GPG_ERROR_CONFIG_LIBS
config_libs="-lgpg-error"
#
# Check for other libraries
#
LIB_SCHED_YIELD=
AC_SUBST([LIB_SCHED_YIELD])
AC_SEARCH_LIBS([sched_yield], [rt posix4],
[if test "$ac_cv_search_sched_yield" != "none required"; then
LIB_SCHED_YIELD=$ac_cv_search_sched_yield
config_libs="$config_libs $LIB_SCHED_YIELD"
fi])
LIB_NETWORK=
AC_SUBST([LIB_NETWORK])
AC_SEARCH_LIBS([inet_addr], [nsl],
[if test "$ac_cv_search_inet_addr" != "none required"; then
LIB_NETWORK=$ac_cv_search_inet_addr
fi])
AC_SEARCH_LIBS([socket], [socket],
[if test "$ac_cv_search_socket" != "none required"; then
LIB_NETWORK="$ac_cv_search_socket $LIB_NETWORK"
fi], [], [$LIB_NETWORK])
if test "x$LIB_NETWORK" != x; then
config_libs="$config_libs $LIB_NETWORK"
fi
# Check for optional readline support
GNUPG_CHECK_READLINE
#
# Prepare building of estream
#
estream_INIT
#
# Substitution used for gpg-error-config and gpg-error.pc
#
GPG_ERROR_CONFIG_LIBS="$config_libs"
if test "x$LIBTHREAD" != x; then
GPG_ERROR_CONFIG_LIBS="${GPG_ERROR_CONFIG_LIBS} ${LIBTHREAD}"
fi
if test "x$LIBMULTITHREAD" != x; then
GPG_ERROR_CONFIG_MT_LIBS="${LIBMULTITHREAD}"
else
GPG_ERROR_CONFIG_MT_LIBS=""
fi
GPG_ERROR_CONFIG_CFLAGS=""
if test "x$THREADLIB_CPPFLAGS" != x; then
GPG_ERROR_CONFIG_MT_CFLAGS="${THREADLIB_CPPFLAGS}"
else
GPG_ERROR_CONFIG_MT_CFLAGS=""
fi
GPG_ERROR_CONFIG_HOST="$host"
case "$includedir" in
/usr/include|/include) ;;
'${prefix}/include')
if test "$prefix" != / -a "$prefix" != /usr; then
if test -z "$GPG_ERROR_CONFIG_CFLAGS"; then
GPG_ERROR_CONFIG_CFLAGS="-I\${includedir}"
else
GPG_ERROR_CONFIG_CFLAGS="-I\${includedir} $GPG_ERROR_CONFIG_CFLAGS"
fi
fi
;;
*)
if test -z "$GPG_ERROR_CONFIG_CFLAGS"; then
GPG_ERROR_CONFIG_CFLAGS="-I\${includedir}"
else
GPG_ERROR_CONFIG_CFLAGS="-I\${includedir} $GPG_ERROR_CONFIG_CFLAGS"
fi
;;
esac
case "$libdir" in
/usr/lib|/usr/lib64|/lib|/lib64) ;;
'${exec_prefix}/lib'|'${exec_prefix}/lib64')
if test "$exec_prefix" = "NONE"; then
if test "$prefix" != / -a "$prefix" != /usr; then
GPG_ERROR_CONFIG_LIBS="-L\${libdir} $GPG_ERROR_CONFIG_LIBS"
fi
elif test "$exec_prefix" != / -a "$exec_prefix" != /usr; then
GPG_ERROR_CONFIG_LIBS="-L\${libdir} $GPG_ERROR_CONFIG_LIBS"
fi
;;
*) GPG_ERROR_CONFIG_LIBS="-L\${libdir} $GPG_ERROR_CONFIG_LIBS" ;;
esac
AC_SUBST(GPG_ERROR_CONFIG_LIBS)
AC_SUBST(GPG_ERROR_CONFIG_CFLAGS)
AC_SUBST(GPG_ERROR_CONFIG_MT_LIBS)
AC_SUBST(GPG_ERROR_CONFIG_MT_CFLAGS)
AC_SUBST(GPG_ERROR_CONFIG_LIBS_PRIVATE)
AC_SUBST(GPG_ERROR_CONFIG_HOST)
#
# Special defines for certain platforms
#
force_use_syscfg=no
if test "$have_w32_system" = yes; then
AC_DEFINE(HAVE_W32_SYSTEM,1,[Defined if we run on a W32 API based system])
if test "$have_w64_system" = yes; then
AC_DEFINE(HAVE_W64_SYSTEM,1,[Defined if we run on 64 bit W32 API system])
fi
force_use_syscfg=yes
fi
if test x"$gl_use_threads" = xno; then
lock_obj_h_generated=yes
if test ! -d src; then mkdir src; fi
host=$host $srcdir/src/gen-lock-obj.sh --disable-threads \
>src/lock-obj-pub.native.h
AC_MSG_NOTICE([generated src/lock-obj-pub.native.h for $host])
elif test x$cross_compiling = xyes; then
case $host in
*-*-linux-gnu* | *-*-linux-musl*)
AC_CHECK_TOOL(OBJDUMP, [objdump])
if test -n "$OBJDUMP"; then
lock_obj_h_generated=yes
if test ! -d src; then mkdir src; fi
LOCK_ABI_VERSION=1 host=$host host_alias=$host_alias \
CC=$CC OBJDUMP=$OBJDUMP \
ac_ext=$ac_ext ac_objext=$ac_objext \
AWK=$AWK $srcdir/src/gen-lock-obj.sh \
>src/lock-obj-pub.native.h
AC_MSG_NOTICE([generated src/lock-obj-pub.native.h using $host_alias-objdump and $AWK])
else
force_use_syscfg=yes
fi
;;
*)
force_use_syscfg=yes
;;
esac
fi
AM_CONDITIONAL(HAVE_W32_SYSTEM, test "$have_w32_system" = yes)
AM_CONDITIONAL(HAVE_W64_SYSTEM, test "$have_w64_system" = yes)
AM_CONDITIONAL(CROSS_COMPILING, test x$cross_compiling = xyes)
AM_CONDITIONAL(FORCE_USE_SYSCFG, test x$force_use_syscfg = xyes)
AM_CONDITIONAL(HAVE_GENERATED_LOCK_OBJ_H, test x$lock_obj_h_generated = xyes)
have_lock_optimization=no
if test "$gl_threads_api" = posix; then
if test x$ac_cv_header_sys_single_threaded_h = xyes; then
have_lock_optimization=yes
else
case "${host_os}" in
*-gnu*) have_lock_optimization=yes ;;
* ) ;;
esac
fi
fi
AM_CONDITIONAL(HAVE_LOCK_OPTIMIZATION, test "$have_lock_optimization" = yes)
AC_DEFINE_UNQUOTED(HOST_TRIPLET_STRING, "$host", [The host triplet])
#
# gpgrt_log_clock may require linking with extra libaries. As long as
# we don't have a good test for this we require the use of this
# configure option to enabling printing of a timestamp.
#
AC_MSG_CHECKING([whether to enable log_clock])
AC_ARG_ENABLE(log_clock,
AS_HELP_STRING([--enable-log-clock],
[enable log_clock timestamps]),
enable_log_clock=$enableval, enable_log_clock=no)
AC_MSG_RESULT($enable_log_clock)
if test "$enable_log_clock" = yes ; then
AC_DEFINE(ENABLE_LOG_CLOCK,1,[Defined to use log_clock timestamps])
fi
#
# For now we do not build gpgscm by default.
# Eventually we will reverse the meaning of that option.
#
build_gpgscm=no
#AC_MSG_CHECKING([whether to build gpgscm])
#AC_ARG_ENABLE(gpgscm,
# AS_HELP_STRING([--enable-gpgscm],
# [build the gpgscm tool]),
# build_gpgscm=$enableval, build_gpgscm=no)
#AC_MSG_RESULT($build_gpgscm)
AM_CONDITIONAL([BUILD_GPGSCM], [test "x$build_gpgscm" != xno])
#
# Add -Werror to CFLAGS. This hack can be used to avoid problems with
# misbehaving autoconf tests in case the user supplied -Werror.
#
AC_ARG_ENABLE(werror,
AS_HELP_STRING([--enable-werror],
[append -Werror to CFLAGS]),
[if test $enableval = yes ; then
CFLAGS="$CFLAGS -Werror"
fi])
#
# Provide information about the build.
#
BUILD_REVISION="mym4_revision"
AC_SUBST(BUILD_REVISION)
AC_DEFINE_UNQUOTED(BUILD_REVISION, "$BUILD_REVISION",
[GIT commit id revision used to build this package])
changequote(,)dnl
BUILD_VERSION=`echo "$PACKAGE_VERSION"|sed 's/\([0-9.]*\).*/\1./'`
changequote([,])dnl
BUILD_VERSION="${BUILD_VERSION}0.mym4_revision_dec"
BUILD_FILEVERSION=`echo "${BUILD_VERSION}" | tr . ,`
AC_SUBST(BUILD_VERSION)
AC_SUBST(BUILD_FILEVERSION)
AC_ARG_ENABLE([build-timestamp],
AS_HELP_STRING([--enable-build-timestamp],
[set an explicit build timestamp for reproducibility.
(default is the current time in ISO-8601 format)]),
[if test "$enableval" = "yes"; then
BUILD_TIMESTAMP=`date -u +%Y-%m-%dT%H:%M+0000 2>/dev/null || date`
else
BUILD_TIMESTAMP="$enableval"
fi],
[BUILD_TIMESTAMP="<none>"])
AC_SUBST(BUILD_TIMESTAMP)
AC_DEFINE_UNQUOTED(BUILD_TIMESTAMP, "$BUILD_TIMESTAMP",
[The time this package was configured for a build])
AC_ARG_ENABLE(languages, AS_HELP_STRING([--disable-languages],
[do not build support for other languages than C]))
AM_CONDITIONAL([LANGUAGES_SOME], [test "x$enable_languages" != xno])
build_doc=yes
AC_ARG_ENABLE([doc], AS_HELP_STRING([--disable-doc],
[do not build the documentation]),
build_doc=$enableval, build_doc=yes)
AM_CONDITIONAL([BUILD_DOC], [test "x$build_doc" != xno])
build_tests=yes
AC_ARG_ENABLE([tests], AS_HELP_STRING([--disable-tests],
[do not build the tests]),
build_tests=$enableval, build_tests=yes)
AM_CONDITIONAL([BUILD_TESTS], [test "x$build_tests" != xno])
#
# Substitution
#
AC_CONFIG_FILES([Makefile])
AC_CONFIG_FILES([doc/Makefile po/Makefile.in m4/Makefile])
AC_CONFIG_FILES([src/Makefile tests/Makefile])
AC_CONFIG_FILES([lang/Makefile lang/cl/Makefile lang/cl/gpg-error.asd])
AC_CONFIG_FILES([src/versioninfo.rc src/gpg-error.w32-manifest])
AC_CONFIG_FILES([src/gpg-error.pc])
AC_CONFIG_FILES([src/gpg-error-config-old:src/gpg-error-config.in], [chmod +x src/gpg-error-config-old])
AC_CONFIG_FILES([src/gpgrt-config], [chmod +x src/gpgrt-config])
AC_CONFIG_FILES([src/gpg-error-config-test.sh], [chmod +x src/gpg-error-config-test.sh])
AC_OUTPUT
tmp=
if test "$have_w32_system" != yes; then
if test x"$gl_use_threads" = xno; then
tmp=" NO-THREADS"
fi
fi
echo "
$PACKAGE_NAME v$PACKAGE_VERSION has been configured as follows:
Revision: mym4_revision (mym4_revision_dec)
Platform: $host$tmp
"
if test "$gcry_cv_gcc_attribute_aligned" != "yes" ; then
cat <<G10EOF
***
*** Please note that your compiler does not support the GCC style
*** aligned attribute. Using this software may evoke bus errors.
***
G10EOF
fi
diff --git a/src/gpg-error.h.in b/src/gpg-error.h.in
index ce5c76a..d9b2365 100644
--- a/src/gpg-error.h.in
+++ b/src/gpg-error.h.in
@@ -1,1383 +1,1385 @@
/* 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_process_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;
@SOCKET_t@ 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
*/
/* Internal flag to ihnerit file descriptor/handle */
#define GPGRT_SPAWN_INHERIT_FILE 1
#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. */
#define GPGRT_SPAWN_KEEP_STDIN 256
#define GPGRT_SPAWN_KEEP_STDOUT 512
#define GPGRT_SPAWN_KEEP_STDERR 1024
/* 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, unsigned int flags,
gpgrt_stream_t *r_infp,
gpgrt_stream_t *r_outfp,
gpgrt_stream_t *r_errfp,
- pid_t *pid);
+ gpgrt_process_t *r_process_id);
/* 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,
int (*spawn_cb) (void *),
void *spawn_cb_arg,
- pid_t *pid);
+ gpgrt_process_t *r_process_id);
/* 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);
+gpg_err_code_t gpgrt_wait_process (const char *pgmname,
+ gpgrt_process_t process_id,
+ int hang, int *r_exitcode);
/* Wait for a multiple processes. */
-gpg_err_code_t gpgrt_wait_processes (const char **pgmnames, pid_t *pids,
+gpg_err_code_t gpgrt_wait_processes (const char **pgmnames,
+ gpgrt_process_t *process_ids,
size_t count, int hang, int *r_exitcodes);
-/* Kill the process identified by PID. */
-void gpgrt_kill_process (pid_t pid);
+/* Kill the process identified by PROCESS_ID. */
+void gpgrt_kill_process (gpgrt_process_t process_id);
-/* Release process resources identified by PID. */
-void gpgrt_release_process (pid_t pid);
+/* Release process resources identified by PROCESS_ID. */
+void gpgrt_release_process (gpgrt_process_t process_id);
/* Close all file resources (descriptors), except KEEP_FDS. */
void gpgrt_close_all_fds (int from, int *keep_fds);
/*
* 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. (Make sure */
/* to act upon ARGPARSE_OPT_IGNORE.) */
/* 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/src/gpgrt-int.h b/src/gpgrt-int.h
index c414272..d2b5d1c 100644
--- a/src/gpgrt-int.h
+++ b/src/gpgrt-int.h
@@ -1,864 +1,867 @@
/* 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_SOCK,
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.
+ * pointer to a new estream there. On success the process id of the
+ * new process is stored at R_PID. On error -1 is stored at R_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 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 systems, so that no new
* console is created and pops up a console window when starting
* the server.
*
* GPGRT_SPAWN_RUN_ASFW
* On W32 run AllowSetForegroundWindow for the child. Note that
* due to unknown problems this actually allows
* SetForegroundWindow for all children of this process.
*
* GNUPG_SPAWN_KEEP_STDIN
* GNUPG_SPAWN_KEEP_STDOUT
* GNUPG_SPAWN_KEEP_STDERR
* Do not assign /dev/null to a non-required standard file
* descriptor.
*
*/
gpg_err_code_t
_gpgrt_spawn_process (const char *pgmname, const char *argv[],
int *execpt, unsigned int flags,
estream_t *r_infp,
estream_t *r_outfp,
estream_t *r_errfp,
- pid_t *pid);
+ gpgrt_process_t *r_process_id);
/* Variant 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. If SPAWN_CB is not NULL,
* the given function will be called with SPAWN_CB_ARG to determine if
* file descriptors/handles should be inherited or not. The callback
* function should return 1 to ask keeping file descriptors/handles.
* If SPAWN_CB is NULL, or it returns 0, all file descriptors (except
* INFD, OUTFD, and ERRFD) will be closed on POSIX machine. On POSIX
* machine, it is called right after the fork, by child process.
*/
gpg_err_code_t _gpgrt_spawn_process_fd (const char *pgmname,
const char *argv[],
int infd, int outfd, int errfd,
int (*spawn_cb) (void *),
void *spawn_cb_arg,
- pid_t *pid);
+ gpgrt_process_t *r_process_id);
/* 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.
+/* If HANG is true, waits for the process identified by PROCESS_ID 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,
+gpg_err_code_t _gpgrt_wait_process (const char *pgmname,
+ gpgrt_process_t process_id, 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);
+gpg_err_code_t _gpgrt_wait_processes (const char **pgmnames,
+ gpgrt_process_t *process_ids,
+ 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);
+ * from the system. An invalid PROCESS_ID is ignored. */
+void _gpgrt_kill_process (gpgrt_process_t process_id);
-/* 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);
+/* Release the process identified by PROCESS_ID. This function is
+ * actually only required for Windows but it does not harm to always
+ * call it. It is a nop if PROCESS_ID is invalid. */
+void _gpgrt_release_process (gpgrt_process_t process_id);
/* Close all file resources (descriptors), except KEEP_FDS. */
void _gpgrt_close_all_fds (int from, int *keep_fds);
/*
* 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);
char *_gpgrt_w32_reg_get_string (const char *key);
wchar_t *_gpgrt_fname_to_wchar (const char *fname);
#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/src/mkheader.c b/src/mkheader.c
index e05dafd..8fbfbd6 100644
--- a/src/mkheader.c
+++ b/src/mkheader.c
@@ -1,782 +1,777 @@
/* 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));
fclose (fp);
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, "SOCKET_t"))
{
if (have_w32_system)
fputs ("uintptr_t", stdout);
else
fputs ("int", stdout);
}
- else if (!strcmp (tag, "define:pid_t"))
+ else if (!strcmp (tag, "define:gpgrt_process_t"))
{
- if (have_sys_types_h)
+ if (have_w32_system || have_w64_system)
{
- if (!sys_types_h_included)
- {
- fputs ("#include <sys/types.h>\n", stdout);
- sys_types_h_included = 1;
- }
+ fputs ("typedef void *gpgrt_process_t;\n", stdout);
}
- else if (have_w64_system)
+ else
{
- if (!stdint_h_included && have_stdint_h)
+ if (have_sys_types_h)
{
- fputs ("#include <stdint.h>\n", stdout);
- stdint_h_included = 1;
+ if (!sys_types_h_included)
+ {
+ fputs ("#include <sys/types.h>\n", stdout);
+ sys_types_h_included = 1;
+ }
}
- fputs ("typedef int64_t pid_t\n", stdout);
- }
- else
- {
- fputs ("typedef int pid_t\n", stdout);
+ fputs ("typedef pid_t gpgrt_process_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 (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/src/spawn-posix.c b/src/spawn-posix.c
index 6914b0b..8e36ee1 100644
--- a/src/spawn-posix.c
+++ b/src/spawn-posix.c
@@ -1,902 +1,949 @@
/* 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)
#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. */
void
_gpgrt_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, unsigned int flags)
{
char **arg_list;
int i, j;
int fds[3];
int nodevnull[3];
fds[0] = fd_in;
fds[1] = fd_out;
fds[2] = fd_err;
nodevnull[0] = !!(flags & GPGRT_SPAWN_KEEP_STDIN);
nodevnull[1] = !!(flags & GPGRT_SPAWN_KEEP_STDOUT);
nodevnull[2] = !!(flags & GPGRT_SPAWN_KEEP_STDERR);
/* 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 (nodevnull[i])
continue;
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 (nodevnull[i])
continue;
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. */
if (!(flags & GPGRT_SPAWN_INHERIT_FILE))
_gpgrt_close_all_fds (3, except);
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);
}
+/*
+ * UNION PROCESS_ID:
+ *
+ * gpgrt_process_t object is an object which represents process handle.
+ * It must be same size as pid_t and must have same bit pattern.
+ */
+union process {
+ gpgrt_process_t process_id;
+ pid_t pid;
+};
+
+static gpgrt_process_t
+convert_from_pid (pid_t pid)
+{
+ union process u;
+
+ u.pid = pid;
+ return u.process_id;
+}
+
+static pid_t
+convert_from_process (gpgrt_process_t process_id)
+{
+ union process u;
+
+ u.process_id = process_id;
+ return u.pid;
+}
+
/* 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, unsigned int flags,
estream_t *r_infp,
estream_t *r_outfp,
estream_t *r_errfp,
- pid_t *pid)
+ gpgrt_process_t *r_process_id)
{
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);
+ pid_t pid;
if (r_infp)
*r_infp = NULL;
if (r_outfp)
*r_outfp = NULL;
if (r_errfp)
*r_errfp = NULL;
- *pid = (pid_t)(-1); /* Always required. */
+ *r_process_id = convert_from_pid (-1);
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 ();
+ pid = fork ();
_gpgrt_post_syscall ();
- if (*pid == (pid_t)(-1))
+ 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)
+ if (!pid)
{
/* This is the child. */
_gpgrt_fclose (infp);
_gpgrt_fclose (outfp);
_gpgrt_fclose (errfp);
do_exec (pgmname, argv, inpipe[0], outpipe[1], errpipe[1],
except, flags);
/*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;
+ *r_process_id = convert_from_pid (pid);
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,
int (*spawn_cb) (void *),
void *spawn_cb_arg,
- pid_t *pid)
+ gpgrt_process_t *r_process_id)
{
gpg_error_t err;
int ask_inherit_fds = 0;
+ pid_t pid;
+ *r_process_id = convert_from_pid (-1);
_gpgrt_pre_syscall ();
- *pid = fork ();
+ pid = fork ();
_gpgrt_post_syscall ();
- if (*pid == (pid_t)(-1))
+ 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)
+ if (!pid)
{
if (spawn_cb)
ask_inherit_fds = (*spawn_cb) (spawn_cb_arg);
/* Run child. */
do_exec (pgmname, argv, infd, outfd, errfd, NULL,
ask_inherit_fds? GPGRT_SPAWN_INHERIT_FILE : 0);
/*NOTREACHED*/
}
+ *r_process_id = convert_from_pid (pid);
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)
+_gpgrt_wait_process (const char *pgmname, gpgrt_process_t process_id, int hang,
+ int *r_exitcode)
{
gpg_err_code_t ec;
int i, status;
+ pid_t pid;
+
+ pid = convert_from_process (process_id);
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)
+_gpgrt_wait_processes (const char **pgmnames, gpgrt_process_t *process_ids,
+ size_t count, int hang, int *r_exitcodes)
{
gpg_err_code_t ec = 0;
size_t i, left;
int *dummy = NULL;
+ pid_t pid;
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;
+ pid = convert_from_process (process_ids[i]);
+
/* Skip invalid PID. */
- if (pids[i] == (pid_t)(-1))
+ if (pid == (pid_t)(-1))
{
r_exitcodes[i] = -1;
left -= 1;
continue;
}
/* See if there was a previously stored result for this pid. */
- if (get_result (pids[i], &status))
+ if (get_result (pid, &status))
left -= 1;
r_exitcodes[i] = status;
}
while (left > 0)
{
- pid_t pid;
+ pid_t pid0;
int status;
_gpgrt_pre_syscall ();
- while ((pid = waitpid (-1, &status, hang ? 0 : WNOHANG)) == (pid_t)(-1)
+ while ((pid0 = waitpid (-1, &status, hang ? 0 : WNOHANG)) == (pid_t)(-1)
&& errno == EINTR);
_gpgrt_post_syscall ();
- if (pid == (pid_t)(-1))
+ if (pid0 == (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)
+ else if (!pid0)
{
ec = GPG_ERR_TIMEOUT; /* Still running. */
break;
}
else
{
for (i = 0; i < count; i++)
- if (pid == pids[i])
- break;
+ {
+ pid = convert_from_process (process_ids[i]);
+ if (pid0 == pid)
+ break;
+ }
if (i == count)
{
/* No match, store this result. */
- ec = store_result (pid, status);
+ ec = store_result (pid0, status);
if (ec)
break;
continue;
}
- /* Process PIDS[i] died. */
+ /* Process PROCESS_PIDS[i] died. */
if (r_exitcodes[i] != (pid_t) -1)
{
- _gpgrt_log_error ("PID %d was reused", (int)pid);
+ _gpgrt_log_error ("PID %d was reused", (int)pid0);
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[] )
+ 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, 0);
/*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)
+_gpgrt_kill_process (gpgrt_process_t process_id)
{
+ pid_t pid;
+
+ pid = convert_from_process (process_id);
if (pid != (pid_t)(-1))
{
_gpgrt_pre_syscall ();
kill (pid, SIGTERM);
_gpgrt_post_syscall ();
}
}
void
-_gpgrt_release_process (pid_t pid)
+_gpgrt_release_process (gpgrt_process_t process_id)
{
- (void)pid;
+ (void)process_id;
}
diff --git a/src/spawn-w32.c b/src/spawn-w32.c
index d17f971..324b5fe 100644
--- a/src/spawn-w32.c
+++ b/src/spawn-w32.c
@@ -1,940 +1,953 @@
/* 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)
#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 with original MinGW: Breaking ABI for pid_t will be needed
- * when the value won't fit within 32-bit range on 64-bit machine.
- *
- * Note that pid_t is 64-bit integer in sys/types.h with MinGW-w64.
- * So, no problem with MinGW-w64.
- */
-#define pid_to_handle(a) ((HANDLE)(a))
-#define handle_to_pid(a) ((pid_t)(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);
}
+/*
+ * UNION PROCESS_ID:
+ *
+ * gpgrt_process_t is an object which represents process handle.
+ * It must be same size as HANDLE and must have same bit pattern.
+ */
+union process {
+ gpgrt_process_t process_id;
+ HANDLE process_handle;
+};
+
+static gpgrt_process_t
+convert_from_handle (HANDLE process_handle)
+{
+ union process u;
+
+ u.process_handle = process_handle;
+ return u.process_id;
+}
+
+static HANDLE
+convert_from_process (gpgrt_process_t process_id)
+{
+ union process u;
+
+ u.process_id = process_id;
+ return u.process_handle;
+}
+
+
/* 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, unsigned int flags,
estream_t *r_infp, estream_t *r_outfp, estream_t *r_errfp,
- pid_t *pid)
+ gpgrt_process_t *r_process_id)
{
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)INVALID_HANDLE_VALUE; /* Always required. */
+ *r_process_id = convert_from_handle (INVALID_HANDLE_VALUE);
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] = ((flags & GPGRT_SPAWN_KEEP_STDIN)?
GetStdHandle (STD_INPUT_HANDLE) : w32_open_null (0));
if (outpipe[1] == INVALID_HANDLE_VALUE)
nullhd[1] = ((flags & GPGRT_SPAWN_KEEP_STDOUT)?
GetStdHandle (STD_OUTPUT_HANDLE) : w32_open_null (1));
if (errpipe[1] == INVALID_HANDLE_VALUE)
nullhd[2] = ((flags & GPGRT_SPAWN_KEEP_STDOUT)?
GetStdHandle (STD_ERROR_HANDLE) : w32_open_null (1));
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);
+ *r_process_id = convert_from_handle (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,
int (*spawn_cb) (void *),
void *spawn_cb_arg,
- pid_t *pid)
+ gpgrt_process_t *r_process_id)
{
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];
int ask_inherit = 0;
if (spawn_cb)
ask_inherit = (*spawn_cb) (spawn_cb_arg);
/* Setup return values. */
- *pid = (pid_t)INVALID_HANDLE_VALUE;
+ *r_process_id = convert_from_handle (INVALID_HANDLE_VALUE);
/* Prepare security attributes. */
memset (&sec_attr, 0, sizeof sec_attr );
sec_attr.nLength = sizeof sec_attr;
if (ask_inherit)
sec_attr.bInheritHandle = TRUE;
else
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);
+ *r_process_id = convert_from_handle (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)
+_gpgrt_wait_process (const char *pgmname, gpgrt_process_t process_id,
+ int hang, int *r_exitcode)
{
- return _gpgrt_wait_processes (&pgmname, &pid, 1, hang, r_exitcode);
+ return _gpgrt_wait_processes (&pgmname, &process_id, 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)
+_gpgrt_wait_processes (const char **pgmnames, gpgrt_process_t *process_ids,
+ 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++)
{
+ HANDLE process_handle = convert_from_process (process_ids[i]);
+
if (r_exitcodes)
r_exitcodes[i] = -1;
- if (pids[i] == (pid_t)INVALID_HANDLE_VALUE)
+ if (process_handle == INVALID_HANDLE_VALUE)
return GPG_ERR_INV_VALUE;
- procs[i] = pid_to_handle (pids[i]);
+ procs[i] = process_handle;
}
_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:"
+ _gpgrt_log_error (_("error getting exit code of process %p:"
" ec=%d\n"),
- (int) pids[i], (int)GetLastError ());
+ process_ids[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[] )
+ 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)
+_gpgrt_kill_process (gpgrt_process_t process_id)
{
- if (pid != (pid_t)INVALID_HANDLE_VALUE)
- {
- HANDLE process = (HANDLE) pid;
+ HANDLE process_handle = convert_from_process (process_id);
+ if (process_handle != INVALID_HANDLE_VALUE)
+ {
/* Arbitrary error code. */
_gpgrt_pre_syscall ();
- TerminateProcess (process, 1);
+ TerminateProcess (process_handle, 1);
_gpgrt_post_syscall ();
}
}
void
-_gpgrt_release_process (pid_t pid)
+_gpgrt_release_process (gpgrt_process_t process_id)
{
- if (pid != (pid_t)INVALID_HANDLE_VALUE)
- {
- HANDLE process = (HANDLE)pid;
+ HANDLE process_handle = convert_from_process (process_id);
- CloseHandle (process);
- }
+ if (process_handle != INVALID_HANDLE_VALUE)
+ CloseHandle (process_handle);
}
void
_gpgrt_close_all_fds (int from, int *keep_fds)
{
(void)from;
(void)keep_fds;
}
diff --git a/src/visibility.c b/src/visibility.c
index 577a2be..dd1a6a8 100644
--- a/src/visibility.c
+++ b/src/visibility.c
@@ -1,1283 +1,1284 @@
/* 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
}
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, unsigned int flags,
estream_t *r_infp, estream_t *r_outfp, estream_t *r_errfp,
- pid_t *pid)
+ gpgrt_process_t *r_process_id)
{
return _gpgrt_spawn_process (pgmname, argv, except, flags,
- r_infp, r_outfp, r_errfp, pid);
+ r_infp, r_outfp, r_errfp, r_process_id);
}
gpg_err_code_t
gpgrt_spawn_process_fd (const char *pgmname, const char *argv[],
int infd, int outfd, int errfd,
int (*spawn_cb)(void *),
- void *spawn_cb_arg,
- pid_t *pid)
+ void *spawn_cb_arg, gpgrt_process_t *r_process_id)
{
return _gpgrt_spawn_process_fd (pgmname, argv, infd, outfd, errfd,
- spawn_cb, spawn_cb_arg, pid);
+ spawn_cb, spawn_cb_arg, r_process_id);
}
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)
+gpgrt_wait_process (const char *pgmname, gpgrt_process_t process_id, int hang,
+ int *r_exitcode)
{
- return _gpgrt_wait_process (pgmname, pid, hang, r_exitcode);
+ return _gpgrt_wait_process (pgmname, process_id, hang, r_exitcode);
}
gpg_err_code_t
-gpgrt_wait_processes (const char **pgmnames, pid_t *pids,
+gpgrt_wait_processes (const char **pgmnames, gpgrt_process_t *process_ids,
size_t count, int hang, int *r_exitcodes)
{
- return _gpgrt_wait_processes (pgmnames, pids, count, hang, r_exitcodes);
+ return _gpgrt_wait_processes (pgmnames, process_ids, count, hang,
+ r_exitcodes);
}
void
-gpgrt_kill_process (pid_t pid)
+gpgrt_kill_process (gpgrt_process_t process_id)
{
- _gpgrt_kill_process (pid);
+ _gpgrt_kill_process (process_id);
}
void
-gpgrt_release_process (pid_t pid)
+gpgrt_release_process (gpgrt_process_t process_id)
{
- _gpgrt_release_process (pid);
+ _gpgrt_release_process (process_id);
}
void
gpgrt_close_all_fds (int from, int *keep_fds)
{
_gpgrt_close_all_fds (from, keep_fds);
}
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
void
gpgrt_free_wchar (wchar_t *wstring)
{
if (wstring)
_gpgrt_free_wchar (wstring);
}
wchar_t *
gpgrt_fname_to_wchar (const char *fname)
{
return _gpgrt_fname_to_wchar (fname);
}
wchar_t *
gpgrt_utf8_to_wchar (const char *string)
{
return _gpgrt_utf8_to_wchar (string);
}
char *
gpgrt_wchar_to_utf8 (const wchar_t *string)
{
return _gpgrt_wchar_to_utf8 (string, (size_t)(-1));
}
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*/
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Dec 23, 3:27 PM (1 d, 1 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
3c/40/c503de5eb2f53fb836bf08fce949
Attached To
rE libgpg-error
Event Timeline
Log In to Comment