diff --git a/src/gpg-error.def.in b/src/gpg-error.def.in index ac8f2f6..f94c6f4 100644 --- a/src/gpg-error.def.in +++ b/src/gpg-error.def.in @@ -1,245 +1,247 @@ /* libgpg-error.def - Exported symbols for W32 * Copyright (C) 2014 g10 Code GmbH * * This file is part of libgpg-error. * * libgpg-error is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * libgpg-error is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ * * Note: This file should be updated manually and the ordinals shall * never be changed. Also check gpg-error.vers and visibility.h. * * This file needs to be pre-processed. */ #include EXPORTS gpg_strerror @1 gpg_strerror_r @2 gpg_strsource @3 gpg_err_code_from_errno @4 gpg_err_code_to_errno @5 /* @6 - Not anymore used. */ gpg_err_code_from_syserror @7 gpg_err_set_errno @8 #ifdef HAVE_W32_SYSTEM _gpg_w32_bindtextdomain @11 _gpg_w32_textdomain @12 _gpg_w32_gettext @13 _gpg_w32_dgettext @14 _gpg_w32_dngettext @15 _gpg_w32_gettext_localename @16 _gpg_w32_gettext_use_utf8 @17 #endif /* @18 - Not anymore used. */ gpg_error_check_version @19 gpgrt_lock_init @20 gpgrt_lock_lock @21 gpgrt_lock_unlock @22 gpgrt_lock_destroy @23 gpgrt_yield @24 gpgrt_lock_trylock @25 gpgrt_set_syscall_clamp @26 gpgrt_fopen @27 gpgrt_mopen @28 gpgrt_fopenmem @29 gpgrt_fopenmem_init @30 gpgrt_fdopen @31 gpgrt_fdopen_nc @32 gpgrt_sysopen @33 gpgrt_sysopen_nc @34 gpgrt_fpopen @35 gpgrt_fpopen_nc @36 gpgrt_freopen @37 gpgrt_fopencookie @38 gpgrt_fclose @39 gpgrt_fclose_snatch @40 gpgrt_onclose @41 gpgrt_fileno @42 gpgrt_fileno_unlocked @43 gpgrt_syshd @44 gpgrt_syshd_unlocked @45 _gpgrt_set_std_fd @46 _gpgrt_get_std_stream @47 gpgrt_flockfile @48 gpgrt_ftrylockfile @49 gpgrt_funlockfile @50 gpgrt_feof @51 gpgrt_feof_unlocked @52 gpgrt_ferror @53 gpgrt_ferror_unlocked @54 gpgrt_clearerr @55 gpgrt_clearerr_unlocked @56 gpgrt_fflush @57 gpgrt_fseek @58 gpgrt_fseeko @59 gpgrt_ftell @60 gpgrt_ftello @61 gpgrt_rewind @62 gpgrt_fgetc @63 _gpgrt_getc_underflow @64 gpgrt_fputc @65 _gpgrt_putc_overflow @66 gpgrt_ungetc @67 gpgrt_read @68 gpgrt_write @69 gpgrt_write_sanitized @70 gpgrt_write_hexstring @71 gpgrt_fread @72 gpgrt_fwrite @73 gpgrt_fgets @74 gpgrt_fputs @75 gpgrt_fputs_unlocked @76 gpgrt_getline @77 gpgrt_read_line @78 gpgrt_free @79 gpgrt_fprintf @80 gpgrt_fprintf_unlocked @81 gpgrt_printf @82 gpgrt_printf_unlocked @83 gpgrt_vfprintf @84 gpgrt_vfprintf_unlocked @85 gpgrt_setvbuf @86 gpgrt_setbuf @87 gpgrt_set_binary @88 gpgrt_tmpfile @89 gpgrt_opaque_set @90 gpgrt_opaque_get @91 gpgrt_fname_set @92 gpgrt_fname_get @93 gpgrt_asprintf @94 gpgrt_vasprintf @95 gpgrt_bsprintf @96 gpgrt_vbsprintf @97 gpgrt_snprintf @98 gpgrt_vsnprintf @99 gpgrt_check_version @100 gpg_err_init @101 gpg_err_deinit @102 gpgrt_set_alloc_func @103 _gpgrt_pending @104 _gpgrt_pending_unlocked @105 gpgrt_set_nonblock @106 gpgrt_get_nonblock @107 gpgrt_poll @108 #ifdef HAVE_W32_SYSTEM gpgrt_w32_iconv_open @109 gpgrt_w32_iconv_close @110 gpgrt_w32_iconv @111 #endif gpgrt_get_syscall_clamp @112 gpgrt_b64dec_start @113 gpgrt_b64dec_proc @114 gpgrt_b64dec_finish @115 gpgrt_get_errorcount @116 gpgrt_inc_errorcount @117 gpgrt_log_set_sink @118 gpgrt_log_set_socket_dir_cb @119 gpgrt_log_set_pid_suffix_cb @120 gpgrt_log_set_prefix @121 gpgrt_log_get_prefix @122 gpgrt_log_test_fd @123 gpgrt_log_get_fd @124 gpgrt_log_get_stream @125 gpgrt_log @126 gpgrt_logv @127 gpgrt_logv_prefix @128 gpgrt_log_string @129 gpgrt_log_bug @130 gpgrt_log_fatal @131 gpgrt_log_error @132 gpgrt_log_info @133 gpgrt_log_debug @134 gpgrt_log_debug_string @135 gpgrt_log_printf @136 gpgrt_log_printhex @137 gpgrt_log_clock @138 gpgrt_log_flush @139 _gpgrt_log_assert @140 gpgrt_realloc @141 gpgrt_malloc @142 gpgrt_calloc @143 gpgrt_strdup @144 gpgrt_strconcat @145 gpgrt_w32_reg_query_string @146 gpgrt_getenv @147 gpgrt_setenv @148 gpgrt_mkdir @149 gpgrt_chdir @150 gpgrt_getcwd @151 gpgrt_make_pipe @152 gpgrt_spawn_process @153 gpgrt_spawn_process_fd @154 gpgrt_spawn_process_detached @155 gpgrt_wait_process @156 gpgrt_wait_processes @157 gpgrt_kill_process @158 gpgrt_release_process @159 gpgrt_argparse @160 gpgrt_usage @161 gpgrt_strusage @162 gpgrt_set_strusage @163 gpgrt_set_usage_outfnc @164 gpgrt_set_fixed_string_mapper @165 gpgrt_b64enc_start @166 gpgrt_b64enc_write @167 gpgrt_b64enc_finish @168 gpgrt_cmp_version @169 gpgrt_ftruncate @170 gpgrt_fprintf_sf @171 gpgrt_fprintf_sf_unlocked @172 gpgrt_w32_override_locale @173 gpgrt_add_emergency_cleanup @174 gpgrt_abort @175 gpgrt_set_confdir @176 gpgrt_argparser @177 gpgrt_fnameconcat @178 gpgrt_absfnameconcat @179 gpgrt_reallocarray @180 gpgrt_fclose @181 gpgrt_fcancel @182 gpgrt_access @183 gpgrt_free_wchar @184 gpgrt_fname_to_wchar @185 gpgrt_utf8_to_wchar @186 gpgrt_wchar_to_utf8 @187 + gpgrt_close_all_fds @188 + ;; end of file with public symbols for Windows. diff --git a/src/gpg-error.h.in b/src/gpg-error.h.in index b7cfdcf..ce5c76a 100644 --- a/src/gpg-error.h.in +++ b/src/gpg-error.h.in @@ -1,1377 +1,1383 @@ /* 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 . * 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 #include #include /* 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 #endif /* Mark heap objects as non-leaked memory. */ static GPGRT_INLINE void gpgrt_annotate_leaked_object (const void *p) { #ifdef GPGRT_HAVE_LEAK_SANITIZER __lsan_ignore_object(p); #else (void)p; #endif } /* * Initialization function. */ /* Initialize the library. This function should be run early. */ gpg_error_t gpg_err_init (void) _GPG_ERR_CONSTRUCTOR; /* If this is defined, the library is already initialized by the constructor and does not need to be initialized explicitely. */ #undef GPG_ERR_INITIALIZED #ifdef _GPG_ERR_HAVE_CONSTRUCTOR # define GPG_ERR_INITIALIZED 1 # define gpgrt_init() do { gpg_err_init (); } while (0) #else # define gpgrt_init() do { ; } while (0) #endif /* See the source on how to use the deinit function; it is usually not required. */ void gpg_err_deinit (int mode); /* Register blocking system I/O clamping functions. */ void gpgrt_set_syscall_clamp (void (*pre)(void), void (*post)(void)); /* Get current I/O clamping functions. */ void gpgrt_get_syscall_clamp (void (**r_pre)(void), void (**r_post)(void)); /* Register a custom malloc/realloc/free function. */ void gpgrt_set_alloc_func (void *(*f)(void *a, size_t n)); /* Register an emergency cleanup handler. */ void gpgrt_add_emergency_cleanup (void (*f)(void)); /* Wrapper around abort to make sure emergency cleanups are run. */ void gpgrt_abort (void) GPGRT_ATTR_NORETURN; /* * Constructor and accessor functions. */ /* Construct an error value from an error code and source. Within a * subsystem, use gpg_error. */ static GPG_ERR_INLINE gpg_error_t gpg_err_make (gpg_err_source_t source, gpg_err_code_t code) { return code == GPG_ERR_NO_ERROR ? GPG_ERR_NO_ERROR : (((source & GPG_ERR_SOURCE_MASK) << GPG_ERR_SOURCE_SHIFT) | (code & GPG_ERR_CODE_MASK)); } /* The user should define GPG_ERR_SOURCE_DEFAULT before including this * file to specify a default source for gpg_error. */ #ifndef GPG_ERR_SOURCE_DEFAULT #define GPG_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_UNKNOWN #endif static GPG_ERR_INLINE gpg_error_t gpg_error (gpg_err_code_t code) { return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, code); } /* Retrieve the error code from an error value. */ static GPG_ERR_INLINE gpg_err_code_t gpg_err_code (gpg_error_t err) { return (gpg_err_code_t) (err & GPG_ERR_CODE_MASK); } /* Retrieve the error source from an error value. */ static GPG_ERR_INLINE gpg_err_source_t gpg_err_source (gpg_error_t err) { return (gpg_err_source_t) ((err >> GPG_ERR_SOURCE_SHIFT) & GPG_ERR_SOURCE_MASK); } /* String functions. */ /* Return a pointer to a string containing a description of the error * code in the error value ERR. This function is not thread-safe. */ const char *gpg_strerror (gpg_error_t err); /* Return the error string for ERR in the user-supplied buffer BUF of * size BUFLEN. This function is, in contrast to gpg_strerror, * thread-safe if a thread-safe strerror_r() function is provided by * the system. If the function succeeds, 0 is returned and BUF * contains the string describing the error. If the buffer was not * large enough, ERANGE is returned and BUF contains as much of the * beginning of the error string as fits into the buffer. */ int gpg_strerror_r (gpg_error_t err, char *buf, size_t buflen); /* Return a pointer to a string containing a description of the error * source in the error value ERR. */ const char *gpg_strsource (gpg_error_t err); /* * Mapping of system errors (errno). */ /* Retrieve the error code for the system error ERR. This returns * GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped (report * this). */ gpg_err_code_t gpg_err_code_from_errno (int err); /* Retrieve the system error for the error code CODE. This returns 0 * if CODE is not a system error code. */ int gpg_err_code_to_errno (gpg_err_code_t code); /* Retrieve the error code directly from the ERRNO variable. This * returns GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped * (report this) and GPG_ERR_MISSING_ERRNO if ERRNO has the value 0. */ gpg_err_code_t gpg_err_code_from_syserror (void); /* Mapper for SQLite primary error codes. */ static GPG_ERR_INLINE gpg_error_t gpg_err_code_from_sqlite (int sqlres) { return sqlres? GPG_ERR_SQL_OK + (sqlres & 0xff) : 0; } /* Set the ERRNO variable. This function is the preferred way to set * ERRNO due to peculiarities on WindowsCE. */ void gpg_err_set_errno (int err); /* Return or check the version. Both functions are identical. */ const char *gpgrt_check_version (const char *req_version); const char *gpg_error_check_version (const char *req_version); /* System specific type definitions. */ @define:pid_t@ @define:gpgrt_ssize_t@ @define:gpgrt_off_t@ @include:os-add@ /* Self-documenting convenience functions. */ static GPG_ERR_INLINE gpg_error_t gpg_err_make_from_errno (gpg_err_source_t source, int err) { return gpg_err_make (source, gpg_err_code_from_errno (err)); } static GPG_ERR_INLINE gpg_error_t gpg_error_from_errno (int err) { return gpg_error (gpg_err_code_from_errno (err)); } static GPG_ERR_INLINE gpg_error_t gpg_error_from_syserror (void) { return gpg_error (gpg_err_code_from_syserror ()); } /* * Malloc and friends */ void *gpgrt_realloc (void *a, size_t n); void *gpgrt_reallocarray (void *a, size_t oldnmemb, size_t nmemb, size_t size); void *gpgrt_malloc (size_t n); void *gpgrt_calloc (size_t n, size_t m); char *gpgrt_strdup (const char *string); char *gpgrt_strconcat (const char *s1, ...) GPGRT_ATTR_SENTINEL(0); void gpgrt_free (void *a); /* * System specific function wrappers. */ /* A getenv replacement which mallocs the returned string. */ char *gpgrt_getenv (const char *name); /* A setenv and a unsetenv replacement.*/ gpg_err_code_t gpgrt_setenv (const char *name, const char *value, int overwrite); #define gpgrt_unsetenv(n) gpgrt_setenv ((n), NULL, 1) /* A wrapper around mkdir using a string for the mode. */ gpg_err_code_t gpgrt_mkdir (const char *name, const char *modestr); /* A simple wrapper around chdir. */ gpg_err_code_t gpgrt_chdir (const char *name); /* Return the current WD as a malloced string. */ char *gpgrt_getcwd (void); /* A wrapper around access to handle UTF-8 on Windows. */ gpg_err_code_t gpgrt_access (const char *fname, int mode); /* * Lock functions. */ @include:lock-obj@ #define GPGRT_LOCK_DEFINE(name) \ static gpgrt_lock_t name = GPGRT_LOCK_INITIALIZER /* NB: If GPGRT_LOCK_DEFINE is not used, zero out the lock variable before passing it to gpgrt_lock_init. */ gpg_err_code_t gpgrt_lock_init (gpgrt_lock_t *lockhd); gpg_err_code_t gpgrt_lock_lock (gpgrt_lock_t *lockhd); gpg_err_code_t gpgrt_lock_trylock (gpgrt_lock_t *lockhd); gpg_err_code_t gpgrt_lock_unlock (gpgrt_lock_t *lockhd); gpg_err_code_t gpgrt_lock_destroy (gpgrt_lock_t *lockhd); /* * Thread functions. */ gpg_err_code_t gpgrt_yield (void); /* * Estream */ /* The definition of this struct is entirely private. You must not use it for anything. It is only here so some functions can be implemented as macros. */ struct _gpgrt_stream_internal; struct _gpgrt__stream { /* The layout of this struct must never change. It may be grown, but only if all functions which access the new members are versioned. */ /* Various flags. */ struct { unsigned int magic: 16; unsigned int writing: 1; unsigned int reserved: 15; } flags; /* A pointer to the stream buffer. */ unsigned char *buffer; /* The size of the buffer in bytes. */ size_t buffer_size; /* The length of the usable data in the buffer, only valid when in read mode (see flags). */ size_t data_len; /* The current position of the offset pointer, valid in read and write mode. */ size_t data_offset; size_t data_flushed; unsigned char *unread_buffer; size_t unread_buffer_size; /* The number of unread bytes. */ size_t unread_data_len; /* A pointer to our internal data for this stream. */ struct _gpgrt_stream_internal *intern; }; /* The opaque type for an estream. */ typedef struct _gpgrt__stream *gpgrt_stream_t; #ifdef GPGRT_ENABLE_ES_MACROS typedef struct _gpgrt__stream *estream_t; #endif typedef @api_ssize_t@ (*gpgrt_cookie_read_function_t) (void *cookie, void *buffer, size_t size); typedef @api_ssize_t@ (*gpgrt_cookie_write_function_t) (void *cookie, const void *buffer, size_t size); typedef int (*gpgrt_cookie_seek_function_t) (void *cookie, gpgrt_off_t *pos, int whence); typedef int (*gpgrt_cookie_close_function_t) (void *cookie); struct _gpgrt_cookie_io_functions { gpgrt_cookie_read_function_t func_read; gpgrt_cookie_write_function_t func_write; gpgrt_cookie_seek_function_t func_seek; gpgrt_cookie_close_function_t func_close; }; typedef struct _gpgrt_cookie_io_functions gpgrt_cookie_io_functions_t; #ifdef GPGRT_ENABLE_ES_MACROS typedef struct _gpgrt_cookie_io_functions es_cookie_io_functions_t; #define es_cookie_read_function_t gpgrt_cookie_read_function_t #define es_cookie_write_function_t gpgrt_cookie_read_function_t #define es_cookie_seek_function_t gpgrt_cookie_read_function_t #define es_cookie_close_function_t gpgrt_cookie_read_function_t #endif enum gpgrt_syshd_types { GPGRT_SYSHD_NONE = 0, /* No system handle available. */ GPGRT_SYSHD_FD = 1, /* A file descriptor as returned by open(). */ GPGRT_SYSHD_SOCK = 2, /* A socket as returned by socket(). */ GPGRT_SYSHD_RVID = 3, /* A rendezvous id (see libassuan's gpgcedev.c). */ GPGRT_SYSHD_HANDLE = 4 /* A HANDLE object (Windows). */ }; struct _gpgrt_syshd { enum gpgrt_syshd_types type; union { int fd; @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); /* 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, - void (*after_fork_cb)(void *), - void *after_fork_cb_arg, + int (*spawn_cb) (void *), + void *spawn_cb_arg, pid_t *pid); /* Fork and exec PGMNAME as a detached process. */ gpg_err_code_t gpgrt_spawn_process_detached (const char *pgmname, const char *argv[], - const char *envp[] ); + const char *envp[]); /* Wait for a single process. */ gpg_err_code_t gpgrt_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode); /* Wait for a multiple processes. */ gpg_err_code_t gpgrt_wait_processes (const char **pgmnames, pid_t *pids, size_t count, int hang, int *r_exitcodes); /* Kill the process identified by PID. */ void gpgrt_kill_process (pid_t pid); /* Release process resources identified by PID. */ void gpgrt_release_process (pid_t pid); + +/* 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/gpg-error.vers b/src/gpg-error.vers index 4182da0..8884e47 100644 --- a/src/gpg-error.vers +++ b/src/gpg-error.vers @@ -1,212 +1,213 @@ # libgpg-error.vers - What symbols to export -*- std -*- # Copyright (C) 2014 g10 Code GmbH # # This file is part of libgpg-error. # # libgpg-error is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as # published by the Free Software Foundation; either version 2.1 of the # License, or (at your option) any later version. # # libgpg-error is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this program; if not, see . # SPDX-License-Identifier: LGPL-2.1+ # # NOTE: When adding new functions, please make sure to add them to # visibility.h and gpg-error.def.in as well. GPG_ERROR_1.0 { global: gpg_strerror; gpg_strerror_r; gpg_strsource; gpg_err_code_from_errno; gpg_err_code_to_errno; gpg_err_code_from_syserror; gpg_err_set_errno; gpg_error_check_version; gpgrt_lock_init; gpgrt_lock_lock; gpgrt_lock_unlock; gpgrt_lock_destroy; gpgrt_yield; gpgrt_lock_trylock; gpgrt_set_syscall_clamp; gpgrt_get_syscall_clamp; gpgrt_fopen; gpgrt_mopen; gpgrt_fopenmem; gpgrt_fopenmem_init; gpgrt_fdopen; gpgrt_fdopen_nc; gpgrt_sysopen; gpgrt_sysopen_nc; gpgrt_fpopen; gpgrt_fpopen_nc; gpgrt_freopen; gpgrt_fopencookie; gpgrt_fclose; gpgrt_fcancel; gpgrt_fclose_snatch; gpgrt_onclose; gpgrt_fileno; gpgrt_fileno_unlocked; gpgrt_syshd; gpgrt_syshd_unlocked; _gpgrt_set_std_fd; _gpgrt_get_std_stream; gpgrt_flockfile; gpgrt_ftrylockfile; gpgrt_funlockfile; _gpgrt_pending; _gpgrt_pending_unlocked; gpgrt_feof; gpgrt_feof_unlocked; gpgrt_ferror; gpgrt_ferror_unlocked; gpgrt_clearerr; gpgrt_clearerr_unlocked; gpgrt_fflush; gpgrt_fseek; gpgrt_fseeko; gpgrt_ftell; gpgrt_ftello; gpgrt_rewind; gpgrt_fgetc; _gpgrt_getc_underflow; gpgrt_fputc; _gpgrt_putc_overflow; gpgrt_ungetc; gpgrt_read; gpgrt_write; gpgrt_write_sanitized; gpgrt_write_hexstring; gpgrt_fread; gpgrt_fwrite; gpgrt_fgets; gpgrt_fputs; gpgrt_fputs_unlocked; gpgrt_getline; gpgrt_read_line; gpgrt_free; gpgrt_fprintf; gpgrt_fprintf_unlocked; gpgrt_printf; gpgrt_printf_unlocked; gpgrt_vfprintf; gpgrt_vfprintf_unlocked; gpgrt_setvbuf; gpgrt_setbuf; gpgrt_set_binary; gpgrt_set_nonblock; gpgrt_get_nonblock; gpgrt_poll; gpgrt_tmpfile; gpgrt_opaque_set; gpgrt_opaque_get; gpgrt_fname_set; gpgrt_fname_get; gpgrt_asprintf; gpgrt_vasprintf; gpgrt_bsprintf; gpgrt_vbsprintf; gpgrt_snprintf; gpgrt_vsnprintf; gpgrt_check_version; gpg_err_init; gpg_err_deinit; gpgrt_set_alloc_func; gpgrt_b64dec_start; gpgrt_b64dec_proc; gpgrt_b64dec_finish; gpgrt_get_errorcount; gpgrt_inc_errorcount; gpgrt_log_set_sink; gpgrt_log_set_socket_dir_cb; gpgrt_log_set_pid_suffix_cb; gpgrt_log_set_prefix; gpgrt_log_get_prefix; gpgrt_log_test_fd; gpgrt_log_get_fd; gpgrt_log_get_stream; gpgrt_log; gpgrt_logv; gpgrt_logv_prefix; gpgrt_log_string; gpgrt_log_bug; gpgrt_log_fatal; gpgrt_log_error; gpgrt_log_info; gpgrt_log_debug; gpgrt_log_debug_string; gpgrt_log_printf; gpgrt_log_printhex; gpgrt_log_clock; gpgrt_log_flush; _gpgrt_log_assert; gpgrt_realloc; gpgrt_reallocarray; gpgrt_malloc; gpgrt_calloc; gpgrt_strdup; gpgrt_strconcat; gpgrt_getenv; gpgrt_setenv; gpgrt_mkdir; gpgrt_chdir; gpgrt_getcwd; gpgrt_make_pipe; gpgrt_spawn_process; gpgrt_spawn_process_fd; gpgrt_spawn_process_detached; gpgrt_wait_process; gpgrt_wait_processes; gpgrt_kill_process; gpgrt_release_process; + gpgrt_close_all_fds; gpgrt_argparse; gpgrt_argparser; gpgrt_usage; gpgrt_strusage; gpgrt_set_strusage; gpgrt_set_usage_outfnc; gpgrt_set_fixed_string_mapper; gpgrt_set_confdir; gpgrt_b64enc_start; gpgrt_b64enc_write; gpgrt_b64enc_finish; gpgrt_cmp_version; gpgrt_ftruncate; gpgrt_fprintf_sf; gpgrt_fprintf_sf_unlocked; gpgrt_add_emergency_cleanup; gpgrt_abort; gpgrt_fnameconcat; gpgrt_absfnameconcat; gpgrt_access; local: *; }; diff --git a/src/gpgrt-int.h b/src/gpgrt-int.h index b95b44c..c414272 100644 --- a/src/gpgrt-int.h +++ b/src/gpgrt-int.h @@ -1,857 +1,864 @@ /* 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 . * 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 # 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 # include # else # ifdef HAVE_WINSOCK2_H # include # endif # include # 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. * * 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); /* 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 AFTER_FORK_CB is not - * NULL, the given function will be called right after the fork, by - * child process. + * 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, - void (*after_fork_cb)(void *), - void *after_fork_cb_arg, + int (*spawn_cb) (void *), + void *spawn_cb_arg, pid_t *pid); /* Spawn a new process and immediately detach from it. The name of * the program to exec is PGMNAME and its arguments are in ARGV (the * programname is automatically passed as first argument). * Environment strings in ENVP are set. An error is returned if * pgmname is not executable; to make this work it is necessary to * provide an absolute file name. */ gpg_err_code_t _gpgrt_spawn_process_detached (const char *pgmname, const char *argv[], const char *envp[]); /* If HANG is true, waits for the process identified by PID to exit; * if HANG is false, checks whether the process has terminated. * PGMNAME should be the same as supplied to the spawn function and is * only used for diagnostics. Return values: * * 0 * The process exited successful. 0 is stored at R_EXITCODE. * * GPG_ERR_GENERAL * The process exited without success. The exit code of process * is then stored at R_EXITCODE. An exit code of -1 indicates * that the process terminated abnormally (e.g. due to a signal). * * GPG_ERR_TIMEOUT * The process is still running (returned only if HANG is false). * * GPG_ERR_INV_VALUE * An invalid PID has been specified. * * Other error codes may be returned as well. Unless otherwise noted, * -1 will be stored at R_EXITCODE. R_EXITCODE may be passed as NULL * if the exit code is not required (in that case an error message will * be printed). Note that under Windows PID is not the process id but * the handle of the process. */ gpg_err_code_t _gpgrt_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode); /* Like _gpgrt_wait_process, but for COUNT processes. */ gpg_err_code_t _gpgrt_wait_processes (const char **pgmnames, pid_t *pids, size_t count, int hang, int *r_exitcodes); /* Kill a process; that is send an appropriate signal to the process. * gpgrt_wait_process must be called to actually remove the process * from the system. An invalid PID is ignored. */ void _gpgrt_kill_process (pid_t pid); /* Release the process identified by PID. This function is actually * only required for Windows but it does not harm to always call it. * It is a nop if PID is invalid. */ void _gpgrt_release_process (pid_t pid); +/* 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/spawn-posix.c b/src/spawn-posix.c index 3ac79ff..6914b0b 100644 --- a/src/spawn-posix.c +++ b/src/spawn-posix.c @@ -1,899 +1,902 @@ /* 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 . * SPDX-License-Identifier: LGPL-2.1+ * * This file was originally a part of GnuPG. */ #include #if defined(HAVE_W32_SYSTEM) #error This code is only used on POSIX #endif #include #include #include #include #include #ifdef HAVE_SIGNAL_H # include #endif #include #include #include #ifdef HAVE_GETRLIMIT #include #include #endif /*HAVE_GETRLIMIT*/ #ifdef HAVE_STAT # include #endif #if __linux__ # include # include #endif /*__linux__ */ #include "gpgrt-int.h" static void out_of_core (int line) { _gpgrt_log_fatal ("malloc failed at line %d: %s\n", line, _gpg_strerror (_gpg_err_code_from_syserror ())); /*NOTREACHED*/ } /* Return the maximum number of currently allowed open file * descriptors. Only useful on POSIX systems but returns a value on * other systems too. */ static int get_max_fds (void) { int max_fds = -1; #ifdef HAVE_GETRLIMIT struct rlimit rl; /* Under Linux we can figure out the highest used file descriptor by * reading /proc/PID/fd. This is in the common cases much fast than * for example doing 4096 close calls where almost all of them will * fail. On a system with a limit of 4096 files and only 8 files * open with the highest number being 10, we speedup close_all_fds * from 125ms to 0.4ms including readdir. * * Another option would be to close the file descriptors as returned * from reading that directory - however then we need to snapshot * that list before starting to close them. */ #ifdef __linux__ { DIR *dir = NULL; struct dirent *dir_entry; const char *s; int x; /* FIXME: Check gpgme on how to do this right on Linux. */ dir = opendir ("/proc/self/fd"); if (dir) { while ((dir_entry = readdir (dir))) { s = dir_entry->d_name; if ( *s < '0' || *s > '9') continue; x = atoi (s); if (x > max_fds) max_fds = x; } closedir (dir); } if (max_fds != -1) return max_fds + 1; } #endif /* __linux__ */ # ifdef RLIMIT_NOFILE if (!getrlimit (RLIMIT_NOFILE, &rl)) max_fds = rl.rlim_max; # endif # ifdef RLIMIT_OFILE if (max_fds == -1 && !getrlimit (RLIMIT_OFILE, &rl)) max_fds = rl.rlim_max; # endif #endif /*HAVE_GETRLIMIT*/ #ifdef _SC_OPEN_MAX if (max_fds == -1) { long int scres = sysconf (_SC_OPEN_MAX); if (scres >= 0) max_fds = scres; } #endif #ifdef _POSIX_OPEN_MAX if (max_fds == -1) max_fds = _POSIX_OPEN_MAX; #endif #ifdef OPEN_MAX if (max_fds == -1) max_fds = OPEN_MAX; #endif if (max_fds == -1) max_fds = 256; /* Arbitrary limit. */ /* AIX returns INT32_MAX instead of a proper value. We assume that this is always an error and use an arbitrary limit. */ #ifdef INT32_MAX if (max_fds == INT32_MAX) max_fds = 256; #endif return max_fds; } /* Close all file descriptors starting with descriptor FIRST. If * EXCEPT is not NULL, it is expected to be a list of file descriptors * which shall not be closed. This list shall be sorted in ascending * order with the end marked by -1. */ -static void -close_all_fds (int first, int *except) +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. */ - close_all_fds (3, except); + 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); } /* 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) { gpg_error_t err; int inpipe[2] = {-1, -1}; int outpipe[2] = {-1, -1}; int errpipe[2] = {-1, -1}; estream_t infp = NULL; estream_t outfp = NULL; estream_t errfp = NULL; int nonblock = !!(flags & GPGRT_SPAWN_NONBLOCK); if (r_infp) *r_infp = NULL; if (r_outfp) *r_outfp = NULL; if (r_errfp) *r_errfp = NULL; *pid = (pid_t)(-1); /* Always required. */ if (r_infp) { err = _gpgrt_create_outbound_pipe (inpipe, &infp, nonblock); if (err) return err; } if (r_outfp) { err = _gpgrt_create_inbound_pipe (outpipe, &outfp, nonblock); if (err) { if (infp) _gpgrt_fclose (infp); else if (inpipe[1] != -1) close (inpipe[1]); if (inpipe[0] != -1) close (inpipe[0]); return err; } } if (r_errfp) { err = _gpgrt_create_inbound_pipe (errpipe, &errfp, nonblock); if (err) { if (infp) _gpgrt_fclose (infp); else if (inpipe[1] != -1) close (inpipe[1]); if (inpipe[0] != -1) close (inpipe[0]); if (outfp) _gpgrt_fclose (outfp); else if (outpipe[0] != -1) close (outpipe[0]); if (outpipe[1] != -1) close (outpipe[1]); return err; } } _gpgrt_pre_syscall (); *pid = fork (); _gpgrt_post_syscall (); if (*pid == (pid_t)(-1)) { err = _gpg_err_code_from_syserror (); _gpgrt_log_error (_("error forking process: %s\n"), _gpg_strerror (err)); if (infp) _gpgrt_fclose (infp); else if (inpipe[1] != -1) close (inpipe[1]); if (inpipe[0] != -1) close (inpipe[0]); if (outfp) _gpgrt_fclose (outfp); else if (outpipe[0] != -1) close (outpipe[0]); if (outpipe[1] != -1) close (outpipe[1]); if (errfp) _gpgrt_fclose (errfp); else if (errpipe[0] != -1) close (errpipe[0]); if (errpipe[1] != -1) close (errpipe[1]); return err; } if (!*pid) { /* This is the child. */ _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; 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, - void (*after_fork_cb)(void *), - void *after_fork_cb_arg, + int (*spawn_cb) (void *), + void *spawn_cb_arg, pid_t *pid) { gpg_error_t err; + int ask_inherit_fds = 0; _gpgrt_pre_syscall (); *pid = fork (); _gpgrt_post_syscall (); if (*pid == (pid_t)(-1)) { err = _gpg_err_code_from_syserror (); _gpgrt_log_error (_("error forking process: %s\n"), _gpg_strerror (err)); return err; } if (!*pid) { - if (after_fork_cb) - (*after_fork_cb) (after_fork_cb_arg); + if (spawn_cb) + ask_inherit_fds = (*spawn_cb) (spawn_cb_arg); /* Run child. */ - do_exec (pgmname, argv, infd, outfd, errfd, NULL, 0); + do_exec (pgmname, argv, infd, outfd, errfd, NULL, + ask_inherit_fds? GPGRT_SPAWN_INHERIT_FILE : 0); /*NOTREACHED*/ } return 0; } /* Waiting for child processes. * * waitpid(2) may return information about terminated children that we * did not yet request, and there is no portable way to wait for a * specific set of children. * * As a workaround, we store the results of children for later use. * * XXX: This assumes that PIDs are not reused too quickly. * FIXME: This is not thread-safe. */ struct terminated_child { pid_t pid; int exitcode; struct terminated_child *next; }; static struct terminated_child *terminated_children; static gpg_err_code_t store_result (pid_t pid, int exitcode) { struct terminated_child *c; c = xtrymalloc (sizeof *c); if (c == NULL) return _gpg_err_code_from_syserror (); c->pid = pid; c->exitcode = exitcode; c->next = terminated_children; terminated_children = c; return 0; } static int get_result (pid_t pid, int *r_exitcode) { struct terminated_child *c, **prevp; for (prevp = &terminated_children, c = terminated_children; c; prevp = &c->next, c = c->next) if (c->pid == pid) { *prevp = c->next; *r_exitcode = c->exitcode; xfree (c); return 1; } return 0; } /* See gpgrt-int.h for a description. */ gpg_err_code_t _gpgrt_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode) { gpg_err_code_t ec; int i, status; if (r_exitcode) *r_exitcode = -1; if (pid == (pid_t)(-1)) return GPG_ERR_INV_VALUE; _gpgrt_pre_syscall (); while ((i=waitpid (pid, &status, hang? 0:WNOHANG)) == (pid_t)(-1) && errno == EINTR); _gpgrt_post_syscall (); if (i == (pid_t)(-1)) { ec = _gpg_err_code_from_syserror (); _gpgrt_log_error (_("waiting for process %d to terminate failed: %s\n"), (int)pid, _gpg_strerror (ec)); } else if (!i) { ec = GPG_ERR_TIMEOUT; /* Still running. */ } else if (WIFEXITED (status) && WEXITSTATUS (status) == 127) { /* FIXME: This is GnuPG specific. */ _gpgrt_log_error (_("error running '%s': probably not installed\n"), pgmname); ec = GPG_ERR_CONFIGURATION; } else if (WIFEXITED (status) && WEXITSTATUS (status)) { if (!r_exitcode) _gpgrt_log_error (_("error running '%s': exit status %d\n"), pgmname, WEXITSTATUS (status)); else *r_exitcode = WEXITSTATUS (status); ec = GPG_ERR_GENERAL; } else if (!WIFEXITED (status)) { _gpgrt_log_error (_("error running '%s': terminated\n"), pgmname); ec = GPG_ERR_GENERAL; } else { if (r_exitcode) *r_exitcode = 0; ec = 0; } return ec; } /* See gpgrt-int.h for a description. * * FIXME: What about using a poll like data structure for the pids and * their exit codes? The whole thing is anyway problematic in a * threaded processs because waitpid has no association between PIDS * and threads. */ gpg_err_code_t _gpgrt_wait_processes (const char **pgmnames, pid_t *pids, size_t count, int hang, int *r_exitcodes) { gpg_err_code_t ec = 0; size_t i, left; int *dummy = NULL; if (!r_exitcodes) { dummy = r_exitcodes = xtrymalloc (sizeof *r_exitcodes * count); if (!dummy) return _gpg_err_code_from_syserror (); } for (i = 0, left = count; i < count; i++) { int status = -1; /* Skip invalid PID. */ if (pids[i] == (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)) left -= 1; r_exitcodes[i] = status; } while (left > 0) { pid_t pid; int status; _gpgrt_pre_syscall (); while ((pid = waitpid (-1, &status, hang ? 0 : WNOHANG)) == (pid_t)(-1) && errno == EINTR); _gpgrt_post_syscall (); if (pid == (pid_t)(-1)) { ec = _gpg_err_code_from_syserror (); _gpgrt_log_error (_("waiting for processes to terminate" " failed: %s\n"), _gpg_strerror (ec)); break; } else if (!pid) { ec = GPG_ERR_TIMEOUT; /* Still running. */ break; } else { for (i = 0; i < count; i++) if (pid == pids[i]) break; if (i == count) { /* No match, store this result. */ ec = store_result (pid, status); if (ec) break; continue; } /* Process PIDS[i] died. */ if (r_exitcodes[i] != (pid_t) -1) { _gpgrt_log_error ("PID %d was reused", (int)pid); ec = GPG_ERR_GENERAL; break; } left -= 1; r_exitcodes[i] = status; } } for (i = 0; i < count; i++) { if (r_exitcodes[i] == -1) continue; if (WIFEXITED (r_exitcodes[i]) && WEXITSTATUS (r_exitcodes[i]) == 127) { _gpgrt_log_error (_("error running '%s': probably not installed\n"), pgmnames[i]); ec = GPG_ERR_CONFIGURATION; } else if (WIFEXITED (r_exitcodes[i]) && WEXITSTATUS (r_exitcodes[i])) { if (dummy) _gpgrt_log_error (_("error running '%s': exit status %d\n"), pgmnames[i], WEXITSTATUS (r_exitcodes[i])); else r_exitcodes[i] = WEXITSTATUS (r_exitcodes[i]); ec = GPG_ERR_GENERAL; } else if (!WIFEXITED (r_exitcodes[i])) { _gpgrt_log_error (_("error running '%s': terminated\n"), pgmnames[i]); ec = GPG_ERR_GENERAL; } } xfree (dummy); return ec; } /* See gpgrt-int.h for a description. FIXME: We should add a prexec * callback. */ gpg_err_code_t _gpgrt_spawn_process_detached (const char *pgmname, const char *argv[], const char *envp[] ) { gpg_err_code_t ec; pid_t pid; int i; /* FIXME: Is this GnuPG specific or should we keep it. */ if (getuid() != geteuid()) return GPG_ERR_BUG; if (access (pgmname, X_OK)) return _gpg_err_code_from_syserror (); _gpgrt_pre_syscall (); pid = fork (); _gpgrt_post_syscall (); if (pid == (pid_t)(-1)) { ec = _gpg_err_code_from_syserror (); _gpgrt_log_error (_("error forking process: %s\n"), _gpg_strerror (ec)); return ec; } if (!pid) { pid_t pid2; /* gcry_control (GCRYCTL_TERM_SECMEM); */ if (setsid() == -1 || chdir ("/")) _exit (1); pid2 = fork (); /* Double fork to let init take over the new child. */ if (pid2 == (pid_t)(-1)) _exit (1); if (pid2) _exit (0); /* Let the parent exit immediately. */ for (i=0; envp && envp[i]; i++) { char *p = xtrystrdup (envp[i]); if (!p) out_of_core (__LINE__); putenv (p); } do_exec (pgmname, argv, -1, -1, -1, NULL, 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) { if (pid != (pid_t)(-1)) { _gpgrt_pre_syscall (); kill (pid, SIGTERM); _gpgrt_post_syscall (); } } void _gpgrt_release_process (pid_t pid) { (void)pid; } diff --git a/src/spawn-w32.c b/src/spawn-w32.c index 963b6a5..d17f971 100644 --- a/src/spawn-w32.c +++ b/src/spawn-w32.c @@ -1,928 +1,940 @@ /* 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 . * SPDX-License-Identifier: LGPL-2.1+ * * This file was originally a part of GnuPG. */ #include #if !defined(HAVE_W32_SYSTEM) #error This code is only used on W32. #endif #include #include #include #include #ifdef HAVE_SIGNAL_H # include #endif #include #include #ifdef HAVE_STAT # include #endif #define WIN32_LEAN_AND_MEAN /* We only need the OS core stuff. */ #include #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); } /* 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) { 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. */ 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); 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, - void (*after_fork_cb)(void *), - void *after_fork_cb_arg, + int (*spawn_cb) (void *), + void *spawn_cb_arg, pid_t *pid) { gpg_err_code_t err; SECURITY_ATTRIBUTES sec_attr; PROCESS_INFORMATION pi = { NULL, 0, 0, 0 }; STARTUPINFO si; char *cmdline; int ret, i; HANDLE stdhd[3]; + int ask_inherit = 0; - (void)after_fork_cb; - (void)after_fork_cb_arg; + if (spawn_cb) + ask_inherit = (*spawn_cb) (spawn_cb_arg); /* Setup return values. */ *pid = (pid_t)INVALID_HANDLE_VALUE; /* Prepare security attributes. */ memset (&sec_attr, 0, sizeof sec_attr ); sec_attr.nLength = sizeof sec_attr; - sec_attr.bInheritHandle = FALSE; + + 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); return 0; } /* See gpgrt-int.h for a description. */ gpg_err_code_t _gpgrt_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode) { return _gpgrt_wait_processes (&pgmname, &pid, 1, hang, r_exitcode); } /* See gpgrt-int.h for a description. */ gpg_err_code_t _gpgrt_wait_processes (const char **pgmnames, pid_t *pids, size_t count, int hang, int *r_exitcodes) { gpg_err_code_t ec = 0; size_t i; HANDLE *procs; int code; procs = xtrycalloc (count, sizeof *procs); if (procs == NULL) return _gpg_err_code_from_syserror (); for (i = 0; i < count; i++) { if (r_exitcodes) r_exitcodes[i] = -1; if (pids[i] == (pid_t)INVALID_HANDLE_VALUE) return GPG_ERR_INV_VALUE; procs[i] = pid_to_handle (pids[i]); } _gpgrt_pre_syscall (); code = WaitForMultipleObjects (count, procs, TRUE, hang? INFINITE : 0); _gpgrt_post_syscall (); switch (code) { case WAIT_TIMEOUT: ec = GPG_ERR_TIMEOUT; goto leave; case WAIT_FAILED: _gpgrt_log_error (_("waiting for processes to terminate failed: ec=%d\n"), (int)GetLastError ()); ec = GPG_ERR_GENERAL; goto leave; case WAIT_OBJECT_0: for (i = 0; i < count; i++) { DWORD exc; if (! GetExitCodeProcess (procs[i], &exc)) { _gpgrt_log_error (_("error getting exit code of process %d:" " ec=%d\n"), (int) pids[i], (int)GetLastError ()); ec = GPG_ERR_GENERAL; } else if (exc) { if (!r_exitcodes) _gpgrt_log_error (_("error running '%s': exit status %d\n"), pgmnames[i], (int)exc); else r_exitcodes[i] = (int)exc; ec = GPG_ERR_GENERAL; } else { if (r_exitcodes) r_exitcodes[i] = 0; } } break; default: _gpgrt_log_debug ("WaitForMultipleObjects returned unexpected code %d\n", code); ec = GPG_ERR_GENERAL; break; } leave: return ec; } /* See gpgrt-int.h for a description. */ gpg_err_code_t _gpgrt_spawn_process_detached (const char *pgmname, const char *argv[], const char *envp[] ) { gpg_err_code_t err; SECURITY_ATTRIBUTES sec_attr; PROCESS_INFORMATION pi = { NULL, /* Returns process handle. */ 0, /* Returns primary thread handle. */ 0, /* Returns pid. */ 0 /* Returns tid. */ }; STARTUPINFO si; int cr_flags; char *cmdline; int ret; gpg_err_code_t ec; /* We don't use ENVP. */ (void)envp; ec = _gpgrt_access (pgmname, X_OK); if (ec) return ec; /* Prepare security attributes. */ memset (&sec_attr, 0, sizeof sec_attr ); sec_attr.nLength = sizeof sec_attr; sec_attr.bInheritHandle = FALSE; /* Build the command line. */ err = build_w32_commandline (pgmname, argv, &cmdline); if (err) return err; /* Start the process. */ memset (&si, 0, sizeof si); si.cb = sizeof (si); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE; cr_flags = (CREATE_DEFAULT_ERROR_MODE | GetPriorityClass (GetCurrentProcess ()) | CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS); _gpgrt_log_debug ("CreateProcess(detached), path='%s' cmdline='%s'\n", pgmname, cmdline); ret = CreateProcess (pgmname, /* Program to start. */ cmdline, /* Command line arguments. */ &sec_attr, /* Process security attributes. */ &sec_attr, /* Thread security attributes. */ FALSE, /* Inherit handles. */ cr_flags, /* Creation flags. */ NULL, /* Environment. */ NULL, /* Use current drive/directory. */ &si, /* Startup information. */ &pi /* Returns process information. */ ); if (!ret) { _gpgrt_log_error ("CreateProcess(detached) failed: ec=%d\n", (int)GetLastError ()); xfree (cmdline); return GPG_ERR_GENERAL; } xfree (cmdline); cmdline = NULL; _gpgrt_log_debug ("CreateProcess(detached) ready: hProcess=%p hThread=%p" " dwProcessID=%d dwThreadId=%d\n", pi.hProcess, pi.hThread, (int) pi.dwProcessId, (int) pi.dwThreadId); CloseHandle (pi.hThread); CloseHandle (pi.hProcess); return 0; } /* Kill a process; that is send an appropriate signal to the process. gnupg_wait_process must be called to actually remove the process from the system. An invalid PID is ignored. */ void _gpgrt_kill_process (pid_t pid) { if (pid != (pid_t)INVALID_HANDLE_VALUE) { HANDLE process = (HANDLE) pid; /* Arbitrary error code. */ _gpgrt_pre_syscall (); TerminateProcess (process, 1); _gpgrt_post_syscall (); } } void _gpgrt_release_process (pid_t pid) { if (pid != (pid_t)INVALID_HANDLE_VALUE) { HANDLE process = (HANDLE)pid; CloseHandle (process); } } + +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 dba48b8..577a2be 100644 --- a/src/visibility.c +++ b/src/visibility.c @@ -1,1277 +1,1283 @@ /* 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 . * SPDX-License-Identifier: LGPL-2.1+ */ #include #include #include /* 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) { return _gpgrt_spawn_process (pgmname, argv, except, flags, r_infp, r_outfp, r_errfp, pid); } gpg_err_code_t gpgrt_spawn_process_fd (const char *pgmname, const char *argv[], int infd, int outfd, int errfd, - void (*after_fork_cb)(void *), - void *after_fork_cb_arg, + int (*spawn_cb)(void *), + void *spawn_cb_arg, pid_t *pid) { return _gpgrt_spawn_process_fd (pgmname, argv, infd, outfd, errfd, - after_fork_cb, after_fork_cb_arg, pid); + spawn_cb, spawn_cb_arg, pid); } gpg_err_code_t gpgrt_spawn_process_detached (const char *pgmname, const char *argv[], const char *envp[]) { return _gpgrt_spawn_process_detached (pgmname, argv, envp); } gpg_err_code_t gpgrt_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode) { return _gpgrt_wait_process (pgmname, pid, hang, r_exitcode); } gpg_err_code_t gpgrt_wait_processes (const char **pgmnames, pid_t *pids, size_t count, int hang, int *r_exitcodes) { return _gpgrt_wait_processes (pgmnames, pids, count, hang, r_exitcodes); } void gpgrt_kill_process (pid_t pid) { _gpgrt_kill_process (pid); } void gpgrt_release_process (pid_t pid) { _gpgrt_release_process (pid); } +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*/ diff --git a/src/visibility.h b/src/visibility.h index 2819394..a3ed6fc 100644 --- a/src/visibility.h +++ b/src/visibility.h @@ -1,421 +1,423 @@ /* visibility.h - Set visibility attribute * Copyright (C) 2014 g10 Code GmbH * * This file is part of libgpg-error. * * libgpg-error is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * libgpg-error is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ */ #ifndef _GPGRT_VISIBILITY_H #define _GPGRT_VISIBILITY_H /* Include the main header here so that public symbols are mapped to the internal underscored ones. */ #ifdef _GPGRT_INCL_BY_VISIBILITY_C # include "gpgrt-int.h" #endif /* Our use of the ELF visibility feature works by passing -fvisibiliy=hidden on the command line and by explicitly marking all exported functions as visible. NOTE: When adding new functions, please make sure to add them to gpg-error.vers and gpg-error.def.in as well. */ #ifdef _GPGRT_INCL_BY_VISIBILITY_C # ifdef GPGRT_USE_VISIBILITY # define MARK_VISIBLE(name) \ extern __typeof__ (name) name __attribute__ ((visibility("default"))); # else # define MARK_VISIBLE(name) /* */ # endif MARK_VISIBLE (gpg_strerror) MARK_VISIBLE (gpg_strerror_r) MARK_VISIBLE (gpg_strsource) MARK_VISIBLE (gpg_err_code_from_errno) MARK_VISIBLE (gpg_err_code_to_errno) MARK_VISIBLE (gpg_err_code_from_syserror) MARK_VISIBLE (gpg_err_set_errno) MARK_VISIBLE (gpg_err_init) MARK_VISIBLE (gpg_err_deinit) MARK_VISIBLE (gpgrt_add_emergency_cleanup) MARK_VISIBLE (gpgrt_abort) MARK_VISIBLE (gpg_error_check_version) MARK_VISIBLE (gpgrt_check_version) MARK_VISIBLE (gpgrt_lock_init) MARK_VISIBLE (gpgrt_lock_lock) MARK_VISIBLE (gpgrt_lock_unlock) MARK_VISIBLE (gpgrt_lock_destroy) MARK_VISIBLE (gpgrt_yield) MARK_VISIBLE (gpgrt_lock_trylock) MARK_VISIBLE (gpgrt_fopen) MARK_VISIBLE (gpgrt_mopen) MARK_VISIBLE (gpgrt_fopenmem) MARK_VISIBLE (gpgrt_fopenmem_init) MARK_VISIBLE (gpgrt_fdopen) MARK_VISIBLE (gpgrt_fdopen_nc) MARK_VISIBLE (gpgrt_sysopen) MARK_VISIBLE (gpgrt_sysopen_nc) MARK_VISIBLE (gpgrt_fpopen) MARK_VISIBLE (gpgrt_fpopen_nc) MARK_VISIBLE (gpgrt_freopen) MARK_VISIBLE (gpgrt_fopencookie) MARK_VISIBLE (gpgrt_fclose) MARK_VISIBLE (gpgrt_fcancel) MARK_VISIBLE (gpgrt_fclose_snatch) MARK_VISIBLE (gpgrt_onclose) MARK_VISIBLE (gpgrt_fileno) MARK_VISIBLE (gpgrt_fileno_unlocked) MARK_VISIBLE (gpgrt_syshd) MARK_VISIBLE (gpgrt_syshd_unlocked) MARK_VISIBLE (_gpgrt_set_std_fd) MARK_VISIBLE (_gpgrt_get_std_stream) MARK_VISIBLE (gpgrt_flockfile) MARK_VISIBLE (gpgrt_ftrylockfile) MARK_VISIBLE (gpgrt_funlockfile) MARK_VISIBLE (_gpgrt_pending) MARK_VISIBLE (_gpgrt_pending_unlocked) MARK_VISIBLE (gpgrt_feof) MARK_VISIBLE (gpgrt_feof_unlocked) MARK_VISIBLE (gpgrt_ferror) MARK_VISIBLE (gpgrt_ferror_unlocked) MARK_VISIBLE (gpgrt_clearerr) MARK_VISIBLE (gpgrt_clearerr_unlocked) MARK_VISIBLE (gpgrt_fflush) MARK_VISIBLE (gpgrt_fseek) MARK_VISIBLE (gpgrt_fseeko) MARK_VISIBLE (gpgrt_ftell) MARK_VISIBLE (gpgrt_ftello) MARK_VISIBLE (gpgrt_rewind) MARK_VISIBLE (gpgrt_ftruncate) MARK_VISIBLE (gpgrt_fgetc) MARK_VISIBLE (_gpgrt_getc_underflow) MARK_VISIBLE (gpgrt_fputc) MARK_VISIBLE (_gpgrt_putc_overflow) MARK_VISIBLE (gpgrt_ungetc) MARK_VISIBLE (gpgrt_read) MARK_VISIBLE (gpgrt_write) MARK_VISIBLE (gpgrt_write_sanitized) MARK_VISIBLE (gpgrt_write_hexstring) MARK_VISIBLE (gpgrt_fread) MARK_VISIBLE (gpgrt_fwrite) MARK_VISIBLE (gpgrt_fgets) MARK_VISIBLE (gpgrt_fputs) MARK_VISIBLE (gpgrt_fputs_unlocked) MARK_VISIBLE (gpgrt_getline) MARK_VISIBLE (gpgrt_read_line) MARK_VISIBLE (gpgrt_fprintf) MARK_VISIBLE (gpgrt_fprintf_unlocked) MARK_VISIBLE (gpgrt_fprintf_sf) MARK_VISIBLE (gpgrt_fprintf_sf_unlocked) MARK_VISIBLE (gpgrt_printf) MARK_VISIBLE (gpgrt_printf_unlocked) MARK_VISIBLE (gpgrt_vfprintf) MARK_VISIBLE (gpgrt_vfprintf_unlocked) MARK_VISIBLE (gpgrt_setvbuf) MARK_VISIBLE (gpgrt_setbuf) MARK_VISIBLE (gpgrt_set_binary) MARK_VISIBLE (gpgrt_set_nonblock) MARK_VISIBLE (gpgrt_get_nonblock) MARK_VISIBLE (gpgrt_poll) MARK_VISIBLE (gpgrt_tmpfile) MARK_VISIBLE (gpgrt_opaque_set) MARK_VISIBLE (gpgrt_opaque_get) MARK_VISIBLE (gpgrt_fname_set) MARK_VISIBLE (gpgrt_fname_get) MARK_VISIBLE (gpgrt_asprintf) MARK_VISIBLE (gpgrt_vasprintf) MARK_VISIBLE (gpgrt_bsprintf) MARK_VISIBLE (gpgrt_vbsprintf) MARK_VISIBLE (gpgrt_snprintf) MARK_VISIBLE (gpgrt_vsnprintf) MARK_VISIBLE (gpgrt_set_syscall_clamp) MARK_VISIBLE (gpgrt_get_syscall_clamp) MARK_VISIBLE (gpgrt_set_alloc_func) MARK_VISIBLE (gpgrt_realloc) MARK_VISIBLE (gpgrt_reallocarray) MARK_VISIBLE (gpgrt_malloc) MARK_VISIBLE (gpgrt_calloc) MARK_VISIBLE (gpgrt_strdup) MARK_VISIBLE (gpgrt_strconcat) MARK_VISIBLE (gpgrt_free) MARK_VISIBLE (gpgrt_getenv) MARK_VISIBLE (gpgrt_setenv) MARK_VISIBLE (gpgrt_mkdir) MARK_VISIBLE (gpgrt_chdir) MARK_VISIBLE (gpgrt_getcwd) MARK_VISIBLE (gpgrt_access) MARK_VISIBLE (gpgrt_b64dec_start) MARK_VISIBLE (gpgrt_b64dec_proc) MARK_VISIBLE (gpgrt_b64dec_finish) MARK_VISIBLE (gpgrt_b64enc_start) MARK_VISIBLE (gpgrt_b64enc_write) MARK_VISIBLE (gpgrt_b64enc_finish) MARK_VISIBLE (gpgrt_get_errorcount) MARK_VISIBLE (gpgrt_inc_errorcount) MARK_VISIBLE (gpgrt_log_set_sink) MARK_VISIBLE (gpgrt_log_set_socket_dir_cb) MARK_VISIBLE (gpgrt_log_set_pid_suffix_cb) MARK_VISIBLE (gpgrt_log_set_prefix) MARK_VISIBLE (gpgrt_log_get_prefix) MARK_VISIBLE (gpgrt_log_test_fd) MARK_VISIBLE (gpgrt_log_get_fd) MARK_VISIBLE (gpgrt_log_get_stream) MARK_VISIBLE (gpgrt_log) MARK_VISIBLE (gpgrt_logv) MARK_VISIBLE (gpgrt_logv_prefix) MARK_VISIBLE (gpgrt_log_string) MARK_VISIBLE (gpgrt_log_bug) MARK_VISIBLE (gpgrt_log_fatal) MARK_VISIBLE (gpgrt_log_error) MARK_VISIBLE (gpgrt_log_info) MARK_VISIBLE (gpgrt_log_debug) MARK_VISIBLE (gpgrt_log_debug_string) MARK_VISIBLE (gpgrt_log_printf) MARK_VISIBLE (gpgrt_log_printhex) MARK_VISIBLE (gpgrt_log_clock) MARK_VISIBLE (gpgrt_log_flush) MARK_VISIBLE (_gpgrt_log_assert) MARK_VISIBLE (gpgrt_make_pipe) MARK_VISIBLE (gpgrt_spawn_process) MARK_VISIBLE (gpgrt_spawn_process_fd) MARK_VISIBLE (gpgrt_spawn_process_detached) MARK_VISIBLE (gpgrt_wait_process) MARK_VISIBLE (gpgrt_wait_processes) MARK_VISIBLE (gpgrt_kill_process) MARK_VISIBLE (gpgrt_release_process) +MARK_VISIBLE (gpgrt_close_all_fds) MARK_VISIBLE (gpgrt_argparse) MARK_VISIBLE (gpgrt_argparser) MARK_VISIBLE (gpgrt_usage) MARK_VISIBLE (gpgrt_strusage) MARK_VISIBLE (gpgrt_set_strusage) MARK_VISIBLE (gpgrt_set_fixed_string_mapper) MARK_VISIBLE (gpgrt_set_usage_outfnc) MARK_VISIBLE (gpgrt_set_confdir) MARK_VISIBLE (gpgrt_cmp_version) MARK_VISIBLE (gpgrt_fnameconcat) MARK_VISIBLE (gpgrt_absfnameconcat) #undef MARK_VISIBLE #else /*!_GPGRT_INCL_BY_VISIBILITY_C*/ /* To avoid accidental use of the public functions inside Libgpg-error, we redefine them to catch such errors. */ #define gpg_strerror _gpgrt_USE_UNDERSCORED_FUNCTION #define gpg_strerror_r _gpgrt_USE_UNDERSCORED_FUNCTION #define gpg_strsource _gpgrt_USE_UNDERSCORED_FUNCTION #define gpg_err_code_from_errno _gpgrt_USE_UNDERSCORED_FUNCTION #define gpg_err_code_to_errno _gpgrt_USE_UNDERSCORED_FUNCTION #define gpg_err_code_from_syserror _gpgrt_USE_UNDERSCORED_FUNCTION #define gpg_err_set_errno _gpgrt_USE_UNDERSCORED_FUNCTION #define gpg_err_init _gpgrt_USE_UNDERSCORED_FUNCTION #define gpg_err_deinit _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_add_emergency_cleanup _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_abort _gpgrt_USE_UNDERSCORED_FUNCTION #define gpg_error_check_version _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_check_version _gpgrt_USE_OTHER_FUNCTION #define gpgrt_lock_init _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_lock_lock _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_lock_unlock _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_lock_destroy _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_yield _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_lock_trylock _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fopen _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_mopen _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fopenmem _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fopenmem_init _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fdopen _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fdopen_nc _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_sysopen _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_sysopen_nc _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fpopen _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fpopen_nc _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_freopen _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fopencookie _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fclose _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fcancel _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fclose_snatch _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_onclose _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fileno _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fileno_unlocked _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_syshd _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_syshd_unlocked _gpgrt_USE_UNDERSCORED_FUNCTION #define _gpgrt_set_std_fd _gpgrt_USE_UNDERSCORED_FUNCTION #define _gpgrt_get_std_stream _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_flockfile _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_ftrylockfile _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_funlockfile _gpgrt_USE_UNDERSCORED_FUNCTION #define _gpgrt_pending _gpgrt_USE_UNDERSCORED_FUNCTION #define _gpgrt_pending_unlocked _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_feof _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_feof_unlocked _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_ferror _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_ferror_unlocked _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_clearerr _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_clearerr_unlocked _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fflush _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fseek _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fseeko _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_ftell _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_ftello _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_rewind _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_ftruncate _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fgetc _gpgrt_USE_UNDERSCORED_FUNCTION #define _gpgrt_getc_underflow _gpgrt_USE_DBLUNDERSCO_FUNCTION #define gpgrt_fputc _gpgrt_USE_UNDERSCORED_FUNCTION #define _gpgrt_putc_overflow _gpgrt_USE_DBLUNDERSCO_FUNCTION #define gpgrt_ungetc _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_read _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_write _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_write_sanitized _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_write_hexstring _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fread _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fwrite _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fgets _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fputs _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fputs_unlocked _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_getline _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_read_line _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fprintf _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fprintf_unlocked _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fprintf_sf _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fprintf_sf_unlocked _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_printf _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_printf_unlocked _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_vfprintf _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_vfprintf_unlocked _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_setvbuf _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_setbuf _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_set_binary _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_set_nonblock _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_get_nonblock _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_poll _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_tmpfile _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_opaque_set _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_opaque_get _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fname_set _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fname_get _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_asprintf _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_vasprintf _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_bsprintf _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_vbsprintf _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_snprintf _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_vsnprintf _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_realloc _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_reallocarray _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_malloc _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_calloc _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_strdup _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_strconcat _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_free _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_getenv _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_setenv _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_mkdir _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_chdir _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_getcwd _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_access _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_set_syscall_clamp _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_get_syscall_clamp _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_set_alloc_func _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_b64enc_start _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_b64enc_write _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_b64enc_finish _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_b64dec_start _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_b64dec_proc _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_b64dec_finish _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_get_errorcount _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_inc_errorcount _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_log_set_sink _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_log_set_socket_dir_cb _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_log_set_pid_suffix_cb _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_log_set_prefix _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_log_get_prefix _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_log_test_fd _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_log_get_fd _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_log_get_stream _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_log _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_logv _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_logv_prefix _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_log_string _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_log_bug _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_log_fatal _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_log_error _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_log_info _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_log_debug _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_log_debug_string _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_log_printf _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_log_printhex _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_log_clock _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_log_flush _gpgrt_USE_UNDERSCORED_FUNCTION #define _gpgrt_log_assert _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_make_pipe _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_spawn_process _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_spawn_process_fd _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_spawn_process_detached _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_wait_process _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_wait_processes _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_kill_process _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_release_process _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_close_all_fds _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_argparse _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_argparser _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_usage _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_set_strusage _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_strusage _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_set_usage_outfnc _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_set_fixed_string_mapper _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_set_confdir _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_cmp_version _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fnameconcat _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_absfnameconcat _gpgrt_USE_UNDERSCORED_FUNCTION /* Windows specific functions. */ #define gpgrt_free_wchar _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_utf8_to_wchar _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_wchar_to_utf8 _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fname_to_wchar _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_w32_reg_query_string _gpgrt_USE_UNDERSCORED_FUNCTION #endif /*!_GPGRT_INCL_BY_VISIBILITY_C*/ #endif /*_GPGRT_VISIBILITY_H*/