Page MenuHome GnuPG

No OneTemporary

diff --git a/agent/ChangeLog b/agent/ChangeLog
index 10674ad18..a76199961 100644
--- a/agent/ChangeLog
+++ b/agent/ChangeLog
@@ -1,752 +1,758 @@
+2004-04-30 Werner Koch <wk@gnupg.org>
+
+ * gpg-agent.c (parse_rereadable_options): New arg REREAD. Allow
+ changing oLogFile.
+ (current_logfile): New.
+
2004-04-26 Werner Koch <wk@gnupg.org>
* call-scd.c (start_scd): Do not register an event signal if we
are running as a pipe server.
2004-04-21 Werner Koch <wk@gnupg.org>
* call-scd.c (start_scd): Send event-signal option. Always check
that the scdaemon is still running.
* gpg-agent.c (handle_signal): Do not use SIGUSR{1,2} anymore for
changing the verbosity.
2004-04-16 Werner Koch <wk@gnupg.org>
* gpg-agent.c (main): Tell the logging code taht we are runnign
detached.
2004-04-06 Werner Koch <wk@gnupg.org>
* gpg-agent.c (main): Use new libgcrypt thread library register
scheme.
2004-03-23 Marcus Brinkmann <marcus@g10code.de>
* gpg-agent.c (main): For now, always print the default config
file name for --gpgconf-list.
2004-03-17 Werner Koch <wk@gnupg.org>
* gpg-agent.c (main) <gpgconf>: Fixed default value quoting.
2004-03-16 Werner Koch <wk@gnupg.org>
* gpg-agent.c (parse_rereadable_options): Use the new
DEFAULT_CACHE_TTL macro.
(main): Updated --gpgconf-list output.
2004-02-21 Werner Koch <wk@gnupg.org>
* command.c (cmd_passwd): Take acount of a key description.
* genkey.c (reenter_compare_cb): Do not set the error text.
(agent_protect_and_store, agent_genkey): Force a re-enter after a
non-matching passphrase.
* query.c (agent_askpin): Add new arg INITIAL_ERRTEXT; changed
all callers.
2004-02-19 Werner Koch <wk@gnupg.org>
* protect-tool.c: New options --have-cert and --prompt.
(export_p12_file): Read a certificate from STDIN and pass it to
p12_build. Detect a keygrip and construct the filename in that
case. Unprotcet a key if needed. Print error messages for key
formats we can't handle.
(release_passphrase): New.
(get_passphrase): New arg PROMPTNO. Return the allocated
string. Changed all callers.
* minip12.c: Revamped the build part.
(p12_build): New args CERT and CERTLEN.
2004-02-18 Werner Koch <wk@gnupg.org>
* protect-tool.c (main): Setup the used character set.
* gpg-agent.c (main): Ditto.
* gpg-agent.c (set_debug): New. New option --debug-level.
(main): New option --gpgconf-list.
2004-02-17 Werner Koch <wk@gnupg.org>
* pksign.c (do_encode_md): Cleaned up by using gcry_sexp_build.
* Makefile.am (gpg_protect_tool_SOURCES): Removed
simple-pwquery.[ch], as we once moved it to ../common.
2004-02-13 Werner Koch <wk@gnupg.org>
* command.c (cmd_setkeydesc): New.
(register_commands): Add command SETKEYDESC.
(cmd_pksign, cmd_pkdecrypt): Use the key description.
(reset_notify): Reset the description.
* findkey.c (unprotect): Add arg DESC_TEXT.
(agent_key_from_file): Ditto.
* pksign.c (agent_pksign): Ditto.
* pkdecrypt.c (agent_pkdecrypt): Ditto. Made CIPHERTEXT an
unsigned char*.
* protect-tool.c (main): New options --no-fail-on-exist, --homedir.
(store_private_key): Use them here.
2004-02-12 Werner Koch <wk@gnupg.org>
* protect-tool.c (read_file, main): Allow reading from stdin.
* Makefile.am: Include cmacros.am for common flags.
(libexec_PROGRAMS): Put gpg-protect-tool there.
2004-02-10 Werner Koch <wk@gnupg.org>
* minip12.c (parse_bag_encrypted_data): Finished implementation.
(p12_parse): Add callback args.
* protect-tool.c (import_p12_cert_cb): New.
(import_p12_file): Use it.
2004-02-06 Werner Koch <wk@gnupg.org>
* minip12.c (crypt_block): Add arg CIPHER_ALGO; changed all callers.
(set_key_iv): Add arg KEYBYTES; changed caller.
2004-02-03 Werner Koch <wk@gnupg.org>
* findkey.c (agent_key_from_file): Extra paranoid wipe.
* protect.c (agent_unprotect): Ditto.
(merge_lists): Ditto. Add arg RESULTLEN.
* pkdecrypt.c (agent_pkdecrypt): Don't show the secret key even in
debug mode.
* protect.c: Add DSA and Elgamal description.
2004-01-29 Werner Koch <wk@gnupg.org>
* agent.h (server_control_s): Add connection_fd field.
* command.c (start_command_handler): Init it here.
* gpg-agent.c (agent_init_default_ctrl): and here.
* call-scd.c: Add the CTRL arg to all functions calling start_scd
and pass it to start_scd. Changed all callers
(start_scd): Keep track of the current active connection.
(agent_reset_scd): New.
* command.c (start_command_handler): Call it here.
* learncard.c (agent_handle_learn): Add arg CTRL; changed caller.
(send_cert_back): Ditto.
2004-01-28 Werner Koch <wk@gnupg.org>
* trustlist.c (agent_marktrusted): Check whether the trustlist is
writable.
2004-01-27 Werner Koch <wk@gnupg.org>
* sexp-parse.h: Moved to ../common.
2004-01-24 Werner Koch <wk@gnupg.org>
* call-scd.c (atfork_cb): New.
(start_scd): Make sure secmem gets cleared.
* query.c (atfork_cb): New.
(start_pinentry): Make sure secmem gets cleared.
2004-01-16 Werner Koch <wk@gnupg.org>
* findkey.c (agent_key_from_file): Now return an error code so
that we have more detailed error messages in the upper layers.
This fixes the handling of pinentry's cancel button.
* pksign.c (agent_pksign): Changed accordingly.
* pkdecrypt.c (agent_pkdecrypt): Ditto.
* command.c (cmd_passwd): Ditto.
2003-12-16 Werner Koch <wk@gnupg.org>
* gpg-agent.c (main): Set the prefixes for assuan logging.
2003-12-15 Werner Koch <wk@gnupg.org>
* protect.c (do_encryption): Use gcry_create_nonce instad of the
obsolete WEAK_RANDOM.
2003-11-20 Werner Koch <wk@gnupg.org>
* sexp-parse.h (snext): Don't use atoi_1 and digitp macros, so
that this file is useful by other applications too.
2003-10-27 Werner Koch <wk@gnupg.org>
* command.c (cmd_get_confirmation): New command.
2003-08-20 Timo Schulz <twoaday@freakmail.de>
* pksign.c (do_encode_md): Allocate enough space. Cast md
byte to unsigned char to prevent sign extension.
2003-08-14 Timo Schulz <twoaday@freakmail.de>
* pksign.c (do_encode_md): Due to the fact pkcs#1 padding
is now in Libgcrypt, use the new interface.
2003-07-31 Werner Koch <wk@gnupg.org>
* Makefile.am (gpg_agent_LDADD): Added INTLLIBS.
(gpg_protect_tool_SOURCES): Added simple-pwquery.[ch]
2003-07-27 Werner Koch <wk@gnupg.org>
Adjusted for gcry_mpi_print and gcry_mpi_scan API change.
2003-07-15 Werner Koch <wk@gnupg.org>
* simple-pwquery.c, simple-pwquery.h: Moved to ../common.
* Makefile.am (gpg_protect_tool_LDADD): Add simple-pwquery.o.
Removed it from xx_SOURCES.
2003-07-04 Werner Koch <wk@gnupg.org>
* gpg-agent.c (handle_connections): Kludge to allow use of Pth 1
and 2.
2003-06-30 Werner Koch <wk@gnupg.org>
* call-scd.c (learn_status_cb): Store the serialno in PARM.
2003-06-26 Werner Koch <wk@gnupg.org>
* call-scd.c (agent_card_serialno): Don't do a RESET anymore.
2003-06-25 Werner Koch <wk@gnupg.org>
* command.c (cmd_scd): New.
* call-scd.c (agent_card_scd): New.
* divert-scd.c (divert_generic_cmd): New
* call-scd.c (agent_card_learn): New callback args SINFO.
(learn_status_cb): Pass all other status lines to the sinfo
callback.
* learncard.c (release_sinfo, sinfo_cb): New.
(agent_handle_learn): Pass the new cb to the learn function and
pass the collected information back to the client's assuan
connection.
* gpg-agent.c (main): Moved pth_init before gcry_check_version.
2003-06-24 Werner Koch <wk@gnupg.org>
* gpg-agent.c (handle_connections): Adjusted for Pth 2.0
Adjusted for changes in the libgcrypt API. Some more fixes for the
libgpg-error stuff.
2003-06-04 Werner Koch <wk@gnupg.org>
Renamed error codes from INVALID to INV and removed _ERROR suffixes.
2003-06-03 Werner Koch <wk@gnupg.org>
Changed all error codes in all files to the new libgpg-error scheme.
* agent.h: Include gpg-error.h and errno.h
* Makefile.am: Link with libgpg-error
* query.c: assuan.h is now a system header.
* genkey.c (agent_genkey): Fixed silly use of xmalloc by
xtrymalloc.
2003-04-29 Werner Koch <wk@gnupg.org>
* command.c (register_commands): Adjusted for new Assuan semantics.
* Makefile.am: Don't override LDFLAGS.
2002-12-04 Werner Koch <wk@gnupg.org>
* gpg-agent.c: New variable config_filename.
(parse_rereadable_options): New.
(main): Use it here. Add setting of default values, set
config_filename.
(reread_configuration): Filled with actual code.
2002-12-03 Werner Koch <wk@gnupg.org>
* protect-tool.c (read_key): Don't run make_canonical on a NULL
buffer.
* command.c (parse_hexstring): New.
(cmd_sethash): Use it.
(parse_keygrip): New.
(cmd_havekey, cmd_sigkey): Use it.
(cmd_passwd): New.
* genkey.c (agent_protect_and_store): New.
(store_key): Add arg FORCE.
(agent_genkey): Pass false to this force of store_key.
2002-11-13 Werner Koch <wk@gnupg.org>
* gpg-agent.c (main): Switch all messages to utf-8.
* simple-pwquery.c (agent_send_all_options): Use $GPG_TTY and
stdin with ttyname.
* cache.c (new_data): Uiih - /sizeof d/sizeof *d/.
2002-11-10 Werner Koch <wk@gnupg.org>
* command.c (option_handler): Fix keep_tty check.
2002-11-06 Werner Koch <wk@gnupg.org>
* gpg-agent.c (main): Make sure we have a default ttyname.
* command.c (option_handler): Check opt.keep_tty here
* query.c (start_pinentry): but not anymore here.
2002-11-05 Werner Koch <wk@gnupg.org>
* agent.h (opt,server_control_s): Move display and lc_ variables
to the control struct so that they are per connection.
* gpg-agent.c (agent_init_default_ctrl): New.
(main): Assign those command line options to new default_* variables.
Reset DISPLAY in server mode so that tehre is no implicit default.
* command.c (start_command_handler): Initialize and deinitialize
the control values.
(option_handler): Work on the ctrl values and not on the opt.
* query.c (start_pinentry): New argument CTRL to set the display
connection specific. Changed all callers to pass this value.
(agent_askpin,agent_get_passphrase,agent_get_confirmation): Add
CTRL arg and pass it ot start_pinentry.
* command.c (cmd_get_passphrase): Pass CTRL argument.
* trustlist.c (agent_marktrusted): Add CTRL argument
* command.c (cmd_marktrusted): Pass CTRL argument
* divert-scd.c (ask_for_card): Add CTRL arg.
(divert_pksign,divert_pkdecrypt): Ditto. Changed caller.
(getpin_cb): Use OPAQUE to pass the CTRL variable. Changed both
users.
* findkey.c (unprotect): Add CTRL arg.
(agent_key_from_file): Ditto.
* query.c (unlock_pinentry): Disconnect the pinentry so that we
start a new one for each request. This is required to support
clients with different environments (e.g. X magic cookies).
2002-09-05 Neal H. Walfield <neal@cs.uml.edu>
* gpg-agent.c (main) [USE_GNU_PTH]: No need to call
assuan_set_io_func as assuan is smart.
2002-09-25 Werner Koch <wk@gnupg.org>
* gpg-agent.c (handle_signal): Flush cache on SIGHUP.
* cache.c (agent_flush_cache): New.
* gpg-agent.c, agent.h: Add --keep-display and --keep-tty.
* query.c (start_pinentry): Implement them. The option passing
needs more thoughts.
2002-09-09 Werner Koch <wk@gnupg.org>
* gpg-agent.c (create_private_keys_directory)
(create_directories): New.
(main): Try to create a home directory.
2002-09-04 Neal H. Walfield <neal@g10code.de>
* gpg-agent.c (main): Use sigaction, not signal.
2002-09-03 Neal H. Walfield <neal@g10code.de>
* findkey.c: Include <fcntl.h>.
(agent_write_private_key): Prefer POSIX compatibity, open and
fdopen, over the simplicity of GNU extensions, fopen(file, "x").
2002-08-22 Werner Koch <wk@gnupg.org>
* query.c (agent_askpin): Provide the default desc text depending
on the pininfo. Do the basic PIN verification only when
min_digits is set.
2002-08-21 Werner Koch <wk@gnupg.org>
* query.c (agent_askpin): Hack to show the right default prompt.
(agent_get_passphrase): Ditto.
* trans.c: Removed and replaced all usages with standard _()
* divert-scd.c (getpin_cb): Pass a more descritive text to the
pinentry.
* Makefile.am: Renamed the binary protect-tool to gpg-protect-tool.
* protect-tool.c: Removed the note about internal use only.
* gpg-agent.c (main): New option --daemon so that the program is
not accidently started in the background.
2002-08-16 Werner Koch <wk@gnupg.org>
* call-scd.c (learn_status_cb): Handle CERTINFO status.
(agent_card_learn): Add args for certinfo cb.
* learncard.c (release_certinfo,certinfo_cb): New.
(send_cert_back): New. With factored out code from ..
(agent_handle_learn): here. Return certinfo stuff.
2002-07-26 Werner Koch <wk@gnupg.org>
* gpg-agent.c (main): New option --ignore-cache-for-signing.
* command.c (option_handler): New server option
use-cache-for-signing defaulting to true.
(cmd_pksign): handle global and per session option.
* findkey.c (agent_key_from_file, unprotect): New arg
ignore_cache. Changed all callers.
* pksign.c (agent_pksign): Likewise.
2002-06-29 Werner Koch <wk@gnupg.org>
* query.c (start_pinentry): Use GNUPG_DERAULT_PINENTRY.
* call-scd.c (start_scd): Use GNUPG_DEFAULT_SCDAEMON.
2002-06-28 Werner Koch <wk@gnupg.org>
* protect-tool.c (export_p12_file): New.
(main): New command --p12-export.
* minip12.c (create_final,p12_build,compute_tag_length): New.
(store_tag_length): New.
2002-06-27 Werner Koch <wk@gnupg.org>
* minip12.c (crypt_block): Renamed from decrypt_block, add arg to
allow encryption.
* Makefile.am (pkglib_PROGRAMS): Put protect-tool there.
* findkey.c (agent_write_private_key,agent_key_from_file)
(agent_key_available): Use GNUPG_PRIVATE_KEYS_DIR constant.
* gpg-agent.c (main): Use GNUPG_DEFAULT_HOMEDIR constant.
* protect-tool.c (store_private_key): New.
(import_p12_file): Store the new file if requested.
(main): New options --force and --store.
* gpg-agent.c (main): Set a global flag when running detached.
* query.c (start_pinentry): Pass the list of FD to keep in the
child when not running detached.
* call-scd.c (start_scd): Ditto.
2002-06-26 Werner Koch <wk@gnupg.org>
* command.c (cmd_istrusted, cmd_listtrusted, cmd_marktrusted)
(cmd_pksign, cmd_pkdecrypt, cmd_genkey, cmd_get_passphrase)
(cmd_learn): Print an error message for a failed operation.
* simple-pwquery.c, simple-pwquery.h: New.
* protect-tool. (get_passphrase): New, used to get a passphrase
from the agent if none was given on the command line.
2002-06-25 Werner Koch <wk@gnupg.org>
* protect-tool.c (rsa_key_check): New.
(import_p12_file): New.
(main): New command --p12-import.
* minip12.c, minip12.h: New.
2002-06-24 Werner Koch <wk@gnupg.org>
* protect-tool.c (read_file): New.
(read_key): Factored most code out to read_file.
2002-06-17 Werner Koch <wk@gnupg.org>
* agent.h: Add a callback function to the pin_entry_info structure.
* query.c (agent_askpin): Use the callback to check for a correct
PIN. Removed the start_err_text argument because it is not
anymore needed; changed callers.
* findkey.c (unprotect): Replace our own check loop by a callback.
(try_unprotect_cb): New.
* genkey.c (reenter_compare_cb): New.
(agent_genkey): Use this callback here. Fixed setting of the pi2
variable and a segv in case of an empty PIN.
* divert-scd.c (getpin_cb): Removed some unused stuff and
explained what we still have to change.
2002-06-12 Werner Koch <wk@gnupg.org>
* gpg-agent.c (main): New option --disable-pth.
2002-06-11 Werner Koch <wk@gnupg.org>
* protect-tool.c: Add command --show-keygrip
(show_keygrip): New.
2002-05-23 Werner Koch <wk@gnupg.org>
* call-scd.c: Seirialized all scdaeom access when using Pth.
* cache.c: Made the cache Pth-thread-safe.
(agent_unlock_cache_entry): New.
* findkey.c (unprotect): Unlock the returned cache value.
* command.c (cmd_get_passphrase): Ditto.
* gpg-agent.c (main): Register pth_read/write with Assuan.
2002-05-22 Werner Koch <wk@gnupg.org>
* query.c: Serialized all pinentry access when using Pth.
* gpg-agent.c (handle_signal,start_connection_thread)
(handle_connections): New
(main): Use the new Pth stuff to allow concurrent connections.
* command.c (start_command_handler): Add new arg FD so that the
fucntion can also be used for an already connected socket.
* Makefile.am: Link with Pth.
2002-05-14 Werner Koch <wk@gnupg.org>
* cache.c (housekeeping, agent_put_cache): Use our time() wrapper.
2002-04-26 Werner Koch <wk@gnupg.org>
* cache.c (agent_put_cache): Reinitialize the creation time and
the ttl when reusing a slot.
* call-scd.c (start_scd): Print debug messages only with debug
flags set.
* query.c (start_pinentry): Ditto.
2002-04-25 Marcus Brinkmann <marcus@g10code.de>
* agent.h (agent_get_confirmation): Replace paramter prompt with
two parameters ok and cancel.
* query.c (agent_get_confirmation): Likewise. Implement this.
* trustlist.c (agent_marktrusted): Fix invocation of
agent_get_confirmation.
* divert-scd.c (ask_for_card): Likewise.
2002-04-24 Marcus Brinkmann <marcus@g10code.de>
* agent.h (struct opt): Add members display, ttyname, ttytype,
lc_ctype, and lc_messages.
* gpg-agent.c (enum cmd_and_opt_values): Add oDisplay, oTTYname,
oTTYtype, oLCctype, and LCmessages.
(main): Handle these options.
* command.c (option_handler): New function.
(register_commands): Register option handler.
* query.c (start_pinentry): Pass the various display and tty
options to the pinentry.
2002-04-05 Werner Koch <wk@gnupg.org>
* protect-tool.c (show_file): New. Used as default action.
2002-03-28 Werner Koch <wk@gnupg.org>
* divert-scd.c (encode_md_for_card): Don't do the pkcs-1 padding,
the scdaemon should take care of it.
(ask_for_card): Hack to not display the trailing zero.
2002-03-11 Werner Koch <wk@gnupg.org>
* learncard.c (kpinfo_cb): Remove the content restrictions from
the keyID.
2002-03-06 Werner Koch <wk@gnupg.org>
* learncard.c: New.
* divert-scd.c (ask_for_card): The serial number is binary so
convert it to hex here.
* findkey.c (agent_write_private_key): New.
* genkey.c (store_key): And use it here.
* pkdecrypt.c (agent_pkdecrypt): Changed the way the diversion is done.
* divert-scd.c (divert_pkdecrypt): Changed interface and
implemented it.
2002-03-05 Werner Koch <wk@gnupg.org>
* call-scd.c (inq_needpin): New.
(agent_card_pksign): Add getpin_cb args.
(agent_card_pkdecrypt): New.
2002-03-04 Werner Koch <wk@gnupg.org>
* pksign.c (agent_pksign): Changed how the diversion is done.
* divert-scd.c (divert_pksign): Changed interface and implemented it.
(encode_md_for_card): New.
* call-scd.c (agent_card_pksign): New.
2002-02-28 Werner Koch <wk@gnupg.org>
* pksign.c (agent_pksign): Detect whether a Smartcard is to be
used and divert the operation in this case.
* pkdecrypt.c (agent_pkdecrypt): Likewise
* findkey.c (agent_key_from_file): Add optional arg shadow_info
and have it return information about a shadowed key.
* protect.c (agent_get_shadow_info): New.
* protect.c (snext,sskip,smatch): Moved to
* sexp-parse.h: New file.
* divert-scd.c: New.
2002-02-27 Werner Koch <wk@gnupg.org>
* protect.c (agent_shadow_key): New.
* command.c (cmd_learn): New command LEARN.
* gpg-agent.c: New option --scdaemon-program.
* call-scd.c (start_scd): New. Based on query.c
* query.c: Add 2 more arguments to all uses of assuan_transact.
2002-02-18 Werner Koch <wk@gnupg.org>
* findkey.c (unprotect): Show an error message for a bad passphrase.
* command.c (cmd_marktrusted): Implemented.
* trustlist.c (agent_marktrusted): New.
(open_list): Add APPEND arg.
* query.c (agent_get_confirmation): New.
2002-02-06 Werner Koch <wk@gnupg.org>
* cache.c (housekeeping): Fixed linking in the remove case.
2002-02-01 Werner Koch <wk@gnupg.org>
* gpg-agent.c: New option --default-cache-ttl.
* cache.c (agent_put_cache): Use it.
* cache.c: Add a few debug outputs.
* protect.c (agent_private_key_type): New.
* agent.h: Add PRIVATE_KEY_ enums.
* findkey.c (agent_key_from_file): Use it to decide whether we
have to unprotect a key.
(unprotect): Cache the passphrase.
* findkey.c (agent_key_from_file,agent_key_available): The key
files do now require a ".key" suffix to make a script's life
easier.
* genkey.c (store_key): Ditto.
2002-01-31 Werner Koch <wk@gnupg.org>
* genkey.c (store_key): Protect the key.
(agent_genkey): Ask for the passphrase.
* findkey.c (unprotect): Actually unprotect the key.
* query.c (agent_askpin): Add an optional start_err_text.
2002-01-30 Werner Koch <wk@gnupg.org>
* protect.c: New.
(hash_passphrase): Based on the GnuPG 1.0.6 version.
* protect-tool.c: New
2002-01-29 Werner Koch <wk@gnupg.org>
* findkey.c (agent_key_available): New.
* command.c (cmd_havekey): New.
(register_commands): And register new command.
2002-01-20 Werner Koch <wk@gnupg.org>
* command.c (cmd_get_passphrase): Remove the plus signs.
* query.c (start_pinentry): Send no-grab option to pinentry
* gpg-agent.c (main): Move variable grab as no_grab to agent.h.
2002-01-19 Werner Koch <wk@gnupg.org>
* gpg-agent.c (main): Disable core dumps.
* cache.c: New.
* command.c (cmd_get_passphrase): Use the cache.
(cmd_clear_passphrase): Ditto.
* gpg-agent.c: Removed unused cruft and implement the socket
based server.
(my_strusage): Take bug report address from configure.ac.
* command.c (start_command_handler): Add an argument to start as
regular server.
(start_command_handler): Enable Assuan logging.
2002-01-15 Werner Koch <wk@gnupg.org>
* trustlist.c: New.
* command.c (cmd_istrusted, cmd_listtrusted, cmd_marktrusted): New.
2002-01-07 Werner Koch <wk@gnupg.org>
* genkey.c: Store the secret part and return the public part.
2002-01-03 Werner Koch <wk@gnupg.org>
* command.c (cmd_get_passphrase): New.
(cmd_clear_passphrase): New.
* query.c (agent_get_passphrase): New.
2002-01-02 Werner Koch <wk@gnupg.org>
* genkey.c: New.
* command.c (cmd_genkey): New.
* command.c (rc_to_assuan_status): Removed and changed all callers
to use map_to_assuan_status.
2001-12-19 Werner Koch <wk@gnupg.org>
* keyformat.txt: New.
2001-12-19 Marcus Brinkmann <marcus@g10code.de>
* query.c (start_pinentry): Add new argument to assuan_pipe_connect.
2001-12-18 Werner Koch <wk@gnupg.org>
* Makefile.am: Use LIBGCRYPT macros
2001-12-14 Werner Koch <wk@gnupg.org>
* gpg-agent.c (main): New option --batch. New option --debug-wait
n, so that it is possible to attach gdb when used in server mode.
* query.c (agent_askpin): Don't ask in batch mode.
* command.c: Removed the conversion macros as they are now in
../common/util.h.
2001-12-14 Marcus Brinkmann <marcus@g10code.de>
* query.c (LINELENGTH): Removed.
(agent_askpin): Use ASSUAN_LINELENGTH, not LINELENGTH.
2001-11-19 Werner Koch <wk@gnupg.org>
* gpg-agent.c: Removed all GUI code, removed code for old
protocol. New code to use the Assuan protocol as a server and
also to communicate with a new ask-passphrase utility.
2000-11-22 Werner Koch <wk@gnupg.org>
* gpg-agent.c (main): csh support by Dan Winship, new options --sh
and --csh and set default by consulting $SHELL.
Mon Aug 21 17:59:17 CEST 2000 Werner Koch <wk@openit.de>
* gpg-agent.c (passphrase_dialog): Cleanup the window and added the
user supplied text to the window.
(main): Fixed segv in gtk_init when used without a command to start.
* gpg-agent.c: --flush option.
(req_flush): New.
(req_clear_passphrase): Implemented.
Fri Aug 18 14:27:14 CEST 2000 Werner Koch <wk@openit.de>
* gpg-agent.c: New.
* Makefile.am: New.
Copyright 2001, 2002 Free Software Foundation, Inc.
This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without
modifications, as long as this notice is preserved.
This file is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
index 9b8678823..3bf62c26f 100644
--- a/agent/gpg-agent.c
+++ b/agent/gpg-agent.c
@@ -1,1182 +1,1198 @@
/* gpg-agent.c - The GnuPG Agent
* Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <time.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <signal.h>
#ifdef USE_GNU_PTH
# include <pth.h>
#endif
#define JNLIB_NEED_LOG_LOGV
#include "agent.h"
#include <assuan.h> /* malloc hooks */
#include "i18n.h"
#include "sysutils.h"
enum cmd_and_opt_values
{ aNull = 0,
oCsh = 'c',
oQuiet = 'q',
oSh = 's',
oVerbose = 'v',
oNoVerbose = 500,
aGPGConfList,
oOptions,
oDebug,
oDebugAll,
oDebugLevel,
oDebugWait,
oNoGreeting,
oNoOptions,
oHomedir,
oNoDetach,
oNoGrab,
oLogFile,
oServer,
oDaemon,
oBatch,
oPinentryProgram,
oDisplay,
oTTYname,
oTTYtype,
oLCctype,
oLCmessages,
oScdaemonProgram,
oDefCacheTTL,
oDisablePth,
oIgnoreCacheForSigning,
oKeepTTY,
oKeepDISPLAY,
aTest };
static ARGPARSE_OPTS opts[] = {
{ aGPGConfList, "gpgconf-list", 256, "@" },
{ 301, NULL, 0, N_("@Options:\n ") },
{ oServer, "server", 0, N_("run in server mode (foreground)") },
{ oDaemon, "daemon", 0, N_("run in daemon mode (background)") },
{ oVerbose, "verbose", 0, N_("verbose") },
{ oQuiet, "quiet", 0, N_("be somewhat more quiet") },
{ oSh, "sh", 0, N_("sh-style command output") },
{ oCsh, "csh", 0, N_("csh-style command output") },
{ oOptions, "options" , 2, N_("|FILE|read options from FILE")},
{ oDebug, "debug" ,4|16, "@"},
{ oDebugAll, "debug-all" ,0, "@"},
{ oDebugLevel, "debug-level" ,2, "@"},
{ oDebugWait,"debug-wait",1, "@"},
{ oNoDetach, "no-detach" ,0, N_("do not detach from the console")},
{ oNoGrab, "no-grab" ,0, N_("do not grab keyboard and mouse")},
{ oLogFile, "log-file" ,2, N_("use a log file for the server")},
{ oDisablePth, "disable-pth", 0, N_("do not allow multiple connections")},
{ oPinentryProgram, "pinentry-program", 2 , "path to PIN Entry program" },
{ oDisplay, "display", 2, "set the display" },
{ oTTYname, "ttyname", 2, "set the tty terminal node name" },
{ oTTYtype, "ttytype", 2, "set the tty terminal type" },
{ oLCctype, "lc-ctype", 2, "set the tty LC_CTYPE value" },
{ oLCmessages, "lc-messages", 2, "set the tty LC_MESSAGES value" },
{ oScdaemonProgram, "scdaemon-program", 2 , "path to SCdaemon program" },
{ oDefCacheTTL, "default-cache-ttl", 4,
"|N|expire cached PINs after N seconds"},
{ oIgnoreCacheForSigning, "ignore-cache-for-signing", 0,
"do not use the PIN cache when signing"},
{ oKeepTTY, "keep-tty", 0, N_("ignore requests to change the TTY")},
{ oKeepDISPLAY, "keep-display",
0, N_("ignore requests to change the X display")},
{0}
};
#define DEFAULT_CACHE_TTL (10*60) /* 10 minutes */
static volatile int caught_fatal_sig = 0;
/* flag to indicate that a shutdown was requested */
static int shutdown_pending;
/* It is possible that we are currently running under setuid permissions */
static int maybe_setuid = 1;
/* Name of the communication socket */
static char socket_name[128];
/* Default values for options passed to the pinentry. */
static char *default_display;
static char *default_ttyname;
static char *default_ttytype;
static char *default_lc_ctype;
static char *default_lc_messages;
/* Name of a config file, which will be reread on a HUP if it is not NULL. */
static char *config_filename;
/* Helper to implement --debug-level */
static const char *debug_level;
+/* Keep track of the current log file so that we can avoid updating
+ the log file afte a SIGHUP if id didn't changed. Malloced. */
+static char *current_logfile;
+
/* Local prototypes. */
static void create_directories (void);
#ifdef USE_GNU_PTH
static void handle_connections (int listen_fd);
/* Pth wrapper function definitions. */
GCRY_THREAD_OPTION_PTH_IMPL;
#endif /*USE_GNU_PTH*/
static const char *
my_strusage (int level)
{
const char *p;
switch (level)
{
case 11: p = "gpg-agent (GnuPG)";
break;
case 13: p = VERSION; break;
case 17: p = PRINTABLE_OS_NAME; break;
case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n");
break;
case 1:
case 40: p = _("Usage: gpg-agent [options] (-h for help)");
break;
case 41: p = _("Syntax: gpg-agent [options] [command [args]]\n"
"Secret key management for GnuPG\n");
break;
default: p = NULL;
}
return p;
}
static void
i18n_init (void)
{
#ifdef USE_SIMPLE_GETTEXT
set_gettext_file( PACKAGE_GT );
#else
#ifdef ENABLE_NLS
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE_GT, LOCALEDIR);
textdomain (PACKAGE_GT);
#endif
#endif
}
/* Used by gcry for logging */
static void
my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
{
/* translate the log levels */
switch (level)
{
case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break;
case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break;
case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break;
case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break;
case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break;
case GCRY_LOG_BUG: level = JNLIB_LOG_BUG; break;
case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break;
default: level = JNLIB_LOG_ERROR; break;
}
log_logv (level, fmt, arg_ptr);
}
/* Setup the debugging. With a LEVEL of NULL only the active debug
flags are propagated to the subsystems. With LEVEL set, a specific
set of debug flags is set; thus overriding all flags already
set. Note that we don't fail here, because it is important to keep
gpg-agent running even after re-reading the options due to a
SIGHUP. */
static void
set_debug (void)
{
if (!debug_level)
;
else if (!strcmp (debug_level, "none"))
opt.debug = 0;
else if (!strcmp (debug_level, "basic"))
opt.debug = DBG_ASSUAN_VALUE;
else if (!strcmp (debug_level, "advanced"))
opt.debug = DBG_ASSUAN_VALUE|DBG_COMMAND_VALUE;
else if (!strcmp (debug_level, "expert"))
opt.debug = (DBG_ASSUAN_VALUE|DBG_COMMAND_VALUE
|DBG_CACHE_VALUE);
else if (!strcmp (debug_level, "guru"))
opt.debug = ~0;
else
{
log_error (_("invalid debug-level `%s' given\n"), debug_level);
opt.debug = 0; /* Reset debugging, so that prior debug
statements won't have an undesired effect. */
}
if (opt.debug && !opt.verbose)
opt.verbose = 1;
if (opt.debug && opt.quiet)
opt.quiet = 0;
if (opt.debug & DBG_MPI_VALUE)
gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 2);
if (opt.debug & DBG_CRYPTO_VALUE )
gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1);
gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
}
static void
cleanup (void)
{
if (*socket_name)
{
char *p;
remove (socket_name);
p = strrchr (socket_name, '/');
if (p)
{
*p = 0;
rmdir (socket_name);
*p = '/';
}
*socket_name = 0;
}
}
static RETSIGTYPE
cleanup_sh (int sig)
{
if (caught_fatal_sig)
raise (sig);
caught_fatal_sig = 1;
/* gcry_control( GCRYCTL_TERM_SECMEM );*/
cleanup ();
#ifndef HAVE_DOSISH_SYSTEM
{ /* reset action to default action and raise signal again */
struct sigaction nact;
nact.sa_handler = SIG_DFL;
sigemptyset( &nact.sa_mask );
nact.sa_flags = 0;
sigaction( sig, &nact, NULL);
}
#endif
raise( sig );
}
/* Handle options which are allowed to be reset after program start.
Return true when the current option in PARGS could be handled and
false if not. As a special feature, passing a value of NULL for
- PARGS, resets the options to the default. */
+ PARGS, resets the options to the default. REREAD should be set
+ true if it is not the initial option parsing. */
static int
-parse_rereadable_options (ARGPARSE_ARGS *pargs)
+parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
{
if (!pargs)
{ /* reset mode */
opt.quiet = 0;
opt.verbose = 0;
opt.debug = 0;
opt.no_grab = 0;
opt.pinentry_program = NULL;
opt.scdaemon_program = NULL;
opt.def_cache_ttl = DEFAULT_CACHE_TTL;
opt.ignore_cache_for_signing = 0;
return 1;
}
switch (pargs->r_opt)
{
case oQuiet: opt.quiet = 1; break;
case oVerbose: opt.verbose++; break;
case oDebug: opt.debug |= pargs->r.ret_ulong; break;
case oDebugAll: opt.debug = ~0; break;
case oDebugLevel: debug_level = pargs->r.ret_str; break;
+ case oLogFile:
+ if (!current_logfile || !pargs->r.ret_str
+ || strcmp (current_logfile, pargs->r.ret_str))
+ {
+ log_set_file (pargs->r.ret_str);
+ xfree (current_logfile);
+ current_logfile = xtrystrdup (pargs->r.ret_str);
+ }
+ break;
+
case oNoGrab: opt.no_grab = 1; break;
case oPinentryProgram: opt.pinentry_program = pargs->r.ret_str; break;
case oScdaemonProgram: opt.scdaemon_program = pargs->r.ret_str; break;
case oDefCacheTTL: opt.def_cache_ttl = pargs->r.ret_ulong; break;
case oIgnoreCacheForSigning: opt.ignore_cache_for_signing = 1; break;
default:
return 0; /* not handled */
}
return 1; /* handled */
}
int
main (int argc, char **argv )
{
ARGPARSE_ARGS pargs;
int orig_argc;
int may_coredump;
char **orig_argv;
FILE *configfp = NULL;
char *configname = NULL;
const char *shell;
unsigned configlineno;
int parse_debug = 0;
int default_config =1;
int greeting = 0;
int nogreeting = 0;
int pipe_server = 0;
int is_daemon = 0;
int nodetach = 0;
int csh_style = 0;
char *logfile = NULL;
int debug_wait = 0;
int disable_pth = 0;
int gpgconf_list = 0;
gpg_error_t err;
set_strusage (my_strusage);
gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
/* Please note that we may running SUID(ROOT), so be very CAREFUL
when adding any stuff between here and the call to INIT_SECMEM()
somewhere after the option parsing */
log_set_prefix ("gpg-agent", JNLIB_LOG_WITH_PREFIX|JNLIB_LOG_WITH_PID);
/* Try to auto set the character set. */
set_native_charset (NULL);
i18n_init ();
/* Libgcrypt requires us to register the threading model first.
Note that this will also do the pth_init. */
#ifdef USE_GNU_PTH
err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth);
if (err)
{
log_fatal ("can't register GNU Pth with Libgcrypt: %s\n",
gpg_strerror (err));
}
#endif /*USE_GNU_PTH*/
/* Check that the libraries are suitable. Do it here because
the option parsing may need services of the library. */
if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
{
log_fatal( _("libgcrypt is too old (need %s, have %s)\n"),
NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
}
assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
assuan_set_assuan_log_stream (log_get_stream ());
assuan_set_assuan_log_prefix (log_get_prefix (NULL));
gcry_set_log_handler (my_gcry_logger, NULL);
gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
may_coredump = disable_core_dumps ();
- parse_rereadable_options (NULL); /* Reset them to default values. */
+ parse_rereadable_options (NULL, 0); /* Reset them to default values. */
shell = getenv ("SHELL");
if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") )
csh_style = 1;
opt.homedir = getenv("GNUPGHOME");
if (!opt.homedir || !*opt.homedir)
opt.homedir = GNUPG_DEFAULT_HOMEDIR;
/* check whether we have a config file on the commandline */
orig_argc = argc;
orig_argv = argv;
pargs.argc = &argc;
pargs.argv = &argv;
pargs.flags= 1|(1<<6); /* do not remove the args, ignore version */
while (arg_parse( &pargs, opts))
{
if (pargs.r_opt == oDebug || pargs.r_opt == oDebugAll)
parse_debug++;
else if (pargs.r_opt == oOptions)
{ /* yes there is one, so we do not try the default one, but
read the option file when it is encountered at the
commandline */
default_config = 0;
}
else if (pargs.r_opt == oNoOptions)
default_config = 0; /* --no-options */
else if (pargs.r_opt == oHomedir)
opt.homedir = pargs.r.ret_str;
}
/* initialize the secure memory. */
gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
maybe_setuid = 0;
/*
Now we are now working under our real uid
*/
if (default_config)
configname = make_filename (opt.homedir, "gpg-agent.conf", NULL );
argc = orig_argc;
argv = orig_argv;
pargs.argc = &argc;
pargs.argv = &argv;
pargs.flags= 1; /* do not remove the args */
next_pass:
if (configname)
{
configlineno = 0;
configfp = fopen (configname, "r");
if (!configfp)
{
if (default_config)
{
if( parse_debug )
log_info (_("NOTE: no default option file `%s'\n"),
configname );
}
else
{
log_error (_("option file `%s': %s\n"),
configname, strerror(errno) );
exit(2);
}
xfree (configname);
configname = NULL;
}
if (parse_debug && configname )
log_info (_("reading options from `%s'\n"), configname );
default_config = 0;
}
while (optfile_parse( configfp, configname, &configlineno, &pargs, opts) )
{
- if (parse_rereadable_options (&pargs))
+ if (parse_rereadable_options (&pargs, 0))
continue; /* Already handled */
switch (pargs.r_opt)
{
case aGPGConfList: gpgconf_list = 1; break;
case oBatch: opt.batch=1; break;
case oDebugWait: debug_wait = pargs.r.ret_int; break;
case oOptions:
/* config files may not be nested (silently ignore them) */
if (!configfp)
{
xfree(configname);
configname = xstrdup(pargs.r.ret_str);
goto next_pass;
}
break;
case oNoGreeting: nogreeting = 1; break;
case oNoVerbose: opt.verbose = 0; break;
case oNoOptions: break; /* no-options */
case oHomedir: opt.homedir = pargs.r.ret_str; break;
case oNoDetach: nodetach = 1; break;
case oLogFile: logfile = pargs.r.ret_str; break;
case oCsh: csh_style = 1; break;
case oSh: csh_style = 0; break;
case oServer: pipe_server = 1; break;
case oDaemon: is_daemon = 1; break;
case oDisablePth: disable_pth = 1; break;
case oDisplay: default_display = xstrdup (pargs.r.ret_str); break;
case oTTYname: default_ttyname = xstrdup (pargs.r.ret_str); break;
case oTTYtype: default_ttytype = xstrdup (pargs.r.ret_str); break;
case oLCctype: default_lc_ctype = xstrdup (pargs.r.ret_str); break;
case oLCmessages: default_lc_messages = xstrdup (pargs.r.ret_str);
break;
case oKeepTTY: opt.keep_tty = 1; break;
case oKeepDISPLAY: opt.keep_display = 1; break;
default : pargs.err = configfp? 1:2; break;
}
}
if (configfp)
{
fclose( configfp );
configfp = NULL;
/* Keep a copy of the name so that it can be read on SIGHUP. */
config_filename = configname;
configname = NULL;
goto next_pass;
}
xfree (configname);
configname = NULL;
if (log_get_errorcount(0))
exit(2);
if (nogreeting )
greeting = 0;
if (greeting)
{
fprintf (stderr, "%s %s; %s\n",
strusage(11), strusage(13), strusage(14) );
fprintf (stderr, "%s\n", strusage(15) );
}
#ifdef IS_DEVELOPMENT_VERSION
log_info ("NOTE: this is a development version!\n");
#endif
set_debug ();
if (atexit (cleanup))
{
log_error ("atexit failed\n");
cleanup ();
exit (1);
}
create_directories ();
if (debug_wait && pipe_server)
{
log_debug ("waiting for debugger - my pid is %u .....\n",
(unsigned int)getpid());
sleep (debug_wait);
log_debug ("... okay\n");
}
if (gpgconf_list)
{
char *filename;
/* List options and default values in the GPG Conf format. */
/* The following list is taken from gnupg/tools/gpgconf-comp.c. */
/* Option flags. YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING
FLAGS, AS THEY ARE PART OF THE EXTERNAL INTERFACE. */
#define GC_OPT_FLAG_NONE 0UL
/* The RUNTIME flag for an option indicates that the option can be
changed at runtime. */
#define GC_OPT_FLAG_RUNTIME (1UL << 3)
/* The DEFAULT flag for an option indicates that the option has a
default value. */
#define GC_OPT_FLAG_DEFAULT (1UL << 4)
/* The DEF_DESC flag for an option indicates that the option has a
default, which is described by the value of the default field. */
#define GC_OPT_FLAG_DEF_DESC (1UL << 5)
/* The NO_ARG_DESC flag for an option indicates that the argument has
a default, which is described by the value of the ARGDEF field. */
#define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6)
filename = make_filename (opt.homedir, "gpg-agent.conf", NULL );
printf ("gpgconf-gpg-agent.conf:%lu:\"%s\n",
GC_OPT_FLAG_DEFAULT, filename);
xfree (filename);
printf ("verbose:%lu:\n"
"quiet:%lu:\n"
"debug-level:%lu:\"none:\n"
"log-file:%lu:\n",
GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME,
GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME,
GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME,
- GC_OPT_FLAG_NONE );
+ GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME );
printf ("default-cache-ttl:%lu:%d:\n",
GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME, DEFAULT_CACHE_TTL );
printf ("no-grab:%lu:\n",
GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
printf ("ignore-cache-for-signing:%lu:\n",
GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
agent_exit (0);
}
if (!pipe_server && !is_daemon)
log_info (_("please use the option `--daemon'"
" to run the program in the background\n"));
#ifdef ENABLE_NLS
/* gpg-agent usually does not output any messages because it runs in
the background. For log files it is acceptable to have messages
always encoded in utf-8. We switch here to utf-8, so that
commands like --help still give native messages. It is far
easier to switch only once instead of for every message and it
actually helps when more then one thread is active (avoids an
extra copy step). */
bind_textdomain_codeset (PACKAGE_GT, "UTF-8");
#endif
/* Now start with logging to a file if this is desired. */
if (logfile)
{
log_set_file (logfile);
log_set_prefix (NULL, (JNLIB_LOG_WITH_PREFIX
|JNLIB_LOG_WITH_TIME
|JNLIB_LOG_WITH_PID));
+ current_logfile = xstrdup (logfile);
}
/* Make sure that we have a default ttyname. */
if (!default_ttyname && ttyname (1))
default_ttyname = xstrdup (ttyname (1));
if (!default_ttytype && getenv ("TERM"))
default_ttytype = xstrdup (getenv ("TERM"));
if (pipe_server)
{ /* this is the simple pipe based server */
start_command_handler (-1, -1);
}
else if (!is_daemon)
;
else
{ /* regular server mode */
int fd;
pid_t pid;
int len;
struct sockaddr_un serv_addr;
char *p;
/* Remove the DISPLAY variable so that a pinentry does not
default to a specific display. There is still a default
display when gpg-agent weas started using --display or a
client requested this using an OPTION command. */
if (!opt.keep_display)
unsetenv ("DISPLAY");
*socket_name = 0;
snprintf (socket_name, DIM(socket_name)-1,
"/tmp/gpg-XXXXXX/S.gpg-agent");
socket_name[DIM(socket_name)-1] = 0;
p = strrchr (socket_name, '/');
if (!p)
BUG ();
*p = 0;;
if (!mkdtemp(socket_name))
{
log_error ("can't create directory `%s': %s\n",
socket_name, strerror(errno) );
exit (1);
}
*p = '/';
if (strchr (socket_name, ':') )
{
log_error ("colons are not allowed in the socket name\n");
exit (1);
}
if (strlen (socket_name)+1 >= sizeof serv_addr.sun_path )
{
log_error ("name of socket too long\n");
exit (1);
}
fd = socket (AF_UNIX, SOCK_STREAM, 0);
if (fd == -1)
{
log_error ("can't create socket: %s\n", strerror(errno) );
exit (1);
}
memset (&serv_addr, 0, sizeof serv_addr);
serv_addr.sun_family = AF_UNIX;
strcpy (serv_addr.sun_path, socket_name);
len = (offsetof (struct sockaddr_un, sun_path)
+ strlen(serv_addr.sun_path) + 1);
if (bind (fd, (struct sockaddr*)&serv_addr, len) == -1)
{
log_error ("error binding socket to `%s': %s\n",
serv_addr.sun_path, strerror (errno) );
close (fd);
exit (1);
}
if (listen (fd, 5 ) == -1)
{
log_error ("listen() failed: %s\n", strerror (errno));
close (fd);
exit (1);
}
if (opt.verbose)
log_info ("listening on socket `%s'\n", socket_name );
fflush (NULL);
pid = fork ();
if (pid == (pid_t)-1)
{
log_fatal ("fork failed: %s\n", strerror (errno) );
exit (1);
}
else if (pid)
{ /* We are the parent */
char *infostr;
close (fd);
/* create the info string: <name>:<pid>:<protocol_version> */
if (asprintf (&infostr, "GPG_AGENT_INFO=%s:%lu:1",
socket_name, (ulong)pid ) < 0)
{
log_error ("out of core\n");
kill (pid, SIGTERM);
exit (1);
}
*socket_name = 0; /* don't let cleanup() remove the socket -
the child should do this from now on */
if (argc)
{ /* run the program given on the commandline */
if (putenv (infostr))
{
log_error ("failed to set environment: %s\n",
strerror (errno) );
kill (pid, SIGTERM );
exit (1);
}
execvp (argv[0], argv);
log_error ("failed to run the command: %s\n", strerror (errno));
kill (pid, SIGTERM);
exit (1);
}
else
{
/* print the environment string, so that the caller can use
shell's eval to set it */
if (csh_style)
{
*strchr (infostr, '=') = ' ';
printf ( "setenv %s\n", infostr);
}
else
{
printf ( "%s; export GPG_AGENT_INFO;\n", infostr);
}
free (infostr);
exit (0);
}
/*NEVER REACHED*/
} /* end parent */
/*
This is the child
*/
/* Detach from tty and put process into a new session */
if (!nodetach )
{
int i;
unsigned int oldflags;
/* Close stdin, stdout and stderr unless it is the log stream */
for (i=0; i <= 2; i++)
{
if (!log_test_fd (i) )
close (i);
}
if (setsid() == -1)
{
log_error ("setsid() failed: %s\n", strerror(errno) );
cleanup ();
exit (1);
}
log_get_prefix (&oldflags);
log_set_prefix (NULL, oldflags | JNLIB_LOG_RUN_DETACHED);
opt.running_detached = 1;
}
if (chdir("/"))
{
log_error ("chdir to / failed: %s\n", strerror (errno));
exit (1);
}
#ifdef USE_GNU_PTH
if (!disable_pth)
{
struct sigaction sa;
sa.sa_handler = SIG_IGN;
sigemptyset (&sa.sa_mask);
sa.sa_flags = 0;
sigaction (SIGPIPE, &sa, NULL);
handle_connections (fd);
}
else
#endif /*!USE_GNU_PTH*/
/* setup signals */
{
struct sigaction oact, nact;
nact.sa_handler = cleanup_sh;
sigemptyset (&nact.sa_mask);
nact.sa_flags = 0;
sigaction (SIGHUP, NULL, &oact);
if (oact.sa_handler != SIG_IGN)
sigaction (SIGHUP, &nact, NULL);
sigaction( SIGTERM, NULL, &oact );
if (oact.sa_handler != SIG_IGN)
sigaction (SIGTERM, &nact, NULL);
nact.sa_handler = SIG_IGN;
sigaction (SIGPIPE, &nact, NULL);
sigaction (SIGINT, &nact, NULL);
start_command_handler (fd, -1);
}
close (fd);
}
return 0;
}
void
agent_exit (int rc)
{
/*FIXME: update_random_seed_file();*/
#if 1
/* at this time a bit annoying */
if (opt.debug & DBG_MEMSTAT_VALUE)
{
gcry_control( GCRYCTL_DUMP_MEMORY_STATS );
gcry_control( GCRYCTL_DUMP_RANDOM_STATS );
}
if (opt.debug)
gcry_control (GCRYCTL_DUMP_SECMEM_STATS );
#endif
gcry_control (GCRYCTL_TERM_SECMEM );
rc = rc? rc : log_get_errorcount(0)? 2 : 0;
exit (rc);
}
void
agent_init_default_ctrl (struct server_control_s *ctrl)
{
ctrl->connection_fd = -1;
/* Note we ignore malloc errors because we can't do much about it
and the request will fail anyway shortly after this
initialization. */
if (ctrl->display)
free (ctrl->display);
ctrl->display = default_display? strdup (default_display) : NULL;
if (ctrl->ttyname)
free (ctrl->ttyname);
ctrl->ttyname = default_ttyname? strdup (default_ttyname) : NULL;
if (ctrl->ttytype)
free (ctrl->ttytype);
ctrl->ttytype = default_ttytype? strdup (default_ttytype) : NULL;
if (ctrl->lc_ctype)
free (ctrl->lc_ctype);
ctrl->lc_ctype = default_lc_ctype? strdup (default_lc_ctype) : NULL;
if (ctrl->lc_messages)
free (ctrl->lc_messages);
ctrl->lc_messages = default_lc_messages? strdup (default_lc_messages) : NULL;
}
/* Reread parts of the configuration. Note, that this function is
obviously not thread-safe and should only be called from the PTH
signal handler.
Fixme: Due to the way the argument parsing works, we create a
memory leak here for all string type arguments. There is currently
no clean way to tell whether the memory for the argument has been
allocated or points into the process' original arguments. Unless
we have a mechanism to tell this, we need to live on with this. */
static void
reread_configuration (void)
{
ARGPARSE_ARGS pargs;
FILE *fp;
unsigned int configlineno = 0;
int dummy;
if (!config_filename)
return; /* No config file. */
fp = fopen (config_filename, "r");
if (!fp)
{
log_error (_("option file `%s': %s\n"),
config_filename, strerror(errno) );
return;
}
- parse_rereadable_options (NULL); /* Start from the default values. */
+ parse_rereadable_options (NULL, 1); /* Start from the default values. */
memset (&pargs, 0, sizeof pargs);
dummy = 0;
pargs.argc = &dummy;
pargs.flags = 1; /* do not remove the args */
while (optfile_parse (fp, config_filename, &configlineno, &pargs, opts) )
{
if (pargs.r_opt < -1)
pargs.err = 1; /* Print a warning. */
else /* Try to parse this option - ignore unchangeable ones. */
- parse_rereadable_options (&pargs);
+ parse_rereadable_options (&pargs, 1);
}
fclose (fp);
set_debug ();
}
static void
create_private_keys_directory (const char *home)
{
char *fname;
struct stat statbuf;
fname = make_filename (home, GNUPG_PRIVATE_KEYS_DIR, NULL);
if (stat (fname, &statbuf) && errno == ENOENT)
{
if (mkdir (fname, S_IRUSR|S_IWUSR|S_IXUSR ))
log_error (_("can't create directory `%s': %s\n"),
fname, strerror(errno) );
else if (!opt.quiet)
log_info (_("directory `%s' created\n"), fname);
}
xfree (fname);
}
/* Create the directory only if the supplied directory name is the
same as the default one. This way we avoid to create arbitrary
directories when a non-default home directory is used. To cope
with HOME, we compare only the suffix if we see that the default
homedir does start with a tilde. We don't stop here in case of
problems because other functions will throw an error anyway.*/
static void
create_directories (void)
{
struct stat statbuf;
const char *defhome = GNUPG_DEFAULT_HOMEDIR;
char *home;
home = make_filename (opt.homedir, NULL);
if ( stat (home, &statbuf) )
{
if (errno == ENOENT)
{
if ( (*defhome == '~'
&& (strlen (home) >= strlen (defhome+1)
&& !strcmp (home + strlen(home)
- strlen (defhome+1), defhome+1)))
|| (*defhome != '~' && !strcmp (home, defhome) )
)
{
if (mkdir (home, S_IRUSR|S_IWUSR|S_IXUSR ))
log_error (_("can't create directory `%s': %s\n"),
home, strerror(errno) );
else
{
if (!opt.quiet)
log_info (_("directory `%s' created\n"), home);
create_private_keys_directory (home);
}
}
}
else
log_error ("error stat-ing `%s': %s\n", home, strerror (errno));
}
else if ( !S_ISDIR(statbuf.st_mode))
{
log_error ("can't use `%s' as home directory\n", home);
}
else /* exists and is a directory. */
{
create_private_keys_directory (home);
}
xfree (home);
}
#ifdef USE_GNU_PTH
static void
handle_signal (int signo)
{
switch (signo)
{
case SIGHUP:
log_info ("SIGHUP received - "
"re-reading configuration and flushing cache\n");
agent_flush_cache ();
reread_configuration ();
break;
case SIGUSR1:
log_info ("SIGUSR1 received - no action defined\n");
break;
case SIGUSR2:
log_info ("SIGUSR2 received - checking smartcard status\n");
break;
case SIGTERM:
if (!shutdown_pending)
log_info ("SIGTERM received - shutting down ...\n");
else
log_info ("SIGTERM received - still %ld running threads\n",
pth_ctrl( PTH_CTRL_GETTHREADS ));
shutdown_pending++;
if (shutdown_pending > 2)
{
log_info ("shutdown forced\n");
log_info ("%s %s stopped\n", strusage(11), strusage(13) );
cleanup ();
agent_exit (0);
}
break;
case SIGINT:
log_info ("SIGINT received - immediate shutdown\n");
log_info( "%s %s stopped\n", strusage(11), strusage(13));
cleanup ();
agent_exit (0);
break;
default:
log_info ("signal %d received - no action defined\n", signo);
}
}
static void *
start_connection_thread (void *arg)
{
int fd = (int)arg;
if (opt.verbose)
log_info ("handler for fd %d started\n", fd);
start_command_handler (-1, fd);
if (opt.verbose)
log_info ("handler for fd %d terminated\n", fd);
return NULL;
}
static void
handle_connections (int listen_fd)
{
pth_attr_t tattr;
pth_event_t ev;
sigset_t sigs;
int signo;
struct sockaddr_un paddr;
socklen_t plen = sizeof( paddr );
int fd;
tattr = pth_attr_new();
pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0);
pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 32*1024);
pth_attr_set (tattr, PTH_ATTR_NAME, "gpg-agent");
sigemptyset (&sigs );
sigaddset (&sigs, SIGHUP);
sigaddset (&sigs, SIGUSR1);
sigaddset (&sigs, SIGUSR2);
sigaddset (&sigs, SIGINT);
sigaddset (&sigs, SIGTERM);
ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo);
for (;;)
{
if (shutdown_pending)
{
if (pth_ctrl (PTH_CTRL_GETTHREADS) == 1)
break; /* ready */
/* Do not accept anymore connections and wait for existing
connections to terminate */
signo = 0;
pth_wait (ev);
if (pth_event_occurred (ev) && signo)
handle_signal (signo);
continue;
}
fd = pth_accept_ev (listen_fd, (struct sockaddr *)&paddr, &plen, ev);
if (fd == -1)
{
#ifdef PTH_STATUS_OCCURRED /* This is Pth 2 */
if (pth_event_status (ev) == PTH_STATUS_OCCURRED)
#else
if (pth_event_occurred (ev))
#endif
{
handle_signal (signo);
continue;
}
log_error ("accept failed: %s - waiting 1s\n", strerror (errno));
pth_sleep(1);
continue;
}
if (!pth_spawn (tattr, start_connection_thread, (void*)fd))
{
log_error ("error spawning connection handler: %s\n",
strerror (errno) );
close (fd);
}
}
pth_event_free (ev, PTH_FREE_ALL);
cleanup ();
log_info ("%s %s stopped\n", strusage(11), strusage(13));
}
#endif /*USE_GNU_PTH*/
diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog
index 99c9177b5..1527fb773 100644
--- a/jnlib/ChangeLog
+++ b/jnlib/ChangeLog
@@ -1,200 +1,205 @@
+2004-04-30 Werner Koch <wk@gnupg.org>
+
+ * logging.c (log_set_file): Make sure the log stream will be
+ closed even if the stderr fileno will be assigned to a new socket.
+
2004-04-16 Werner Koch <wk@gnupg.org>
* logging.h (JNLIB_LOG_WITH_PREFIX): Add constants for the flag
values.
* logging.c (log_set_prefix): New flag DETACHED.
(fun_writer): Take care of this flag.
(log_test_fd): New.
2004-02-18 Werner Koch <wk@gnupg.org>
* stringhelp.c (print_sanitized_buffer): Don't care about
non-ASCII characaters.
(sanitize_buffer): Ditto.
2004-02-12 Werner Koch <wk@gnupg.org>
* Makefile.am: Replaced INCLUDES by AM_CPPFLAGS.
2004-01-05 Werner Koch <wk@gnupg.org>
* argparse.c (strusage): Changed default copyright year to 2004.
2003-12-17 Werner Koch <wk@gnupg.org>
* argparse.c (initialize): Replaced use of non-literal format
args. Suggested by Florian Weimer.
2003-12-16 Werner Koch <wk@gnupg.org>
* logging.c (writen, fun_writer, fun_closer): New.
(log_set_file): Add feature to log to a socket.
(log_set_file, do_logv): Force printing with prefix and pid.
2003-11-13 Werner Koch <wk@gnupg.org>
* strlist.c (strlist_copy): New.
* dotlock.c: Define DIRSEP_C et al. if not defined.
2003-11-06 Werner Koch <wk@gnupg.org>
* strlist.h (strlist_t): New. STRLIST is now deprecated.
2003-06-18 Werner Koch <wk@gnupg.org>
* strlist.c (strlist_pop): New.
* dotlock.c (dotlock_remove_lockfiles): Prefixed with dotlock_ and
made global.
2003-06-17 Werner Koch <wk@gnupg.org>
* stringhelp.c (length_sans_trailing_chars)
(length_sans_trailing_ws): New.
* logging.c (log_inc_errorcount): New.
* stringhelp.c (print_sanitized_utf8_buffer): Implement utf8
conversion.
(sanitize_buffer): New. Based on gnupg 1.3.2 make_printable_string.
* dotlock.c: Updated to match the version from 1.3.2
* utf8conv.c: New. Code taken from strgutil.c of gnupg 1.3.2.
* utf8conv.h: New.
2003-06-16 Werner Koch <wk@gnupg.org>
* logging.c (do_logv): Hack to optionally suppress a leading space.
* stringhelp.c (ascii_strncasecmp): New. Taken from gnupg 1.3.
(ascii_memistr): New. Taken from gnupg 1.3
2003-06-13 Werner Koch <wk@gnupg.org>
* mischelp.h (wipememory2,wipememory): New. Taken from GnuPG 1.3.2.
2002-06-04 Werner Koch <wk@gnupg.org>
* stringhelp.c (print_sanitized_utf8_string): New. No real
implementation for now.
(print_sanitized_utf8_buffer): Ditto.
2002-04-04 Werner Koch <wk@gnupg.org>
* logging.c (log_get_prefix): New.
2002-03-15 Werner Koch <wk@gnupg.org>
* argparse.c (optfile_parse): Fixed missing argument handling.
2002-02-25 Werner Koch <wk@gnupg.org>
* stringhelp.c (ascii_memcasemem): New.
2002-02-14 Werner Koch <wk@gnupg.org>
* Makefile.am (INCLUDES): Add cflags for libgcrypt.
2002-02-07 Werner Koch <wk@gnupg.org>
* logging.c (log_set_fd): New.
* stringhelp.c (print_sanitized_buffer): New.
(print_sanitized_string): New.
2002-01-24 Werner Koch <wk@gnupg.org>
* argparse.c (strusage): Set default copyright notice year to 2002.
Fixed the copyright notice of this file, as it has always been
part of GnuPG and therefore belongs to the FSF.
2001-11-01 Marcus Brinkmann <marcus@g10code.de>
* logging.c (log_printf): Do not initialize ARG_PTR with 0, we
don't know the correct type. Instead, run va_start and va_end
unconditionally.
Reported by Jose Carlos Garcia Sogo <jsogo@debian.org>.
2002-01-19 Werner Koch <wk@gnupg.org>
* logging.c (log_get_stream): New.
2001-12-05 Werner Koch <wk@gnupg.org>
* logging.c (log_set_prefix): New.
(do_logv): Include prefix and pid only if enabled. Print time only
when explicitly enabled.
(log_logv): New.
* logging.h: Include log_logv() only when requested.
2001-11-06 Werner Koch <wk@gnupg.org>
* strlist.c, strlist.h: New. Taken from pgnupg/util/strgutil.c
2001-08-30 Werner Koch <wk@gnupg.org>
* logging.c (log_printf): Don't pass NULL instead of arg_ptr.
2001-07-19 Werner Koch <wk@gnupg.org>
* stringhelp.c (ascii_memistr,ascii_isupper,ascii_islower,
ascii_toupper,ascii_tolower, ascii_strcasecmp, ascii_memcasecmp): New.
2000-07-26 10:02:51 Werner Koch (wk@habibti.openit.de)
* stringhelp.c.: Add stdarg.h
* argparse.h: s/ulong/unsigned long/ although this should be defined
by types.h.
2000-06-28 19:40:23 Werner Koch (wk@habibti.openit.de)
* Makefile.am: Replaced second logging.c by .h
2000-05-24 08:58:15 Werner Koch (wk@habibti.openit.de)
* logging.c (log_get_errorcount): New.
2000-05-24 08:44:47 Werner Koch (wk@habibti.openit.de)
* stringhelp.c: Added a few filename related helper functions.
2000-05-11 18:04:43 Werner Koch (wk@habibti.openit.de)
* xmalloc.c (xstrcat2): Replaced stpcpy to quickly address W32
problems.
2000-05-02 19:43:38 Werner Koch (wk@habibti.openit.de)
* xmalloc.c (xstrcat2): New.
Mon Jan 24 13:04:28 CET 2000 Werner Koch <wk@gnupg.de>
* README: New.
* Makefile.am: new.
* argparse.c argparse.h logging.c logging.h
mischelp.h stringhelp.c stringhelp.h xmalloc.c
xmalloc.h dotlock.c: Moved from ../util to here.
* dotlock.h: New.
* libjnlib-config.h: New.
* logging.c (log_set_file): New.
(log_printf): New.
(do_logv): Add kludge to insert LFs.
***********************************************************
* Please note that Jnlib is maintained as part of GnuPG. *
* You may find it source-copied in other packages. *
***********************************************************
Copyright 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without
modifications, as long as this notice is preserved.
This file is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/jnlib/logging.c b/jnlib/logging.c
index fdf2d7fcb..7397ddd30 100644
--- a/jnlib/logging.c
+++ b/jnlib/logging.c
@@ -1,551 +1,558 @@
/* logging.c - useful logging functions
* Copyright (C) 1998, 1999, 2000, 2001, 2003,
* 2004 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
/* This file should replace logger.c in the future - for now it is not
* used by GnuPG but by GPA.
* It is a quite simple implemenation but sufficient for most purposes.
*/
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stddef.h>
#include <errno.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#ifdef __MINGW32__
# include <io.h>
#endif
#define JNLIB_NEED_LOG_LOGV 1
#include "libjnlib-config.h"
#include "logging.h"
static FILE *logstream;
static int log_socket = -1;
static char prefix_buffer[80];
static int with_time;
static int with_prefix;
static int with_pid;
static int running_detached;
static int force_prefixes;
static int missing_lf;
static int errorcount;
#if 0
static void
write2stderr( const char *s )
{
write( 2, s, strlen(s) );
}
static void
do_die(int rc, const char *text )
{
write2stderr("\nFatal error: ");
write2stderr(text);
write2stderr("\n");
abort();
}
#endif
int
log_get_errorcount (int clear)
{
int n = errorcount;
if( clear )
errorcount = 0;
return n;
}
void
log_inc_errorcount (void)
{
errorcount++;
}
/* The follwing 3 functions are used by funopen to write logs to a
socket. */
#if defined (HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN)
struct fun_cookie_s {
int fd;
int quiet;
char name[1];
};
/* Write NBYTES of BUF to file descriptor FD. */
static int
writen (int fd, const unsigned char *buf, size_t nbytes)
{
size_t nleft = nbytes;
int nwritten;
while (nleft > 0)
{
nwritten = write (fd, buf, nleft);
if (nwritten < 0 && errno == EINTR)
continue;
if (nwritten < 0)
return -1;
nleft -= nwritten;
buf = buf + nwritten;
}
return 0;
}
static int
fun_writer (void *cookie_arg, const char *buffer, size_t size)
{
struct fun_cookie_s *cookie = cookie_arg;
/* Note that we always try to reconnect to the socket but print
error messages only the first time an error occured. IF
RUNNING_DETACHED is set we don't fall back to stderr and even do
not print any error messages. This is needed becuase detached
processes often close stderr and my printing to fiel descriptor 2
we might send the log message to a file not intended for logging
(e.g. a pipe or network connection). */
if (cookie->fd == -1)
{
/* Note yet open or meanwhile closed due to an error. */
struct sockaddr_un addr;
size_t addrlen;
cookie->fd = socket (PF_LOCAL, SOCK_STREAM, 0);
if (cookie->fd == -1)
{
if (!cookie->quiet && !running_detached)
fprintf (stderr, "failed to create socket for logging: %s\n",
strerror(errno));
goto failure;
}
log_socket = cookie->fd;
memset (&addr, 0, sizeof addr);
addr.sun_family = PF_LOCAL;
strncpy (addr.sun_path, cookie->name, sizeof (addr.sun_path)-1);
addr.sun_path[sizeof (addr.sun_path)-1] = 0;
addrlen = (offsetof (struct sockaddr_un, sun_path)
+ strlen (addr.sun_path) + 1);
if (connect (cookie->fd, (struct sockaddr *) &addr, addrlen) == -1)
{
log_socket = -1;
if (!cookie->quiet && !running_detached)
fprintf (stderr, "can't connect to `%s': %s\n",
cookie->name, strerror(errno));
close (cookie->fd);
cookie->fd = -1;
goto failure;
}
/* Connection established. */
cookie->quiet = 0;
}
if (!writen (cookie->fd, buffer, size))
return size; /* Okay. */
log_socket = -1;
if (!running_detached)
fprintf (stderr, "error writing to `%s': %s\n",
cookie->name, strerror(errno));
close (cookie->fd);
cookie->fd = -1;
failure:
if (!running_detached)
{
if (!cookie->quiet)
{
fputs ("switching logging to stderr\n", stderr);
cookie->quiet = 1;
}
fwrite (buffer, size, 1, stderr);
}
return size;
}
static int
fun_closer (void *cookie_arg)
{
struct fun_cookie_s *cookie = cookie_arg;
if (cookie->fd != -1)
close (cookie->fd);
jnlib_free (cookie);
return 0;
}
#endif /* HAVE_FOPENCOOKIE || HAVE_FUNOPEN */
-/* Set the file to write log to. The sepcial names NULL and "_" may
+/* Set the file to write log to. The special names NULL and "-" may
be used to select stderr and names formatted like
"socket:///home/foo/mylogs" may be used to write the logging to the
socket "/home/foo/mylogs". If the connection to the socket fails
or a write error is detected, the function writes to stderr and
tries the next time again to connect the socket.
*/
void
log_set_file (const char *name)
{
FILE *fp;
force_prefixes = 0;
if (name && !strncmp (name, "socket://", 9) && name[9])
{
#if defined (HAVE_FOPENCOOKIE)|| defined (HAVE_FUNOPEN)
struct fun_cookie_s *cookie;
cookie = jnlib_xmalloc (sizeof *cookie + strlen (name+9));
cookie->fd = -1;
cookie->quiet = 0;
strcpy (cookie->name, name+9);
#ifdef HAVE_FOPENCOOKIE
{
cookie_io_functions_t io = { NULL };
io.write = fun_writer;
io.close = fun_closer;
fp = fopencookie (cookie, "w", io);
}
#else /*!HAVE_FOPENCOOKIE*/
{
fp = funopen (cookie, NULL, fun_writer, NULL, fun_closer);
}
#endif /*!HAVE_FOPENCOOKIE*/
#else /* Neither fopencookie nor funopen. */
{
fprintf (stderr, "system does not support logging to a socket - "
"using stderr\n");
fp = stderr;
}
#endif /* Neither fopencookie nor funopen. */
/* We always need to print the prefix and the pid, so that the
server reading the socket can do something meanigful. */
force_prefixes = 1;
+ /* On success close the old logstream right now, so that we are
+ really sure it has been closed. */
+ if (fp)
+ {
+ fclose (logstream);
+ logstream = NULL;
+ }
}
else
fp = (name && strcmp(name,"-"))? fopen (name, "a") : stderr;
if (!fp)
{
fprintf (stderr, "failed to open log file `%s': %s\n",
name? name:"[stderr]", strerror(errno));
return;
}
setvbuf (fp, NULL, _IOLBF, 0);
if (logstream && logstream != stderr && logstream != stdout)
fclose (logstream);
logstream = fp;
missing_lf = 0;
}
void
log_set_fd (int fd)
{
FILE *fp;
force_prefixes = 0;
if (fd == 1)
fp = stdout;
else if (fd == 2)
fp = stderr;
else
fp = fdopen (fd, "a");
if (!fp)
{
fprintf (stderr, "failed to fdopen log fd %d: %s\n",
fd, strerror(errno));
return;
}
setvbuf (fp, NULL, _IOLBF, 0);
if (logstream && logstream != stderr && logstream != stdout)
fclose( logstream);
logstream = fp;
missing_lf = 0;
}
void
log_set_prefix (const char *text, unsigned int flags)
{
if (text)
{
strncpy (prefix_buffer, text, sizeof (prefix_buffer)-1);
prefix_buffer[sizeof (prefix_buffer)-1] = 0;
}
with_prefix = (flags & JNLIB_LOG_WITH_PREFIX);
with_time = (flags & JNLIB_LOG_WITH_TIME);
with_pid = (flags & JNLIB_LOG_WITH_PID);
running_detached = (flags & JNLIB_LOG_RUN_DETACHED);
}
const char *
log_get_prefix (unsigned int *flags)
{
if (flags)
{
*flags = 0;
if (with_prefix)
*flags |= JNLIB_LOG_WITH_PREFIX;
if (with_time)
*flags |= JNLIB_LOG_WITH_TIME;
if (with_pid)
*flags |= JNLIB_LOG_WITH_PID;
if (running_detached)
*flags |= JNLIB_LOG_RUN_DETACHED;
}
return prefix_buffer;
}
/* This function returns true if the file descriptor FD is in use for
logging. This is preferable over a test using log_get_fd in that
it allows the logging code to use more then one file descriptor. */
int
log_test_fd (int fd)
{
if (fileno (logstream?logstream:stderr) == fd)
return 1;
if (log_socket == fd)
return 1;
return 0;
}
int
log_get_fd ()
{
return fileno(logstream?logstream:stderr);
}
FILE *
log_get_stream ()
{
return logstream?logstream:stderr;
}
static void
do_logv (int level, const char *fmt, va_list arg_ptr)
{
if (!logstream)
logstream = stderr;
if (missing_lf && level != JNLIB_LOG_CONT)
putc('\n', logstream );
missing_lf = 0;
if (level != JNLIB_LOG_CONT)
{ /* Note this does not work for multiple line logging as we would
* need to print to a buffer first */
if (with_time && !force_prefixes)
{
struct tm *tp;
time_t atime = time (NULL);
tp = localtime (&atime);
fprintf (logstream, "%04d-%02d-%02d %02d:%02d:%02d ",
1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
tp->tm_hour, tp->tm_min, tp->tm_sec );
}
if (with_prefix || force_prefixes)
fputs (prefix_buffer, logstream);
if (with_pid || force_prefixes)
fprintf (logstream, "[%u]", (unsigned int)getpid ());
if (!with_time || force_prefixes)
putc (':', logstream);
/* A leading backspace suppresses the extra space so that we can
correctly output, programname, filename and linenumber. */
if (fmt && *fmt == '\b')
fmt++;
else
putc (' ', logstream);
}
switch (level)
{
case JNLIB_LOG_BEGIN: break;
case JNLIB_LOG_CONT: break;
case JNLIB_LOG_INFO: break;
case JNLIB_LOG_WARN: break;
case JNLIB_LOG_ERROR: break;
case JNLIB_LOG_FATAL: fputs("Fatal: ",logstream ); break;
case JNLIB_LOG_BUG: fputs("Ohhhh jeeee: ", logstream); break;
case JNLIB_LOG_DEBUG: fputs("DBG: ", logstream ); break;
default: fprintf(logstream,"[Unknown log level %d]: ", level ); break;
}
if (fmt)
{
vfprintf(logstream,fmt,arg_ptr) ;
if (*fmt && fmt[strlen(fmt)-1] != '\n')
missing_lf = 1;
}
if (level == JNLIB_LOG_FATAL)
exit(2);
if (level == JNLIB_LOG_BUG)
abort();
}
static void
do_log( int level, const char *fmt, ... )
{
va_list arg_ptr ;
va_start( arg_ptr, fmt ) ;
do_logv( level, fmt, arg_ptr );
va_end(arg_ptr);
}
void
log_logv (int level, const char *fmt, va_list arg_ptr)
{
do_logv (level, fmt, arg_ptr);
}
void
log_info( const char *fmt, ... )
{
va_list arg_ptr ;
va_start( arg_ptr, fmt ) ;
do_logv( JNLIB_LOG_INFO, fmt, arg_ptr );
va_end(arg_ptr);
}
void
log_error( const char *fmt, ... )
{
va_list arg_ptr ;
va_start( arg_ptr, fmt ) ;
do_logv( JNLIB_LOG_ERROR, fmt, arg_ptr );
va_end(arg_ptr);
/* protect against counter overflow */
if( errorcount < 30000 )
errorcount++;
}
void
log_fatal( const char *fmt, ... )
{
va_list arg_ptr ;
va_start( arg_ptr, fmt ) ;
do_logv( JNLIB_LOG_FATAL, fmt, arg_ptr );
va_end(arg_ptr);
abort(); /* never called, but it makes the compiler happy */
}
void
log_bug( const char *fmt, ... )
{
va_list arg_ptr ;
va_start( arg_ptr, fmt ) ;
do_logv( JNLIB_LOG_BUG, fmt, arg_ptr );
va_end(arg_ptr);
abort(); /* never called, but it makes the compiler happy */
}
void
log_debug( const char *fmt, ... )
{
va_list arg_ptr ;
va_start( arg_ptr, fmt ) ;
do_logv( JNLIB_LOG_DEBUG, fmt, arg_ptr );
va_end(arg_ptr);
}
void
log_printf (const char *fmt, ...)
{
va_list arg_ptr;
va_start (arg_ptr, fmt);
do_logv (fmt ? JNLIB_LOG_CONT : JNLIB_LOG_BEGIN, fmt, arg_ptr);
va_end (arg_ptr);
}
/* Print a hexdump of BUFFER. With TEXT of NULL print just the raw
dump, with TEXT just an empty string, print a trailing linefeed,
otherwise print an entire debug line. */
void
log_printhex (const char *text, const void *buffer, size_t length)
{
if (text && *text)
log_debug ("%s ", text);
if (length)
{
const unsigned char *p = buffer;
log_printf ("%02X", *p);
for (length--, p++; length--; p++)
log_printf (" %02X", *p);
}
if (text)
log_printf ("\n");
}
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
void
bug_at( const char *file, int line, const char *func )
{
do_log( JNLIB_LOG_BUG,
("... this is a bug (%s:%d:%s)\n"), file, line, func );
abort(); /* never called, but it makes the compiler happy */
}
#else
void
bug_at( const char *file, int line )
{
do_log( JNLIB_LOG_BUG,
_("you found a bug ... (%s:%d)\n"), file, line);
abort(); /* never called, but it makes the compiler happy */
}
#endif

File Metadata

Mime Type
text/x-diff
Expires
Tue, Jul 8, 12:22 PM (14 h, 56 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
ca/16/8bd9387e1318ebf339c8fac15b0e

Event Timeline