1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-01-18 14:17:03 +01:00

Do not use pth functions after pth_kill. Fixes bug#1320.

Fabian Keil found the reason for a SIGBUS:

  In the "gpg-agent --daemon" case, main() calls pth_kill()
  after the client has been forked, so when es_deinit() is
  called on exit, acquiring the estream_list_lock seems to
  cause pth to dereference a pointer located in a memory
  region that has previously been free()'d.

My approach to fix it is different than his suggestion.  It should
allow to continue all estream operations after a pth_kill except for
restarting pth.
This commit is contained in:
Werner Koch 2011-04-29 10:16:58 +02:00
parent 1226772ffd
commit ce98524554
5 changed files with 341 additions and 276 deletions

View File

@ -1,3 +1,7 @@
2011-04-29 Werner Koch <wk@g10code.com>
* gpg-agent.c (main): s/pth_kill/es_pth_kill/.
2010-11-11 Werner Koch <wk@g10code.com> 2010-11-11 Werner Koch <wk@g10code.com>
* agent.h (opt): Add field SIGUSR2_ENABLED. * agent.h (opt): Add field SIGUSR2_ENABLED.
@ -211,7 +215,7 @@
* trustlist.c: Include estream.h. * trustlist.c: Include estream.h.
(agent_marktrusted): Replace stdio stream by estream functions. (agent_marktrusted): Replace stdio stream by estream functions.
* protect-tool.c (store_private_key): Use bin2hex. * protect-tool.c (store_private_key): Use bin2hex.
2009-06-02 Werner Koch <wk@g10code.com> 2009-06-02 Werner Koch <wk@g10code.com>
@ -225,7 +229,7 @@
2009-05-15 Werner Koch <wk@g10code.com> 2009-05-15 Werner Koch <wk@g10code.com>
Fix bug #1053. Fix bug #1053.
* agent.h (lookup_ttl_t): New. * agent.h (lookup_ttl_t): New.
* findkey.c (unprotect): Add arg LOOKUP_TTL. * findkey.c (unprotect): Add arg LOOKUP_TTL.
(agent_key_from_file): Ditto. (agent_key_from_file): Ditto.
@ -303,7 +307,7 @@
(agent_istrusted): Add arg R_DISABLED. Change all callers. (agent_istrusted): Add arg R_DISABLED. Change all callers.
(agent_marktrusted): Do not ask if flagged as disabled. Reverse (agent_marktrusted): Do not ask if flagged as disabled. Reverse
the order of the questions. Store the disabled flag. the order of the questions. Store the disabled flag.
* gpg-agent.c (main): Save signal mask and open fds. Restore mask * gpg-agent.c (main): Save signal mask and open fds. Restore mask
and close all fds prior to the exec. Fixes bug#1013. and close all fds prior to the exec. Fixes bug#1013.
@ -414,11 +418,11 @@
* command.c (cmd_geteventcounter): Mark unused arg. * command.c (cmd_geteventcounter): Mark unused arg.
(cmd_listtrusted, cmd_pksign, cmd_pkdecrypt, cmd_genkey): Ditto. (cmd_listtrusted, cmd_pksign, cmd_pkdecrypt, cmd_genkey): Ditto.
(cmd_updatestartuptty, post_cmd_notify): Ditto. (cmd_updatestartuptty, post_cmd_notify): Ditto.
* command-ssh.c (add_control_entry) * command-ssh.c (add_control_entry)
(ssh_handler_request_identities, ssh_handler_remove_identity) (ssh_handler_request_identities, ssh_handler_remove_identity)
(ssh_handler_remove_all_identities, ssh_handler_lock) (ssh_handler_remove_all_identities, ssh_handler_lock)
(ssh_handler_unlock): Ditto. (ssh_handler_unlock): Ditto.
* call-pinentry.c (pinentry_active_p, popup_message_thread) * call-pinentry.c (pinentry_active_p, popup_message_thread)
(agent_popup_message_stop): Ditto. (agent_popup_message_stop): Ditto.
* findkey.c (agent_public_key_from_file): Ditto. * findkey.c (agent_public_key_from_file): Ditto.
* genkey.c (check_passphrase_pattern): Ditto. * genkey.c (check_passphrase_pattern): Ditto.
@ -537,7 +541,7 @@
* agent.h (struct server_control_s): Add XAUTHORITY and * agent.h (struct server_control_s): Add XAUTHORITY and
PINENTRY_USER_DATA. PINENTRY_USER_DATA.
* gpg-agent.c: New option --xauthority. * gpg-agent.c: New option --xauthority.
(main, agent_init_default_ctrl) (main, agent_init_default_ctrl)
(agent_deinit_default_ctrl): Implemented (agent_deinit_default_ctrl): Implemented
* command.c (cmd_updatestartuptty): Ditto. * command.c (cmd_updatestartuptty): Ditto.
* command-ssh.c (start_command_handler_ssh): Ditto. * command-ssh.c (start_command_handler_ssh): Ditto.
@ -697,7 +701,7 @@
2007-06-21 Werner Koch <wk@g10code.com> 2007-06-21 Werner Koch <wk@g10code.com>
* agent.h (ctrl_t): Remove. It is now declared in ../common/util.h. * agent.h (ctrl_t): Remove. It is now declared in ../common/util.h.
* gpg-agent.c (check_for_running_agent): New arg SILENT. Changed * gpg-agent.c (check_for_running_agent): New arg SILENT. Changed
all callers. all callers.
@ -730,7 +734,7 @@
* preset-passphrase.c (main): Setup default socket name for * preset-passphrase.c (main): Setup default socket name for
simple-pwquery. simple-pwquery.
(map_spwq_error): Remove. (map_spwq_error): Remove.
(MAP_SPWQ_ERROR_IMPL): New. (MAP_SPWQ_ERROR_IMPL): New.
* call-pinentry.c (start_pinentry): Use gnupg_module_name. * call-pinentry.c (start_pinentry): Use gnupg_module_name.
* call-scd.c (start_scd): Ditto. * call-scd.c (start_scd): Ditto.
@ -792,7 +796,7 @@
(main): Call the setup_libgcrypt_logging helper. (main): Call the setup_libgcrypt_logging helper.
* protect-tool.c (my_gcry_logger): Removed. * protect-tool.c (my_gcry_logger): Removed.
(main): Call the setup_libgcrypt_logging helper. (main): Call the setup_libgcrypt_logging helper.
2007-04-03 Werner Koch <wk@g10code.com> 2007-04-03 Werner Koch <wk@g10code.com>
* trustlist.c (read_trustfiles): Take a missing trustlist as an * trustlist.c (read_trustfiles): Take a missing trustlist as an
@ -800,7 +804,7 @@
2007-03-20 Werner Koch <wk@g10code.com> 2007-03-20 Werner Koch <wk@g10code.com>
* protect-tool.c: New option --p12-charset. * protect-tool.c: New option --p12-charset.
* minip12.c (p12_build): Implement it. * minip12.c (p12_build): Implement it.
2007-03-19 Werner Koch <wk@g10code.com> 2007-03-19 Werner Koch <wk@g10code.com>
@ -835,7 +839,7 @@
2007-01-31 Werner Koch <wk@g10code.com> 2007-01-31 Werner Koch <wk@g10code.com>
* command-ssh.c (start_command_handler_ssh): * command-ssh.c (start_command_handler_ssh):
* Makefile.am (t_common_ldadd): Add LIBICONV. * Makefile.am (t_common_ldadd): Add LIBICONV.
@ -963,7 +967,7 @@
(agent_pksign_do): Use it here for the TLS algo. (agent_pksign_do): Use it here for the TLS algo.
* agent.h (GCRY_MD_USER_TLS_MD5SHA1): New. * agent.h (GCRY_MD_USER_TLS_MD5SHA1): New.
* divert-scd.c (pksign): Add case for tls-md5sha1. * divert-scd.c (pksign): Add case for tls-md5sha1.
* divert-scd.c (encode_md_for_card): Check that the algo is valid. * divert-scd.c (encode_md_for_card): Check that the algo is valid.
2006-10-04 Werner Koch <wk@g10code.com> 2006-10-04 Werner Koch <wk@g10code.com>
@ -1033,7 +1037,7 @@
Replaced all Assuan error codes by libgpg-error codes. Removed Replaced all Assuan error codes by libgpg-error codes. Removed
all map_to_assuan_status and map_assuan_err. all map_to_assuan_status and map_assuan_err.
* gpg-agent.c (main): Call assuan_set_assuan_err_source to have Assuan * gpg-agent.c (main): Call assuan_set_assuan_err_source to have Assuan
switch to gpg-error codes. switch to gpg-error codes.
* command.c (set_error): Adjusted. * command.c (set_error): Adjusted.
@ -1077,7 +1081,7 @@
* minip12.c (oid_pkcs_12_keyBag): New. * minip12.c (oid_pkcs_12_keyBag): New.
(parse_bag_encrypted_data): New arg R_RESULT. Support keybags and (parse_bag_encrypted_data): New arg R_RESULT. Support keybags and
return the key object. return the key object.
(p12_parse): Take new arg into account. Free RESULT on error. (p12_parse): Take new arg into account. Free RESULT on error.
2006-06-26 Werner Koch <wk@g10code.com> 2006-06-26 Werner Koch <wk@g10code.com>
@ -1145,7 +1149,7 @@
* call-scd.c (inq_needpin): Reworked to support the new KEYPADINFO. * call-scd.c (inq_needpin): Reworked to support the new KEYPADINFO.
* query.c (start_pinentry): Keep track of the owner. * query.c (start_pinentry): Keep track of the owner.
(popup_message_thread, agent_popup_message_start) (popup_message_thread, agent_popup_message_start)
(agent_popup_message_stop, agent_reset_query): New. (agent_popup_message_stop, agent_reset_query): New.
* command.c (start_command_handler): Make sure a popup window gets * command.c (start_command_handler): Make sure a popup window gets
closed. closed.
@ -1196,7 +1200,7 @@
2005-06-21 Werner Koch <wk@g10code.com> 2005-06-21 Werner Koch <wk@g10code.com>
* minip12.c (create_final): Cast size_t to ulong for printf. * minip12.c (create_final): Cast size_t to ulong for printf.
(build_key_bag, build_cert_bag, build_cert_sequence): Ditto. (build_key_bag, build_cert_bag, build_cert_sequence): Ditto.
2005-06-16 Werner Koch <wk@g10code.com> 2005-06-16 Werner Koch <wk@g10code.com>
@ -1211,7 +1215,7 @@
* protect.c (do_encryption): Ditto. * protect.c (do_encryption): Ditto.
(do_encryption): Made arg PROTBEGIN unsigned. Initialize RESULT (do_encryption): Made arg PROTBEGIN unsigned. Initialize RESULT
and RESULTLEN even on error. and RESULTLEN even on error.
(merge_lists): Need to cast unsigned char * for strcpy. Initialize (merge_lists): Need to cast unsigned char * for strcpy. Initialize
RESULTand RESULTLEN even on error. RESULTand RESULTLEN even on error.
(agent_unprotect): Likewise for strtoul. (agent_unprotect): Likewise for strtoul.
(make_shadow_info): Made P and INFO plain char. (make_shadow_info): Made P and INFO plain char.
@ -1271,7 +1275,7 @@
* command.c (cmd_updatestartuptty): New. * command.c (cmd_updatestartuptty): New.
* gpg-agent.c: New option --write-env-file. * gpg-agent.c: New option --write-env-file.
* gpg-agent.c (handle_connections): Make sure that the signals we * gpg-agent.c (handle_connections): Make sure that the signals we
are handling are not blocked.Block signals while creating new are handling are not blocked.Block signals while creating new
threads. threads.
@ -1541,8 +1545,8 @@
(make_cstring): Ditto. (make_cstring): Ditto.
(data_sign): Don't use a variable for the passphrase prompt, make (data_sign): Don't use a variable for the passphrase prompt, make
it translatable. it translatable.
(ssh_request_process): (ssh_request_process):
* findkey.c (modify_description): Renamed arguments for clarity, * findkey.c (modify_description): Renamed arguments for clarity,
polished documentation. Make comment a C-string. Fixed case of polished documentation. Make comment a C-string. Fixed case of
@ -1668,7 +1672,7 @@
2004-12-21 Werner Koch <wk@g10code.com> 2004-12-21 Werner Koch <wk@g10code.com>
* gpg-agent.c (main): Use default_homedir(). * gpg-agent.c (main): Use default_homedir().
* protect-tool.c (main): Ditto. * protect-tool.c (main): Ditto.
2004-12-20 Werner Koch <wk@g10code.com> 2004-12-20 Werner Koch <wk@g10code.com>
@ -1694,7 +1698,7 @@
* query.c (initialize_module_query): New. * query.c (initialize_module_query): New.
* call-scd.c (initialize_module_call_scd): New. * call-scd.c (initialize_module_call_scd): New.
* gpg-agent.c (main): Call them. * gpg-agent.c (main): Call them.
2004-12-18 Werner Koch <wk@g10code.com> 2004-12-18 Werner Koch <wk@g10code.com>
* gpg-agent.c (main): Remove special Pth initialize. * gpg-agent.c (main): Remove special Pth initialize.
@ -1746,10 +1750,10 @@
to Moritz for pointing this out. to Moritz for pointing this out.
2004-09-25 Moritz Schulte <moritz@g10code.com> 2004-09-25 Moritz Schulte <moritz@g10code.com>
* agent.h: Declare: agent_pksign_do. * agent.h: Declare: agent_pksign_do.
(struct server_control_s): New member: raw_value. (struct server_control_s): New member: raw_value.
* pksign.c (do_encode_md): New argument: raw_value; support * pksign.c (do_encode_md): New argument: raw_value; support
generation of raw (non-pkcs1) data objects; adjust callers. generation of raw (non-pkcs1) data objects; adjust callers.
(agent_pksign_do): New function, based on code ripped (agent_pksign_do): New function, based on code ripped
@ -1757,7 +1761,7 @@
(agent_pksign): Use agent_pksign_do. (agent_pksign): Use agent_pksign_do.
* command.c (start_command_handler): Set ctrl.digest.raw_value. * command.c (start_command_handler): Set ctrl.digest.raw_value.
2004-09-09 Werner Koch <wk@g10code.de> 2004-09-09 Werner Koch <wk@g10code.de>
* gpg-agent.c (check_for_running_agent): New. * gpg-agent.c (check_for_running_agent): New.
@ -1798,14 +1802,14 @@
* gpg-agent.c (handle_signal): Reload the trustlist on SIGHUP. * gpg-agent.c (handle_signal): Reload the trustlist on SIGHUP.
(start_connection_thread): Hack to simulate a ticker. (start_connection_thread): Hack to simulate a ticker.
* trustlist.c (agent_trustlist_housekeeping) * trustlist.c (agent_trustlist_housekeeping)
(agent_reload_trustlist): New. Protected all global functions (agent_reload_trustlist): New. Protected all global functions
here with a simple counter which is sufficient for Pth. here with a simple counter which is sufficient for Pth.
2004-05-03 Werner Koch <wk@gnupg.org> 2004-05-03 Werner Koch <wk@gnupg.org>
* gpg-agent.c: Remove help texts for options lile --lc-ctype. * gpg-agent.c: Remove help texts for options lile --lc-ctype.
(main): New option --allow-mark-trusted. (main): New option --allow-mark-trusted.
* trustlist.c (agent_marktrusted): Use it here. * trustlist.c (agent_marktrusted): Use it here.
2004-04-30 Werner Koch <wk@gnupg.org> 2004-04-30 Werner Koch <wk@gnupg.org>
@ -1878,7 +1882,7 @@
string. Changed all callers. string. Changed all callers.
* minip12.c: Revamped the build part. * minip12.c: Revamped the build part.
(p12_build): New args CERT and CERTLEN. (p12_build): New args CERT and CERTLEN.
2004-02-18 Werner Koch <wk@gnupg.org> 2004-02-18 Werner Koch <wk@gnupg.org>
@ -1972,7 +1976,7 @@
* findkey.c (agent_key_from_file): Now return an error code so * findkey.c (agent_key_from_file): Now return an error code so
that we have more detailed error messages in the upper layers. that we have more detailed error messages in the upper layers.
This fixes the handling of pinentry's cancel button. This fixes the handling of pinentry's cancel button.
* pksign.c (agent_pksign): Changed accordingly. * pksign.c (agent_pksign): Changed accordingly.
* pkdecrypt.c (agent_pkdecrypt): Ditto. * pkdecrypt.c (agent_pkdecrypt): Ditto.
* command.c (cmd_passwd): Ditto. * command.c (cmd_passwd): Ditto.
@ -1999,12 +2003,12 @@
* pksign.c (do_encode_md): Allocate enough space. Cast md * pksign.c (do_encode_md): Allocate enough space. Cast md
byte to unsigned char to prevent sign extension. byte to unsigned char to prevent sign extension.
2003-08-14 Timo Schulz <twoaday@freakmail.de> 2003-08-14 Timo Schulz <twoaday@freakmail.de>
* pksign.c (do_encode_md): Due to the fact pkcs#1 padding * pksign.c (do_encode_md): Due to the fact pkcs#1 padding
is now in Libgcrypt, use the new interface. is now in Libgcrypt, use the new interface.
2003-07-31 Werner Koch <wk@gnupg.org> 2003-07-31 Werner Koch <wk@gnupg.org>
* Makefile.am (gpg_agent_LDADD): Added INTLLIBS. * Makefile.am (gpg_agent_LDADD): Added INTLLIBS.
@ -2054,7 +2058,7 @@
* gpg-agent.c (handle_connections): Adjusted for Pth 2.0 * gpg-agent.c (handle_connections): Adjusted for Pth 2.0
Adjusted for changes in the libgcrypt API. Some more fixes for the Adjusted for changes in the libgcrypt API. Some more fixes for the
libgpg-error stuff. libgpg-error stuff.
2003-06-04 Werner Koch <wk@gnupg.org> 2003-06-04 Werner Koch <wk@gnupg.org>
@ -2133,11 +2137,11 @@
(agent_askpin,agent_get_passphrase,agent_get_confirmation): Add (agent_askpin,agent_get_passphrase,agent_get_confirmation): Add
CTRL arg and pass it ot start_pinentry. CTRL arg and pass it ot start_pinentry.
* command.c (cmd_get_passphrase): Pass CTRL argument. * command.c (cmd_get_passphrase): Pass CTRL argument.
* trustlist.c (agent_marktrusted): Add CTRL argument * trustlist.c (agent_marktrusted): Add CTRL argument
* command.c (cmd_marktrusted): Pass CTRL argument * command.c (cmd_marktrusted): Pass CTRL argument
* divert-scd.c (ask_for_card): Add CTRL arg. * divert-scd.c (ask_for_card): Add CTRL arg.
(divert_pksign,divert_pkdecrypt): Ditto. Changed caller. (divert_pksign,divert_pkdecrypt): Ditto. Changed caller.
(getpin_cb): Use OPAQUE to pass the CTRL variable. Changed both (getpin_cb): Use OPAQUE to pass the CTRL variable. Changed both
users. users.
* findkey.c (unprotect): Add CTRL arg. * findkey.c (unprotect): Add CTRL arg.
(agent_key_from_file): Ditto. (agent_key_from_file): Ditto.
@ -2372,7 +2376,7 @@
convert it to hex here. convert it to hex here.
* findkey.c (agent_write_private_key): New. * findkey.c (agent_write_private_key): New.
* genkey.c (store_key): And use it here. * genkey.c (store_key): And use it here.
* pkdecrypt.c (agent_pkdecrypt): Changed the way the diversion is done. * pkdecrypt.c (agent_pkdecrypt): Changed the way the diversion is done.
* divert-scd.c (divert_pkdecrypt): Changed interface and * divert-scd.c (divert_pkdecrypt): Changed interface and
implemented it. implemented it.
@ -2402,7 +2406,7 @@
* protect.c (snext,sskip,smatch): Moved to * protect.c (snext,sskip,smatch): Moved to
* sexp-parse.h: New file. * sexp-parse.h: New file.
* divert-scd.c: New. * divert-scd.c: New.
2002-02-27 Werner Koch <wk@gnupg.org> 2002-02-27 Werner Koch <wk@gnupg.org>
* protect.c (agent_shadow_key): New. * protect.c (agent_shadow_key): New.
@ -2430,7 +2434,7 @@
* gpg-agent.c: New option --default-cache-ttl. * gpg-agent.c: New option --default-cache-ttl.
* cache.c (agent_put_cache): Use it. * cache.c (agent_put_cache): Use it.
* cache.c: Add a few debug outputs. * cache.c: Add a few debug outputs.
* protect.c (agent_private_key_type): New. * protect.c (agent_private_key_type): New.
@ -2438,10 +2442,10 @@
* findkey.c (agent_key_from_file): Use it to decide whether we * findkey.c (agent_key_from_file): Use it to decide whether we
have to unprotect a key. have to unprotect a key.
(unprotect): Cache the passphrase. (unprotect): Cache the passphrase.
* findkey.c (agent_key_from_file,agent_key_available): The key * findkey.c (agent_key_from_file,agent_key_available): The key
files do now require a ".key" suffix to make a script's life files do now require a ".key" suffix to make a script's life
easier. easier.
* genkey.c (store_key): Ditto. * genkey.c (store_key): Ditto.
2002-01-31 Werner Koch <wk@gnupg.org> 2002-01-31 Werner Koch <wk@gnupg.org>
@ -2449,11 +2453,11 @@
* genkey.c (store_key): Protect the key. * genkey.c (store_key): Protect the key.
(agent_genkey): Ask for the passphrase. (agent_genkey): Ask for the passphrase.
* findkey.c (unprotect): Actually unprotect the key. * findkey.c (unprotect): Actually unprotect the key.
* query.c (agent_askpin): Add an optional start_err_text. * query.c (agent_askpin): Add an optional start_err_text.
2002-01-30 Werner Koch <wk@gnupg.org> 2002-01-30 Werner Koch <wk@gnupg.org>
* protect.c: New. * protect.c: New.
(hash_passphrase): Based on the GnuPG 1.0.6 version. (hash_passphrase): Based on the GnuPG 1.0.6 version.
* protect-tool.c: New * protect-tool.c: New
@ -2507,10 +2511,10 @@
* command.c (rc_to_assuan_status): Removed and changed all callers * command.c (rc_to_assuan_status): Removed and changed all callers
to use map_to_assuan_status. to use map_to_assuan_status.
2001-12-19 Werner Koch <wk@gnupg.org> 2001-12-19 Werner Koch <wk@gnupg.org>
* keyformat.txt: New. * keyformat.txt: New.
2001-12-19 Marcus Brinkmann <marcus@g10code.de> 2001-12-19 Marcus Brinkmann <marcus@g10code.de>

View File

@ -50,7 +50,7 @@
#include "gc-opt-flags.h" #include "gc-opt-flags.h"
#include "exechelp.h" #include "exechelp.h"
enum cmd_and_opt_values enum cmd_and_opt_values
{ aNull = 0, { aNull = 0,
oCsh = 'c', oCsh = 'c',
oQuiet = 'q', oQuiet = 'q',
@ -115,8 +115,8 @@ static ARGPARSE_OPTS opts[] = {
{ aGPGConfList, "gpgconf-list", 256, "@" }, { aGPGConfList, "gpgconf-list", 256, "@" },
{ aGPGConfTest, "gpgconf-test", 256, "@" }, { aGPGConfTest, "gpgconf-test", 256, "@" },
{ aUseStandardSocketP, "use-standard-socket-p", 256, "@" }, { aUseStandardSocketP, "use-standard-socket-p", 256, "@" },
{ 301, NULL, 0, N_("@Options:\n ") }, { 301, NULL, 0, N_("@Options:\n ") },
{ oServer, "server", 0, N_("run in server mode (foreground)") }, { oServer, "server", 0, N_("run in server mode (foreground)") },
@ -145,7 +145,7 @@ static ARGPARSE_OPTS opts[] = {
{ oFakedSystemTime, "faked-system-time", 2, "@" }, /* (epoch time) */ { oFakedSystemTime, "faked-system-time", 2, "@" }, /* (epoch time) */
{ oBatch, "batch", 0, "@" }, { oBatch, "batch", 0, "@" },
{ oHomedir, "homedir", 2, "@"}, { oHomedir, "homedir", 2, "@"},
{ oDisplay, "display", 2, "@" }, { oDisplay, "display", 2, "@" },
{ oTTYname, "ttyname", 2, "@" }, { oTTYname, "ttyname", 2, "@" },
@ -187,8 +187,8 @@ static ARGPARSE_OPTS opts[] = {
#define DEFAULT_CACHE_TTL_SSH (30*60) /* 30 minutes */ #define DEFAULT_CACHE_TTL_SSH (30*60) /* 30 minutes */
#define MAX_CACHE_TTL (120*60) /* 2 hours */ #define MAX_CACHE_TTL (120*60) /* 2 hours */
#define MAX_CACHE_TTL_SSH (120*60) /* 2 hours */ #define MAX_CACHE_TTL_SSH (120*60) /* 2 hours */
#define MIN_PASSPHRASE_LEN (8) #define MIN_PASSPHRASE_LEN (8)
#define MIN_PASSPHRASE_NONALPHA (1) #define MIN_PASSPHRASE_NONALPHA (1)
#define MAX_PASSPHRASE_DAYS (0) #define MAX_PASSPHRASE_DAYS (0)
/* The timer tick used for housekeeping stuff. For Windows we use a /* The timer tick used for housekeeping stuff. For Windows we use a
@ -257,11 +257,11 @@ static pid_t parent_pid = (pid_t)(-1);
/* /*
Local prototypes. Local prototypes.
*/ */
static char *create_socket_name (char *standard_name, char *template); static char *create_socket_name (char *standard_name, char *template);
static gnupg_fd_t create_server_socket (char *name, int is_ssh, static gnupg_fd_t create_server_socket (char *name, int is_ssh,
assuan_sock_nonce_t *nonce); assuan_sock_nonce_t *nonce);
static void create_directories (void); static void create_directories (void);
@ -293,7 +293,7 @@ static unsigned long pth_thread_id (void)
/* /*
Functions. Functions.
*/ */
static char * static char *
@ -301,7 +301,7 @@ make_libversion (const char *libname, const char *(*getfnc)(const char*))
{ {
const char *s; const char *s;
char *result; char *result;
if (maybe_setuid) if (maybe_setuid)
{ {
gcry_control (GCRYCTL_INIT_SECMEM, 0, 0); /* Drop setuid. */ gcry_control (GCRYCTL_INIT_SECMEM, 0, 0); /* Drop setuid. */
@ -343,7 +343,7 @@ my_strusage (int level)
case 41: p = _("Syntax: gpg-agent [options] [command [args]]\n" case 41: p = _("Syntax: gpg-agent [options] [command [args]]\n"
"Secret key management for GnuPG\n"); "Secret key management for GnuPG\n");
break; break;
default: p = NULL; default: p = NULL;
} }
return p; return p;
@ -380,7 +380,7 @@ set_debug (void)
/* Unless the "guru" string has been used we don't want to allow /* Unless the "guru" string has been used we don't want to allow
hashing debugging. The rationale is that people tend to hashing debugging. The rationale is that people tend to
select the highest debug value and would then clutter their select the highest debug value and would then clutter their
disk with debug files which may reveal confidential data. */ disk with debug files which may reveal confidential data. */
if (numok) if (numok)
opt.debug &= ~(DBG_HASHING_VALUE); opt.debug &= ~(DBG_HASHING_VALUE);
} }
@ -404,16 +404,16 @@ set_debug (void)
if (opt.debug) if (opt.debug)
log_info ("enabled debug flags:%s%s%s%s%s%s%s%s\n", log_info ("enabled debug flags:%s%s%s%s%s%s%s%s\n",
(opt.debug & DBG_COMMAND_VALUE)? " command":"", (opt.debug & DBG_COMMAND_VALUE)? " command":"",
(opt.debug & DBG_MPI_VALUE )? " mpi":"", (opt.debug & DBG_MPI_VALUE )? " mpi":"",
(opt.debug & DBG_CRYPTO_VALUE )? " crypto":"", (opt.debug & DBG_CRYPTO_VALUE )? " crypto":"",
(opt.debug & DBG_MEMORY_VALUE )? " memory":"", (opt.debug & DBG_MEMORY_VALUE )? " memory":"",
(opt.debug & DBG_CACHE_VALUE )? " cache":"", (opt.debug & DBG_CACHE_VALUE )? " cache":"",
(opt.debug & DBG_MEMSTAT_VALUE)? " memstat":"", (opt.debug & DBG_MEMSTAT_VALUE)? " memstat":"",
(opt.debug & DBG_HASHING_VALUE)? " hashing":"", (opt.debug & DBG_HASHING_VALUE)? " hashing":"",
(opt.debug & DBG_ASSUAN_VALUE )? " assuan":""); (opt.debug & DBG_ASSUAN_VALUE )? " assuan":"");
} }
/* Helper for cleanup to remove one socket with NAME. */ /* Helper for cleanup to remove one socket with NAME. */
static void static void
@ -433,7 +433,7 @@ remove_socket (char *name)
} }
*name = 0; *name = 0;
} }
} }
static void static void
cleanup (void) cleanup (void)
@ -501,7 +501,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
break; break;
case oNoGrab: opt.no_grab = 1; break; case oNoGrab: opt.no_grab = 1; break;
case oPinentryProgram: opt.pinentry_program = pargs->r.ret_str; break; case oPinentryProgram: opt.pinentry_program = pargs->r.ret_str; break;
case oPinentryTouchFile: opt.pinentry_touch_file = pargs->r.ret_str; break; case oPinentryTouchFile: opt.pinentry_touch_file = pargs->r.ret_str; break;
case oScdaemonProgram: opt.scdaemon_program = pargs->r.ret_str; break; case oScdaemonProgram: opt.scdaemon_program = pargs->r.ret_str; break;
@ -511,19 +511,19 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
case oDefCacheTTLSSH: opt.def_cache_ttl_ssh = pargs->r.ret_ulong; break; case oDefCacheTTLSSH: opt.def_cache_ttl_ssh = pargs->r.ret_ulong; break;
case oMaxCacheTTL: opt.max_cache_ttl = pargs->r.ret_ulong; break; case oMaxCacheTTL: opt.max_cache_ttl = pargs->r.ret_ulong; break;
case oMaxCacheTTLSSH: opt.max_cache_ttl_ssh = pargs->r.ret_ulong; break; case oMaxCacheTTLSSH: opt.max_cache_ttl_ssh = pargs->r.ret_ulong; break;
case oEnforcePassphraseConstraints: case oEnforcePassphraseConstraints:
opt.enforce_passphrase_constraints=1; opt.enforce_passphrase_constraints=1;
break; break;
case oMinPassphraseLen: opt.min_passphrase_len = pargs->r.ret_ulong; break; case oMinPassphraseLen: opt.min_passphrase_len = pargs->r.ret_ulong; break;
case oMinPassphraseNonalpha: case oMinPassphraseNonalpha:
opt.min_passphrase_nonalpha = pargs->r.ret_ulong; opt.min_passphrase_nonalpha = pargs->r.ret_ulong;
break; break;
case oCheckPassphrasePattern: case oCheckPassphrasePattern:
opt.check_passphrase_pattern = pargs->r.ret_str; opt.check_passphrase_pattern = pargs->r.ret_str;
break; break;
case oMaxPassphraseDays: case oMaxPassphraseDays:
opt.max_passphrase_days = pargs->r.ret_ulong; opt.max_passphrase_days = pargs->r.ret_ulong;
break; break;
case oEnablePassphraseHistory: case oEnablePassphraseHistory:
opt.enable_passhrase_history = 1; opt.enable_passhrase_history = 1;
@ -585,7 +585,7 @@ main (int argc, char **argv )
/* Please note that we may running SUID(ROOT), so be very CAREFUL /* Please note that we may running SUID(ROOT), so be very CAREFUL
when adding any stuff between here and the call to INIT_SECMEM() when adding any stuff between here and the call to INIT_SECMEM()
somewhere after the option parsing */ somewhere after the option parsing */
log_set_prefix ("gpg-agent", JNLIB_LOG_WITH_PREFIX|JNLIB_LOG_WITH_PID); log_set_prefix ("gpg-agent", JNLIB_LOG_WITH_PREFIX|JNLIB_LOG_WITH_PID);
/* Make sure that our subsystems are ready. */ /* Make sure that our subsystems are ready. */
i18n_init (); i18n_init ();
@ -631,7 +631,7 @@ main (int argc, char **argv )
opt.use_standard_socket = 1; /* Under Windows we always use a standard opt.use_standard_socket = 1; /* Under Windows we always use a standard
socket. */ socket. */
#endif #endif
shell = getenv ("SHELL"); shell = getenv ("SHELL");
if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") ) if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") )
csh_style = 1; csh_style = 1;
@ -642,7 +642,7 @@ main (int argc, char **argv )
{ {
const char *s; const char *s;
int idx; int idx;
static const char *names[] = static const char *names[] =
{ "DISPLAY", "TERM", "XAUTHORITY", "PINENTRY_USER_DATA", NULL }; { "DISPLAY", "TERM", "XAUTHORITY", "PINENTRY_USER_DATA", NULL };
err = 0; err = 0;
@ -664,10 +664,10 @@ main (int argc, char **argv )
if (err) if (err)
log_fatal ("error recording startup environment: %s\n", log_fatal ("error recording startup environment: %s\n",
gpg_strerror (err)); gpg_strerror (err));
/* Fixme: Better use the locale function here. */ /* Fixme: Better use the locale function here. */
opt.startup_lc_ctype = getenv ("LC_CTYPE"); opt.startup_lc_ctype = getenv ("LC_CTYPE");
if (opt.startup_lc_ctype) if (opt.startup_lc_ctype)
opt.startup_lc_ctype = xstrdup (opt.startup_lc_ctype); opt.startup_lc_ctype = xstrdup (opt.startup_lc_ctype);
opt.startup_lc_messages = getenv ("LC_MESSAGES"); opt.startup_lc_messages = getenv ("LC_MESSAGES");
if (opt.startup_lc_messages) if (opt.startup_lc_messages)
@ -700,13 +700,13 @@ main (int argc, char **argv )
gcry_control (GCRYCTL_INIT_SECMEM, 32768, 0); gcry_control (GCRYCTL_INIT_SECMEM, 32768, 0);
maybe_setuid = 0; maybe_setuid = 0;
/* /*
Now we are now working under our real uid Now we are now working under our real uid
*/ */
if (default_config) if (default_config)
configname = make_filename (opt.homedir, "gpg-agent.conf", NULL ); configname = make_filename (opt.homedir, "gpg-agent.conf", NULL );
argc = orig_argc; argc = orig_argc;
argv = orig_argv; argv = orig_argv;
pargs.argc = &argc; pargs.argc = &argc;
@ -737,7 +737,7 @@ main (int argc, char **argv )
configname, strerror(errno) ); configname, strerror(errno) );
exit(2); exit(2);
} }
xfree (configname); xfree (configname);
configname = NULL; configname = NULL;
} }
if (parse_debug && configname ) if (parse_debug && configname )
@ -791,7 +791,7 @@ main (int argc, char **argv )
case oFakedSystemTime: case oFakedSystemTime:
{ {
time_t faked_time = isotime2epoch (pargs.r.ret_str); time_t faked_time = isotime2epoch (pargs.r.ret_str);
if (faked_time == (time_t)(-1)) if (faked_time == (time_t)(-1))
faked_time = (time_t)strtoul (pargs.r.ret_str, NULL, 10); faked_time = (time_t)strtoul (pargs.r.ret_str, NULL, 10);
gnupg_set_time (faked_time, 0); gnupg_set_time (faked_time, 0);
@ -825,7 +825,7 @@ main (int argc, char **argv )
configname = NULL; configname = NULL;
goto next_pass; goto next_pass;
} }
xfree (configname); xfree (configname);
configname = NULL; configname = NULL;
if (log_get_errorcount(0)) if (log_get_errorcount(0))
@ -846,7 +846,7 @@ main (int argc, char **argv )
#endif #endif
set_debug (); set_debug ();
if (atexit (cleanup)) if (atexit (cleanup))
{ {
log_error ("atexit failed\n"); log_error ("atexit failed\n");
@ -857,7 +857,7 @@ main (int argc, char **argv )
initialize_module_call_pinentry (); initialize_module_call_pinentry ();
initialize_module_call_scd (); initialize_module_call_scd ();
initialize_module_trustlist (); initialize_module_trustlist ();
/* Try to create missing directories. */ /* Try to create missing directories. */
create_directories (); create_directories ();
@ -868,7 +868,7 @@ main (int argc, char **argv )
gnupg_sleep (debug_wait); gnupg_sleep (debug_wait);
log_debug ("... okay\n"); log_debug ("... okay\n");
} }
if (gpgconf_list == 3) if (gpgconf_list == 3)
agent_exit (!opt.use_standard_socket); agent_exit (!opt.use_standard_socket);
if (gpgconf_list == 2) if (gpgconf_list == 2)
@ -903,21 +903,21 @@ main (int argc, char **argv )
GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME, MAX_CACHE_TTL ); GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME, MAX_CACHE_TTL );
printf ("max-cache-ttl-ssh:%lu:%d:\n", printf ("max-cache-ttl-ssh:%lu:%d:\n",
GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME, MAX_CACHE_TTL_SSH ); GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME, MAX_CACHE_TTL_SSH );
printf ("enforce-passphrase-constraints:%lu:\n", printf ("enforce-passphrase-constraints:%lu:\n",
GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME); GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
printf ("min-passphrase-len:%lu:%d:\n", printf ("min-passphrase-len:%lu:%d:\n",
GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME, MIN_PASSPHRASE_LEN ); GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME, MIN_PASSPHRASE_LEN );
printf ("min-passphrase-nonalpha:%lu:%d:\n", printf ("min-passphrase-nonalpha:%lu:%d:\n",
GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME, GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME,
MIN_PASSPHRASE_NONALPHA); MIN_PASSPHRASE_NONALPHA);
printf ("check-passphrase-pattern:%lu:\n", printf ("check-passphrase-pattern:%lu:\n",
GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME); GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME);
printf ("max-passphrase-days:%lu:%d:\n", printf ("max-passphrase-days:%lu:%d:\n",
GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME, GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME,
MAX_PASSPHRASE_DAYS); MAX_PASSPHRASE_DAYS);
printf ("enable-passphrase-history:%lu:\n", printf ("enable-passphrase-history:%lu:\n",
GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME); GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
printf ("no-grab:%lu:\n", printf ("no-grab:%lu:\n",
GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME); GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
printf ("ignore-cache-for-signing:%lu:\n", printf ("ignore-cache-for-signing:%lu:\n",
GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME); GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
@ -934,11 +934,11 @@ main (int argc, char **argv )
don't clobber a logfile but print it directly to stderr. */ don't clobber a logfile but print it directly to stderr. */
if (!pipe_server && !is_daemon) if (!pipe_server && !is_daemon)
{ {
log_set_prefix (NULL, JNLIB_LOG_WITH_PREFIX); log_set_prefix (NULL, JNLIB_LOG_WITH_PREFIX);
check_for_running_agent (0, 0); check_for_running_agent (0, 0);
agent_exit (0); agent_exit (0);
} }
#ifdef ENABLE_NLS #ifdef ENABLE_NLS
/* gpg-agent usually does not output any messages because it runs in /* gpg-agent usually does not output any messages because it runs in
the background. For log files it is acceptable to have messages the background. For log files it is acceptable to have messages
@ -970,7 +970,7 @@ main (int argc, char **argv )
if (pipe_server) if (pipe_server)
{ {
/* This is the simple pipe based server */ /* This is the simple pipe based server */
ctrl_t ctrl; ctrl_t ctrl;
@ -1015,10 +1015,10 @@ main (int argc, char **argv )
/* Create the sockets. */ /* Create the sockets. */
socket_name = create_socket_name socket_name = create_socket_name
("S.gpg-agent", "/tmp/gpg-XXXXXX/S.gpg-agent"); ("S.gpg-agent", "/tmp/gpg-XXXXXX/S.gpg-agent");
if (opt.ssh_support) if (opt.ssh_support)
socket_name_ssh = create_socket_name socket_name_ssh = create_socket_name
("S.gpg-agent.ssh", "/tmp/gpg-XXXXXX/S.gpg-agent.ssh"); ("S.gpg-agent.ssh", "/tmp/gpg-XXXXXX/S.gpg-agent.ssh");
fd = create_server_socket (socket_name, 0, &socket_nonce); fd = create_server_socket (socket_name, 0, &socket_nonce);
@ -1039,12 +1039,12 @@ main (int argc, char **argv )
printf ("set GPG_AGENT_INFO=%s;%lu;1\n", socket_name, (ulong)pid); printf ("set GPG_AGENT_INFO=%s;%lu;1\n", socket_name, (ulong)pid);
#else /*!HAVE_W32_SYSTEM*/ #else /*!HAVE_W32_SYSTEM*/
pid = fork (); pid = fork ();
if (pid == (pid_t)-1) if (pid == (pid_t)-1)
{ {
log_fatal ("fork failed: %s\n", strerror (errno) ); log_fatal ("fork failed: %s\n", strerror (errno) );
exit (1); exit (1);
} }
else if (pid) else if (pid)
{ /* We are the parent */ { /* We are the parent */
char *infostr, *infostr_ssh_sock, *infostr_ssh_pid; char *infostr, *infostr_ssh_sock, *infostr_ssh_pid;
@ -1060,10 +1060,12 @@ main (int argc, char **argv )
with the signal mask the signal mask might not be correct with the signal mask the signal mask might not be correct
right now and thus we restore it. That is not strictly right now and thus we restore it. That is not strictly
necessary but some programs falsely assume a cleared necessary but some programs falsely assume a cleared
signal mask. */ signal mask. es_pth_kill is a wrapper around pth_kill to
if ( !pth_kill () ) take care not to use any Pth functions in the estream
code after Pth has been killed. */
if ( !es_pth_kill () )
log_error ("pth_kill failed in forked process\n"); log_error ("pth_kill failed in forked process\n");
#ifdef HAVE_SIGPROCMASK #ifdef HAVE_SIGPROCMASK
if (startup_signal_mask_valid) if (startup_signal_mask_valid)
{ {
@ -1073,7 +1075,7 @@ main (int argc, char **argv )
} }
else else
log_info ("no saved signal mask\n"); log_info ("no saved signal mask\n");
#endif /*HAVE_SIGPROCMASK*/ #endif /*HAVE_SIGPROCMASK*/
/* Create the info string: <name>:<pid>:<protocol_version> */ /* Create the info string: <name>:<pid>:<protocol_version> */
if (asprintf (&infostr, "GPG_AGENT_INFO=%s:%lu:1", if (asprintf (&infostr, "GPG_AGENT_INFO=%s:%lu:1",
@ -1109,7 +1111,7 @@ main (int argc, char **argv )
if (env_file_name) if (env_file_name)
{ {
FILE *fp; FILE *fp;
fp = fopen (env_file_name, "w"); fp = fopen (env_file_name, "w");
if (!fp) if (!fp)
log_error (_("error creating `%s': %s\n"), log_error (_("error creating `%s': %s\n"),
@ -1130,7 +1132,7 @@ main (int argc, char **argv )
} }
if (argc) if (argc)
{ /* Run the program given on the commandline. */ { /* Run the program given on the commandline. */
if (putenv (infostr)) if (putenv (infostr))
{ {
@ -1191,29 +1193,29 @@ main (int argc, char **argv )
printf ("%s; export SSH_AGENT_PID;\n", infostr_ssh_pid); printf ("%s; export SSH_AGENT_PID;\n", infostr_ssh_pid);
} }
} }
xfree (infostr); xfree (infostr);
if (opt.ssh_support) if (opt.ssh_support)
{ {
xfree (infostr_ssh_sock); xfree (infostr_ssh_sock);
xfree (infostr_ssh_pid); xfree (infostr_ssh_pid);
} }
exit (0); exit (0);
} }
/*NOTREACHED*/ /*NOTREACHED*/
} /* End parent */ } /* End parent */
/* /*
This is the child This is the child
*/ */
/* Detach from tty and put process into a new session */ /* Detach from tty and put process into a new session */
if (!nodetach ) if (!nodetach )
{ {
int i; int i;
unsigned int oldflags; unsigned int oldflags;
/* Close stdin, stdout and stderr unless it is the log stream */ /* Close stdin, stdout and stderr unless it is the log stream */
for (i=0; i <= 2; i++) for (i=0; i <= 2; i++)
{ {
if (!log_test_fd (i) && i != fd ) if (!log_test_fd (i) && i != fd )
{ {
@ -1247,7 +1249,7 @@ main (int argc, char **argv )
{ {
struct sigaction sa; struct sigaction sa;
sa.sa_handler = SIG_IGN; sa.sa_handler = SIG_IGN;
sigemptyset (&sa.sa_mask); sigemptyset (&sa.sa_mask);
sa.sa_flags = 0; sa.sa_flags = 0;
@ -1259,7 +1261,7 @@ main (int argc, char **argv )
handle_connections (fd, opt.ssh_support ? fd_ssh : GNUPG_INVALID_FD); handle_connections (fd, opt.ssh_support ? fd_ssh : GNUPG_INVALID_FD);
assuan_sock_close (fd); assuan_sock_close (fd);
} }
return 0; return 0;
} }
@ -1295,11 +1297,11 @@ agent_init_default_ctrl (ctrl_t ctrl)
session_env_setenv (ctrl->session_env, "TERM", default_ttytype); session_env_setenv (ctrl->session_env, "TERM", default_ttytype);
session_env_setenv (ctrl->session_env, "XAUTHORITY", default_xauthority); session_env_setenv (ctrl->session_env, "XAUTHORITY", default_xauthority);
session_env_setenv (ctrl->session_env, "PINENTRY_USER_DATA", NULL); session_env_setenv (ctrl->session_env, "PINENTRY_USER_DATA", NULL);
if (ctrl->lc_ctype) if (ctrl->lc_ctype)
xfree (ctrl->lc_ctype); xfree (ctrl->lc_ctype);
ctrl->lc_ctype = default_lc_ctype? xtrystrdup (default_lc_ctype) : NULL; ctrl->lc_ctype = default_lc_ctype? xtrystrdup (default_lc_ctype) : NULL;
if (ctrl->lc_messages) if (ctrl->lc_messages)
xfree (ctrl->lc_messages); xfree (ctrl->lc_messages);
ctrl->lc_messages = default_lc_messages? xtrystrdup (default_lc_messages) ctrl->lc_messages = default_lc_messages? xtrystrdup (default_lc_messages)
@ -1322,7 +1324,7 @@ agent_deinit_default_ctrl (ctrl_t ctrl)
/* Reread parts of the configuration. Note, that this function is /* Reread parts of the configuration. Note, that this function is
obviously not thread-safe and should only be called from the PTH obviously not thread-safe and should only be called from the PTH
signal handler. signal handler.
Fixme: Due to the way the argument parsing works, we create a Fixme: Due to the way the argument parsing works, we create a
memory leak here for all string type arguments. There is currently memory leak here for all string type arguments. There is currently
@ -1412,7 +1414,7 @@ get_agent_scd_notify_event (void)
log_error ("can't create scd notify event: %s\n", w32_strerror (-1) ); log_error ("can't create scd notify event: %s\n", w32_strerror (-1) );
else if (!DuplicateHandle (GetCurrentProcess(), h, else if (!DuplicateHandle (GetCurrentProcess(), h,
GetCurrentProcess(), &h2, GetCurrentProcess(), &h2,
EVENT_MODIFY_STATE|SYNCHRONIZE, TRUE, 0)) EVENT_MODIFY_STATE|SYNCHRONIZE, TRUE, 0))
{ {
log_error ("setting syncronize for scd notify event failed: %s\n", log_error ("setting syncronize for scd notify event failed: %s\n",
w32_strerror (-1) ); w32_strerror (-1) );
@ -1497,7 +1499,7 @@ create_server_socket (char *name, int is_ssh, assuan_sock_nonce_t *nonce)
agent_exit (2); agent_exit (2);
} }
serv_addr = xmalloc (sizeof (*serv_addr)); serv_addr = xmalloc (sizeof (*serv_addr));
memset (serv_addr, 0, sizeof *serv_addr); memset (serv_addr, 0, sizeof *serv_addr);
serv_addr->sun_family = AF_UNIX; serv_addr->sun_family = AF_UNIX;
if (strlen (name) + 1 >= sizeof (serv_addr->sun_path)) if (strlen (name) + 1 >= sizeof (serv_addr->sun_path))
@ -1529,7 +1531,7 @@ create_server_socket (char *name, int is_ssh, assuan_sock_nonce_t *nonce)
remove (name); remove (name);
rc = assuan_sock_bind (fd, (struct sockaddr*) serv_addr, len); rc = assuan_sock_bind (fd, (struct sockaddr*) serv_addr, len);
} }
if (rc != -1 if (rc != -1
&& (rc=assuan_sock_get_nonce ((struct sockaddr*)serv_addr, len, nonce))) && (rc=assuan_sock_get_nonce ((struct sockaddr*)serv_addr, len, nonce)))
log_error (_("error getting nonce for the socket\n")); log_error (_("error getting nonce for the socket\n"));
if (rc == -1) if (rc == -1)
@ -1537,9 +1539,9 @@ create_server_socket (char *name, int is_ssh, assuan_sock_nonce_t *nonce)
/* We use gpg_strerror here because it allows us to get strings /* We use gpg_strerror here because it allows us to get strings
for some W32 socket error codes. */ for some W32 socket error codes. */
log_error (_("error binding socket to `%s': %s\n"), log_error (_("error binding socket to `%s': %s\n"),
serv_addr->sun_path, serv_addr->sun_path,
gpg_strerror (gpg_error_from_errno (errno))); gpg_strerror (gpg_error_from_errno (errno)));
assuan_sock_close (fd); assuan_sock_close (fd);
if (opt.use_standard_socket) if (opt.use_standard_socket)
*name = 0; /* Inhibit removal of the socket by cleanup(). */ *name = 0; /* Inhibit removal of the socket by cleanup(). */
@ -1552,7 +1554,7 @@ create_server_socket (char *name, int is_ssh, assuan_sock_nonce_t *nonce)
assuan_sock_close (fd); assuan_sock_close (fd);
agent_exit (2); agent_exit (2);
} }
if (opt.verbose) if (opt.verbose)
log_info (_("listening on socket `%s'\n"), serv_addr->sun_path); log_info (_("listening on socket `%s'\n"), serv_addr->sun_path);
@ -1626,7 +1628,7 @@ create_directories (void)
log_error (_("can't create directory `%s': %s\n"), log_error (_("can't create directory `%s': %s\n"),
home, strerror (errno) ); home, strerror (errno) );
#endif #endif
else else
{ {
if (!opt.quiet) if (!opt.quiet)
log_info (_("directory `%s' created\n"), home); log_info (_("directory `%s' created\n"), home);
@ -1681,7 +1683,7 @@ handle_tick (void)
} }
} }
#endif /*HAVE_W32_SYSTEM*/ #endif /*HAVE_W32_SYSTEM*/
/* Code to be run every minute. */ /* Code to be run every minute. */
if (last_minute + 60 <= time (NULL)) if (last_minute + 60 <= time (NULL))
{ {
@ -1724,14 +1726,14 @@ handle_signal (int signo)
case SIGHUP: case SIGHUP:
agent_sighup_action (); agent_sighup_action ();
break; break;
case SIGUSR1: case SIGUSR1:
log_info ("SIGUSR1 received - printing internal information:\n"); log_info ("SIGUSR1 received - printing internal information:\n");
pth_ctrl (PTH_CTRL_DUMPSTATE, log_get_stream ()); pth_ctrl (PTH_CTRL_DUMPSTATE, log_get_stream ());
agent_query_dump_state (); agent_query_dump_state ();
agent_scd_dump_state (); agent_scd_dump_state ();
break; break;
case SIGUSR2: case SIGUSR2:
agent_sigusr2_action (); agent_sigusr2_action ();
break; break;
@ -1751,7 +1753,7 @@ handle_signal (int signo)
agent_exit (0); agent_exit (0);
} }
break; break;
case SIGINT: case SIGINT:
log_info ("SIGINT received - immediate shutdown\n"); log_info ("SIGINT received - immediate shutdown\n");
log_info( "%s %s stopped\n", strusage(11), strusage(13)); log_info( "%s %s stopped\n", strusage(11), strusage(13));
@ -1767,12 +1769,12 @@ handle_signal (int signo)
/* Check the nonce on a new connection. This is a NOP unless we we /* Check the nonce on a new connection. This is a NOP unless we we
are using our Unix domain socket emulation under Windows. */ are using our Unix domain socket emulation under Windows. */
static int static int
check_nonce (ctrl_t ctrl, assuan_sock_nonce_t *nonce) check_nonce (ctrl_t ctrl, assuan_sock_nonce_t *nonce)
{ {
if (assuan_sock_check_nonce (ctrl->thread_startup.fd, nonce)) if (assuan_sock_check_nonce (ctrl->thread_startup.fd, nonce))
{ {
log_info (_("error reading nonce on fd %d: %s\n"), log_info (_("error reading nonce on fd %d: %s\n"),
FD2INT(ctrl->thread_startup.fd), strerror (errno)); FD2INT(ctrl->thread_startup.fd), strerror (errno));
assuan_sock_close (ctrl->thread_startup.fd); assuan_sock_close (ctrl->thread_startup.fd);
xfree (ctrl); xfree (ctrl);
@ -1794,14 +1796,14 @@ start_connection_thread (void *arg)
agent_init_default_ctrl (ctrl); agent_init_default_ctrl (ctrl);
if (opt.verbose) if (opt.verbose)
log_info (_("handler 0x%lx for fd %d started\n"), log_info (_("handler 0x%lx for fd %d started\n"),
pth_thread_id (), FD2INT(ctrl->thread_startup.fd)); pth_thread_id (), FD2INT(ctrl->thread_startup.fd));
start_command_handler (ctrl, GNUPG_INVALID_FD, ctrl->thread_startup.fd); start_command_handler (ctrl, GNUPG_INVALID_FD, ctrl->thread_startup.fd);
if (opt.verbose) if (opt.verbose)
log_info (_("handler 0x%lx for fd %d terminated\n"), log_info (_("handler 0x%lx for fd %d terminated\n"),
pth_thread_id (), FD2INT(ctrl->thread_startup.fd)); pth_thread_id (), FD2INT(ctrl->thread_startup.fd));
agent_deinit_default_ctrl (ctrl); agent_deinit_default_ctrl (ctrl);
xfree (ctrl); xfree (ctrl);
return NULL; return NULL;
@ -1826,7 +1828,7 @@ start_connection_thread_ssh (void *arg)
if (opt.verbose) if (opt.verbose)
log_info (_("ssh handler 0x%lx for fd %d terminated\n"), log_info (_("ssh handler 0x%lx for fd %d terminated\n"),
pth_thread_id (), FD2INT(ctrl->thread_startup.fd)); pth_thread_id (), FD2INT(ctrl->thread_startup.fd));
agent_deinit_default_ctrl (ctrl); agent_deinit_default_ctrl (ctrl);
xfree (ctrl); xfree (ctrl);
return NULL; return NULL;
@ -1872,7 +1874,7 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
sa.sa_handler = SIG_IGN; sa.sa_handler = SIG_IGN;
sa.sa_flags = 0; sa.sa_flags = 0;
sigaction (mysigs[i], &sa, NULL); sigaction (mysigs[i], &sa, NULL);
sigaddset (&sigs, mysigs[i]); sigaddset (&sigs, mysigs[i]);
} }
} }
@ -2020,7 +2022,7 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
xfree (ctrl); xfree (ctrl);
assuan_sock_close (fd); assuan_sock_close (fd);
} }
else else
{ {
char threadname[50]; char threadname[50];
@ -2040,7 +2042,7 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
fd = GNUPG_INVALID_FD; fd = GNUPG_INVALID_FD;
} }
if (!shutdown_pending && listen_fd_ssh != GNUPG_INVALID_FD if (!shutdown_pending && listen_fd_ssh != GNUPG_INVALID_FD
&& FD_ISSET ( FD2INT (listen_fd_ssh), &read_fdset)) && FD_ISSET ( FD2INT (listen_fd_ssh), &read_fdset))
{ {
ctrl_t ctrl; ctrl_t ctrl;
@ -2133,7 +2135,7 @@ check_own_socket_thread (void *arg)
log_error ("can't connect my own socket: %s\n", gpg_strerror (rc)); log_error ("can't connect my own socket: %s\n", gpg_strerror (rc));
goto leave; goto leave;
} }
init_membuf (&mb, 100); init_membuf (&mb, 100);
rc = assuan_transact (ctx, "GETINFO pid", check_own_socket_pid_cb, &mb, rc = assuan_transact (ctx, "GETINFO pid", check_own_socket_pid_cb, &mb,
NULL, NULL, NULL, NULL); NULL, NULL, NULL, NULL);
@ -2141,7 +2143,7 @@ check_own_socket_thread (void *arg)
buffer = get_membuf (&mb, NULL); buffer = get_membuf (&mb, NULL);
if (rc || !buffer) if (rc || !buffer)
{ {
log_error ("sending command \"%s\" to my own socket failed: %s\n", log_error ("sending command \"%s\" to my own socket failed: %s\n",
"GETINFO pid", gpg_strerror (rc)); "GETINFO pid", gpg_strerror (rc));
rc = 1; rc = 1;
} }
@ -2152,7 +2154,7 @@ check_own_socket_thread (void *arg)
} }
else if (opt.verbose > 1) else if (opt.verbose > 1)
log_error ("socket is still served by this server\n"); log_error ("socket is still served by this server\n");
xfree (buffer); xfree (buffer);
leave: leave:

View File

@ -1,3 +1,14 @@
2011-04-29 Werner Koch <wk@g10code.com>
* estream.c (es_pth_kill): New.
(estream_pth_killed): New.
(ESTREAM_MUTEX_LOCK, ESTREAM_MUTEX_UNLOCK)
(ESTREAM_MUTEX_TRYLOCK, ESTREAM_MUTEX_INITIALIZE): Take care of
the killed status.
(ESTREAM_SYS_YIELD): Ditto.
(es_pth_read, es_pth_write): Ditto.
(es_init_do): Ditto.
2011-01-20 Werner Koch <wk@g10code.com> 2011-01-20 Werner Koch <wk@g10code.com>
* estream.c (es_func_mem_write): Fix computation of NEWSIZE. * estream.c (es_func_mem_write): Fix computation of NEWSIZE.
@ -288,7 +299,7 @@
* percent.c, t-percent.c: New. * percent.c, t-percent.c: New.
* exechelp.c (gnupg_spawn_process, gnupg_spawn_process_fd) * exechelp.c (gnupg_spawn_process, gnupg_spawn_process_fd)
(gnupg_spawn_process_detached) [W32]: Remove debug output. (gnupg_spawn_process_detached) [W32]: Remove debug output.
2008-11-20 Werner Koch <wk@g10code.com> 2008-11-20 Werner Koch <wk@g10code.com>
@ -503,7 +514,7 @@
2007-11-05 Werner Koch <wk@g10code.com> 2007-11-05 Werner Koch <wk@g10code.com>
* audit.c, audit.h: New. * audit.c, audit.h: New.
* Makefile.am: Add rules to build audit-events.h. * Makefile.am: Add rules to build audit-events.h.
* exaudit.awk: New. * exaudit.awk: New.
* mkstrtable.awk: New. Taken from libgpg-error. * mkstrtable.awk: New. Taken from libgpg-error.
@ -528,7 +539,7 @@
(gnupg_create_inbound_pipe): New. (gnupg_create_inbound_pipe): New.
* util.h (GNUPG_MODULE_NAME_GPGSM, GNUPG_MODULE_NAME_GPG): New. * util.h (GNUPG_MODULE_NAME_GPGSM, GNUPG_MODULE_NAME_GPG): New.
* homedir.c (gnupg_module_name): Add them * homedir.c (gnupg_module_name): Add them
2007-08-28 Werner Koch <wk@g10code.com> 2007-08-28 Werner Koch <wk@g10code.com>
* gettime.c (check_isotime, add_isotime): New. Originally written * gettime.c (check_isotime, add_isotime): New. Originally written
@ -549,7 +560,7 @@
2007-08-22 Werner Koch <wk@g10code.com> 2007-08-22 Werner Koch <wk@g10code.com>
Updated estream from libestream. Updated estream from libestream.
* estream.c (mem_malloc, mem_realloc, mem_free): New. Use them * estream.c (mem_malloc, mem_realloc, mem_free): New. Use them
instead of the ES_MEM_foo. instead of the ES_MEM_foo.
* estream.c (estream_cookie_mem): Remove members DONT_FREE, * estream.c (estream_cookie_mem): Remove members DONT_FREE,
@ -618,7 +629,7 @@
2007-07-05 Werner Koch <wk@g10code.com> 2007-07-05 Werner Koch <wk@g10code.com>
* t-gettime.c: New. * t-gettime.c: New.
* gettime.c (isotime2epoch, epoch2isotime): New. * gettime.c (isotime2epoch, epoch2isotime): New.
2007-07-04 Werner Koch <wk@g10code.com> 2007-07-04 Werner Koch <wk@g10code.com>
@ -650,7 +661,7 @@
(iobuf_translate_file_handle): Remove. (iobuf_translate_file_handle): Remove.
(translate_file_handle): Use new function. (translate_file_handle): Use new function.
* estream-printf.c [TEST]: Header including fixes. * estream-printf.c [TEST]: Header including fixes.
(do_format): Do not append a trailing Nul. This avoids spurious (do_format): Do not append a trailing Nul. This avoids spurious
Nuls in the es_printf output. Nuls in the es_printf output.
(estream_vsnprintf, estream_vasprintf): Take this in account. (estream_vsnprintf, estream_vasprintf): Take this in account.
@ -664,11 +675,11 @@
(es_convert_mode): Set O_BINARY. (es_convert_mode): Set O_BINARY.
(es_func_fd_create, es_func_fp_create, es_func_file_create) [W32]: (es_func_fd_create, es_func_fp_create, es_func_file_create) [W32]:
Call setmode if requested. Call setmode if requested.
2007-06-24 Werner Koch <wk@g10code.com> 2007-06-24 Werner Koch <wk@g10code.com>
* estream.c (do_fpopen, es_fpopen, es_fpopen_nc): New. * estream.c (do_fpopen, es_fpopen, es_fpopen_nc): New.
(es_func_fp_create, es_func_fp_read, es_func_fp_write) (es_func_fp_create, es_func_fp_read, es_func_fp_write)
(es_func_fp_seek, es_func_fp_destroy): New. (es_func_fp_seek, es_func_fp_destroy): New.
2007-06-22 Werner Koch <wk@g10code.com> 2007-06-22 Werner Koch <wk@g10code.com>
@ -676,7 +687,7 @@
* estream.c (es_fdopen): Factored code out to.. * estream.c (es_fdopen): Factored code out to..
(do_fdopen): .. new. (do_fdopen): .. new.
(es_fdopen_nc): New. (es_fdopen_nc): New.
(estream_cookie_fd): Add field NO_CLOSE. (estream_cookie_fd): Add field NO_CLOSE.
(es_func_fd_create): Add arg NO_CLOSE and changed all callers. (es_func_fd_create): Add arg NO_CLOSE and changed all callers.
(es_func_fd_destroy): Handle the new flag. (es_func_fd_destroy): Handle the new flag.
@ -718,8 +729,8 @@
(agent_open): Use it if GPG_AGENT_INFO is not set. (agent_open): Use it if GPG_AGENT_INFO is not set.
(simple_pwquery): Extended to allow returning of otehyr error codes. (simple_pwquery): Extended to allow returning of otehyr error codes.
* util.h (GNUPG_MODULE_NAME_AGENT, GNUPG_MODULE_NAME_PINENTRY) * util.h (GNUPG_MODULE_NAME_AGENT, GNUPG_MODULE_NAME_PINENTRY)
(GNUPG_MODULE_NAME_SCDAEMON, GNUPG_MODULE_NAME_DIRMNGR) (GNUPG_MODULE_NAME_SCDAEMON, GNUPG_MODULE_NAME_DIRMNGR)
(GNUPG_MODULE_NAME_PROTECT_TOOL): New. (GNUPG_MODULE_NAME_PROTECT_TOOL): New.
* homedir.c (gnupg_module_name): New. * homedir.c (gnupg_module_name): New.
(gnupg_bindir): New. (gnupg_bindir): New.
@ -800,7 +811,7 @@
2007-05-07 Werner Koch <wk@g10code.com> 2007-05-07 Werner Koch <wk@g10code.com>
* signal.c (got_fatal_signal): Protect SIG from being clobbered by * signal.c (got_fatal_signal): Protect SIG from being clobbered by
a faulty signal implementaion. Suggested by James Juran. a faulty signal implementaion. Suggested by James Juran.
2007-04-25 Werner Koch <wk@g10code.com> 2007-04-25 Werner Koch <wk@g10code.com>
@ -876,9 +887,9 @@
2006-10-17 Werner Koch <wk@g10code.com> 2006-10-17 Werner Koch <wk@g10code.com>
* estream.c (struct estream_internal, es_initialize) * estream.c (struct estream_internal, es_initialize)
(es_deinitialize, print_fun_writer, es_print): New and modified (es_deinitialize, print_fun_writer, es_print): New and modified
functions to avoid tempfiles for printf style printing. functions to avoid tempfiles for printf style printing.
* Makefile.am (libcommonpth_a_SOURCES): New. We now build a secon * Makefile.am (libcommonpth_a_SOURCES): New. We now build a secon
version of the library with explicit Pth support. version of the library with explicit Pth support.
@ -921,7 +932,7 @@
buffer. buffer.
2006-09-27 Florian Weimer <fweimer@bfk.de> (wk) 2006-09-27 Florian Weimer <fweimer@bfk.de> (wk)
* iobuf.c (iobuf_unread): New. * iobuf.c (iobuf_unread): New.
2006-09-22 Werner Koch <wk@g10code.com> 2006-09-22 Werner Koch <wk@g10code.com>
@ -1108,7 +1119,7 @@
* estream.c (estream_cookie_mem): Make MEMORY unsigned char*. * estream.c (estream_cookie_mem): Make MEMORY unsigned char*.
(es_write): Make BUFFER a void *. (es_write): Make BUFFER a void *.
(es_writen): Ditto. (es_writen): Ditto.
(es_func_fd_read, es_func_fd_write, es_func_mem_read) (es_func_fd_read, es_func_fd_write, es_func_mem_read)
(es_func_mem_write): Ditto. (es_func_mem_write): Ditto.
(es_read, es_readn): Ditto. (es_read, es_readn): Ditto.
(es_func_mem_write): Made MEMORY_NEW an unsigned char *. (es_func_mem_write): Made MEMORY_NEW an unsigned char *.
@ -1119,7 +1130,7 @@
* estream.c: Use HAVE_CONFIG_H and not USE_CONFIG_H! * estream.c: Use HAVE_CONFIG_H and not USE_CONFIG_H!
(es_func_fd_read, es_func_fd_write): Protect against EINTR. (es_func_fd_read, es_func_fd_write): Protect against EINTR.
2005-06-01 Werner Koch <wk@g10code.com> 2005-06-01 Werner Koch <wk@g10code.com>
* Makefile.am (AM_CPPFLAGS): Added. * Makefile.am (AM_CPPFLAGS): Added.
@ -1191,7 +1202,7 @@
* signal.c (got_fatal_signal, got_usr_signal) * signal.c (got_fatal_signal, got_usr_signal)
(got_fatal_signal) [DOSISH]: Don't build. (got_fatal_signal) [DOSISH]: Don't build.
* simple-gettext.c: Include sysutils.h * simple-gettext.c: Include sysutils.h
* homedir.c: New. Use CSIDL_APPDATA for W32 as the default home * homedir.c: New. Use CSIDL_APPDATA for W32 as the default home
directory. directory.
@ -1385,10 +1396,10 @@
2003-08-14 Timo Schulz <twoaday@freakmail.de> 2003-08-14 Timo Schulz <twoaday@freakmail.de>
* dynload.h. New. W32 wrapper around the dynload mechanism. * dynload.h. New. W32 wrapper around the dynload mechanism.
2003-07-15 Werner Koch <wk@gnupg.org> 2003-07-15 Werner Koch <wk@gnupg.org>
* simple-pwquery.c, simple-pwquery.h: New; moved from ../agent. * simple-pwquery.c, simple-pwquery.h: New; moved from ../agent.
* Makefile.am (libsimple_pwquery_a_LIBADD): New. * Makefile.am (libsimple_pwquery_a_LIBADD): New.
2003-06-25 Werner Koch <wk@gnupg.org> 2003-06-25 Werner Koch <wk@gnupg.org>
@ -1562,10 +1573,10 @@
* sysutils.c: New. This is the misc.c file from gnupg 1.0.6 with * sysutils.c: New. This is the misc.c file from gnupg 1.0.6 with
the OpenPGP stuff removed. the OpenPGP stuff removed.
* sysutils.h: New. * sysutils.h: New.
2002-01-15 Werner Koch <wk@gnupg.org> 2002-01-15 Werner Koch <wk@gnupg.org>
* maperror.c: Add mapping for Not_Trusted. * maperror.c: Add mapping for Not_Trusted.
2002-01-11 Werner Koch <wk@gnupg.org> 2002-01-11 Werner Koch <wk@gnupg.org>
@ -1592,8 +1603,8 @@
* util.h (digitp, hexdigitp): New ctype like macros. * util.h (digitp, hexdigitp): New ctype like macros.
(atoi_1,atoi_2,atoi_4,xtoi_1,xtoi_2): New. (atoi_1,atoi_2,atoi_4,xtoi_1,xtoi_2): New.
Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007,
2008, 2009 Free Software Foundation, Inc. 2008, 2009 Free Software Foundation, Inc.
@ -1604,5 +1615,3 @@
This file is distributed in the hope that it will be useful, but This file is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

View File

@ -150,20 +150,10 @@ typedef void (*func_free_t) (void *mem);
/* Locking. */ /* Locking. */
#ifdef HAVE_PTH #ifdef HAVE_PTH
typedef pth_mutex_t estream_mutex_t; typedef pth_mutex_t estream_mutex_t;
# define ESTREAM_MUTEX_INITIALIZER PTH_MUTEX_INIT #else /*!HAVE_PTH*/
# define ESTREAM_MUTEX_LOCK(mutex) \
pth_mutex_acquire (&(mutex), 0, NULL)
# define ESTREAM_MUTEX_UNLOCK(mutex) \
pth_mutex_release (&(mutex))
# define ESTREAM_MUTEX_TRYLOCK(mutex) \
((pth_mutex_acquire (&(mutex), 1, NULL) == TRUE) ? 0 : -1)
# define ESTREAM_MUTEX_INITIALIZE(mutex) \
pth_mutex_init (&(mutex))
#else
typedef void *estream_mutex_t; typedef void *estream_mutex_t;
#endif /*!HAVE_PTH*/
static inline void static inline void
dummy_mutex_call_void (estream_mutex_t mutex) dummy_mutex_call_void (estream_mutex_t mutex)
@ -178,19 +168,42 @@ dummy_mutex_call_int (estream_mutex_t mutex)
return 0; return 0;
} }
#ifdef HAVE_PTH
static int estream_pth_killed;
# define ESTREAM_MUTEX_INITIALIZER PTH_MUTEX_INIT
# define ESTREAM_MUTEX_LOCK(mutex) \
(estream_pth_killed ? dummy_mutex_call_void ((mutex)) \
: pth_mutex_acquire (&(mutex), 0, NULL))
# define ESTREAM_MUTEX_UNLOCK(mutex) \
(estream_pth_killed ? dummy_mutex_call_void ((mutex)) \
: pth_mutex_release (&(mutex)))
# define ESTREAM_MUTEX_TRYLOCK(mutex) \
(estream_pth_killed ? dummy_mutex_call_int ((mutex)) \
: ((pth_mutex_acquire (&(mutex), 1, NULL) == TRUE)? 0:-1))
# define ESTREAM_MUTEX_INITIALIZE(mutex) \
(estream_pth_killed ? dummy_mutex_call_void ((mutex)) \
: pth_mutex_init (&(mutex)))
#else /*!HAVE_PTH*/
# define ESTREAM_MUTEX_INITIALIZER NULL # define ESTREAM_MUTEX_INITIALIZER NULL
# define ESTREAM_MUTEX_LOCK(mutex) dummy_mutex_call_void ((mutex)) # define ESTREAM_MUTEX_LOCK(mutex) dummy_mutex_call_void ((mutex))
# define ESTREAM_MUTEX_UNLOCK(mutex) dummy_mutex_call_void ((mutex)) # define ESTREAM_MUTEX_UNLOCK(mutex) dummy_mutex_call_void ((mutex))
# define ESTREAM_MUTEX_TRYLOCK(mutex) dummy_mutex_call_int ((mutex)) # define ESTREAM_MUTEX_TRYLOCK(mutex) dummy_mutex_call_int ((mutex))
# define ESTREAM_MUTEX_INITIALIZE(mutex) dummy_mutex_call_void ((mutex)) # define ESTREAM_MUTEX_INITIALIZE(mutex) dummy_mutex_call_void ((mutex))
#endif
#endif /*!HAVE_PTH*/
/* Primitive system I/O. */ /* Primitive system I/O. */
#ifdef HAVE_PTH #ifdef HAVE_PTH
# define ESTREAM_SYS_READ es_pth_read # define ESTREAM_SYS_READ es_pth_read
# define ESTREAM_SYS_WRITE es_pth_write # define ESTREAM_SYS_WRITE es_pth_write
# define ESTREAM_SYS_YIELD() pth_yield (NULL) # define ESTREAM_SYS_YIELD() \
do { if (!estream_pth_killed) pth_yield (NULL); } while (0)
#else #else
# define ESTREAM_SYS_READ read # define ESTREAM_SYS_READ read
# define ESTREAM_SYS_WRITE write # define ESTREAM_SYS_WRITE write
@ -361,7 +374,7 @@ static void
es_list_remove (estream_t stream, int with_locked_list) es_list_remove (estream_t stream, int with_locked_list)
{ {
estream_list_t list_obj; estream_list_t list_obj;
if (!with_locked_list) if (!with_locked_list)
ESTREAM_LIST_LOCK; ESTREAM_LIST_LOCK;
for (list_obj = estream_list; list_obj; list_obj = list_obj->cdr) for (list_obj = estream_list; list_obj; list_obj = list_obj->cdr)
@ -411,27 +424,37 @@ es_list_iterate (estream_iterator_t iterator)
static int static int
es_pth_read (int fd, void *buffer, size_t size) es_pth_read (int fd, void *buffer, size_t size)
{ {
if (estream_pth_killed)
return read (fd, buffer, size);
else
{
# ifdef HAVE_W32_SYSTEM # ifdef HAVE_W32_SYSTEM
int rc = pth_read (fd, buffer, size); int rc = pth_read (fd, buffer, size);
if (rc == -1 && errno == EINVAL) if (rc == -1 && errno == EINVAL)
rc = read (fd, buffer, size); rc = read (fd, buffer, size);
return rc; return rc;
# else /*!HAVE_W32_SYSTEM*/ # else /*!HAVE_W32_SYSTEM*/
return pth_read (fd, buffer, size); return pth_read (fd, buffer, size);
# endif /* !HAVE_W32_SYSTEM*/ # endif /* !HAVE_W32_SYSTEM*/
}
} }
static int static int
es_pth_write (int fd, const void *buffer, size_t size) es_pth_write (int fd, const void *buffer, size_t size)
{ {
if (estream_pth_killed)
return write (fd, buffer, size);
else
{
# ifdef HAVE_W32_SYSTEM # ifdef HAVE_W32_SYSTEM
int rc = pth_write (fd, buffer, size); int rc = pth_write (fd, buffer, size);
if (rc == -1 && errno == EINVAL) if (rc == -1 && errno == EINVAL)
rc = write (fd, buffer, size); rc = write (fd, buffer, size);
return rc; return rc;
# else /*!HAVE_W32_SYSTEM*/ # else /*!HAVE_W32_SYSTEM*/
return pth_write (fd, buffer, size); return pth_write (fd, buffer, size);
# endif /* !HAVE_W32_SYSTEM*/ # endif /* !HAVE_W32_SYSTEM*/
}
} }
#endif /*HAVE_PTH*/ #endif /*HAVE_PTH*/
@ -445,6 +468,26 @@ es_deinit (void)
} }
/* A replacement for pth_kill. The reason we need this is that after
a pth_kill all our pth functions may not be used anymore. Thus
applications using estream and pth need to use this function
instead of a plain pth_kill. */
int
es_pth_kill (void)
{
#ifdef HAVE_PTH
int rc;
rc = pth_kill ();
if (rc)
estream_pth_killed = 1;
return rc;
#else /*!HAVE_PTH*/
return 0;
#endif /*!HAVE_PTH*/
}
/* /*
* Initialization. * Initialization.
*/ */
@ -457,14 +500,19 @@ es_init_do (void)
if (!initialized) if (!initialized)
{ {
#ifdef HAVE_PTH #ifdef HAVE_PTH
if (!pth_init () && errno != EPERM ) if (estream_pth_killed)
return -1;
if (pth_mutex_init (&estream_list_lock))
initialized = 1; initialized = 1;
else
{
if (!pth_init () && errno != EPERM )
return -1;
if (pth_mutex_init (&estream_list_lock))
initialized = 1;
}
#else #else
initialized = 1; initialized = 1;
#endif #endif
atexit (es_deinit); atexit (es_deinit);
} }
return 0; return 0;
} }
@ -557,7 +605,7 @@ es_func_mem_read (void *cookie, void *buffer, size_t size)
memcpy (buffer, mem_cookie->memory + mem_cookie->offset, size); memcpy (buffer, mem_cookie->memory + mem_cookie->offset, size);
mem_cookie->offset += size; mem_cookie->offset += size;
} }
ret = size; ret = size;
return ret; return ret;
} }
@ -582,7 +630,7 @@ es_func_mem_write (void *cookie, const void *buffer, size_t size)
assert (mem_cookie->memory_size >= mem_cookie->offset); assert (mem_cookie->memory_size >= mem_cookie->offset);
nleft = mem_cookie->memory_size - mem_cookie->offset; nleft = mem_cookie->memory_size - mem_cookie->offset;
/* If we are not allowed to grow limit the size to the left space. */ /* If we are not allowed to grow limit the size to the left space. */
if (!mem_cookie->flags.grow && size > nleft) if (!mem_cookie->flags.grow && size > nleft)
size = nleft; size = nleft;
@ -623,20 +671,20 @@ es_func_mem_write (void *cookie, const void *buffer, size_t size)
_set_errno (ENOSPC); _set_errno (ENOSPC);
return -1; return -1;
} }
newbuf = mem_cookie->func_realloc (mem_cookie->memory, newsize); newbuf = mem_cookie->func_realloc (mem_cookie->memory, newsize);
if (!newbuf) if (!newbuf)
return -1; return -1;
mem_cookie->memory = newbuf; mem_cookie->memory = newbuf;
mem_cookie->memory_size = newsize; mem_cookie->memory_size = newsize;
assert (mem_cookie->memory_size >= mem_cookie->offset); assert (mem_cookie->memory_size >= mem_cookie->offset);
nleft = mem_cookie->memory_size - mem_cookie->offset; nleft = mem_cookie->memory_size - mem_cookie->offset;
assert (size <= nleft); assert (size <= nleft);
} }
memcpy (mem_cookie->memory + mem_cookie->offset, buffer, size); memcpy (mem_cookie->memory + mem_cookie->offset, buffer, size);
if (mem_cookie->offset + size > mem_cookie->data_len) if (mem_cookie->offset + size > mem_cookie->data_len)
mem_cookie->data_len = mem_cookie->offset + size; mem_cookie->data_len = mem_cookie->offset + size;
@ -698,7 +746,7 @@ es_func_mem_seek (void *cookie, off_t *offset, int whence)
_set_errno (ENOSPC); _set_errno (ENOSPC);
return -1; return -1;
} }
newbuf = mem_cookie->func_realloc (mem_cookie->memory, newsize); newbuf = mem_cookie->func_realloc (mem_cookie->memory, newsize);
if (!newbuf) if (!newbuf)
return -1; return -1;
@ -780,7 +828,7 @@ es_func_fd_create (void **cookie, int fd, unsigned int modeflags, int no_close)
*cookie = fd_cookie; *cookie = fd_cookie;
err = 0; err = 0;
} }
return err; return err;
} }
@ -791,7 +839,7 @@ es_func_fd_read (void *cookie, void *buffer, size_t size)
{ {
estream_cookie_fd_t file_cookie = cookie; estream_cookie_fd_t file_cookie = cookie;
ssize_t bytes_read; ssize_t bytes_read;
if (IS_INVALID_FD (file_cookie->fd)) if (IS_INVALID_FD (file_cookie->fd))
{ {
ESTREAM_SYS_YIELD (); ESTREAM_SYS_YIELD ();
@ -799,7 +847,7 @@ es_func_fd_read (void *cookie, void *buffer, size_t size)
} }
else else
{ {
do do
bytes_read = ESTREAM_SYS_READ (file_cookie->fd, buffer, size); bytes_read = ESTREAM_SYS_READ (file_cookie->fd, buffer, size);
while (bytes_read == -1 && errno == EINTR); while (bytes_read == -1 && errno == EINTR);
} }
@ -901,7 +949,7 @@ typedef struct estream_cookie_fp
/* Create function for fd objects. */ /* Create function for fd objects. */
static int static int
es_func_fp_create (void **cookie, FILE *fp, es_func_fp_create (void **cookie, FILE *fp,
unsigned int modeflags, int no_close) unsigned int modeflags, int no_close)
{ {
estream_cookie_fp_t fp_cookie; estream_cookie_fp_t fp_cookie;
@ -924,7 +972,7 @@ es_func_fp_create (void **cookie, FILE *fp,
*cookie = fp_cookie; *cookie = fp_cookie;
err = 0; err = 0;
} }
return err; return err;
} }
@ -948,7 +996,7 @@ es_func_fp_read (void *cookie, void *buffer, size_t size)
/* Write function for FILE* objects. */ /* Write function for FILE* objects. */
static ssize_t static ssize_t
es_func_fp_write (void *cookie, const void *buffer, size_t size) es_func_fp_write (void *cookie, const void *buffer, size_t size)
{ {
estream_cookie_fp_t file_cookie = cookie; estream_cookie_fp_t file_cookie = cookie;
size_t bytes_written; size_t bytes_written;
@ -973,7 +1021,7 @@ es_func_fp_seek (void *cookie, off_t *offset, int whence)
if (!file_cookie->fp) if (!file_cookie->fp)
{ {
_set_errno (ESPIPE); _set_errno (ESPIPE);
return -1; return -1;
} }
if ( fseek (file_cookie->fp, (long int)*offset, whence) ) if ( fseek (file_cookie->fp, (long int)*offset, whence) )
@ -1114,7 +1162,7 @@ es_convert_mode (const char *mode, unsigned int *modeflags)
oflags |= O_EXCL; oflags |= O_EXCL;
break; break;
default: /* Ignore unknown flags. */ default: /* Ignore unknown flags. */
break; break;
} }
} }
@ -1195,10 +1243,10 @@ es_flush (estream_t stream)
they were asked to write, we have to check for they were asked to write, we have to check for
"(stream->data_offset - data_flushed) > 0" instead of "(stream->data_offset - data_flushed) > 0" instead of
"stream->data_offset - data_flushed". */ "stream->data_offset - data_flushed". */
data_flushed = 0; data_flushed = 0;
err = 0; err = 0;
while ((((ssize_t) (stream->data_offset - data_flushed)) > 0) && (! err)) while ((((ssize_t) (stream->data_offset - data_flushed)) > 0) && (! err))
{ {
ret = (*func_write) (stream->intern->cookie, ret = (*func_write) (stream->intern->cookie,
@ -1232,7 +1280,7 @@ es_flush (estream_t stream)
err = 0; err = 0;
out: out:
if (err) if (err)
stream->intern->indicators.err = 1; stream->intern->indicators.err = 1;
@ -1518,7 +1566,7 @@ es_readn (estream_t ES__RESTRICT stream,
if (err) if (err)
goto out; goto out;
stream->flags.writing = 0; stream->flags.writing = 0;
} }
/* Read unread data first. */ /* Read unread data first. */
while ((bytes_to_read - data_read_unread) && stream->unread_data_len) while ((bytes_to_read - data_read_unread) && stream->unread_data_len)
@ -1615,7 +1663,7 @@ es_seek (estream_t ES__RESTRICT stream, off_t offset, int whence,
off = off - stream->data_len + stream->data_offset; off = off - stream->data_len + stream->data_offset;
off -= stream->unread_data_len; off -= stream->unread_data_len;
} }
ret = (*func_seek) (stream->intern->cookie, &off, whence); ret = (*func_seek) (stream->intern->cookie, &off, whence);
if (ret == -1) if (ret == -1)
{ {
@ -1633,7 +1681,7 @@ es_seek (estream_t ES__RESTRICT stream, off_t offset, int whence,
stream->intern->offset = off; stream->intern->offset = off;
out: out:
if (err) if (err)
stream->intern->indicators.err = 1; stream->intern->indicators.err = 1;
@ -1657,11 +1705,11 @@ es_write_nbf (estream_t ES__RESTRICT stream,
{ {
err = EOPNOTSUPP; err = EOPNOTSUPP;
goto out; goto out;
} }
data_written = 0; data_written = 0;
err = 0; err = 0;
while (bytes_to_write - data_written) while (bytes_to_write - data_written)
{ {
ret = (*func_write) (stream->intern->cookie, ret = (*func_write) (stream->intern->cookie,
@ -1709,12 +1757,12 @@ es_write_fbf (estream_t ES__RESTRICT stream,
if (! err) if (! err)
{ {
/* Flushing resulted in empty container. */ /* Flushing resulted in empty container. */
data_to_write = bytes_to_write - data_written; data_to_write = bytes_to_write - data_written;
space_available = stream->buffer_size - stream->data_offset; space_available = stream->buffer_size - stream->data_offset;
if (data_to_write > space_available) if (data_to_write > space_available)
data_to_write = space_available; data_to_write = space_available;
memcpy (stream->buffer + stream->data_offset, memcpy (stream->buffer + stream->data_offset,
buffer + data_written, data_to_write); buffer + data_written, data_to_write);
stream->data_offset += data_to_write; stream->data_offset += data_to_write;
@ -1775,7 +1823,7 @@ es_writen (estream_t ES__RESTRICT stream,
data_written = 0; data_written = 0;
err = 0; err = 0;
if (!stream->flags.writing) if (!stream->flags.writing)
{ {
/* Switching to writing mode -> discard input data and seek to /* Switching to writing mode -> discard input data and seek to
@ -1810,7 +1858,7 @@ es_writen (estream_t ES__RESTRICT stream,
} }
out: out:
if (bytes_written) if (bytes_written)
*bytes_written = data_written; *bytes_written = data_written;
if (data_written) if (data_written)
@ -1834,7 +1882,7 @@ es_peek (estream_t ES__RESTRICT stream, unsigned char **ES__RESTRICT data,
if (err) if (err)
goto out; goto out;
stream->flags.writing = 0; stream->flags.writing = 0;
} }
if (stream->data_offset == stream->data_len) if (stream->data_offset == stream->data_len)
{ {
@ -1843,7 +1891,7 @@ es_peek (estream_t ES__RESTRICT stream, unsigned char **ES__RESTRICT data,
if (err) if (err)
goto out; goto out;
} }
if (data) if (data)
*data = stream->buffer + stream->data_offset; *data = stream->buffer + stream->data_offset;
if (data_len) if (data_len)
@ -1898,7 +1946,7 @@ doreadline (estream_t ES__RESTRICT stream, size_t max_length,
err = es_func_mem_create (&line_stream_cookie, NULL, 0, 0, err = es_func_mem_create (&line_stream_cookie, NULL, 0, 0,
BUFFER_BLOCK_SIZE, 1, BUFFER_BLOCK_SIZE, 1,
mem_realloc, mem_free, mem_realloc, mem_free,
O_RDWR, O_RDWR,
0); 0);
if (err) if (err)
@ -1953,7 +2001,7 @@ doreadline (estream_t ES__RESTRICT stream, size_t max_length,
goto out; goto out;
/* Complete line has been written to line_stream. */ /* Complete line has been written to line_stream. */
if ((max_length > 1) && (! line_size)) if ((max_length > 1) && (! line_size))
{ {
stream->intern->indicators.eof = 1; stream->intern->indicators.eof = 1;
@ -2049,7 +2097,7 @@ static int
es_get_indicator (estream_t stream, int ind_err, int ind_eof) es_get_indicator (estream_t stream, int ind_err, int ind_eof)
{ {
int ret = 0; int ret = 0;
if (ind_err) if (ind_err)
ret = stream->intern->indicators.err; ret = stream->intern->indicators.err;
else if (ind_eof) else if (ind_eof)
@ -2076,7 +2124,7 @@ es_set_buffering (estream_t ES__RESTRICT stream,
es_empty (stream); es_empty (stream);
es_set_indicators (stream, -1, 0); es_set_indicators (stream, -1, 0);
/* Free old buffer in case that was allocated by this function. */ /* Free old buffer in case that was allocated by this function. */
if (stream->intern->deallocate_buffer) if (stream->intern->deallocate_buffer)
{ {
@ -2090,7 +2138,7 @@ es_set_buffering (estream_t ES__RESTRICT stream,
else else
{ {
void *buffer_new; void *buffer_new;
if (buffer) if (buffer)
buffer_new = buffer; buffer_new = buffer;
else else
@ -2183,7 +2231,7 @@ es_fopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode)
err = es_convert_mode (mode, &modeflags); err = es_convert_mode (mode, &modeflags);
if (err) if (err)
goto out; goto out;
err = es_func_file_create (&cookie, &fd, path, modeflags); err = es_func_file_create (&cookie, &fd, path, modeflags);
if (err) if (err)
goto out; goto out;
@ -2197,7 +2245,7 @@ es_fopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode)
fname_set_internal (stream, path, 1); fname_set_internal (stream, path, 1);
out: out:
if (err && create_called) if (err && create_called)
(*estream_functions_fd.func_close) (cookie); (*estream_functions_fd.func_close) (cookie);
@ -2220,17 +2268,17 @@ es_mopen (unsigned char *ES__RESTRICT data, size_t data_n, size_t data_len,
cookie = 0; cookie = 0;
stream = NULL; stream = NULL;
create_called = 0; create_called = 0;
err = es_convert_mode (mode, &modeflags); err = es_convert_mode (mode, &modeflags);
if (err) if (err)
goto out; goto out;
err = es_func_mem_create (&cookie, data, data_n, data_len, err = es_func_mem_create (&cookie, data, data_n, data_len,
BUFFER_BLOCK_SIZE, grow, BUFFER_BLOCK_SIZE, grow,
func_realloc, func_free, modeflags, 0); func_realloc, func_free, modeflags, 0);
if (err) if (err)
goto out; goto out;
create_called = 1; create_called = 1;
err = es_create (&stream, cookie, -1, estream_functions_mem, modeflags, 0); err = es_create (&stream, cookie, -1, estream_functions_mem, modeflags, 0);
@ -2256,13 +2304,13 @@ es_fopenmem (size_t memlimit, const char *ES__RESTRICT mode)
return NULL; return NULL;
modeflags |= O_RDWR; modeflags |= O_RDWR;
if (es_func_mem_create (&cookie, NULL, 0, 0, if (es_func_mem_create (&cookie, NULL, 0, 0,
BUFFER_BLOCK_SIZE, 1, BUFFER_BLOCK_SIZE, 1,
mem_realloc, mem_free, modeflags, mem_realloc, mem_free, modeflags,
memlimit)) memlimit))
return NULL; return NULL;
if (es_create (&stream, cookie, -1, estream_functions_mem, modeflags, 0)) if (es_create (&stream, cookie, -1, estream_functions_mem, modeflags, 0))
(*estream_functions_mem.func_close) (cookie); (*estream_functions_mem.func_close) (cookie);
@ -2282,7 +2330,7 @@ es_fopencookie (void *ES__RESTRICT cookie,
stream = NULL; stream = NULL;
modeflags = 0; modeflags = 0;
err = es_convert_mode (mode, &modeflags); err = es_convert_mode (mode, &modeflags);
if (err) if (err)
goto out; goto out;
@ -2366,7 +2414,7 @@ do_fpopen (FILE *fp, const char *mode, int no_close, int with_locked_list)
err = es_func_fp_create (&cookie, fp, modeflags, no_close); err = es_func_fp_create (&cookie, fp, modeflags, no_close);
if (err) if (err)
goto out; goto out;
create_called = 1; create_called = 1;
err = es_create (&stream, cookie, fp? fileno (fp):-1, estream_functions_fp, err = es_create (&stream, cookie, fp? fileno (fp):-1, estream_functions_fp,
modeflags, with_locked_list); modeflags, with_locked_list);
@ -2379,7 +2427,7 @@ do_fpopen (FILE *fp, const char *mode, int no_close, int with_locked_list)
return stream; return stream;
} }
/* Create an estream from the stdio stream FP. This mechanism is /* Create an estream from the stdio stream FP. This mechanism is
useful in case the stdio streams have special properties and may useful in case the stdio streams have special properties and may
not be mixed with fd based functions. This is for example the case not be mixed with fd based functions. This is for example the case
@ -2445,7 +2493,7 @@ _es_get_std_stream (int fd)
stream = do_fdopen (custom_std_fds[1], "a", 1, 1); stream = do_fdopen (custom_std_fds[1], "a", 1, 1);
else if (custom_std_fds_valid[2]) else if (custom_std_fds_valid[2])
stream = do_fdopen (custom_std_fds[2], "a", 1, 1); stream = do_fdopen (custom_std_fds[2], "a", 1, 1);
if (!stream) if (!stream)
{ {
/* Second try is to use the standard C streams. */ /* Second try is to use the standard C streams. */
@ -2456,8 +2504,8 @@ _es_get_std_stream (int fd)
else else
stream = do_fpopen (stderr, "a", 1, 1); stream = do_fpopen (stderr, "a", 1, 1);
} }
if (!stream) if (!stream)
{ {
/* Last try: Create a bit bucket. */ /* Last try: Create a bit bucket. */
stream = do_fpopen (NULL, fd? "a":"r", 0, 1); stream = do_fpopen (NULL, fd? "a":"r", 0, 1);
@ -2473,7 +2521,7 @@ _es_get_std_stream (int fd)
stream->intern->stdstream_fd = fd; stream->intern->stdstream_fd = fd;
if (fd == 2) if (fd == 2)
es_set_buffering (stream, NULL, _IOLBF, 0); es_set_buffering (stream, NULL, _IOLBF, 0);
fname_set_internal (stream, fname_set_internal (stream,
fd == 0? "[stdin]" : fd == 0? "[stdin]" :
fd == 1? "[stdout]" : "[stderr]", 0); fd == 1? "[stdout]" : "[stderr]", 0);
} }
@ -2497,7 +2545,7 @@ es_freopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode,
cookie = NULL; cookie = NULL;
create_called = 0; create_called = 0;
ESTREAM_LOCK (stream); ESTREAM_LOCK (stream);
es_deinitialize (stream); es_deinitialize (stream);
@ -2505,7 +2553,7 @@ es_freopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode,
err = es_convert_mode (mode, &modeflags); err = es_convert_mode (mode, &modeflags);
if (err) if (err)
goto leave; goto leave;
err = es_func_file_create (&cookie, &fd, path, modeflags); err = es_func_file_create (&cookie, &fd, path, modeflags);
if (err) if (err)
goto leave; goto leave;
@ -2519,7 +2567,7 @@ es_freopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode,
{ {
if (create_called) if (create_called)
es_func_fd_destroy (cookie); es_func_fd_destroy (cookie);
es_destroy (stream, 0); es_destroy (stream, 0);
stream = NULL; stream = NULL;
} }
@ -2654,7 +2702,7 @@ static int
do_fflush (estream_t stream) do_fflush (estream_t stream)
{ {
int err; int err;
if (stream->flags.writing) if (stream->flags.writing)
err = es_flush (stream); err = es_flush (stream);
else else
@ -2671,7 +2719,7 @@ int
es_fflush (estream_t stream) es_fflush (estream_t stream)
{ {
int err; int err;
if (stream) if (stream)
{ {
ESTREAM_LOCK (stream); ESTREAM_LOCK (stream);
@ -2702,7 +2750,7 @@ int
es_fseeko (estream_t stream, off_t offset, int whence) es_fseeko (estream_t stream, off_t offset, int whence)
{ {
int err; int err;
ESTREAM_LOCK (stream); ESTREAM_LOCK (stream);
err = es_seek (stream, offset, whence, NULL); err = es_seek (stream, offset, whence, NULL);
ESTREAM_UNLOCK (stream); ESTREAM_UNLOCK (stream);
@ -2715,7 +2763,7 @@ long int
es_ftell (estream_t stream) es_ftell (estream_t stream)
{ {
long int ret; long int ret;
ESTREAM_LOCK (stream); ESTREAM_LOCK (stream);
ret = es_offset_calculate (stream); ret = es_offset_calculate (stream);
ESTREAM_UNLOCK (stream); ESTREAM_UNLOCK (stream);
@ -2776,7 +2824,7 @@ int
es_fgetc (estream_t stream) es_fgetc (estream_t stream)
{ {
int ret; int ret;
ESTREAM_LOCK (stream); ESTREAM_LOCK (stream);
ret = es_getc_unlocked (stream); ret = es_getc_unlocked (stream);
ESTREAM_UNLOCK (stream); ESTREAM_UNLOCK (stream);
@ -2789,7 +2837,7 @@ int
es_fputc (int c, estream_t stream) es_fputc (int c, estream_t stream)
{ {
int ret; int ret;
ESTREAM_LOCK (stream); ESTREAM_LOCK (stream);
ret = es_putc_unlocked (c, stream); ret = es_putc_unlocked (c, stream);
ESTREAM_UNLOCK (stream); ESTREAM_UNLOCK (stream);
@ -2901,10 +2949,10 @@ es_fgets (char *ES__RESTRICT buffer, int length, estream_t ES__RESTRICT stream)
{ {
unsigned char *s = (unsigned char*)buffer; unsigned char *s = (unsigned char*)buffer;
int c; int c;
if (!length) if (!length)
return NULL; return NULL;
c = EOF; c = EOF;
ESTREAM_LOCK (stream); ESTREAM_LOCK (stream);
while (length > 1 && (c = es_getc_unlocked (stream)) != EOF && c != '\n') while (length > 1 && (c = es_getc_unlocked (stream)) != EOF && c != '\n')
@ -2968,7 +3016,7 @@ es_getline (char *ES__RESTRICT *ES__RESTRICT lineptr, size_t *ES__RESTRICT n,
if (*n) if (*n)
{ {
/* Caller wants us to use his buffer. */ /* Caller wants us to use his buffer. */
if (*n < (line_n + 1)) if (*n < (line_n + 1))
{ {
/* Provided buffer is too small -> resize. */ /* Provided buffer is too small -> resize. */
@ -3012,7 +3060,7 @@ es_getline (char *ES__RESTRICT *ES__RESTRICT lineptr, size_t *ES__RESTRICT n,
considered a byte stream ending in a LF. considered a byte stream ending in a LF.
If MAX_LENGTH is not NULL, it shall point to a value with the If MAX_LENGTH is not NULL, it shall point to a value with the
maximum allowed allocation. maximum allowed allocation.
Returns the length of the line. EOF is indicated by a line of Returns the length of the line. EOF is indicated by a line of
length zero. A truncated line is indicated my setting the value at length zero. A truncated line is indicated my setting the value at
@ -3036,7 +3084,7 @@ es_getline (char *ES__RESTRICT *ES__RESTRICT lineptr, size_t *ES__RESTRICT n,
released using es_free. released using es_free.
*/ */
ssize_t ssize_t
es_read_line (estream_t stream, es_read_line (estream_t stream,
char **addr_of_buffer, size_t *length_of_buffer, char **addr_of_buffer, size_t *length_of_buffer,
size_t *max_length) size_t *max_length)
{ {
@ -3048,7 +3096,7 @@ es_read_line (estream_t stream,
char *p; char *p;
if (!buffer) if (!buffer)
{ {
/* No buffer given - allocate a new one. */ /* No buffer given - allocate a new one. */
length = 256; length = 256;
buffer = mem_alloc (length); buffer = mem_alloc (length);
@ -3077,9 +3125,9 @@ es_read_line (estream_t stream,
while ((c = es_getc_unlocked (stream)) != EOF) while ((c = es_getc_unlocked (stream)) != EOF)
{ {
if (nbytes == length) if (nbytes == length)
{ {
/* Enlarge the buffer. */ /* Enlarge the buffer. */
if (maxlen && length > maxlen) if (maxlen && length > maxlen)
{ {
/* We are beyond our limit: Skip the rest of the line. */ /* We are beyond our limit: Skip the rest of the line. */
while (c != '\n' && (c=es_getc_unlocked (stream)) != EOF) while (c != '\n' && (c=es_getc_unlocked (stream)) != EOF)
@ -3096,7 +3144,7 @@ es_read_line (estream_t stream,
if (!*addr_of_buffer) if (!*addr_of_buffer)
{ {
int save_errno = errno; int save_errno = errno;
mem_free (buffer); mem_free (buffer);
*length_of_buffer = 0; *length_of_buffer = 0;
if (max_length) if (max_length)
*max_length = 0; *max_length = 0;
@ -3106,7 +3154,7 @@ es_read_line (estream_t stream,
} }
buffer = *addr_of_buffer; buffer = *addr_of_buffer;
*length_of_buffer = length; *length_of_buffer = length;
length -= 3; length -= 3;
p = buffer + nbytes; p = buffer + nbytes;
} }
*p++ = c; *p++ = c;
@ -3144,7 +3192,7 @@ es_vfprintf (estream_t ES__RESTRICT stream, const char *ES__RESTRICT format,
va_list ap) va_list ap)
{ {
int ret; int ret;
ESTREAM_LOCK (stream); ESTREAM_LOCK (stream);
ret = es_print (stream, format, ap); ret = es_print (stream, format, ap);
ESTREAM_UNLOCK (stream); ESTREAM_UNLOCK (stream);
@ -3158,7 +3206,7 @@ es_fprintf_unlocked (estream_t ES__RESTRICT stream,
const char *ES__RESTRICT format, ...) const char *ES__RESTRICT format, ...)
{ {
int ret; int ret;
va_list ap; va_list ap;
va_start (ap, format); va_start (ap, format);
ret = es_print (stream, format, ap); ret = es_print (stream, format, ap);
@ -3173,7 +3221,7 @@ es_fprintf (estream_t ES__RESTRICT stream,
const char *ES__RESTRICT format, ...) const char *ES__RESTRICT format, ...)
{ {
int ret; int ret;
va_list ap; va_list ap;
va_start (ap, format); va_start (ap, format);
ESTREAM_LOCK (stream); ESTREAM_LOCK (stream);
@ -3210,7 +3258,7 @@ es_asprintf (const char *ES__RESTRICT format, ...)
should use es_free to release the buffer. This function actually should use es_free to release the buffer. This function actually
belongs into estream-printf but we put it here as a convenience belongs into estream-printf but we put it here as a convenience
and because es_free is required anyway. */ and because es_free is required anyway. */
char * char *
es_vasprintf (const char *ES__RESTRICT format, va_list ap) es_vasprintf (const char *ES__RESTRICT format, va_list ap)
{ {
int rc; int rc;
@ -3241,7 +3289,7 @@ tmpfd (void)
int pid = GetCurrentProcessId (); int pid = GetCurrentProcessId ();
unsigned int value; unsigned int value;
int i; int i;
n = GetTempPath (MAX_PATH+1, buffer); n = GetTempPath (MAX_PATH+1, buffer);
if (!n || n > MAX_PATH || mystrlen (buffer) > MAX_PATH) if (!n || n > MAX_PATH || mystrlen (buffer) > MAX_PATH)
{ {
@ -3307,7 +3355,7 @@ tmpfd (void)
fp = NULL; fp = NULL;
fd = -1; fd = -1;
fp = tmpfile (); fp = tmpfile ();
if (! fp) if (! fp)
goto out; goto out;
@ -3338,7 +3386,7 @@ es_tmpfile (void)
stream = NULL; stream = NULL;
modeflags = O_RDWR | O_TRUNC | O_CREAT; modeflags = O_RDWR | O_TRUNC | O_CREAT;
cookie = NULL; cookie = NULL;
fd = tmpfd (); fd = tmpfd ();
if (fd == -1) if (fd == -1)
{ {
@ -3363,7 +3411,7 @@ es_tmpfile (void)
close (fd); close (fd);
stream = NULL; stream = NULL;
} }
return stream; return stream;
} }
@ -3373,7 +3421,7 @@ es_setvbuf (estream_t ES__RESTRICT stream,
char *ES__RESTRICT buf, int type, size_t size) char *ES__RESTRICT buf, int type, size_t size)
{ {
int err; int err;
if ((type == _IOFBF || type == _IOLBF || type == _IONBF) if ((type == _IOFBF || type == _IOLBF || type == _IONBF)
&& (!buf || size || type == _IONBF)) && (!buf || size || type == _IONBF))
{ {
@ -3412,7 +3460,7 @@ void *
es_opaque_get (estream_t stream) es_opaque_get (estream_t stream)
{ {
void *opaque; void *opaque;
ESTREAM_LOCK (stream); ESTREAM_LOCK (stream);
es_opaque_ctrl (stream, NULL, &opaque); es_opaque_ctrl (stream, NULL, &opaque);
ESTREAM_UNLOCK (stream); ESTREAM_UNLOCK (stream);
@ -3487,10 +3535,10 @@ es_fname_get (estream_t stream)
Returns 0 on success or -1 on error. If BYTES_WRITTEN is not NULL Returns 0 on success or -1 on error. If BYTES_WRITTEN is not NULL
the number of bytes actually written are stored at this the number of bytes actually written are stored at this
address. */ address. */
int int
es_write_sanitized (estream_t ES__RESTRICT stream, es_write_sanitized (estream_t ES__RESTRICT stream,
const void * ES__RESTRICT buffer, size_t length, const void * ES__RESTRICT buffer, size_t length,
const char * delimiters, const char * delimiters,
size_t * ES__RESTRICT bytes_written) size_t * ES__RESTRICT bytes_written)
{ {
const unsigned char *p = buffer; const unsigned char *p = buffer;
@ -3500,9 +3548,9 @@ es_write_sanitized (estream_t ES__RESTRICT stream,
ESTREAM_LOCK (stream); ESTREAM_LOCK (stream);
for (; length; length--, p++, count++) for (; length; length--, p++, count++)
{ {
if (*p < 0x20 if (*p < 0x20
|| *p == 0x7f || *p == 0x7f
|| (delimiters || (delimiters
&& (strchr (delimiters, *p) || *p == '\\'))) && (strchr (delimiters, *p) || *p == '\\')))
{ {
es_putc_unlocked ('\\', stream); es_putc_unlocked ('\\', stream);
@ -3604,19 +3652,19 @@ es_write_hexstring (estream_t ES__RESTRICT stream,
#ifdef GNUPG_MAJOR_VERSION #ifdef GNUPG_MAJOR_VERSION
/* Special estream function to print an UTF8 string in the native /* Special estream function to print an UTF8 string in the native
encoding. The interface is the same as es_write_sanitized, however encoding. The interface is the same as es_write_sanitized, however
only one delimiter may be supported. only one delimiter may be supported.
THIS IS NOT A STANDARD ESTREAM FUNCTION AND ONLY USED BY GNUPG!. */ THIS IS NOT A STANDARD ESTREAM FUNCTION AND ONLY USED BY GNUPG!. */
int int
es_write_sanitized_utf8_buffer (estream_t stream, es_write_sanitized_utf8_buffer (estream_t stream,
const void *buffer, size_t length, const void *buffer, size_t length,
const char *delimiters, size_t *bytes_written) const char *delimiters, size_t *bytes_written)
{ {
const char *p = buffer; const char *p = buffer;
size_t i; size_t i;
/* We can handle plain ascii simpler, so check for it first. */ /* We can handle plain ascii simpler, so check for it first. */
for (i=0; i < length; i++ ) for (i=0; i < length; i++ )
{ {
if ( (p[i] & 0x80) ) if ( (p[i] & 0x80) )
break; break;

View File

@ -231,6 +231,8 @@ typedef struct es_cookie_io_functions
int es_init (void); int es_init (void);
int es_pth_kill (void);
estream_t es_fopen (const char *ES__RESTRICT path, estream_t es_fopen (const char *ES__RESTRICT path,
const char *ES__RESTRICT mode); const char *ES__RESTRICT mode);
estream_t es_mopen (unsigned char *ES__RESTRICT data, estream_t es_mopen (unsigned char *ES__RESTRICT data,