From d8b1099d01ebc1d305d47ec6dcb326980ad56396 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 10 Mar 2010 12:24:58 +0000 Subject: Merged jnlib into common. --- ChangeLog | 9 + Makefile.am | 2 +- acinclude.m4 | 5 +- agent/ChangeLog | 6 + agent/Makefile.am | 4 +- agent/command-ssh.c | 1 - agent/minip12.c | 6 +- agent/protect-tool.c | 1 - agent/trustlist.c | 1 - common/ChangeLog | 27 ++ common/ChangeLog.jnlib | 769 +++++++++++++++++++++++++++++ common/Makefile.am | 54 ++- common/README.jnlib | 101 ++++ common/argparse.c | 1205 ++++++++++++++++++++++++++++++++++++++++++++++ common/argparse.h | 183 +++++++ common/audit.h | 2 +- common/dotlock.c | 713 +++++++++++++++++++++++++++ common/dotlock.h | 33 ++ common/dynload.h | 86 ++++ common/exechelp.c | 10 +- common/exechelp.h | 2 +- common/http.h | 2 +- common/i18n.h | 2 +- common/init.c | 1 - common/iobuf.c | 4 +- common/libjnlib-config.h | 99 ++++ common/localename.c | 4 +- common/logging.c | 651 +++++++++++++++++++++++++ common/logging.h | 88 ++++ common/mischelp.c | 197 ++++++++ common/mischelp.h | 102 ++++ common/simple-pwquery.c | 4 +- common/simple-pwquery.h | 2 +- common/stringhelp.c | 1151 +++++++++++++++++++++++++++++++++++++++++++ common/stringhelp.h | 136 ++++++ common/strlist.c | 204 ++++++++ common/strlist.h | 50 ++ common/sysutils.h | 2 +- common/t-stringhelp.c | 414 ++++++++++++++++ common/t-support.c | 147 ++++++ common/t-support.h | 60 +++ common/t-timestuff.c | 145 ++++++ common/t-w32-reg.c | 70 +++ common/ttyio.c | 1 - common/types.h | 114 +++++ common/utf8conv.c | 813 +++++++++++++++++++++++++++++++ common/utf8conv.h | 45 ++ common/util.h | 27 +- common/w32-afunix.c | 138 ++++++ common/w32-afunix.h | 52 ++ common/w32-reg.c | 312 ++++++++++++ common/w32help.h | 32 ++ common/xasprintf.c | 1 - common/xmalloc.c | 87 ++++ common/xmalloc.h | 30 ++ configure.ac | 10 +- g10/ChangeLog | 6 + g10/Makefile.am | 2 +- g10/main.h | 1 - g10/packet.h | 2 +- g10/rmd160.c | 2 +- g13/Makefile.am | 2 +- jnlib/ChangeLog | 758 ----------------------------- jnlib/Makefile.am | 85 ---- jnlib/README | 8 - jnlib/argparse.c | 1205 ---------------------------------------------- jnlib/argparse.h | 183 ------- jnlib/dotlock.c | 713 --------------------------- jnlib/dotlock.h | 33 -- jnlib/dynload.h | 86 ---- jnlib/libjnlib-config.h | 99 ---- jnlib/logging.c | 651 ------------------------- jnlib/logging.h | 88 ---- jnlib/mischelp.c | 197 -------- jnlib/mischelp.h | 102 ---- jnlib/stringhelp.c | 1151 ------------------------------------------- jnlib/stringhelp.h | 136 ------ jnlib/strlist.c | 204 -------- jnlib/strlist.h | 50 -- jnlib/t-stringhelp.c | 414 ---------------- jnlib/t-support.c | 147 ------ jnlib/t-support.h | 60 --- jnlib/t-timestuff.c | 145 ------ jnlib/t-w32-reg.c | 70 --- jnlib/types.h | 114 ----- jnlib/utf8conv.c | 813 ------------------------------- jnlib/utf8conv.h | 45 -- jnlib/w32-afunix.c | 138 ------ jnlib/w32-afunix.h | 52 -- jnlib/w32-reg.c | 312 ------------ jnlib/w32help.h | 32 -- jnlib/xmalloc.c | 87 ---- jnlib/xmalloc.h | 30 -- kbx/ChangeLog | 7 + kbx/Makefile.am | 4 +- kbx/kbxutil.c | 10 +- kbx/keybox-defs.h | 6 +- kbx/keybox-dump.c | 2 +- kbx/keybox-init.c | 2 +- kbx/keybox-search.c | 2 +- keyserver/Makefile.am | 4 +- po/POTFILES.in | 11 +- scd/ChangeLog | 4 + scd/Makefile.am | 2 +- sm/ChangeLog | 6 + sm/Makefile.am | 3 +- sm/gpgsm.h | 1 - tools/ChangeLog | 4 + tools/Makefile.am | 6 +- 109 files changed, 8419 insertions(+), 8295 deletions(-) create mode 100644 common/ChangeLog.jnlib create mode 100644 common/README.jnlib create mode 100644 common/argparse.c create mode 100644 common/argparse.h create mode 100644 common/dotlock.c create mode 100644 common/dotlock.h create mode 100644 common/dynload.h create mode 100644 common/libjnlib-config.h create mode 100644 common/logging.c create mode 100644 common/logging.h create mode 100644 common/mischelp.c create mode 100644 common/mischelp.h create mode 100644 common/stringhelp.c create mode 100644 common/stringhelp.h create mode 100644 common/strlist.c create mode 100644 common/strlist.h create mode 100644 common/t-stringhelp.c create mode 100644 common/t-support.c create mode 100644 common/t-support.h create mode 100644 common/t-timestuff.c create mode 100644 common/t-w32-reg.c create mode 100644 common/types.h create mode 100644 common/utf8conv.c create mode 100644 common/utf8conv.h create mode 100644 common/w32-afunix.c create mode 100644 common/w32-afunix.h create mode 100644 common/w32-reg.c create mode 100644 common/w32help.h create mode 100644 common/xmalloc.c create mode 100644 common/xmalloc.h delete mode 100644 jnlib/ChangeLog delete mode 100644 jnlib/Makefile.am delete mode 100644 jnlib/README delete mode 100644 jnlib/argparse.c delete mode 100644 jnlib/argparse.h delete mode 100644 jnlib/dotlock.c delete mode 100644 jnlib/dotlock.h delete mode 100644 jnlib/dynload.h delete mode 100644 jnlib/libjnlib-config.h delete mode 100644 jnlib/logging.c delete mode 100644 jnlib/logging.h delete mode 100644 jnlib/mischelp.c delete mode 100644 jnlib/mischelp.h delete mode 100644 jnlib/stringhelp.c delete mode 100644 jnlib/stringhelp.h delete mode 100644 jnlib/strlist.c delete mode 100644 jnlib/strlist.h delete mode 100644 jnlib/t-stringhelp.c delete mode 100644 jnlib/t-support.c delete mode 100644 jnlib/t-support.h delete mode 100644 jnlib/t-timestuff.c delete mode 100644 jnlib/t-w32-reg.c delete mode 100644 jnlib/types.h delete mode 100644 jnlib/utf8conv.c delete mode 100644 jnlib/utf8conv.h delete mode 100644 jnlib/w32-afunix.c delete mode 100644 jnlib/w32-afunix.h delete mode 100644 jnlib/w32-reg.c delete mode 100644 jnlib/w32help.h delete mode 100644 jnlib/xmalloc.c delete mode 100644 jnlib/xmalloc.h diff --git a/ChangeLog b/ChangeLog index ae040c30a..f96332e20 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2010-03-10 Werner Koch + + * jnlib/: Move all code to common/. + * Makefile.am (SUBDIRS): Remove jnlib. + * configure.ac (AC_CONFIG_FILES): Remove jnlib/Makefile. + + * configure.ac (AM_PATH_LIBASSUAN): Remove double test. + * acinclude.m4 (GNUPG_CHECK_ENDIAN): Remove bogus warning. + 2010-03-09 Werner Koch * configure.ac: Add option --disable-ccid-driver. diff --git a/Makefile.am b/Makefile.am index 0579d0591..59e8226c5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -76,7 +76,7 @@ else tests = tests endif -SUBDIRS = m4 gl include jnlib common ${kbx} \ +SUBDIRS = m4 gl include common ${kbx} \ ${gpg} ${keyserver} ${sm} ${agent} ${scd} ${g13} ${tools} po ${doc} ${tests} dist_doc_DATA = README diff --git a/acinclude.m4 b/acinclude.m4 index d8f2e174b..28366ee38 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -103,6 +103,7 @@ dnl AC_DEFUN([GNUPG_CHECK_ENDIAN], [ tmp_assumed_endian=big + tmp_assume_warn="" if test "$cross_compiling" = yes; then case "$host_cpu" in i@<:@345678@:>@* ) @@ -111,7 +112,6 @@ AC_DEFUN([GNUPG_CHECK_ENDIAN], *) ;; esac - AC_MSG_WARN(cross compiling; assuming $tmp_assumed_endian endianess) fi AC_MSG_CHECKING(endianess) AC_CACHE_VAL(gnupg_cv_c_endian, @@ -141,10 +141,11 @@ AC_DEFUN([GNUPG_CHECK_ENDIAN], gnupg_cv_c_endian=little, gnupg_cv_c_endian=big, gnupg_cv_c_endian=$tmp_assumed_endian + tmp_assumed_warn=" (assumed)" ) fi ]) - AC_MSG_RESULT([$gnupg_cv_c_endian]) + AC_MSG_RESULT([${gnupg_cv_c_endian}${tmp_assumed_warn}]) if test "$gnupg_cv_c_endian" = little; then AC_DEFINE(LITTLE_ENDIAN_HOST,1, [Defined if the host has little endian byte ordering]) diff --git a/agent/ChangeLog b/agent/ChangeLog index 0c68c1436..e4fbe073b 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,9 @@ +2010-03-10 Werner Koch + + * Makefile.am (common_libs): Remove libjnlib.a. + + * trustlist.c, protect-tool.c, command-ssh.c: Remove estream.h. + 2010-02-17 Werner Koch * call-pinentry.c (start_pinentry): Always free OPTSTR. Send diff --git a/agent/Makefile.am b/agent/Makefile.am index 38200c1d8..4f5c08ef9 100644 --- a/agent/Makefile.am +++ b/agent/Makefile.am @@ -45,8 +45,8 @@ gpg_agent_SOURCES = \ call-scd.c \ learncard.c -common_libs = $(libcommon) ../jnlib/libjnlib.a ../gl/libgnu.a -commonpth_libs = $(libcommonpth) ../jnlib/libjnlib.a ../gl/libgnu.a +common_libs = $(libcommon) ../gl/libgnu.a +commonpth_libs = $(libcommonpth) ../gl/libgnu.a pwquery_libs = ../common/libsimple-pwquery.a #if HAVE_W32_SYSTEM diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 12fe60a15..077d93209 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -32,7 +32,6 @@ #include "agent.h" -#include "estream.h" #include "i18n.h" diff --git a/agent/minip12.c b/agent/minip12.c index 247171773..6f512e9e5 100644 --- a/agent/minip12.c +++ b/agent/minip12.c @@ -32,8 +32,8 @@ #include #endif -#include "../jnlib/logging.h" -#include "../jnlib/utf8conv.h" +#include "../common/logging.h" +#include "../common/utf8conv.h" #include "minip12.h" #ifndef DIM @@ -2354,7 +2354,7 @@ main (int argc, char **argv) /* Local Variables: -compile-command: "gcc -Wall -O0 -g -DTEST=1 -o minip12 minip12.c ../jnlib/libjnlib.a -L /usr/local/lib -lgcrypt -lgpg-error" +compile-command: "gcc -Wall -O0 -g -DTEST=1 -o minip12 minip12.c ../common/libcommon.a -L /usr/local/lib -lgcrypt -lgpg-error" End: */ #endif /* TEST */ diff --git a/agent/protect-tool.c b/agent/protect-tool.c index dc040f9d8..4008a8867 100644 --- a/agent/protect-tool.c +++ b/agent/protect-tool.c @@ -44,7 +44,6 @@ #include "i18n.h" #include "get-passphrase.h" #include "sysutils.h" -#include "estream.h" enum cmd_and_opt_values diff --git a/agent/trustlist.c b/agent/trustlist.c index be5406b05..3236ae425 100644 --- a/agent/trustlist.c +++ b/agent/trustlist.c @@ -31,7 +31,6 @@ #include "agent.h" #include /* fixme: need a way to avoid assuan calls here */ #include "i18n.h" -#include "estream.h" /* A structure to store the information from the trust file. */ diff --git a/common/ChangeLog b/common/ChangeLog index 7408123ec..6f4b70b30 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,5 +1,32 @@ +2010-03-10 Werner Koch + + * util.h: Replace jnlib path part by common. + (snprintf): Use the replacement macro on all platforms. + + * Makefile.am (jnlib_sources): New. + (libcommon_a_SOURCES, libcommonpth_a_SOURCES): Add jnlib_sources. + (jnlib_tests): New. + (noinst_PROGRAMS, TESTS): Add jnlib_tests. + (t_common_ldadd): Remove libjnlib.a. + + * README.jnlib, ChangeLog.jnlib, libjnlib-config.h, argparse.c + * argparse.h, dotlock.c, dotlock.h, dynload.h, logging.c + * logging.h, mischelp.c, mischelp.h, stringhelp.c, stringhelp.h + * strlist.c, strlist.h, types.h, utf8conv.c, utf8conv.h + * w32-afunix.c, w32-afunix.h, w32-reg.c, w32help.h, xmalloc.c + * xmalloc.h, t-stringhelp.c, t-support.c, t-support.h + * t-timestuff.c, t-w32-reg.c: Move from jnlib to here. + + * init.c: Remove "estream.h". + * util.h: Include "estream.h". + + * xasprintf.c, ttyio.c: Remove "estream-printf.h". + 2010-03-08 Werner Koch + * exechelp.c [!HAVE_SIGNAL_H]: Do not include signal.h. + (DETACHED_PROCESS, CREATE_NEW_PROCESS_GROUP) [W32CE]: Provide stubs. + * iobuf.h (iobuf_ioctl_t): New. Use the new macros instead of the hard wired values. * iobuf.c (iobuf_append): Remove. diff --git a/common/ChangeLog.jnlib b/common/ChangeLog.jnlib new file mode 100644 index 000000000..f51525e42 --- /dev/null +++ b/common/ChangeLog.jnlib @@ -0,0 +1,769 @@ +2010-03-10 Werner Koch + + See gnupg/common/ChangeLog for newer changes. + + JNLIB has been merged into GnuPG's common directory. README.jnlib + list the files making up JNLIB. + + * README: Rename to README.jnlib + * ChangeLog: Rename to ChangeLog.jnlib. + * Makefile.am: Remove. + +2010-03-01 Werner Koch + + * t-w32-reg.c: New. + + * w32-reg.c (read_w32_registry_string) + (write_w32_registry_string): Support W32CE. + +2010-02-26 Werner Koch + + * t-timestuff.c: New. + + * dynload.h (dlopen, dlsym) [W32CE]: Map to wchar_t. + + * mischelp.c (_jnlib_free): New. + (same_file_p) [W32CE]: Map to wchar_t. + + * utf8conv.c (set_native_charset) [W32CE]: Do not use + GetConsoleOutputCP. + (wchar_to_utf8, utf8_to_wchar) [W32]: New. + + * Makefile.am (t_jnlib_ldadd) [W32CE]: Add gpg-error. + + * t-support.h (getenv) [HAVE_GETENV]: Add getenv stub. + [W32CE]: Include gpg-error.h + * t-support.c (gpg_err_code_from_errno) + (gpg_err_code_from_syserror) [GPG_ERROR_H]: Do not build. + + * t-stringhelp.c (gethome) [!HAVE_GETPWUID]: Keep result of getenv. + + * dotlock.c [!HAVE_SIGNAL_H]: Don't include signal.h. + (create_dotlock) [W32CE]: Map filename top wchar_t. + + * libjnlib-config.h [USE_SIMPLE_GETTEXT]: Include gpg-error.h and + remove w32help.h. + (jnlib_set_errno): New. Use it everywhere to set ERRNO. + (getenv) [!HAVE_GETENV]: New. + (getpid) [W32E]: New. + + * stringhelp.c (get_pwdir) [!HAVE_PWD_H]: Mark unused args. + (w32_strerror) [W32CE]: Use a simple implementation. + + * w32help.h [USE_SIMPLE_GETTEXT]: Remove all definitions; we are + now using the gpg-error included implementation. + * w32-gettext.c: Remove. + + * mischelp.c (same_file_p): Fix bug in case the second file can't + be opened. + +2009-10-19 Werner Koch + + * strlist.c (add_to_strlist_try): New. + +2009-09-22 Werner Koch + + * dotlock.h (DOTLOCK): Rename to dotlock_t. Change all users. + +2009-08-26 Werner Koch + + * stringhelp.c (do_make_filename): Factor some code out to .. + (get_pwdir): .. new. + +2009-08-26 Werner Koch + + * stringhelp.c [HAVE_PWD_H]: Include pwd.h. + (do_make_filename): New. + (make_filename, make_filename_try): Implement using the new + function. + * t-stringhelp.c (test_make_filename_try): New. + * t-support.c (gcry_strdup): Fix. + + * stringhelp.h (make_filename, make_filename_try): Add sentinel + attribute. + +2009-08-25 Werner Koch + + * stringhelp.c: Include errno.h. + (do_strconcat): New. + (strconcat, xstrconcat): New. + * types.h (GNUPG_GCC_A_SENTINEL): New. + * t-stringhelp.c (test_strconcat, test_xstrconcat): New. + (main): Run them. + +2009-07-07 Werner Koch + + * stringhelp.c (make_filename_try): Use jnlib_malloc. + + * dotlock.c (read_lockfile): Replace jnlib_xmalloc by jnlib_malloc. + +2009-06-04 Werner Koch + + * mischelp.h: Include SUN_LEN etc also for W32. + +2009-05-19 Werner Koch + + * mischelp.h: Define PF_LOCAL, AF_LOCAL and SUN_LEN if requested. + * logging.c (fun_writer): Use SUN_LEN to fix a Mac OS X freeze. + +2009-03-25 Werner Koch + + * logging.c (fun_closer): Never close fd 2. + (set_file_fd): Close logstream early. + +2009-02-25 Werner Koch + + * logging.c (get_tid_callback): New. + (do_logv): Use it. + (log_set_get_tid_callback): New. + +2009-01-22 Werner Koch + + * t-support.c (gpg_err_code_from_errno) + (gpg_err_code_from_syserror): New. + +2008-11-20 Werner Koch + + * argparse.c (arg_parse): Fix last change. + +2008-11-11 Werner Koch + + * argparse.h: Add a bunch of macros and constants. + * argparse.c: Use the new macros. Re-indent the code. Change + license back to LGPL 2.1. + +2008-11-04 Werner Koch + + * w32-gettext.c: Merged with code from libgpg-error and rewrote + most parts. + + * Makefile.am (AM_CFLAGS): Add -DJNLIB_IN_JNLIB. + +2008-10-29 Werner Koch + + * stringhelp.c (make_filename): Implement using macros. Factor some + code out to .. + (change_slashes): New. + (make_filename_try): New. + + * w32-gettext.c (gettext): Return if no domain is loaded. + Reported by Tom Pegios. + +2008-10-28 Werner Koch + + * w32-gettext.c (gettext): Try the binary search if the string was + not found in the hash table. + +2008-10-20 Werner Koch + + * w32-afunix.c (_w32_sock_connect): Mark ADDRLEN as unused. + + * dotlock.c (release_dotlock): Do not mix declaration and code. + + * stringhelp.c (make_basename): Silent gcc warning about unused arg. + * argparse.c (store_alias): Ditto. + (find_long_option): + +2008-10-15 Werner Koch + + * logging.c (do_logv) [W32]: Flush the log stream. + +2008-09-29 Werner Koch + + * argparse.c (ARGERR_): Use constants for error values. + (optfile_parse): Prettify. Replace xmalloc and xrealloc by malloc + and realloc. + * libjnlib-config.h (jnlib_strdup, jnlib_realloc): New. + +2008-06-26 Werner Koch + + * stringhelp.c (print_sanitized_buffer2): Loose check for control + characters to better cope with utf-8. The range 0x80..0x9f is + nowadays not anymore accidently used for control charaters. + +2008-06-13 Werner Koch + + * dotlock.c: Reformat code and implement locking for W32. + (create_dotlock): Use snprintf. + +2008-06-11 Werner Koch + + * utf8conv.c: Remove useless variable ACTIVE_CHARSET. Suggested + by Petr Uzel. + +2008-05-26 Werner Koch + + * argparse.c (usage): Make sure to print a trailing LF for usage(1). + +2008-04-08 Werner Koch + + * w32-gettext.c (gettext_select_utf8): New. + (get_string): Support switching encodings. + (load_domain): Allocate space for DATA_NATIVE. + +2008-03-25 Werner Koch + + * w32-gettext.c (_nl_locale_name): New. Taken from + ../common/localename and GNU gettext's localename.c. + (set_gettext_file): Rewritten. + (gettext_localename): New. + +2008-03-17 Werner Koch + + * logging.c (my_funopen_hook_size_t): New. + (fun_writer): Use it to cope with fopencookie/funopen differences. + * dotlock.c (read_lockfile): Initialize PID. Reported by Stéphane + Corthésy. + +2008-02-22 Werner Koch + + * argparse.c (strusage): Set copyright year to 2008. + +2007-11-19 Werner Koch + + * stringhelp.c (percent_escape): Factor code out to + (do_percent_escape): .. new. + (try_percent_escape): New. + +2007-10-01 Werner Koch + + * w32-afunix.c: Only keep the client related code. + (read_port_and_nonce): New. Taken from Assuan. + (_w32_sock_connect): Rewritten. + +2007-08-29 Werner Koch + + * argparse.c (initialize): Make strings translatable and remove + extra LF. + +2007-08-24 Werner Koch + + * mischelp.c (same_file_p): New. + (libjnlib_dummy_mischelp_func): Remove as we now always have one + function. + +2007-08-09 Werner Koch + + * argparse.c (show_help): Expand the @EMAIL@ macro in the package + bug reporting address. + +2007-08-02 Werner Koch + + * t-stringhelp.c (test_compare_filenames): New. + + * stringhelp.c (compare_filenames) [HAVE_DRIVE_LETTERS]: Fixed + comparison to take slash and backslash in account. + (make_filename): Avoid mixing / and \. + +2007-07-04 Werner Koch + + * utf8conv.c (load_libiconv): Remove URL from translatble string. + + Switched JNLIB from LGPLv2.1 to LGPLv3. + +2007-07-01 Werner Koch + + * argparse.c (strusage): Use id 10 for the license string; + default to GPL3+. Change long note to version 3 or later. + (show_version): Print the license info. + +2007-06-19 Werner Koch + + * Makefile.am: Add support for regression tests. + * t-support.h, t-support.c: New. + * t-stringhelp.c: New. + + * stringhelp.c (percent_escape): Add arg EXTRA to make it a more + general function. Changed all callers. + +2007-06-18 Werner Koch + + * w32-afunix.c (_w32_sock_bind): Changed to properly detect an + already used socket. + +2007-06-18 Marcus Brinkmann + + * stringhelp.h (percent_escape): New prototype. + * stringhelp.c (percent_escape): New function. + +2007-06-11 Werner Koch + + * utf8conv.c (jnlib_iconv_open, jnlib_iconv, jnlib_iconv_close): New. + +2007-06-06 Werner Koch + + * w32help.h: New. + * w32-gettext.c: New. Taken from gnupg 1.4, added ngettext, + changed to use jnlib malloc functions and put under the LGPL. + * w32-reg.c: New. Taken from../common/w32reg.c and changed to + LGPL. Changed API to use the jnlib malloc functions. + * Makefile.am (libjnlib_a_SOURCES) [!W32]: Do not build the w32 + specific modules. + + * dotlock.c: Include stringhelp.h for stpcpy prototype. + +2007-06-04 Werner Koch + + * dynload.h: New. Taken from ../common and changed to LGPL. + + * utf8conv.c (load_libiconv): New. Taken from GnuPG 1.4 + +2007-05-30 Werner Koch + + * w32-pth.h, w32-pth.c: Remove. + +2007-04-25 Werner Koch + + * argparse.c (long_opt_strlen): Fixed for utf-8. + +2007-03-07 Werner Koch + + * argparse.c (strusage): Set copyright year to 2007. + +2007-01-25 Werner Koch + + * stringhelp.c (utf8_charcount): New. + +2006-11-29 Werner Koch + + * utf8conv.c (set_native_charset) [HAVE_W32_SYSTEM]: Fixed typo in + macro name. + +2006-11-15 Werner Koch + + * logging.c (my_funopen_hook_ret_t): New. + (fun_writer): Use it. + +2006-10-19 Werner Koch + + * stringhelp.c (memrchr) [!HAVE_MEMRCHR]: Provide a replacement. + +2006-09-27 Werner Koch + + * mischelp.c: New. + (timegm): Copied from gnupg 1.4, changed from GPL to LGPL. Fixed + a memory leak. + + * stringhelp.h (isascii): New. + + * stringhelp.c (strsep): New. Copied from gnupg 1.4.5 + util/strgutil.c. + + * strlist.h (STRLIST): Removed deprecated typedef. + + * types.h: Made cpp commands work with old compilers. Also shows + up nicer with Emacs' font locking. + + * w32-afunix.c (_w32_sock_connect): Set ERRNO for an invalid port. + + Changed license from GPL to LGPL. Note that all code has either + been written by me, David, employees of g10 Code or taken from + glibc. + + * libjnlib-config.h, stringhelp.c, stringhelp.h: + * strlist.c, strlist.h, utf8conv.c, utf8conv.h: + * argparse.c, argparse.h, logging.c, logging.h: + * dotlock.c, dotlock.h, types.h, mischelp.h: + * xmalloc.c, xmalloc.h, w32-pth.c, w32-pth.h: + * w32-afunix.c, w32-afunix.h: Tagged them to be long to jnlib + which is a part of GnuPG but also used by other projetcs. + +2006-09-22 Werner Koch + + * utf8conv.c: Reworked to match the gnupg 1.4.5 code. This now + requires iconv support but this is reasonable for all modern + systems. + +2006-08-29 Werner Koch + + * logging.c (do_logv): Emit a missing LF for fatal errors. + +2006-06-28 Werner Koch + + * dotlock.c (make_dotlock, release_dotlock, read_lockfile) + (maybe_deadlock, destroy_dotlock, create_dotlock): Re-indented. + (create_dotlock): Repalces some log_fatal by log_error as it was + not intended that they should terminate. Write the nodename to + the locking file. Code cleanups. + (read_lockfile): Reworked to read the node name. + (make_dotlock): Test for identical node name and delete lock stale + file. + (release_dotlock): Likewise. + +2006-05-23 Werner Koch + + * libjnlib-config.h (JNLIB_NEED_UTF8CONV): Fixed typo in name. + + * dotlock.c (release_dotlock): Don't act if we don't have any + locks at all. + (destroy_dotlock): New. From 1.4.3. + (dotlock_remove_lockfiles): Make use of destroy function. + +2006-05-19 Werner Koch + + * strlist.c (append_to_strlist2): Enabled. + + * stringhelp.c (print_sanitized_buffer2): New. Changed the rules + to match the behaviour of print_string2 from gnupg 1.4.3. + (print_sanitized_buffer): Use the new function. + (print_sanitized_string2): New. + (hextobyte): New. Taken from gpg 1.4.3. + +2006-04-28 Werner Koch + + * stringhelp.c (print_sanitized_buffer): Fix bug where the count + got wrong for the \xNN representation. + (sanitize_buffer): Fix bug where some control characters lose part + of their \xNN representation. + +2006-04-20 Werner Koch + + * stringhelp.c (make_basename): New arg INPUTPATH for future + riscos compatibility. + +2006-04-18 Werner Koch + + * libjnlib-config.h (JNLIB_NEED_UTF8CONF): Defined. + * strlist.c (add_to_strlist2) [JNLIB_NEED_UTF8CONV]: Enabled. + +2005-06-15 Werner Koch + + * stringhelp.c (sanitize_buffer): Make P a void*. + (ascii_memistr, memistr): Ditto. + (ascii_memcasecmp): Ditto. + * logging.c (writen): Use void * for arg BUFFER. + * stringhelp.c (memistr): Fixed unsigned/signed pointer conflict. + (ascii_memistr): Ditto. + (ascii_memcasemem): Ditto. + * utf8conv.c (utf8_to_native): Ditto. + (utf8_to_native): Ditto. + * argparse.c (show_version): Removed non-required cast. + +2005-01-19 Werner Koch + + * logging.c (fun_writer): Don't fallback to stderr. Print to + stderr only if connected to a tty. + +2004-12-20 Werner Koch + + * w32-pth.c (do_pth_event_free): The events are hold in a ring + buffer. Adjust for that. + (do_pth_event_body): Ditto. + (pth_event_isolate): Ditto. + (do_pth_wait): Ditto. + (_pth_event_count): Renamed to .. + (event_count): .. and adjusted as above. + (pth_init): Define 3 debug levels and change all debug calls to + make use of them. This makes the moule now silent. + +2004-12-19 Werner Koch + + * w32-pth.c (pth_init): Enable debugging depending on env var. + (pth_self): New. + (pth_mutex_release, pth_mutex_acquire): Implemented directly using + the W32 API. + +2004-12-18 Werner Koch + + * w32-pth.c (pth_init): Reverse return values. Use TRUE and FALSE + constants. + (pth_kill, pth_mutex_acquire, pth_attr_set, pth_join, pth_cancel): + Ditto. + +2004-12-15 Werner Koch + + * logging.c [W32]: Don't include unavailable headers. + +2004-12-14 Werner Koch + + * w32-pth.c (_pth_strerror): Renamed to ... + (w32_strerror): .. this. And let callers provide a buffer. + (spawn_helper_thread): Removed HD arg and hardwire the stack size + to 32k. + (do_pth_wait): Removed use of ATTR; not needed for the helper + threads. + (helper_thread): Renamed to .. + (launch_thread): .. this. Release handle if not joinable. + (struct pth_priv_hd_s): Renamed to ... + (struct thread_info_s): .. this. Add member JOINABLE and TH. + +2004-12-14 Timo Schulz + + * w32-pth.c (pth_kill): Just release the crit section if + pth_init was really called. And set all handles to NULL. + (_pth_strerror): New. + (do_pth_wait): Before we enter the loop we check if there + are too much events in the ring. + +2004-12-14 Werner Koch + + * w32-pth.h (pth_event_occured): Removed macro. + * w32-pth.c: Fixed license statement; its under the LGPL. + (enter_pth, leave_pth): Use them to bracket almost all public + functions. + +2004-12-13 Timo Schulz + + * w32-pth.c (enter_pth, leave_pth): New. + (pth_init): Initialize global mutex section. + (pth_kill): Release global mutex section. + (helper_thread): New. + (pth_spawn): Make sure only one thread is running. + +2004-12-13 Werner Koch + + * stringhelp.c (w32_strerror) [W32]: New. + + * w32-pth.c, w32-pth.h: Added real code written by Timo Schulz. + Not finished, though. + +2004-12-07 Werner Koch + + * w32-pth.c, w32-pth.h: New. + +2004-11-26 Werner Koch + + * logging.c [_WIN32]: Don't include socket headers. + +2004-11-30 Timo Schulz + + * w32-afunix.c: New. AF_UNIX emulation for W32. + * w32-afunix.h: Likewise. + +2004-11-22 Werner Koch + + * logging.c (log_test_fd): Add test on LOGSTREAM. Reported by + Barry Schwartz. + +2004-11-18 Werner Koch + + * logging.c: Explicitly include sys/stat.h for the S_I* constants. + +2004-10-21 Werner Koch + + * logging.c (do_logv): Use set_log_stream to setup a default. + (log_set_file): Factored code out to .. + (set_file_fd): .. New function to allow using a file descriptor. + (log_set_fd): Make use of new fucntion. + (fun_writer): Reworked. + +2004-08-18 Werner Koch + + * stringhelp.c (print_sanitized_utf8_string): Actually implement + it. + +2004-06-21 Werner Koch + + * logging.c (log_set_file): Do not close an old logstream if it + used to be stderr or stdout. + +2004-05-05 Werner Koch + + * logging.c (log_set_file): Oops, don't close if LOGSTREAM is NULL. + +2004-04-30 Werner Koch + + * 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 + + * 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 + + * stringhelp.c (print_sanitized_buffer): Don't care about + non-ASCII characaters. + (sanitize_buffer): Ditto. + +2004-02-12 Werner Koch + + * Makefile.am: Replaced INCLUDES by AM_CPPFLAGS. + +2004-01-05 Werner Koch + + * argparse.c (strusage): Changed default copyright year to 2004. + +2003-12-17 Werner Koch + + * argparse.c (initialize): Replaced use of non-literal format + args. Suggested by Florian Weimer. + +2003-12-16 Werner Koch + + * 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 + + * strlist.c (strlist_copy): New. + + * dotlock.c: Define DIRSEP_C et al. if not defined. + +2003-11-06 Werner Koch + + * strlist.h (strlist_t): New. STRLIST is now deprecated. + +2003-06-18 Werner Koch + + * strlist.c (strlist_pop): New. + + * dotlock.c (dotlock_remove_lockfiles): Prefixed with dotlock_ and + made global. + +2003-06-17 Werner Koch + + * 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 + + * 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 + + * mischelp.h (wipememory2,wipememory): New. Taken from GnuPG 1.3.2. + +2002-06-04 Werner Koch + + * stringhelp.c (print_sanitized_utf8_string): New. No real + implementation for now. + (print_sanitized_utf8_buffer): Ditto. + +2002-04-04 Werner Koch + + * logging.c (log_get_prefix): New. + +2002-03-15 Werner Koch + + * argparse.c (optfile_parse): Fixed missing argument handling. + +2002-02-25 Werner Koch + + * stringhelp.c (ascii_memcasemem): New. + +2002-02-14 Werner Koch + + * Makefile.am (INCLUDES): Add cflags for libgcrypt. + +2002-02-07 Werner Koch + + * logging.c (log_set_fd): New. + + * stringhelp.c (print_sanitized_buffer): New. + (print_sanitized_string): New. + +2002-01-24 Werner Koch + + * 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 + + * 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 . + +2002-01-19 Werner Koch + + * logging.c (log_get_stream): New. + +2001-12-05 Werner Koch + + * 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 + + * strlist.c, strlist.h: New. Taken from pgnupg/util/strgutil.c + +2001-08-30 Werner Koch + + * logging.c (log_printf): Don't pass NULL instead of arg_ptr. + +2001-07-19 Werner Koch + + * 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 + + * 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, 2005, 2006, 2007, 2008, + 2010 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/common/Makefile.am b/common/Makefile.am index c7a9f09ba..1a73d31b1 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -1,5 +1,5 @@ # Makefile for common gnupg modules -# Copyright (C) 2001, 2003, 2007 Free Software Foundation, Inc. +# Copyright (C) 2001, 2003, 2007, 2010 Free Software Foundation, Inc. # # This file is part of GnuPG. # @@ -19,11 +19,11 @@ ## Process this file with automake to produce Makefile.in EXTRA_DIST = mkstrtable.awk exaudit.awk exstatus.awk \ - audit-events.h status-codes.h + audit-events.h status-codes.h README.jnlib ChangeLog.jnlib noinst_LIBRARIES = libcommon.a libcommonpth.a libsimple-pwquery.a libgpgrl.a -noinst_PROGRAMS = $(module_tests) $(module_maint_tests) -TESTS = $(module_tests) +noinst_PROGRAMS = $(jnlib_tests) $(module_tests) $(module_maint_tests) +TESTS = $(jnlib_tests) $(module_tests) BUILT_SOURCES = audit-events.h status-codes.h @@ -35,9 +35,26 @@ AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(KSBA_CFLAGS) include $(top_srcdir)/am/cmacros.am +jnlib_sources = \ + libjnlib-config.h \ + types.h dynload.h w32help.h \ + stringhelp.c stringhelp.h \ + strlist.c strlist.h \ + utf8conv.c utf8conv.h \ + argparse.c argparse.h \ + logging.c logging.h \ + dotlock.c dotlock.h \ + mischelp.c mischelp.h + +if HAVE_W32_SYSTEM +jnlib_sources += w32-reg.c w32-afunix.c w32-afunix.h +endif + + common_sources = \ common-defs.h \ util.h i18n.c i18n.h \ + estream.c estream.h estream-printf.c estream-printf.h \ status.c status.h\ openpgpdefs.h \ gc-opt-flags.h \ @@ -62,7 +79,6 @@ common_sources = \ asshelp.c asshelp.h \ exechelp.c exechelp.h \ signal.c \ - estream.c estream.h estream-printf.c estream-printf.h \ audit.c audit.h \ srv.h \ dns-cert.c dns-cert.h \ @@ -78,13 +94,13 @@ without_pth_sources = \ get-passphrase.c get-passphrase.h -libcommon_a_SOURCES = $(common_sources) $(without_pth_sources) +libcommon_a_SOURCES = $(jnlib_sources) $(common_sources) $(without_pth_sources) if USE_DNS_SRV libcommon_a_SOURCES += srv.c endif libcommon_a_CFLAGS = $(AM_CFLAGS) $(LIBASSUAN_CFLAGS) -DWITHOUT_GNU_PTH=1 -libcommonpth_a_SOURCES = $(common_sources) +libcommonpth_a_SOURCES = $(jnlib_sources) $(common_sources) if USE_DNS_SRV libcommonpth_a_SOURCES += srv.c endif @@ -121,13 +137,32 @@ endif # # Module tests # +t_jnlib_src = t-support.c t-support.h +jnlib_tests = t-stringhelp t-timestuff +if HAVE_W32_SYSTEM +jnlib_tests += t-w32-reg +endif module_tests = t-convert t-percent t-gettime t-sysutils t-sexputil t-exechelp \ t-session-env module_maint_tests = t-helpfile t-b64 -t_common_ldadd = libcommon.a ../jnlib/libjnlib.a ../gl/libgnu.a \ + +t_common_ldadd = libcommon.a ../gl/libgnu.a \ $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) $(LIBINTL) $(LIBICONV) +# jnlib tests +t_stringhelp_SOURCES = t-stringhelp.c $(t_jnlib_src) +t_stringhelp_LDADD = $(t_common_ldadd) + +t_timestuff_SOURCES = t-timestuff.c $(t_jnlib_src) +t_timestuff_LDADD = $(t_common_ldadd) + +if HAVE_W32_SYSTEM +t_w32_reg_SOURCES = t-w32-reg.c $(t_jnlib_src) +t_w32_reg_LDADD = $(t_common_ldadd) +endif + +# common tests t_convert_LDADD = $(t_common_ldadd) t_percent_LDADD = $(t_common_ldadd) t_gettime_LDADD = $(t_common_ldadd) @@ -138,3 +173,6 @@ t_b64_LDADD = $(t_common_ldadd) t_exechelp_LDADD = $(t_common_ldadd) t_session_env_LDADD = $(t_common_ldadd) + + + diff --git a/common/README.jnlib b/common/README.jnlib new file mode 100644 index 000000000..e8df795cb --- /dev/null +++ b/common/README.jnlib @@ -0,0 +1,101 @@ +JNLIB - This is a collection of utility function which are too small +to put into a library. The code here is licensed under the LGPL. + +libjnlib-config.h should be be modified for each project to make these +functions fit into the software. Mainly these are memory functions in +case you need another allocator. + +Files which make up jnlib: + README.jnlib + ChangeLog.jnlib + libjnlib-config.h + argparse.c + argparse.h + dotlock.c + dotlock.h + dynload.h + logging.c + logging.h + mischelp.c + mischelp.h + stringhelp.c + stringhelp.h + strlist.c + strlist.h + types.h + utf8conv.c + utf8conv.h + w32-afunix.c + w32-afunix.h + w32-reg.c + w32help.h + xmalloc.c + xmalloc.h + t-stringhelp.c + t-support.c + t-support.h + t-timestuff.c + t-w32-reg.c + + +Here is a template Makefile.am for these jnlib modules: +===8<================================================== +EXTRA_DIST = README +noinst_PROGRAMS = $(module_tests) +TESTS = $(module_tests) + +AM_CPPFLAGS = -I$(top_srcdir)/intl + +# We need libgcrypt because libjnlib-config includes gcrypt.h +AM_CFLAGS = $(LIBGCRYPT_CFLAGS) + +noinst_LIBRARIES = libjnlib.a + +libjnlib_a_SOURCES = \ + libjnlib-config.h \ + stringhelp.c stringhelp.h \ + strlist.c strlist.h \ + utf8conv.c utf8conv.h \ + argparse.c argparse.h \ + logging.c logging.h \ + dotlock.c dotlock.h \ + types.h mischelp.c mischelp.h dynload.h w32help.h \ + xmalloc.c xmalloc.h + +if HAVE_W32_SYSTEM +libjnlib_a_SOURCES += w32-reg.c w32-afunix.c w32-afunix.h +endif + +# +# Module tests. +# +# These tests should only be used at the canonical location of jnlib +# which is the GnuPG package. The reason for this is that t-support.c +# defines replacements for the actual used memory allocation functions +# so that there is no dependency on libgcrypt. +# +module_tests = t-stringhelp t-timestuff +if HAVE_W32_SYSTEM +module_tests += t-w32-reg +endif + +t_jnlib_src = t-support.c t-support.h +t_jnlib_ldadd = libjnlib.a $(LIBINTL) $(LIBICONV) +# For W32 we need libgpg-error because it provides gettext. +if HAVE_W32_SYSTEM +t_jnlib_ldadd += $(GPG_ERROR_LIBS) +endif + +t_stringhelp_SOURCES = t-stringhelp.c $(t_jnlib_src) +t_stringhelp_LDADD = $(t_jnlib_ldadd) + +t_timestuff_SOURCES = t-timestuff.c $(t_jnlib_src) +t_timestuff_LDADD = $(t_jnlib_ldadd) + +if HAVE_W32_SYSTEM +t_w32_reg_SOURCES = t-w32-reg.c $(t_jnlib_src) +t_w32_reg_LDADD = $(t_jnlib_ldadd) +endif +==>8=================================================== + + diff --git a/common/argparse.c b/common/argparse.c new file mode 100644 index 000000000..ab88922a4 --- /dev/null +++ b/common/argparse.c @@ -0,0 +1,1205 @@ +/* [argparse.c wk 17.06.97] Argument Parser for option handling + * Copyright (C) 1998, 1999, 2000, 2001, 2006 + * 2007, 2008 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include "libjnlib-config.h" +#include "mischelp.h" +#include "stringhelp.h" +#include "logging.h" +#ifdef JNLIB_NEED_UTF8CONV +#include "utf8conv.h" +#endif +#include "argparse.h" + + + +/********************************* + * @Summary arg_parse + * #include + * + * typedef struct { + * char *argc; pointer to argc (value subject to change) + * char ***argv; pointer to argv (value subject to change) + * unsigned flags; Global flags (DO NOT CHANGE) + * int err; print error about last option + * 1 = warning, 2 = abort + * int r_opt; return option + * int r_type; type of return value (0 = no argument found) + * union { + * int ret_int; + * long ret_long + * ulong ret_ulong; + * char *ret_str; + * } r; Return values + * struct { + * int idx; + * const char *last; + * void *aliases; + * } internal; DO NOT CHANGE + * } ARGPARSE_ARGS; + * + * typedef struct { + * int short_opt; + * const char *long_opt; + * unsigned flags; + * } ARGPARSE_OPTS; + * + * int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts ); + * + * @Description + * This is my replacement for getopt(). See the example for a typical usage. + * Global flags are: + * Bit 0 : Do not remove options form argv + * Bit 1 : Do not stop at last option but return other args + * with r_opt set to -1. + * Bit 2 : Assume options and real args are mixed. + * Bit 3 : Do not use -- to stop option processing. + * Bit 4 : Do not skip the first arg. + * Bit 5 : allow usage of long option with only one dash + * Bit 6 : ignore --version + * all other bits must be set to zero, this value is modified by the + * function, so assume this is write only. + * Local flags (for each option): + * Bit 2-0 : 0 = does not take an argument + * 1 = takes int argument + * 2 = takes string argument + * 3 = takes long argument + * 4 = takes ulong argument + * Bit 3 : argument is optional (r_type will the be set to 0) + * Bit 4 : allow 0x etc. prefixed values. + * Bit 7 : this is a command and not an option + * You stop the option processing by setting opts to NULL, the function will + * then return 0. + * @Return Value + * Returns the args.r_opt or 0 if ready + * r_opt may be -2/-7 to indicate an unknown option/command. + * @See Also + * ArgExpand + * @Notes + * You do not need to process the options 'h', '--help' or '--version' + * because this function includes standard help processing; but if you + * specify '-h', '--help' or '--version' you have to do it yourself. + * The option '--' stops argument processing; if bit 1 is set the function + * continues to return normal arguments. + * To process float args or unsigned args you must use a string args and do + * the conversion yourself. + * @Example + * + * ARGPARSE_OPTS opts[] = { + * { 'v', "verbose", 0 }, + * { 'd', "debug", 0 }, + * { 'o', "output", 2 }, + * { 'c', "cross-ref", 2|8 }, + * { 'm', "my-option", 1|8 }, + * { 500, "have-no-short-option-for-this-long-option", 0 }, + * {0} }; + * ARGPARSE_ARGS pargs = { &argc, &argv, 0 } + * + * while( ArgParse( &pargs, &opts) ) { + * switch( pargs.r_opt ) { + * case 'v': opt.verbose++; break; + * case 'd': opt.debug++; break; + * case 'o': opt.outfile = pargs.r.ret_str; break; + * case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break; + * case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break; + * case 500: opt.a_long_one++; break + * default : pargs.err = 1; break; -- force warning output -- + * } + * } + * if( argc > 1 ) + * log_fatal( "Too many args"); + * + */ + +typedef struct alias_def_s *ALIAS_DEF; +struct alias_def_s { + ALIAS_DEF next; + char *name; /* malloced buffer with name, \0, value */ + const char *value; /* ptr into name */ +}; + +static const char *(*strusage_handler)( int ) = NULL; + +static int set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s); +static void show_help(ARGPARSE_OPTS *opts, unsigned flags); +static void show_version(void); + + +static void +initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno ) +{ + if( !(arg->flags & (1<<15)) ) + { + /* Initialize this instance. */ + arg->internal.idx = 0; + arg->internal.last = NULL; + arg->internal.inarg = 0; + arg->internal.stopped = 0; + arg->internal.aliases = NULL; + arg->internal.cur_alias = NULL; + arg->err = 0; + arg->flags |= 1<<15; /* Mark as initialized. */ + if ( *arg->argc < 0 ) + jnlib_log_bug ("invalid argument for arg_parsee\n"); + } + + + if (arg->err) + { + /* Last option was erroneous. */ + const char *s; + + if (filename) + { + if ( arg->r_opt == ARGPARSE_UNEXPECTED_ARG ) + s = _("argument not expected"); + else if ( arg->r_opt == ARGPARSE_READ_ERROR ) + s = _("read error"); + else if ( arg->r_opt == ARGPARSE_KEYWORD_TOO_LONG ) + s = _("keyword too long"); + else if ( arg->r_opt == ARGPARSE_MISSING_ARG ) + s = _("missing argument"); + else if ( arg->r_opt == ARGPARSE_INVALID_COMMAND ) + s = _("invalid command"); + else if ( arg->r_opt == ARGPARSE_INVALID_ALIAS ) + s = _("invalid alias definition"); + else if ( arg->r_opt == ARGPARSE_OUT_OF_CORE ) + s = _("out of core"); + else + s = _("invalid option"); + jnlib_log_error ("%s:%u: %s\n", filename, *lineno, s); + } + else + { + s = arg->internal.last? arg->internal.last:"[??]"; + + if ( arg->r_opt == ARGPARSE_MISSING_ARG ) + jnlib_log_error (_("missing argument for option \"%.50s\"\n"), s); + else if ( arg->r_opt == ARGPARSE_UNEXPECTED_ARG ) + jnlib_log_error (_("option \"%.50s\" does not expect an " + "argument\n"), s ); + else if ( arg->r_opt == ARGPARSE_INVALID_COMMAND ) + jnlib_log_error (_("invalid command \"%.50s\"\n"), s); + else if ( arg->r_opt == ARGPARSE_AMBIGUOUS_OPTION ) + jnlib_log_error (_("option \"%.50s\" is ambiguous\n"), s); + else if ( arg->r_opt == ARGPARSE_AMBIGUOUS_OPTION ) + jnlib_log_error (_("command \"%.50s\" is ambiguous\n"),s ); + else if ( arg->r_opt == ARGPARSE_OUT_OF_CORE ) + jnlib_log_error ("%s\n", _("out of core\n")); + else + jnlib_log_error (_("invalid option \"%.50s\"\n"), s); + } + if ( arg->err != 1 ) + exit (2); + arg->err = 0; + } + + /* Zero out the return value union. */ + arg->r.ret_str = NULL; + arg->r.ret_long = 0; +} + + +static void +store_alias( ARGPARSE_ARGS *arg, char *name, char *value ) +{ + /* TODO: replace this dummy function with a rea one + * and fix the probelms IRIX has with (ALIAS_DEV)arg.. + * used as lvalue + */ + (void)arg; + (void)name; + (void)value; +#if 0 + ALIAS_DEF a = jnlib_xmalloc( sizeof *a ); + a->name = name; + a->value = value; + a->next = (ALIAS_DEF)arg->internal.aliases; + (ALIAS_DEF)arg->internal.aliases = a; +#endif +} + +/**************** + * Get options from a file. + * Lines starting with '#' are comment lines. + * Syntax is simply a keyword and the argument. + * Valid keywords are all keywords from the long_opt list without + * the leading dashes. The special keywords "help", "warranty" and "version" + * are not valid here. + * The special keyword "alias" may be used to store alias definitions, + * which are later expanded like long options. + * Caller must free returned strings. + * If called with FP set to NULL command line args are parse instead. + * + * Q: Should we allow the syntax + * keyword = value + * and accept for boolean options a value of 1/0, yes/no or true/false? + * Note: Abbreviation of options is here not allowed. + */ +int +optfile_parse (FILE *fp, const char *filename, unsigned *lineno, + ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts) +{ + int state, i, c; + int idx=0; + char keyword[100]; + char *buffer = NULL; + size_t buflen = 0; + int in_alias=0; + + if (!fp) /* Divert to to arg_parse() in this case. */ + return arg_parse (arg, opts); + + initialize (arg, filename, lineno); + + /* Find the next keyword. */ + state = i = 0; + for (;;) + { + c = getc (fp); + if (c == '\n' || c== EOF ) + { + if ( c != EOF ) + ++*lineno; + if (state == -1) + break; + else if (state == 2) + { + keyword[i] = 0; + for (i=0; opts[i].short_opt; i++ ) + { + if (opts[i].long_opt && !strcmp (opts[i].long_opt, keyword)) + break; + } + idx = i; + arg->r_opt = opts[idx].short_opt; + if (!opts[idx].short_opt ) + arg->r_opt = ((opts[idx].flags & ARGPARSE_OPT_COMMAND) + ? ARGPARSE_INVALID_COMMAND + : ARGPARSE_INVALID_OPTION); + else if (!(opts[idx].flags & 7)) + arg->r_type = 0; /* Does not take an arg. */ + else if ((opts[idx].flags & 8) ) + arg->r_type = 0; /* Arg is optional. */ + else + arg->r_opt = ARGPARSE_MISSING_ARG; + + break; + } + else if (state == 3) + { + /* No argument found. */ + if (in_alias) + arg->r_opt = ARGPARSE_MISSING_ARG; + else if (!(opts[idx].flags & 7)) + arg->r_type = 0; /* Does not take an arg. */ + else if ((opts[idx].flags & 8)) + arg->r_type = 0; /* No optional argument. */ + else + arg->r_opt = ARGPARSE_MISSING_ARG; + + break; + } + else if (state == 4) + { + /* Has an argument. */ + if (in_alias) + { + if (!buffer) + arg->r_opt = ARGPARSE_UNEXPECTED_ARG; + else + { + char *p; + + buffer[i] = 0; + p = strpbrk (buffer, " \t"); + if (p) + { + *p++ = 0; + trim_spaces (p); + } + if (!p || !*p) + { + jnlib_free (buffer); + arg->r_opt = ARGPARSE_INVALID_ALIAS; + } + else + { + store_alias (arg, buffer, p); + } + } + } + else if (!(opts[idx].flags & 7)) + arg->r_opt = ARGPARSE_UNEXPECTED_ARG; + else + { + char *p; + + if (!buffer) + { + keyword[i] = 0; + buffer = jnlib_strdup (keyword); + if (!buffer) + arg->r_opt = ARGPARSE_OUT_OF_CORE; + } + else + buffer[i] = 0; + + if (buffer) + { + trim_spaces (buffer); + p = buffer; + if (*p == '"') + { + /* Remove quotes. */ + p++; + if (*p && p[strlen(p)-1] == '\"' ) + p[strlen(p)-1] = 0; + } + if (!set_opt_arg (arg, opts[idx].flags, p)) + jnlib_free(buffer); + } + } + break; + } + else if (c == EOF) + { + if (ferror (fp)) + arg->r_opt = ARGPARSE_READ_ERROR; + else + arg->r_opt = 0; /* EOF. */ + break; + } + state = 0; + i = 0; + } + else if (state == -1) + ; /* Skip. */ + else if (state == 0 && isascii (c) && isspace(c)) + ; /* Skip leading white space. */ + else if (state == 0 && c == '#' ) + state = 1; /* Start of a comment. */ + else if (state == 1) + ; /* Skip comments. */ + else if (state == 2 && isascii (c) && isspace(c)) + { + /* Check keyword. */ + keyword[i] = 0; + for (i=0; opts[i].short_opt; i++ ) + if (opts[i].long_opt && !strcmp (opts[i].long_opt, keyword)) + break; + idx = i; + arg->r_opt = opts[idx].short_opt; + if (!opts[idx].short_opt) + { + if (!strcmp (keyword, "alias")) + { + in_alias = 1; + state = 3; + } + else + { + arg->r_opt = ((opts[idx].flags & ARGPARSE_OPT_COMMAND) + ? ARGPARSE_INVALID_COMMAND + : ARGPARSE_INVALID_OPTION); + state = -1; /* Skip rest of line and leave. */ + } + } + else + state = 3; + } + else if (state == 3) + { + /* Skip leading spaces of the argument. */ + if (!isascii (c) || !isspace(c)) + { + i = 0; + keyword[i++] = c; + state = 4; + } + } + else if (state == 4) + { + /* Collect the argument. */ + if (buffer) + { + if (i < buflen-1) + buffer[i++] = c; + else + { + char *tmp; + size_t tmplen = buflen + 50; + + tmp = jnlib_realloc (buffer, tmplen); + if (tmp) + { + buflen = tmplen; + buffer = tmp; + buffer[i++] = c; + } + else + { + jnlib_free (buffer); + arg->r_opt = ARGPARSE_OUT_OF_CORE; + break; + } + } + } + else if (i < DIM(keyword)-1) + keyword[i++] = c; + else + { + size_t tmplen = DIM(keyword) + 50; + buffer = jnlib_malloc (tmplen); + if (buffer) + { + buflen = tmplen; + memcpy(buffer, keyword, i); + buffer[i++] = c; + } + else + { + arg->r_opt = ARGPARSE_OUT_OF_CORE; + break; + } + } + } + else if (i >= DIM(keyword)-1) + { + arg->r_opt = ARGPARSE_KEYWORD_TOO_LONG; + state = -1; /* Skip rest of line and leave. */ + } + else + { + keyword[i++] = c; + state = 2; + } + } + + return arg->r_opt; +} + + + +static int +find_long_option( ARGPARSE_ARGS *arg, + ARGPARSE_OPTS *opts, const char *keyword ) +{ + int i; + size_t n; + + (void)arg; + + /* Would be better if we can do a binary search, but it is not + possible to reorder our option table because we would mess + up our help strings - What we can do is: Build a nice option + lookup table wehn this function is first invoked */ + if( !*keyword ) + return -1; + for(i=0; opts[i].short_opt; i++ ) + if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) ) + return i; +#if 0 + { + ALIAS_DEF a; + /* see whether it is an alias */ + for( a = args->internal.aliases; a; a = a->next ) { + if( !strcmp( a->name, keyword) ) { + /* todo: must parse the alias here */ + args->internal.cur_alias = a; + return -3; /* alias available */ + } + } + } +#endif + /* not found, see whether it is an abbreviation */ + /* aliases may not be abbreviated */ + n = strlen( keyword ); + for(i=0; opts[i].short_opt; i++ ) { + if( opts[i].long_opt && !strncmp( opts[i].long_opt, keyword, n ) ) { + int j; + for(j=i+1; opts[j].short_opt; j++ ) { + if( opts[j].long_opt + && !strncmp( opts[j].long_opt, keyword, n ) ) + return -2; /* abbreviation is ambiguous */ + } + return i; + } + } + return -1; +} + +int +arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts) +{ + int idx; + int argc; + char **argv; + char *s, *s2; + int i; + + initialize( arg, NULL, NULL ); + argc = *arg->argc; + argv = *arg->argv; + idx = arg->internal.idx; + + if (!idx && argc && !(arg->flags & ARGPARSE_FLAG_ARG0)) + { + /* Skip the first argument. */ + argc--; argv++; idx++; + } + + next_one: + if (!argc) + { + /* No more args. */ + arg->r_opt = 0; + goto leave; /* Ready. */ + } + + s = *argv; + arg->internal.last = s; + + if (arg->internal.stopped && (arg->flags & ARGPARSE_FLAG_ALL)) + { + arg->r_opt = ARGPARSE_IS_ARG; /* Not an option but an argument. */ + arg->r_type = 2; + arg->r.ret_str = s; + argc--; argv++; idx++; /* set to next one */ + } + else if( arg->internal.stopped ) + { + arg->r_opt = 0; + goto leave; /* Ready. */ + } + else if ( *s == '-' && s[1] == '-' ) + { + /* Long option. */ + char *argpos; + + arg->internal.inarg = 0; + if (!s[2] && !(arg->flags & ARGPARSE_FLAG_NOSTOP)) + { + /* Stop option processing. */ + arg->internal.stopped = 1; + argc--; argv++; idx++; + goto next_one; + } + + argpos = strchr( s+2, '=' ); + if ( argpos ) + *argpos = 0; + i = find_long_option ( arg, opts, s+2 ); + if ( argpos ) + *argpos = '='; + + if ( i < 0 && !strcmp ( "help", s+2) ) + show_help (opts, arg->flags); + else if ( i < 0 && !strcmp ( "version", s+2) ) + { + if (!(arg->flags & ARGPARSE_FLAG_NOVERSION)) + { + show_version (); + exit(0); + } + } + else if ( i < 0 && !strcmp( "warranty", s+2)) + { + puts ( strusage (16) ); + exit (0); + } + else if ( i < 0 && !strcmp( "dump-options", s+2) ) + { + for (i=0; opts[i].short_opt; i++ ) + { + if ( opts[i].long_opt ) + printf ("--%s\n", opts[i].long_opt); + } + fputs ("--dump-options\n--help\n--version\n--warranty\n", stdout); + exit (0); + } + + if ( i == -2 ) + arg->r_opt = ARGPARSE_AMBIGUOUS_OPTION; + else if ( i == -1 ) + { + arg->r_opt = ARGPARSE_INVALID_OPTION; + arg->r.ret_str = s+2; + } + else + arg->r_opt = opts[i].short_opt; + if ( i < 0 ) + ; + else if ( (opts[i].flags & 0x07) ) + { + if ( argpos ) + { + s2 = argpos+1; + if ( !*s2 ) + s2 = NULL; + } + else + s2 = argv[1]; + if ( !s2 && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) ) + { + arg->r_type = ARGPARSE_TYPE_NONE; /* Argument is optional. */ + } + else if ( !s2 ) + { + arg->r_opt = ARGPARSE_MISSING_ARG; + } + else if ( !argpos && *s2 == '-' + && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) ) + { + /* The argument is optional and the next seems to be an + option. We do not check this possible option but + assume no argument */ + arg->r_type = ARGPARSE_TYPE_NONE; + } + else + { + set_opt_arg (arg, opts[i].flags, s2); + if ( !argpos ) + { + argc--; argv++; idx++; /* Skip one. */ + } + } + } + else + { + /* Does not take an argument. */ + if ( argpos ) + arg->r_type = ARGPARSE_UNEXPECTED_ARG; + else + arg->r_type = 0; + } + argc--; argv++; idx++; /* Set to next one. */ + } + else if ( (*s == '-' && s[1]) || arg->internal.inarg ) + { + /* Short option. */ + int dash_kludge = 0; + + i = 0; + if ( !arg->internal.inarg ) + { + arg->internal.inarg++; + if ( (arg->flags & ARGPARSE_FLAG_ONEDASH) ) + { + for (i=0; opts[i].short_opt; i++ ) + if ( opts[i].long_opt && !strcmp (opts[i].long_opt, s+1)) + { + dash_kludge = 1; + break; + } + } + } + s += arg->internal.inarg; + + if (!dash_kludge ) + { + for (i=0; opts[i].short_opt; i++ ) + if ( opts[i].short_opt == *s ) + break; + } + + if ( !opts[i].short_opt && ( *s == 'h' || *s == '?' ) ) + show_help (opts, arg->flags); + + arg->r_opt = opts[i].short_opt; + if (!opts[i].short_opt ) + { + arg->r_opt = (opts[i].flags & ARGPARSE_OPT_COMMAND)? + ARGPARSE_INVALID_COMMAND:ARGPARSE_INVALID_OPTION; + arg->internal.inarg++; /* Point to the next arg. */ + arg->r.ret_str = s; + } + else if ( (opts[i].flags & 7) ) + { + if ( s[1] && !dash_kludge ) + { + s2 = s+1; + set_opt_arg (arg, opts[i].flags, s2); + } + else + { + s2 = argv[1]; + if ( !s2 && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) ) + { + arg->r_type = ARGPARSE_TYPE_NONE; + } + else if ( !s2 ) + { + arg->r_opt = ARGPARSE_MISSING_ARG; + } + else if ( *s2 == '-' && s2[1] + && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) ) + { + /* The argument is optional and the next seems to + be an option. We do not check this possible + option but assume no argument. */ + arg->r_type = ARGPARSE_TYPE_NONE; + } + else + { + set_opt_arg (arg, opts[i].flags, s2); + argc--; argv++; idx++; /* Skip one. */ + } + } + s = "x"; /* This is so that !s[1] yields false. */ + } + else + { + /* Does not take an argument. */ + arg->r_type = ARGPARSE_TYPE_NONE; + arg->internal.inarg++; /* Point to the next arg. */ + } + if ( !s[1] || dash_kludge ) + { + /* No more concatenated short options. */ + arg->internal.inarg = 0; + argc--; argv++; idx++; + } + } + else if ( arg->flags & ARGPARSE_FLAG_MIXED ) + { + arg->r_opt = ARGPARSE_IS_ARG; + arg->r_type = 2; + arg->r.ret_str = s; + argc--; argv++; idx++; /* Set to next one. */ + } + else + { + arg->internal.stopped = 1; /* Stop option processing. */ + goto next_one; + } + + leave: + *arg->argc = argc; + *arg->argv = argv; + arg->internal.idx = idx; + return arg->r_opt; +} + + + +static int +set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s) +{ + int base = (flags & 16)? 0 : 10; + + switch ( (arg->r_type = (flags & 7)) ) + { + case ARGPARSE_TYPE_INT: + arg->r.ret_int = (int)strtol(s,NULL,base); + return 0; + case ARGPARSE_TYPE_LONG: + arg->r.ret_long= strtol(s,NULL,base); + return 0; + case ARGPARSE_TYPE_ULONG: + arg->r.ret_ulong= strtoul(s,NULL,base); + return 0; + case ARGPARSE_TYPE_STRING: + default: + arg->r.ret_str = s; + return 1; + } +} + + +static size_t +long_opt_strlen( ARGPARSE_OPTS *o ) +{ + size_t n = strlen (o->long_opt); + + if ( o->description && *o->description == '|' ) + { + const char *s; +#ifdef JNLIB_NEED_UTF8CONV + int is_utf8 = is_native_utf8 (); +#endif + + s=o->description+1; + if ( *s != '=' ) + n++; + /* For a (mostly) correct length calculation we exclude + continuation bytes (10xxxxxx) if we are on a native utf8 + terminal. */ + for (; *s && *s != '|'; s++ ) +#ifdef JNLIB_NEED_UTF8CONV + if ( is_utf8 && (*s&0xc0) != 0x80 ) +#endif + n++; + } + return n; +} + + +/**************** + * Print formatted help. The description string has some special + * meanings: + * - A description string which is "@" suppresses help output for + * this option + * - a description,ine which starts with a '@' and is followed by + * any other characters is printed as is; this may be used for examples + * ans such. + * - A description which starts with a '|' outputs the string between this + * bar and the next one as arguments of the long option. + */ +static void +show_help (ARGPARSE_OPTS *opts, unsigned int flags) +{ + const char *s; + + show_version (); + putchar ('\n'); + s = strusage(41); + puts (s); + if ( opts[0].description ) + { + /* Auto format the option description. */ + int i,j, indent; + + /* Get max. length of long options. */ + for (i=indent=0; opts[i].short_opt; i++ ) + { + if ( opts[i].long_opt ) + if ( !opts[i].description || *opts[i].description != '@' ) + if ( (j=long_opt_strlen(opts+i)) > indent && j < 35 ) + indent = j; + } + + /* Example: " -v, --verbose Viele Sachen ausgeben" */ + indent += 10; + if ( *opts[0].description != '@' ) + puts ("Options:"); + for (i=0; opts[i].short_opt; i++ ) + { + s = _( opts[i].description ); + if ( s && *s== '@' && !s[1] ) /* Hide this line. */ + continue; + if ( s && *s == '@' ) /* Unindented comment only line. */ + { + for (s++; *s; s++ ) + { + if ( *s == '\n' ) + { + if( s[1] ) + putchar('\n'); + } + else + putchar(*s); + } + putchar('\n'); + continue; + } + + j = 3; + if ( opts[i].short_opt < 256 ) + { + printf (" -%c", opts[i].short_opt); + if ( !opts[i].long_opt ) + { + if (s && *s == '|' ) + { + putchar (' '); j++; + for (s++ ; *s && *s != '|'; s++, j++ ) + putchar (*s); + if ( *s ) + s++; + } + } + } + else + fputs(" ", stdout); + if ( opts[i].long_opt ) + { + j += printf ("%c --%s", opts[i].short_opt < 256?',':' ', + opts[i].long_opt ); + if (s && *s == '|' ) + { + if ( *++s != '=' ) + { + putchar(' '); + j++; + } + for ( ; *s && *s != '|'; s++, j++ ) + putchar(*s); + if ( *s ) + s++; + } + fputs (" ", stdout); + j += 3; + } + for (;j < indent; j++ ) + putchar(' '); + if ( s ) + { + if ( *s && j > indent ) + { + putchar('\n'); + for (j=0;j < indent; j++ ) + putchar (' '); + } + for (; *s; s++ ) + { + if ( *s == '\n' ) + { + if ( s[1] ) + { + putchar ('\n'); + for (j=0; j < indent; j++ ) + putchar (' '); + } + } + else + putchar (*s); + } + } + putchar ('\n'); + } + if ( (flags & ARGPARSE_FLAG_ONEDASH) ) + puts ("\n(A single dash may be used instead of the double ones)"); + } + if ( (s=strusage(19)) ) + { + /* bug reports to ... */ + char *s2; + + putchar('\n'); + s2 = strstr (s, "@EMAIL@"); + if (s2) + { + if (s2-s) + fwrite (s, s2-s, 1, stdout); +#ifdef PACKAGE_BUGREPORT + fputs (PACKAGE_BUGREPORT, stdout); +#else + fputs ("bug@example.org", stdout); +#endif + s2 += 7; + if (*s2) + fputs (s2, stdout); + } + else + fputs(s, stdout); + } + fflush(stdout); + exit(0); +} + +static void +show_version () +{ + const char *s; + int i; + + /* Version line. */ + fputs (strusage (11), stdout); + if ((s=strusage (12))) + printf (" (%s)", s ); + printf (" %s\n", strusage (13) ); + /* Additional version lines. */ + for (i=20; i < 30; i++) + if ((s=strusage (i))) + printf ("%s\n", s ); + /* Copyright string. */ + if( (s=strusage (14)) ) + printf("%s\n", s ); + /* Licence string. */ + if( (s=strusage (10)) ) + printf("%s\n", s ); + /* Copying conditions. */ + if ( (s=strusage(15)) ) + fputs (s, stdout); + /* Thanks. */ + if ((s=strusage(18))) + fputs (s, stdout); + /* Additional program info. */ + for (i=30; i < 40; i++ ) + if ( (s=strusage (i)) ) + fputs (s, stdout); + fflush (stdout); +} + + +void +usage (int level) +{ + const char *p; + + if (!level) + { + fprintf(stderr,"%s %s; %s\n", strusage(11), strusage(13), strusage (14)); + fflush (stderr); + } + else if (level == 1) + { + p = strusage (40); + fputs (p, stderr); + if (*p && p[strlen(p)] != '\n') + putc ('\n', stderr); + exit (2); + } + else if (level == 2) + { + puts (strusage(41)); + exit (0); + } +} + +/* Level + * 0: Print copyright string to stderr + * 1: Print a short usage hint to stderr and terminate + * 2: Print a long usage hint to stdout and terminate + * 10: Return license info string + * 11: Return the name of the program + * 12: Return optional name of package which includes this program. + * 13: version string + * 14: copyright string + * 15: Short copying conditions (with LFs) + * 16: Long copying conditions (with LFs) + * 17: Optional printable OS name + * 18: Optional thanks list (with LFs) + * 19: Bug report info + *20..29: Additional lib version strings. + *30..39: Additional program info (with LFs) + * 40: short usage note (with LF) + * 41: long usage note (with LF) + */ +const char * +strusage( int level ) +{ + const char *p = strusage_handler? strusage_handler(level) : NULL; + + if ( p ) + return p; + + switch ( level ) + { + case 10: p = ("License GPLv3+: GNU GPL version 3 or later " + ""); + break; + case 11: p = "foo"; break; + case 13: p = "0.0"; break; + case 14: p = "Copyright (C) 2010 Free Software Foundation, Inc."; break; + case 15: p = +"This is free software: you are free to change and redistribute it.\n" +"There is NO WARRANTY, to the extent permitted by law.\n"; + break; + case 16: p = +"This is free software; you can redistribute it and/or modify\n" +"it under the terms of the GNU General Public License as published by\n" +"the Free Software Foundation; either version 3 of the License, or\n" +"(at your option) any later version.\n\n" +"It is distributed in the hope that it will be useful,\n" +"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" +"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" +"GNU General Public License for more details.\n\n" +"You should have received a copy of the GNU General Public License\n" +"along with this software. If not, see .\n"; + break; + case 40: /* short and long usage */ + case 41: p = ""; break; + } + + return p; +} + +void +set_strusage ( const char *(*f)( int ) ) +{ + strusage_handler = f; +} + + +#ifdef TEST +static struct { + int verbose; + int debug; + char *outfile; + char *crf; + int myopt; + int echo; + int a_long_one; +}opt; + +int +main(int argc, char **argv) +{ + ARGPARSE_OPTS opts[] = { + ARGPARSE_x('v', "verbose", NONE, 0, "Laut sein"), + ARGPARSE_s_n('e', "echo" , ("Zeile ausgeben, damit wir sehen, " + "was wir ein gegeben haben")), + ARGPARSE_s_n('d', "debug", "Debug\nfalls mal etwas\nschief geht"), + ARGPARSE_s_s('o', "output", 0 ), + ARGPARSE_o_s('c', "cross-ref", "cross-reference erzeugen\n" ), + /* Note that on a non-utf8 terminal the ß might garble the output. */ + ARGPARSE_s_n('s', "street","|Straße|set the name of the street to Straße"), + ARGPARSE_o_i('m', "my-option", 0), + ARGPARSE_s_n(500, "a-long-option", 0 ), + ARGPARSE_end + }; + ARGPARSE_ARGS pargs = { &argc, &argv, 2|4|32 }; + int i; + + while( arg_parse ( &pargs, opts) ) { + switch( pargs.r_opt ) { + case -1 : printf( "arg=`%s'\n", pargs.r.ret_str); break; + case 'v': opt.verbose++; break; + case 'e': opt.echo++; break; + case 'd': opt.debug++; break; + case 'o': opt.outfile = pargs.r.ret_str; break; + case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break; + case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break; + case 500: opt.a_long_one++; break; + default : pargs.err = ARGPARSE_PRINT_WARNING; break; + } + } + for(i=0; i < argc; i++ ) + printf("%3d -> (%s)\n", i, argv[i] ); + puts("Options:"); + if( opt.verbose ) + printf(" verbose=%d\n", opt.verbose ); + if( opt.debug ) + printf(" debug=%d\n", opt.debug ); + if( opt.outfile ) + printf(" outfile=`%s'\n", opt.outfile ); + if( opt.crf ) + printf(" crffile=`%s'\n", opt.crf ); + if( opt.myopt ) + printf(" myopt=%d\n", opt.myopt ); + if( opt.a_long_one ) + printf(" a-long-one=%d\n", opt.a_long_one ); + if( opt.echo ) + printf(" echo=%d\n", opt.echo ); + return 0; +} +#endif + +/**** bottom of file ****/ diff --git a/common/argparse.h b/common/argparse.h new file mode 100644 index 000000000..b211e5fdf --- /dev/null +++ b/common/argparse.h @@ -0,0 +1,183 @@ +/* argparse.h - Argument parser for option handling. + * Copyright (C) 1998,1999,2000,2001,2006 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#ifndef LIBJNLIB_ARGPARSE_H +#define LIBJNLIB_ARGPARSE_H + +#include +#include "types.h" + +typedef struct +{ + int *argc; /* Pointer to ARGC (value subject to change). */ + char ***argv; /* Pointer to ARGV (value subject to change). */ + unsigned int flags; /* Global flags. May be set prior to calling the + parser. The parser may change the value. */ + int err; /* Print error description for last option. + Either 0, ARGPARSE_PRINT_WARNING or + ARGPARSE_PRINT_ERROR. */ + + int r_opt; /* Returns option code. */ + int r_type; /* Returns type of option value. */ + union { + int ret_int; + long ret_long; + unsigned long ret_ulong; + char *ret_str; + } r; /* Return values */ + + struct { + int idx; + int inarg; + int stopped; + const char *last; + void *aliases; + const void *cur_alias; + } internal; /* Private - do not change. */ +} ARGPARSE_ARGS; + +typedef struct +{ + int short_opt; + const char *long_opt; + unsigned int flags; + const char *description; /* Optional option description. */ +} ARGPARSE_OPTS; + + +/* Global flags (ARGPARSE_ARGS). */ +#define ARGPARSE_FLAG_KEEP 1 /* Do not remove options form argv. */ +#define ARGPARSE_FLAG_ALL 2 /* Do not stop at last option but return + remaining args with R_OPT set to -1. */ +#define ARGPARSE_FLAG_MIXED 4 /* Assume options and args are mixed. */ +#define ARGPARSE_FLAG_NOSTOP 8 /* Do not stop processing at "--". */ +#define ARGPARSE_FLAG_ARG0 16 /* Do not skip the first arg. */ +#define ARGPARSE_FLAG_ONEDASH 32 /* Allow long options with one dash. */ +#define ARGPARSE_FLAG_NOVERSION 64 /* No output for "--version". */ + +/* Flags for each option (ARGPARSE_OPTS). The type code may be + ORed with the OPT flags. */ +#define ARGPARSE_TYPE_NONE 0 /* Does not take an argument. */ +#define ARGPARSE_TYPE_INT 1 /* Takes an int argument. */ +#define ARGPARSE_TYPE_STRING 2 /* Takes a string argument. */ +#define ARGPARSE_TYPE_LONG 3 /* Takes a long argument. */ +#define ARGPARSE_TYPE_ULONG 4 /* Takes an unsigned long argument. */ +#define ARGPARSE_OPT_OPTIONAL (1<<3) /* Argument is optional. */ +#define ARGPARSE_OPT_PREFIX (1<<4) /* Allow 0x etc. prefixed values. */ +#define ARGPARSE_OPT_COMMAND (1<<8) /* The argument is a command. */ + +/* A set of macros to make option definitions easier to read. */ +#define ARGPARSE_x(s,l,t,f,d) \ + { (s), (l), ARGPARSE_TYPE_ ## t | (f), (d) } + +#define ARGPARSE_s(s,l,t,d) \ + { (s), (l), ARGPARSE_TYPE_ ## t, (d) } +#define ARGPARSE_s_n(s,l,d) \ + { (s), (l), ARGPARSE_TYPE_NONE, (d) } +#define ARGPARSE_s_i(s,l,d) \ + { (s), (l), ARGPARSE_TYPE_INT, (d) } +#define ARGPARSE_s_s(s,l,d) \ + { (s), (l), ARGPARSE_TYPE_STRING, (d) } +#define ARGPARSE_s_l(s,l,d) \ + { (s), (l), ARGPARSE_TYPE_LONG, (d) } +#define ARGPARSE_s_u(s,l,d) \ + { (s), (l), ARGPARSE_TYPE_ULONG, (d) } + +#define ARGPARSE_o(s,l,t,d) \ + { (s), (l), (ARGPARSE_TYPE_ ## t | ARGPARSE_OPT_OPTIONAL), (d) } +#define ARGPARSE_o_n(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_OPTIONAL), (d) } +#define ARGPARSE_o_i(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_INT | ARGPARSE_OPT_OPTIONAL), (d) } +#define ARGPARSE_o_s(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_STRING | ARGPARSE_OPT_OPTIONAL), (d) } +#define ARGPARSE_o_l(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_LONG | ARGPARSE_OPT_OPTIONAL), (d) } +#define ARGPARSE_o_u(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_ULONG | ARGPARSE_OPT_OPTIONAL), (d) } + +#define ARGPARSE_p(s,l,t,d) \ + { (s), (l), (ARGPARSE_TYPE_ ## t | ARGPARSE_OPT_PREFIX), (d) } +#define ARGPARSE_p_n(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_PREFIX), (d) } +#define ARGPARSE_p_i(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_INT | ARGPARSE_OPT_PREFIX), (d) } +#define ARGPARSE_p_s(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_STRING | ARGPARSE_OPT_PREFIX), (d) } +#define ARGPARSE_p_l(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_LONG | ARGPARSE_OPT_PREFIX), (d) } +#define ARGPARSE_p_u(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_ULONG | ARGPARSE_OPT_PREFIX), (d) } + +#define ARGPARSE_op(s,l,t,d) \ + { (s), (l), (ARGPARSE_TYPE_ ## t \ + | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } +#define ARGPARSE_op_n(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_NONE \ + | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } +#define ARGPARSE_op_i(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_INT \ + | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } +#define ARGPARSE_op_s(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_STRING \ + | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } +#define ARGPARSE_op_l(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_LONG \ + | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } +#define ARGPARSE_op_u(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_ULONG \ + | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } + +#define ARGPARSE_c(s,l,d) \ + { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_COMMAND), (d) } + + +#define ARGPARSE_group(s,d) \ + { (s), NULL, 0, (d) } + +#define ARGPARSE_end() { 0, NULL, 0, NULL } + + +/* Other constants. */ +#define ARGPARSE_PRINT_WARNING 1 +#define ARGPARSE_PRINT_ERROR 2 + + +/* Error values. */ +#define ARGPARSE_IS_ARG (-1) +#define ARGPARSE_INVALID_OPTION (-2) +#define ARGPARSE_MISSING_ARG (-3) +#define ARGPARSE_KEYWORD_TOO_LONG (-4) +#define ARGPARSE_READ_ERROR (-5) +#define ARGPARSE_UNEXPECTED_ARG (-6) +#define ARGPARSE_INVALID_COMMAND (-7) +#define ARGPARSE_AMBIGUOUS_OPTION (-8) +#define ARGPARSE_AMBIGUOUS_COMMAND (-9) +#define ARGPARSE_INVALID_ALIAS (-10) +#define ARGPARSE_OUT_OF_CORE (-11) + + +int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts); +int optfile_parse( FILE *fp, const char *filename, unsigned *lineno, + ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts); +void usage( int level ); +const char *strusage( int level ); +void set_strusage( const char *(*f)( int ) ); + +#endif /*LIBJNLIB_ARGPARSE_H*/ diff --git a/common/audit.h b/common/audit.h index 28d1edbd1..8f413aa30 100644 --- a/common/audit.h +++ b/common/audit.h @@ -22,7 +22,7 @@ #include -#include "estream.h" +#include "../common/estream.h" struct audit_ctx_s; typedef struct audit_ctx_s *audit_ctx_t; diff --git a/common/dotlock.c b/common/dotlock.c new file mode 100644 index 000000000..0d5a7bce9 --- /dev/null +++ b/common/dotlock.c @@ -0,0 +1,713 @@ +/* dotlock.c - dotfile locking + * Copyright (C) 1998, 2000, 2001, 2003, 2004, + * 2005, 2006, 2008 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_DOSISH_SYSTEM +# define WIN32_LEAN_AND_MEAN +# include +#else +# include +#endif +#include +#include +#include +#include +#ifdef HAVE_SIGNAL_H +# include +#endif + +#include "libjnlib-config.h" +#include "stringhelp.h" +#include "dotlock.h" +#include "utf8conv.h" + +#if !defined(DIRSEP_C) && !defined(EXTSEP_C) \ + && !defined(DIRSEP_S) && !defined(EXTSEP_S) +#ifdef HAVE_DOSISH_SYSTEM +#define DIRSEP_C '\\' +#define EXTSEP_C '.' +#define DIRSEP_S "\\" +#define EXTSEP_S "." +#else +#define DIRSEP_C '/' +#define EXTSEP_C '.' +#define DIRSEP_S "/" +#define EXTSEP_S "." +#endif +#endif + + +/* The object describing a lock. */ +struct dotlock_handle +{ + struct dotlock_handle *next; + char *lockname; /* Name of the actual lockfile. */ + int locked; /* Lock status. */ + int disable; /* If true, locking is disabled. */ + +#ifdef HAVE_DOSISH_SYSTEM + HANDLE lockhd; /* The W32 handle of the lock file. */ +#else + char *tname; /* Name of the lockfile template. */ + size_t nodename_off; /* Offset in TNAME of the nodename part. */ + size_t nodename_len; /* Length of the nodename part. */ +#endif /* HAVE_DOSISH_SYSTEM */ +}; + + +/* A list of of all lock handles. */ +static volatile dotlock_t all_lockfiles; + +/* If this has the value true all locking is disabled. */ +static int never_lock; + + +/* Local protototypes. */ +#ifndef HAVE_DOSISH_SYSTEM +static int read_lockfile (dotlock_t h, int *same_node); +#endif /*!HAVE_DOSISH_SYSTEM*/ + + + + +/* Entirely disable all locking. This function should be called + before any locking is done. It may be called right at startup of + the process as it only sets a global value. */ +void +disable_dotlock(void) +{ + never_lock = 1; +} + + + +/* Create a lockfile for a file name FILE_TO_LOCK and returns an + object of type dotlock_t which may be used later to actually acquire + the lock. A cleanup routine gets installed to cleanup left over + locks or other files used internally by the lock mechanism. + + Calling this function with NULL does only install the atexit + handler and may thus be used to assure that the cleanup is called + after all other atexit handlers. + + This function creates a lock file in the same directory as + FILE_TO_LOCK using that name and a suffix of ".lock". Note that on + POSIX systems a temporary file ".#lk..pid[.threadid] is + used. + + The function returns an new handle which needs to be released using + destroy_dotlock but gets also released at the termination of the + process. On error NULL is returned. + */ +dotlock_t +create_dotlock (const char *file_to_lock) +{ + static int initialized; + dotlock_t h; +#ifndef HAVE_DOSISH_SYSTEM + int fd = -1; + char pidstr[16]; + const char *nodename; + const char *dirpart; + int dirpartlen; + struct utsname utsbuf; + size_t tnamelen; +#endif + + if ( !initialized ) + { + atexit (dotlock_remove_lockfiles); + initialized = 1; + } + + if ( !file_to_lock ) + return NULL; /* Only initialization was requested. */ + + h = jnlib_calloc (1, sizeof *h); + if (!h) + return NULL; + + if (never_lock) + { + h->disable = 1; +#ifdef _REENTRANT + /* fixme: aquire mutex on all_lockfiles */ +#endif + h->next = all_lockfiles; + all_lockfiles = h; + return h; + } + +#ifndef HAVE_DOSISH_SYSTEM + /* + This is the POSIX version which uses a temporary file and the + link system call to make locking an atomic operation. + */ + + snprintf (pidstr, sizeof pidstr, "%10d\n", (int)getpid() ); + + /* Create a temporary file. */ + if ( uname ( &utsbuf ) ) + nodename = "unknown"; + else + nodename = utsbuf.nodename; + +#ifdef __riscos__ + { + char *iter = (char *) nodename; + for (; iter[0]; iter++) + if (iter[0] == '.') + iter[0] = '/'; + } +#endif /* __riscos__ */ + + if ( !(dirpart = strrchr (file_to_lock, DIRSEP_C)) ) + { + dirpart = EXTSEP_S; + dirpartlen = 1; + } + else + { + dirpartlen = dirpart - file_to_lock; + dirpart = file_to_lock; + } + +#ifdef _REENTRANT + /* fixme: aquire mutex on all_lockfiles */ +#endif + h->next = all_lockfiles; + all_lockfiles = h; + + tnamelen = dirpartlen + 6 + 30 + strlen(nodename) + 10; + h->tname = jnlib_malloc (tnamelen + 1); + if (!h->tname) + { + all_lockfiles = h->next; + jnlib_free (h); + return NULL; + } + h->nodename_len = strlen (nodename); + +#ifndef __riscos__ + snprintf (h->tname, tnamelen, "%.*s/.#lk%p.", dirpartlen, dirpart, h ); + h->nodename_off = strlen (h->tname); + snprintf (h->tname+h->nodename_off, tnamelen - h->nodename_off, + "%s.%d", nodename, (int)getpid ()); +#else /* __riscos__ */ + snprintf (h->tname, tnamelen, "%.*s.lk%p/", dirpartlen, dirpart, h ); + h->nodename_off = strlen (h->tname); + snprintf (h->tname+h->nodename_off, tnamelen - h->modename_off, + "%s/%d", nodename, (int)getpid () ); +#endif /* __riscos__ */ + + do + { + jnlib_set_errno (0); + fd = open (h->tname, O_WRONLY|O_CREAT|O_EXCL, + S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR ); + } + while (fd == -1 && errno == EINTR); + + if ( fd == -1 ) + { + all_lockfiles = h->next; + log_error (_("failed to create temporary file `%s': %s\n"), + h->tname, strerror(errno)); + jnlib_free (h->tname); + jnlib_free (h); + return NULL; + } + if ( write (fd, pidstr, 11 ) != 11 ) + goto write_failed; + if ( write (fd, nodename, strlen (nodename) ) != strlen (nodename) ) + goto write_failed; + if ( write (fd, "\n", 1 ) != 1 ) + goto write_failed; + if ( close (fd) ) + goto write_failed; + +# ifdef _REENTRANT + /* release mutex */ +# endif + h->lockname = jnlib_malloc ( strlen (file_to_lock) + 6 ); + if (!h->lockname) + { + all_lockfiles = h->next; + unlink (h->tname); + jnlib_free (h->tname); + jnlib_free (h); + return NULL; + } + strcpy (stpcpy (h->lockname, file_to_lock), EXTSEP_S "lock"); + return h; + + write_failed: + all_lockfiles = h->next; +# ifdef _REENTRANT + /* fixme: release mutex */ +# endif + log_error ( _("error writing to `%s': %s\n"), h->tname, strerror(errno) ); + close (fd); + unlink (h->tname); + jnlib_free (h->tname); + jnlib_free (h); + return NULL; + +#else /* HAVE_DOSISH_SYSTEM */ + + /* The Windows version does not need a temporary file but uses the + plain lock file along with record locking. We create this file + here so that we later do only need to do the file locking. For + error reporting it is useful to keep the name of the file in the + handle. */ + h->next = all_lockfiles; + all_lockfiles = h; + + h->lockname = jnlib_malloc ( strlen (file_to_lock) + 6 ); + if (!h->lockname) + { + all_lockfiles = h->next; + jnlib_free (h); + return NULL; + } + strcpy (stpcpy(h->lockname, file_to_lock), EXTSEP_S "lock"); + + /* If would be nice if we would use the FILE_FLAG_DELETE_ON_CLOSE + along with FILE_SHARE_DELETE but that does not work due to a race + condition: Despite the OPEN_ALWAYS flag CreateFile may return an + error and we can't reliable create/open the lock file unless we + would wait here until it works - however there are other valid + reasons why a lock file can't be created and thus the process + would not stop as expected but spin til until Windows crashes. + Our solution is to keep the lock file open; that does not + harm. */ + { +#ifdef HAVE_W32CE_SYSTEM + wchar_t *wname = utf8_to_wchar (h->lockname); + + h->lockhd = INVALID_HANDLE_VALUE; + if (wname) + h->lockhd = CreateFile (wname, +#else + h->lockhd = CreateFile (h->lockname, +#endif + GENERIC_READ|GENERIC_WRITE, + FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL, OPEN_ALWAYS, 0, NULL); +#ifdef HAVE_W32CE_SYSTEM + jnlib_free (wname); +#endif + } + if (h->lockhd == INVALID_HANDLE_VALUE) + { + log_error (_("can't create `%s': %s\n"), h->lockname, w32_strerror (-1)); + all_lockfiles = h->next; + jnlib_free (h->lockname); + jnlib_free (h); + return NULL; + } + return h; + +#endif /* HAVE_DOSISH_SYSTEM */ +} + + +/* Destroy the local handle H and release the lock. */ +void +destroy_dotlock (dotlock_t h) +{ + dotlock_t hprev, htmp; + + if ( !h ) + return; + + /* First remove the handle from our global list of all locks. */ + for (hprev=NULL, htmp=all_lockfiles; htmp; hprev=htmp, htmp=htmp->next) + if (htmp == h) + { + if (hprev) + hprev->next = htmp->next; + else + all_lockfiles = htmp->next; + h->next = NULL; + break; + } + + /* Then destroy the lock. */ + if (!h->disable) + { +#ifdef HAVE_DOSISH_SYSTEM + if (h->locked) + { + UnlockFile (h->lockhd, 0, 0, 1, 0); + } + CloseHandle (h->lockhd); +#else /* !HAVE_DOSISH_SYSTEM */ + if (h->locked && h->lockname) + unlink (h->lockname); + if (h->tname) + unlink (h->tname); + jnlib_free (h->tname); +#endif /* HAVE_DOSISH_SYSTEM */ + jnlib_free (h->lockname); + } + jnlib_free(h); +} + + +#ifndef HAVE_DOSISH_SYSTEM +static int +maybe_deadlock (dotlock_t h) +{ + dotlock_t r; + + for ( r=all_lockfiles; r; r = r->next ) + { + if ( r != h && r->locked ) + return 1; + } + return 0; +} +#endif /*!HAVE_DOSISH_SYSTEM*/ + + + +/* Do a lock on H. A TIMEOUT of 0 returns immediately, -1 waits + forever (hopefully not), other values are reserved (should then be + timeouts in milliseconds). Returns: 0 on success */ +int +make_dotlock (dotlock_t h, long timeout) +{ + int backoff = 0; +#ifndef HAVE_DOSISH_SYSTEM + int pid; + const char *maybe_dead=""; + int same_node; +#endif /*!HAVE_DOSISH_SYSTEM*/ + + if ( h->disable ) + return 0; /* Locks are completely disabled. Return success. */ + + if ( h->locked ) + { +#ifndef __riscos__ + log_debug ("Oops, `%s' is already locked\n", h->lockname); +#endif /* !__riscos__ */ + return 0; + } + + for (;;) + { +#ifndef HAVE_DOSISH_SYSTEM +# ifndef __riscos__ + if ( !link(h->tname, h->lockname) ) + { + /* fixme: better use stat to check the link count */ + h->locked = 1; + return 0; /* okay */ + } + if ( errno != EEXIST ) + { + log_error ( "lock not made: link() failed: %s\n", strerror(errno) ); + return -1; + } +# else /* __riscos__ */ + if ( !renamefile(h->tname, h->lockname) ) + { + h->locked = 1; + return 0; /* okay */ + } + if ( errno != EEXIST ) + { + log_error( "lock not made: rename() failed: %s\n", strerror(errno) ); + return -1; + } +# endif /* __riscos__ */ + + if ( (pid = read_lockfile (h, &same_node)) == -1 ) + { + if ( errno != ENOENT ) + { + log_info ("cannot read lockfile\n"); + return -1; + } + log_info( "lockfile disappeared\n"); + continue; + } + else if ( pid == getpid() && same_node ) + { + log_info( "Oops: lock already held by us\n"); + h->locked = 1; + return 0; /* okay */ + } + else if ( same_node && kill (pid, 0) && errno == ESRCH ) + { +# ifndef __riscos__ + log_info (_("removing stale lockfile (created by %d)\n"), pid ); + unlink (h->lockname); + continue; +# else /* __riscos__ */ + /* Under RISCOS we are *pretty* sure that the other task + is dead and therefore we remove the stale lock file. */ + maybe_dead = _(" - probably dead - removing lock"); + unlink(h->lockname); +# endif /* __riscos__ */ + } + + if ( timeout == -1 ) + { + /* Wait until lock has been released. */ + struct timeval tv; + + log_info (_("waiting for lock (held by %d%s) %s...\n"), + pid, maybe_dead, maybe_deadlock(h)? _("(deadlock?) "):""); + + + /* We can't use sleep, cause signals may be blocked. */ + tv.tv_sec = 1 + backoff; + tv.tv_usec = 0; + select(0, NULL, NULL, NULL, &tv); + if ( backoff < 10 ) + backoff++ ; + } + else + return -1; +#else /*HAVE_DOSISH_SYSTEM*/ + int w32err; + + if (LockFile (h->lockhd, 0, 0, 1, 0)) + { + h->locked = 1; + return 0; /* okay */ + } + w32err = GetLastError (); + if (w32err != ERROR_LOCK_VIOLATION) + { + log_error (_("lock `%s' not made: %s\n"), + h->lockname, w32_strerror (w32err)); + return -1; + } + + if ( timeout == -1 ) + { + /* Wait until lock has been released. */ + log_info (_("waiting for lock %s...\n"), h->lockname); + Sleep ((1 + backoff)*1000); + if ( backoff < 10 ) + backoff++ ; + } + else + return -1; +#endif /*HAVE_DOSISH_SYSTEM*/ + } + /*NOTREACHED*/ +} + + +/* Release a lock. Returns 0 on success. */ +int +release_dotlock (dotlock_t h) +{ +#ifndef HAVE_DOSISH_SYSTEM + int pid, same_node; +#endif + + /* To avoid atexit race conditions we first check whether there are + any locks left. It might happen that another atexit handler + tries to release the lock while the atexit handler of this module + already ran and thus H is undefined. */ + if (!all_lockfiles) + return 0; + + if ( h->disable ) + return 0; + + if ( !h->locked ) + { + log_debug("Oops, `%s' is not locked\n", h->lockname); + return 0; + } + +#ifdef HAVE_DOSISH_SYSTEM + if (!UnlockFile (h->lockhd, 0, 0, 1, 0)) + { + log_error ("release_dotlock: error removing lockfile `%s': %s\n", + h->lockname, w32_strerror (-1)); + return -1; + } +#else + + pid = read_lockfile (h, &same_node); + if ( pid == -1 ) + { + log_error( "release_dotlock: lockfile error\n"); + return -1; + } + if ( pid != getpid() || !same_node ) + { + log_error( "release_dotlock: not our lock (pid=%d)\n", pid); + return -1; + } + +#ifndef __riscos__ + if ( unlink( h->lockname ) ) + { + log_error ("release_dotlock: error removing lockfile `%s'\n", + h->lockname); + return -1; + } + /* Fixme: As an extra check we could check whether the link count is + now really at 1. */ +#else /* __riscos__ */ + if ( renamefile (h->lockname, h->tname) ) + { + log_error ("release_dotlock: error renaming lockfile `%s' to `%s'\n", + h->lockname, h->tname); + return -1; + } +#endif /* __riscos__ */ + +#endif /* !HAVE_DOSISH_SYSTEM */ + h->locked = 0; + return 0; +} + + +/* Read the lock file and return the pid, returns -1 on error. True + will be stored in the integer at address SAME_NODE if the lock file + has been created on the same node. */ +#ifndef HAVE_DOSISH_SYSTEM +static int +read_lockfile (dotlock_t h, int *same_node ) +{ + char buffer_space[10+1+70+1]; /* 70 is just an estimated value; node + name are usually shorter. */ + int fd; + int pid = -1; + char *buffer, *p; + size_t expected_len; + int res, nread; + + *same_node = 0; + expected_len = 10 + 1 + h->nodename_len + 1; + if ( expected_len >= sizeof buffer_space) + { + buffer = jnlib_malloc (expected_len); + if (!buffer) + return -1; + } + else + buffer = buffer_space; + + if ( (fd = open (h->lockname, O_RDONLY)) == -1 ) + { + int e = errno; + log_info ("error opening lockfile `%s': %s\n", + h->lockname, strerror(errno) ); + if (buffer != buffer_space) + jnlib_free (buffer); + jnlib_set_errno (e); /* Need to return ERRNO here. */ + return -1; + } + + p = buffer; + nread = 0; + do + { + res = read (fd, p, expected_len - nread); + if (res == -1 && errno == EINTR) + continue; + if (res < 0) + { + log_info ("error reading lockfile `%s'", h->lockname ); + close (fd); + if (buffer != buffer_space) + jnlib_free (buffer); + jnlib_set_errno (0); /* Do not return an inappropriate ERRNO. */ + return -1; + } + p += res; + nread += res; + } + while (res && nread != expected_len); + close(fd); + + if (nread < 11) + { + log_info ("invalid size of lockfile `%s'", h->lockname ); + if (buffer != buffer_space) + jnlib_free (buffer); + jnlib_set_errno (0); /* Better don't return an inappropriate ERRNO. */ + return -1; + } + + if (buffer[10] != '\n' + || (buffer[10] = 0, pid = atoi (buffer)) == -1 +#ifndef __riscos__ + || !pid +#else /* __riscos__ */ + || (!pid && riscos_getpid()) +#endif /* __riscos__ */ + ) + { + log_error ("invalid pid %d in lockfile `%s'", pid, h->lockname ); + if (buffer != buffer_space) + jnlib_free (buffer); + jnlib_set_errno (0); + return -1; + } + + if (nread == expected_len + && !memcmp (h->tname+h->nodename_off, buffer+11, h->nodename_len) + && buffer[11+h->nodename_len] == '\n') + *same_node = 1; + + if (buffer != buffer_space) + jnlib_free (buffer); + return pid; +} +#endif /* !HAVE_DOSISH_SYSTEM */ + + +/* Remove all lockfiles. This is usually called by the atexit handler + installed by this module but may also be called by other + termination handlers. */ +void +dotlock_remove_lockfiles (void) +{ + dotlock_t h, h2; + + h = all_lockfiles; + all_lockfiles = NULL; + + while ( h ) + { + h2 = h->next; + destroy_dotlock (h); + h = h2; + } +} + diff --git a/common/dotlock.h b/common/dotlock.h new file mode 100644 index 000000000..407a80b37 --- /dev/null +++ b/common/dotlock.h @@ -0,0 +1,33 @@ +/* dotlock.h + * Copyright (C) 2000, 2001, 2006 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#ifndef LIBJNLIB_DOTLOCK_H +#define LIBJNLIB_DOTLOCK_H + +struct dotlock_handle; +typedef struct dotlock_handle *dotlock_t; + +void disable_dotlock (void); +dotlock_t create_dotlock (const char *file_to_lock); +void destroy_dotlock ( dotlock_t h ); +int make_dotlock (dotlock_t h, long timeout); +int release_dotlock (dotlock_t h); +void dotlock_remove_lockfiles (void); + +#endif /*LIBJNLIB_DOTLOCK_H*/ diff --git a/common/dynload.h b/common/dynload.h new file mode 100644 index 000000000..0c8a3bbaa --- /dev/null +++ b/common/dynload.h @@ -0,0 +1,86 @@ +/* dynload.h - Wrapper functions for run-time dynamic loading + * Copyright (C) 2003, 2010 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#ifndef LIBJNLIB_DYNLOAD_H +#define LIBJNLIB_DYNLOAD_H + +#ifndef __MINGW32__ +# include +#else +# include +# include "utf8conv.h" +# include "mischelp.h" +# define RTLD_LAZY 0 + +static inline void * +dlopen (const char *name, int flag) +{ + void *hd; +#ifdef HAVE_W32CE_SYSTEM + wchar_t *wname = utf8_to_wchar (name); + hd = wname? LoadLibrary (wname) : NULL; + _jnlib_free (wname); +#else + hd = LoadLibrary (name); +#endif + (void)flag; + return hd; +} + +static inline void * +dlsym (void *hd, const char *sym) +{ + if (hd && sym) + { +#ifdef HAVE_W32CE_SYSTEM + wchar_t *wsym = utf8_to_wchar (sym); + void *fnc = wsym? GetProcAddress (hd, wsym) : NULL; + _jnlib_free (wsym); +#else + void *fnc = GetProcAddress (hd, sym); +#endif + if (!fnc) + return NULL; + return fnc; + } + return NULL; +} + + +static inline const char * +dlerror (void) +{ + static char buf[32]; + snprintf (buf, sizeof buf, "ec=%lu", GetLastError ()); + return buf; +} + + +static inline int +dlclose (void * hd) +{ + if (hd) + { + CloseHandle (hd); + return 0; + } + return -1; +} +# endif /*__MINGW32__*/ +#endif /*LIBJNLIB_DYNLOAD_H*/ diff --git a/common/exechelp.c b/common/exechelp.c index 95e5b633c..f71cd7349 100644 --- a/common/exechelp.c +++ b/common/exechelp.c @@ -25,7 +25,9 @@ #include #include #include -#include +#ifdef HAVE_SIGNAL_H +# include +#endif #include #include @@ -78,6 +80,12 @@ #define X_OK F_OK #endif /* HAVE_W32_SYSTEM */ +/* Constants not supported by WindowsCE. */ +#ifdef HAVE_W32CE_SYSTEM +# define DETACHED_PROCESS (0) +# define CREATE_NEW_PROCESS_GROUP (0) +#endif + #ifdef HAVE_W32_SYSTEM /* We assume that a HANDLE can be represented by an int which should diff --git a/common/exechelp.h b/common/exechelp.h index 06cb79c29..c5ecc0dea 100644 --- a/common/exechelp.h +++ b/common/exechelp.h @@ -20,7 +20,7 @@ #ifndef GNUPG_COMMON_EXECHELP_H #define GNUPG_COMMON_EXECHELP_H -#include "estream.h" +#include "../common/estream.h" /* Return the maximum number of currently allowed file descriptors. diff --git a/common/http.h b/common/http.h index 28a5304eb..e7120f561 100644 --- a/common/http.h +++ b/common/http.h @@ -22,7 +22,7 @@ #include #ifdef HTTP_USE_ESTREAM -#include "estream.h" +#include "../common/estream.h" #endif struct uri_tuple_s { diff --git a/common/i18n.h b/common/i18n.h index 7405f9a55..abb8bd83e 100644 --- a/common/i18n.h +++ b/common/i18n.h @@ -16,7 +16,7 @@ #ifdef USE_SIMPLE_GETTEXT -# include "../jnlib/w32help.h" +# include "../common/w32help.h" # define _(a) gettext (a) # define N_(a) (a) #else diff --git a/common/init.c b/common/init.c index 5425acee8..d8e0be7bf 100644 --- a/common/init.c +++ b/common/init.c @@ -31,7 +31,6 @@ #include #endif -#include "estream.h" #include "util.h" diff --git a/common/iobuf.c b/common/iobuf.c index 87af2868f..441c69467 100644 --- a/common/iobuf.c +++ b/common/iobuf.c @@ -1156,10 +1156,10 @@ iobuf_open_fd_or_name (gnupg_fd_t fd, const char *fname, const char *mode) { iobuf_t a; - if (fd == -1) + if (fd == GNUPG_INVALID_FD) a = iobuf_open (fname); else - a = iobuf_fdopen_nc (fd, mode); + a = iobuf_fdopen_nc (FD2INT(fd), mode); return a; } diff --git a/common/libjnlib-config.h b/common/libjnlib-config.h new file mode 100644 index 000000000..621e89feb --- /dev/null +++ b/common/libjnlib-config.h @@ -0,0 +1,99 @@ +/* libjnlib-config.h - local configuration of the jnlib functions + * Copyright (C) 2000, 2001, 2006 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +/**************** + * This header is to be included only by the files in this directory + * it should not be used by other modules. + */ + +#ifndef LIBJNLIB_CONFIG_H +#define LIBJNLIB_CONFIG_H + +#include /* gcry_malloc & Cie. */ +#include "logging.h" + +/* We require support for utf-8 conversion. */ +#define JNLIB_NEED_UTF8CONV 1 + + + +#if !defined(JNLIB_NEED_UTF8CONV) && defined(HAVE_W32_SYSTEM) +#define JNLIB_NEED_UTF8CONV 1 +#endif + +/* Gettext stuff */ +#ifdef USE_SIMPLE_GETTEXT +# include +# define _(a) gettext (a) +# define N_(a) (a) + +#else +#ifdef HAVE_LOCALE_H +# include +#endif + +#ifdef ENABLE_NLS +# include +# define _(a) gettext (a) +# ifdef gettext_noop +# define N_(a) gettext_noop (a) +# else +# define N_(a) (a) +# endif +#else +# define _(a) (a) +# define N_(a) (a) +#endif +#endif /* !USE_SIMPLE_GETTEXT */ + +/* Malloc functions to be used by jnlib. */ +#define jnlib_malloc(a) gcry_malloc( (a) ) +#define jnlib_calloc(a,b) gcry_calloc( (a), (b) ) +#define jnlib_realloc(a,b) gcry_realloc( (a), (b) ) +#define jnlib_strdup(a) gcry_strdup( (a) ) +#define jnlib_xmalloc(a) gcry_xmalloc( (a) ) +#define jnlib_xcalloc(a,b) gcry_xcalloc( (a), (b) ) +#define jnlib_xrealloc(a,n) gcry_xrealloc( (a), (n) ) +#define jnlib_xstrdup(a) gcry_xstrdup( (a) ) +#define jnlib_free(a) gcry_free( (a) ) + +/* Logging functions to be used by jnlib. */ +#define jnlib_log_debug log_debug +#define jnlib_log_info log_info +#define jnlib_log_error log_error +#define jnlib_log_fatal log_fatal +#define jnlib_log_bug log_bug + +/* Wrapper to set ERRNO. */ +#ifdef HAVE_W32CE_SYSTEM +# define jnlib_set_errno(e) gpg_err_set_errno ((e)) +#else +# define jnlib_set_errno(e) do { errno = (e); } while (0) +#endif + +/* Dummy replacement for getenv. */ +#ifndef HAVE_GETENV +#define getenv(a) (NULL) +#endif + +#ifdef HAVE_W32CE_SYSTEM +#define getpid() GetCurrentProcessId () +#endif + +#endif /*LIBJNUTIL_CONFIG_H*/ diff --git a/common/localename.c b/common/localename.c index cb7fcc2f7..5c46ddd34 100644 --- a/common/localename.c +++ b/common/localename.c @@ -30,7 +30,7 @@ #include #endif -#include "../jnlib/w32help.h" +#include "../common/w32help.h" /* XPG3 defines the result of 'setlocale (category, NULL)' as: "Directs 'setlocale()' to query 'category' and return the current @@ -101,7 +101,7 @@ gnupg_messages_locale_name (void) const char *s; #ifdef HAVE_W32_SYSTEM - /* We use the localname function from ../jnlib/w32-gettext.c. */ + /* We use the localname function from ../common/w32-gettext.c. */ s = gettext_localename (); #else s = do_nl_locale_name (LC_MESSAGES, "LC_MESSAGES"); diff --git a/common/logging.c b/common/logging.c new file mode 100644 index 000000000..028697b78 --- /dev/null +++ b/common/logging.c @@ -0,0 +1,651 @@ +/* logging.c - Useful logging functions + * Copyright (C) 1998, 1999, 2000, 2001, 2003, + * 2004, 2005, 2006, 2009 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef HAVE_W32_SYSTEM +#include +#include +#endif /*!HAVE_W32_SYSTEM*/ +#include +#include +#include + + +#define JNLIB_NEED_LOG_LOGV 1 +#define JNLIB_NEED_AFLOCAL 1 +#include "libjnlib-config.h" +#include "logging.h" + +#if defined (HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN) +#define USE_FUNWRITER 1 +#endif + +#ifdef HAVE_FOPENCOOKIE +typedef ssize_t my_funopen_hook_ret_t; +typedef size_t my_funopen_hook_size_t; +#else +typedef int my_funopen_hook_ret_t; +typedef int my_funopen_hook_size_t; +#endif + + +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 unsigned long (*get_tid_callback)(void); +static int running_detached; +static int force_prefixes; + +static int missing_lf; +static int errorcount; + + +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. */ +#ifdef USE_FUNWRITER +struct fun_cookie_s { + int fd; + int quiet; + int want_socket; + int is_socket; + char name[1]; +}; + +/* Write NBYTES of BUFFER to file descriptor FD. */ +static int +writen (int fd, const void *buffer, size_t nbytes) +{ + const char *buf = buffer; + 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 my_funopen_hook_ret_t +fun_writer (void *cookie_arg, const char *buffer, my_funopen_hook_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 because detached + processes often close stderr and by writing to file descriptor 2 + we might send the log message to a file not intended for logging + (e.g. a pipe or network connection). */ + if (cookie->want_socket && cookie->fd == -1) + { + /* Not yet open or meanwhile closed due to an error. */ + cookie->is_socket = 0; + cookie->fd = socket (PF_LOCAL, SOCK_STREAM, 0); + if (cookie->fd == -1) + { + if (!cookie->quiet && !running_detached + && isatty (fileno (stderr))) + fprintf (stderr, "failed to create socket for logging: %s\n", + strerror(errno)); + } + else + { + struct sockaddr_un addr; + size_t addrlen; + + 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 = SUN_LEN (&addr); + + if (connect (cookie->fd, (struct sockaddr *) &addr, addrlen) == -1) + { + if (!cookie->quiet && !running_detached + && isatty (fileno (stderr))) + fprintf (stderr, "can't connect to `%s': %s\n", + cookie->name, strerror(errno)); + close (cookie->fd); + cookie->fd = -1; + } + } + + if (cookie->fd == -1) + { + if (!running_detached) + { + /* Due to all the problems with apps not running + detached but being called with stderr closed or + used for a different purposes, it does not make + sense to switch to stderr. We therefore disable it. */ + if (!cookie->quiet) + { + /* fputs ("switching logging to stderr\n", stderr);*/ + cookie->quiet = 1; + } + cookie->fd = -1; /*fileno (stderr);*/ + } + } + else /* Connection has been established. */ + { + cookie->quiet = 0; + cookie->is_socket = 1; + } + } + + log_socket = cookie->fd; + if (cookie->fd != -1 && !writen (cookie->fd, buffer, size)) + return (my_funopen_hook_ret_t)size; /* Okay. */ + + if (!running_detached && cookie->fd != -1 + && isatty (fileno (stderr))) + { + if (*cookie->name) + fprintf (stderr, "error writing to `%s': %s\n", + cookie->name, strerror(errno)); + else + fprintf (stderr, "error writing to file descriptor %d: %s\n", + cookie->fd, strerror(errno)); + } + if (cookie->is_socket && cookie->fd != -1) + { + close (cookie->fd); + cookie->fd = -1; + log_socket = -1; + } + + return (my_funopen_hook_ret_t)size; +} + +static int +fun_closer (void *cookie_arg) +{ + struct fun_cookie_s *cookie = cookie_arg; + + if (cookie->fd != -1 && cookie->fd != 2) + close (cookie->fd); + jnlib_free (cookie); + log_socket = -1; + return 0; +} +#endif /*USE_FUNWRITER*/ + + + +/* Common function to either set the logging to a file or a file + descriptor. */ +static void +set_file_fd (const char *name, int fd) +{ + FILE *fp; + int want_socket; +#ifdef USE_FUNWRITER + struct fun_cookie_s *cookie; +#endif + + /* Close an open log stream. */ + if (logstream) + { + if (logstream != stderr && logstream != stdout) + fclose (logstream); + logstream = NULL; + } + + /* Figure out what kind of logging we want. */ + if (name && !strcmp (name, "-")) + { + name = NULL; + fd = fileno (stderr); + } + + if (name) + { + want_socket = (!strncmp (name, "socket://", 9) && name[9]); + if (want_socket) + name += 9; + } + else + { + want_socket = 0; + } + + /* Setup a new stream. */ +#ifdef USE_FUNWRITER + /* The xmalloc below is justified because we can expect that this + function is called only during initialization and there is no + easy way out of this error condition. */ + cookie = jnlib_xmalloc (sizeof *cookie + (name? strlen (name):0)); + strcpy (cookie->name, name? name:""); + cookie->quiet = 0; + cookie->is_socket = 0; + cookie->want_socket = want_socket; + if (!name) + cookie->fd = fd; + else if (want_socket) + cookie->fd = -1; + else + { + do + cookie->fd = open (name, O_WRONLY|O_APPEND|O_CREAT, + (S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWGRP|S_IWOTH)); + while (cookie->fd == -1 && errno == EINTR); + } + log_socket = cookie->fd; + +#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 /*!USE_FUNWRITER*/ + + /* The system does not feature custom streams. Thus fallback to + plain stdio. */ + if (want_socket) + { + fprintf (stderr, "system does not support logging to a socket - " + "using stderr\n"); + fp = stderr; + } + else if (name) + fp = fopen (name, "a"); + else if (fd == 1) + fp = stdout; + else if (fd == 2) + fp = stderr; + else + fp = fdopen (fd, "a"); + + log_socket = -1; + +#endif /*!USE_FUNWRITER*/ + + /* On error default to stderr. */ + if (!fp) + { + if (name) + fprintf (stderr, "failed to open log file `%s': %s\n", + name, strerror(errno)); + else + fprintf (stderr, "failed to fdopen file descriptor %d: %s\n", + fd, strerror(errno)); + /* We need to make sure that there is a log stream. We use stderr. */ + fp = stderr; + } + else + setvbuf (fp, NULL, _IOLBF, 0); + + logstream = fp; + + /* We always need to print the prefix and the pid for socket mode, + so that the server reading the socket can do something + meaningful. */ + force_prefixes = want_socket; + + missing_lf = 0; +} + + +/* Set the file to write log to. The special names NULL and "-" may + be used to select stderr and names formatted like + "socket:///home/foo/mylogs" may be used to write the logging to the + socket "/home/foo/mylogs". If the connection to the socket fails + or a write error is detected, the function writes to stderr and + tries the next time again to connect the socket. + */ +void +log_set_file (const char *name) +{ + set_file_fd (name? name: "-", -1); +} + +void +log_set_fd (int fd) +{ + set_file_fd (NULL, fd); +} + + +void +log_set_get_tid_callback (unsigned long (*cb)(void)) +{ + get_tid_callback = cb; +} + + +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 (logstream) + { + int tmp = fileno (logstream); + if ( tmp != -1 && tmp == fd) + return 1; + } + if (log_socket != -1 && log_socket == fd) + return 1; + return 0; +} + +int +log_get_fd () +{ + return fileno(logstream?logstream:stderr); +} + +FILE * +log_get_stream () +{ + /* FIXME: We should not return stderr here but initialize the log + stream properly. This might break more things than using stderr, + though */ + return logstream?logstream:stderr; +} + +static void +do_logv (int level, const char *fmt, va_list arg_ptr) +{ + if (!logstream) + { + log_set_file (NULL); /* Make sure a log stream has been set. */ + assert (logstream); + } + + 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) + { + if (get_tid_callback) + fprintf (logstream, "[%u.%lx]", + (unsigned int)getpid (), get_tid_callback ()); + else + 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; +#ifdef HAVE_W32_SYSTEM + else + fflush (logstream); +#endif + } + + if (level == JNLIB_LOG_FATAL) + { + if (missing_lf) + putc('\n', logstream ); + exit(2); + } + if (level == JNLIB_LOG_BUG) + { + if (missing_lf) + putc('\n', logstream ); + 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 + diff --git a/common/logging.h b/common/logging.h new file mode 100644 index 000000000..0b96108a8 --- /dev/null +++ b/common/logging.h @@ -0,0 +1,88 @@ +/* logging.h + * Copyright (C) 1999, 2000, 2001, 2004, 2006 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#ifndef LIBJNLIB_LOGGING_H +#define LIBJNLIB_LOGGING_H + +#include +#include "mischelp.h" + +/* Flag values for log_set_prefix. */ +#define JNLIB_LOG_WITH_PREFIX 1 +#define JNLIB_LOG_WITH_TIME 2 +#define JNLIB_LOG_WITH_PID 4 +#define JNLIB_LOG_RUN_DETACHED 256 + +int log_get_errorcount (int clear); +void log_inc_errorcount (void); +void log_set_file( const char *name ); +void log_set_fd (int fd); +void log_set_get_tid_callback (unsigned long (*cb)(void)); +void log_set_prefix (const char *text, unsigned int flags); +const char *log_get_prefix (unsigned int *flags); +int log_test_fd (int fd); +int log_get_fd(void); +FILE *log_get_stream (void); + +#ifdef JNLIB_GCC_M_FUNCTION + void bug_at( const char *file, int line, const char *func ) JNLIB_GCC_A_NR; +# define BUG() bug_at( __FILE__ , __LINE__, __FUNCTION__ ) +#else + void bug_at( const char *file, int line ); +# define BUG() bug_at( __FILE__ , __LINE__ ) +#endif + +/* To avoid mandatory inclusion of stdarg and other stuff, do it only + if explicitly requested to do so. */ +#ifdef JNLIB_NEED_LOG_LOGV +#include +enum jnlib_log_levels { + JNLIB_LOG_BEGIN, + JNLIB_LOG_CONT, + JNLIB_LOG_INFO, + JNLIB_LOG_WARN, + JNLIB_LOG_ERROR, + JNLIB_LOG_FATAL, + JNLIB_LOG_BUG, + JNLIB_LOG_DEBUG +}; +void log_logv (int level, const char *fmt, va_list arg_ptr); +#endif /*JNLIB_NEED_LOG_LOGV*/ + + +void log_bug( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2); +void log_fatal( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2); +void log_error( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); +void log_info( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); +void log_debug( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); +void log_printf( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); + +/* Print a hexdump of BUFFER. With TEXT passes as NULL print just the + raw dump, with TEXT being an empty string, print a trailing + linefeed, otherwise print an entire debug line with TEXT followed + by the hexdump and a final LF. */ +void log_printhex (const char *text, const void *buffer, size_t length); + + +#endif /*LIBJNLIB_LOGGING_H*/ + + + + + diff --git a/common/mischelp.c b/common/mischelp.c new file mode 100644 index 000000000..e06be21f2 --- /dev/null +++ b/common/mischelp.c @@ -0,0 +1,197 @@ +/* mischelp.c - Miscellaneous helper functions + * Copyright (C) 1998, 2000, 2001, 2006, 2007 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#include +#include +#include +#include +#ifdef HAVE_W32_SYSTEM +# define WIN32_LEAN_AND_MEAN +# include +#else /*!HAVE_W32_SYSTEM*/ +# include +# include +# include +#endif /*!HAVE_W32_SYSTEM*/ +#include + +#include "libjnlib-config.h" +#include "stringhelp.h" +#include "utf8conv.h" +#include "mischelp.h" + + +/* Because we can't use our jnlib_free macro in inline functions we + provide this wrapper. */ +void +_jnlib_free (void *p) +{ + if (p) + jnlib_free (p); +} + + +/* Check whether the files NAME1 and NAME2 are identical. This is for + example achieved by comparing the inode numbers of the files. */ +int +same_file_p (const char *name1, const char *name2) +{ + int yes; + + /* First try a shortcut. */ + if (!compare_filenames (name1, name2)) + yes = 1; + else + { +#ifdef HAVE_W32_SYSTEM + HANDLE file1, file2; + BY_HANDLE_FILE_INFORMATION info1, info2; + +#ifdef HAVE_W32CE_SYSTEM + { + wchar_t *wname = utf8_to_wchar (name1); + if (wname) + file1 = CreateFile (wname, 0, 0, NULL, OPEN_EXISTING, 0, NULL); + else + file1 = INVALID_HANDLE_VALUE; + jnlib_free (wname); + } +#else + file1 = CreateFile (name1, 0, 0, NULL, OPEN_EXISTING, 0, NULL); +#endif + if (file1 == INVALID_HANDLE_VALUE) + yes = 0; /* If we can't open the file, it is not the same. */ + else + { +#ifdef HAVE_W32CE_SYSTEM + { + wchar_t *wname = utf8_to_wchar (name2); + if (wname) + file2 = CreateFile (wname, 0, 0, NULL, OPEN_EXISTING, 0, NULL); + else + file2 = INVALID_HANDLE_VALUE; + jnlib_free (wname); + } +#else + file2 = CreateFile (name2, 0, 0, NULL, OPEN_EXISTING, 0, NULL); +#endif + if (file2 == INVALID_HANDLE_VALUE) + yes = 0; /* If we can't open the file, it is not the same. */ + else + { + yes = (GetFileInformationByHandle (file1, &info1) + && GetFileInformationByHandle (file2, &info2) + && info1.dwVolumeSerialNumber==info2.dwVolumeSerialNumber + && info1.nFileIndexHigh == info2.nFileIndexHigh + && info1.nFileIndexLow == info2.nFileIndexLow); + CloseHandle (file2); + } + CloseHandle (file1); + } +#else /*!HAVE_W32_SYSTEM*/ + struct stat info1, info2; + + yes = (!stat (name1, &info1) && !stat (name2, &info2) + && info1.st_dev == info2.st_dev && info1.st_ino == info2.st_ino); +#endif /*!HAVE_W32_SYSTEM*/ + } + return yes; +} + + +/* + timegm() is a GNU function that might not be available everywhere. + It's basically the inverse of gmtime() - you give it a struct tm, + and get back a time_t. It differs from mktime() in that it handles + the case where the struct tm is UTC and the local environment isn't. + + Note, that this replacement implementation might not be thread-safe! + + Some BSDs don't handle the putenv("foo") case properly, so we use + unsetenv if the platform has it to remove environment variables. +*/ +#ifndef HAVE_TIMEGM +time_t +timegm (struct tm *tm) +{ +#ifdef HAVE_W32_SYSTEM + /* This one is thread safe. */ + SYSTEMTIME st; + FILETIME ft; + unsigned long long cnsecs; + + st.wYear = tm->tm_year + 1900; + st.wMonth = tm->tm_mon + 1; + st.wDay = tm->tm_mday; + st.wHour = tm->tm_hour; + st.wMinute = tm->tm_min; + st.wSecond = tm->tm_sec; + st.wMilliseconds = 0; /* Not available. */ + st.wDayOfWeek = 0; /* Ignored. */ + + /* System time is UTC thus the conversion is pretty easy. */ + if (!SystemTimeToFileTime (&st, &ft)) + { + jnlib_set_errno (EINVAL); + return (time_t)(-1); + } + + cnsecs = (((unsigned long long)ft.dwHighDateTime << 32) + | ft.dwLowDateTime); + cnsecs -= 116444736000000000ULL; /* The filetime epoch is 1601-01-01. */ + return (time_t)(cnsecs / 10000000ULL); + +#else /* (Non thread safe implementation!) */ + + time_t answer; + char *zone; + + zone=getenv("TZ"); + putenv("TZ=UTC"); + tzset(); + answer=mktime(tm); + if(zone) + { + static char *old_zone; + + if (!old_zone) + { + old_zone = malloc(3+strlen(zone)+1); + if (old_zone) + { + strcpy(old_zone,"TZ="); + strcat(old_zone,zone); + } + } + if (old_zone) + putenv (old_zone); + } + else +#ifdef HAVE_UNSETENV + unsetenv("TZ"); +#else + putenv("TZ"); +#endif + + tzset(); + return answer; +#endif +} +#endif /*!HAVE_TIMEGM*/ + diff --git a/common/mischelp.h b/common/mischelp.h new file mode 100644 index 000000000..5a0132aa6 --- /dev/null +++ b/common/mischelp.h @@ -0,0 +1,102 @@ +/* mischelp.h - Miscellaneous helper macros and functions + * Copyright (C) 1999, 2000, 2001, 2002, 2003, + * 2006, 2007, 2009 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#ifndef LIBJNLIB_MISCHELP_H +#define LIBJNLIB_MISCHHELP_H + + +/* Because we can't use the internal jnlib_free macro in inline + functions we provide a wrapper function as well. */ +void _jnlib_free (void *p); + +/* Check whether the files NAME1 and NAME2 are identical. This is for + example achieved by comparing the inode numbers of the files. */ +int same_file_p (const char *name1, const char *name2); + + +#ifndef HAVE_TIMEGM +#include +time_t timegm (struct tm *tm); +#endif /*!HAVE_TIMEGM*/ + + +#define DIM(v) (sizeof(v)/sizeof((v)[0])) +#define DIMof(type,member) DIM(((type *)0)->member) + + +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ) +# define JNLIB_GCC_M_FUNCTION 1 +# define JNLIB_GCC_A_NR __attribute__ ((noreturn)) +# define JNLIB_GCC_A_PRINTF( f, a ) __attribute__ ((format (printf,f,a))) +# define JNLIB_GCC_A_NR_PRINTF( f, a ) \ + __attribute__ ((noreturn, format (printf,f,a))) +#else +# define JNLIB_GCC_A_NR +# define JNLIB_GCC_A_PRINTF( f, a ) +# define JNLIB_GCC_A_NR_PRINTF( f, a ) +#endif + + +/* To avoid that a compiler optimizes certain memset calls away, these + macros may be used instead. */ +#define wipememory2(_ptr,_set,_len) do { \ + volatile char *_vptr=(volatile char *)(_ptr); \ + size_t _vlen=(_len); \ + while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \ + } while(0) +#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len) + + +/* Include hacks which are mainly required for Slowaris. */ +#ifdef JNLIB_NEED_AFLOCAL +#ifndef HAVE_W32_SYSTEM +# include +# include +#else +# include +#endif + +#ifndef PF_LOCAL +# ifdef PF_UNIX +# define PF_LOCAL PF_UNIX +# else +# define PF_LOCAL AF_UNIX +# endif +#endif /*PF_LOCAL*/ +#ifndef AF_LOCAL +# define AF_LOCAL AF_UNIX +#endif /*AF_UNIX*/ + +/* We used to avoid this macro in GnuPG and inlined the AF_LOCAL name + length computation directly with the little twist of adding 1 extra + byte. It seems that this was needed once on an old HP/UX box and + there are also rumours that 4.3 Reno and DEC systems need it. This + one-off buglet did not harm any current system until it came to Mac + OS X where the kernel (as of May 2009) exhibited a strange bug: The + systems basically froze in the connect call if the passed name + contained an invalid directory part. Ignore the old Unices. */ +#ifndef SUN_LEN +# define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \ + + strlen ((ptr)->sun_path)) +#endif /*SUN_LEN*/ +#endif /*JNLIB_NEED_AFLOCAL*/ + + +#endif /*LIBJNLIB_MISCHELP_H*/ diff --git a/common/simple-pwquery.c b/common/simple-pwquery.c index 3598b3598..fd48b6f5a 100644 --- a/common/simple-pwquery.c +++ b/common/simple-pwquery.c @@ -41,9 +41,9 @@ #endif #define JNLIB_NEED_AFLOCAL -#include "../jnlib/mischelp.h" +#include "../common/mischelp.h" #ifdef HAVE_W32_SYSTEM -#include "../jnlib/w32-afunix.h" +#include "../common/w32-afunix.h" #endif diff --git a/common/simple-pwquery.h b/common/simple-pwquery.h index 8de9b1bd2..edd834ef4 100644 --- a/common/simple-pwquery.h +++ b/common/simple-pwquery.h @@ -24,7 +24,7 @@ /* Include whatever files you need. */ #include -#include "../jnlib/logging.h" +#include "../common/logging.h" /* Try to write error message using the standard log mechanism. The current implementation requires that the HAVE_JNLIB_LOGGING is also diff --git a/common/stringhelp.c b/common/stringhelp.c new file mode 100644 index 000000000..36f96b8ff --- /dev/null +++ b/common/stringhelp.c @@ -0,0 +1,1151 @@ +/* stringhelp.c - standard string helper functions + * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005, + * 2006, 2007, 2008, 2009 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#include +#include +#include +#include +#include +#include +#ifdef HAVE_PWD_H +# include +#endif +#include +#include +#ifdef HAVE_W32_SYSTEM +# include +#endif + +#include "libjnlib-config.h" +#include "utf8conv.h" +#include "stringhelp.h" + + +#define tohex_lower(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'a')) + +/* Sometimes we want to avoid mixing slashes and backslashes on W32 + and prefer backslashes. There is usual no problem with mixing + them, however a very few W32 API calls can't grok plain slashes. + Printing filenames with mixed slashes also looks a bit strange. + This function has no effext on POSIX. */ +static inline char * +change_slashes (char *name) +{ +#ifdef HAVE_DRIVE_LETTERS + char *p; + + if (strchr (name, '\\')) + { + for (p=name; *p; p++) + if (*p == '/') + *p = '\\'; + } +#endif /*HAVE_DRIVE_LETTERS*/ + return name; +} + + +/* + * Look for the substring SUB in buffer and return a pointer to that + * substring in BUFFER or NULL if not found. + * Comparison is case-insensitive. + */ +const char * +memistr (const void *buffer, size_t buflen, const char *sub) +{ + const unsigned char *buf = buffer; + const unsigned char *t = (const unsigned char *)buffer; + const unsigned char *s = (const unsigned char *)sub; + size_t n = buflen; + + for ( ; n ; t++, n-- ) + { + if ( toupper (*t) == toupper (*s) ) + { + for ( buf=t++, buflen = n--, s++; + n && toupper (*t) == toupper (*s); t++, s++, n-- ) + ; + if (!*s) + return (const char*)buf; + t = buf; + s = (const unsigned char *)sub ; + n = buflen; + } + } + return NULL; +} + +const char * +ascii_memistr ( const void *buffer, size_t buflen, const char *sub ) +{ + const unsigned char *buf = buffer; + const unsigned char *t = (const unsigned char *)buf; + const unsigned char *s = (const unsigned char *)sub; + size_t n = buflen; + + for ( ; n ; t++, n-- ) + { + if (ascii_toupper (*t) == ascii_toupper (*s) ) + { + for ( buf=t++, buflen = n--, s++; + n && ascii_toupper (*t) == ascii_toupper (*s); t++, s++, n-- ) + ; + if (!*s) + return (const char*)buf; + t = (const unsigned char *)buf; + s = (const unsigned char *)sub ; + n = buflen; + } + } + return NULL; +} + +/* This function is similar to strncpy(). However it won't copy more + than N - 1 characters and makes sure that a '\0' is appended. With + N given as 0, nothing will happen. With DEST given as NULL, memory + will be allocated using jnlib_xmalloc (i.e. if it runs out of core + the function terminates). Returns DES or a pointer to the + allocated memory. + */ +char * +mem2str( char *dest , const void *src , size_t n ) +{ + char *d; + const char *s; + + if( n ) { + if( !dest ) + dest = jnlib_xmalloc( n ) ; + d = dest; + s = src ; + for(n--; n && *s; n-- ) + *d++ = *s++; + *d = '\0' ; + } + + return dest ; +} + + +/**************** + * remove leading and trailing white spaces + */ +char * +trim_spaces( char *str ) +{ + char *string, *p, *mark; + + string = str; + /* find first non space character */ + for( p=string; *p && isspace( *(byte*)p ) ; p++ ) + ; + /* move characters */ + for( (mark = NULL); (*string = *p); string++, p++ ) + if( isspace( *(byte*)p ) ) { + if( !mark ) + mark = string ; + } + else + mark = NULL ; + if( mark ) + *mark = '\0' ; /* remove trailing spaces */ + + return str ; +} + +/**************** + * remove trailing white spaces + */ +char * +trim_trailing_spaces( char *string ) +{ + char *p, *mark; + + for( mark = NULL, p = string; *p; p++ ) { + if( isspace( *(byte*)p ) ) { + if( !mark ) + mark = p; + } + else + mark = NULL; + } + if( mark ) + *mark = '\0' ; + + return string ; +} + + +unsigned +trim_trailing_chars( byte *line, unsigned len, const char *trimchars ) +{ + byte *p, *mark; + unsigned n; + + for(mark=NULL, p=line, n=0; n < len; n++, p++ ) { + if( strchr(trimchars, *p ) ) { + if( !mark ) + mark = p; + } + else + mark = NULL; + } + + if( mark ) { + *mark = 0; + return mark - line; + } + return len; +} + +/**************** + * remove trailing white spaces and return the length of the buffer + */ +unsigned +trim_trailing_ws( byte *line, unsigned len ) +{ + return trim_trailing_chars( line, len, " \t\r\n" ); +} + +size_t +length_sans_trailing_chars (const unsigned char *line, size_t len, + const char *trimchars ) +{ + const unsigned char *p, *mark; + size_t n; + + for( mark=NULL, p=line, n=0; n < len; n++, p++ ) + { + if (strchr (trimchars, *p )) + { + if( !mark ) + mark = p; + } + else + mark = NULL; + } + + if (mark) + return mark - line; + return len; +} + +/* + * Return the length of line ignoring trailing white-space. + */ +size_t +length_sans_trailing_ws (const unsigned char *line, size_t len) +{ + return length_sans_trailing_chars (line, len, " \t\r\n"); +} + + + +/* + * Extract from a given path the filename component. This function + * terminates the process on memory shortage. + */ +char * +make_basename(const char *filepath, const char *inputpath) +{ +#ifdef __riscos__ + return riscos_make_basename(filepath, inputpath); +#else + char *p; + + (void)inputpath; /* Only required for riscos. */ + + if ( !(p=strrchr(filepath, '/')) ) +#ifdef HAVE_DRIVE_LETTERS + if ( !(p=strrchr(filepath, '\\')) ) + if ( !(p=strrchr(filepath, ':')) ) +#endif + { + return jnlib_xstrdup(filepath); + } + + return jnlib_xstrdup(p+1); +#endif +} + + + +/* + * Extract from a given filename the path prepended to it. If there + * isn't a path prepended to the filename, a dot is returned ('.'). + * This function terminates the process on memory shortage. + */ +char * +make_dirname(const char *filepath) +{ + char *dirname; + int dirname_length; + char *p; + + if ( !(p=strrchr(filepath, '/')) ) +#ifdef HAVE_DRIVE_LETTERS + if ( !(p=strrchr(filepath, '\\')) ) + if ( !(p=strrchr(filepath, ':')) ) +#endif + { + return jnlib_xstrdup("."); + } + + dirname_length = p-filepath; + dirname = jnlib_xmalloc(dirname_length+1); + strncpy(dirname, filepath, dirname_length); + dirname[dirname_length] = 0; + + return dirname; +} + + + +static char * +get_pwdir (int xmode, const char *name) +{ + char *result = NULL; +#ifdef HAVE_PWD_H + struct passwd *pwd = NULL; + + if (name) + { +#ifdef HAVE_GETPWNAM + /* Fixme: We should use getpwnam_r if available. */ + pwd = getpwnam (name); +#endif + } + else + { +#ifdef HAVE_GETPWUID + /* Fixme: We should use getpwuid_r if available. */ + pwd = getpwuid (getuid()); +#endif + } + if (pwd) + { + if (xmode) + result = jnlib_xstrdup (pwd->pw_dir); + else + result = jnlib_strdup (pwd->pw_dir); + } +#else /*!HAVE_PWD_H*/ + /* No support at all. */ + (void)xmode; + (void)name; +#endif /*HAVE_PWD_H*/ + return result; +} + +static char * +do_make_filename (int xmode, const char *first_part, va_list arg_ptr) +{ + const char *argv[32]; + int argc; + size_t n; + int skip = 1; + char *home_buffer = NULL; + char *name, *home, *p; + + n = strlen (first_part) + 1; + argc = 0; + while ( (argv[argc] = va_arg (arg_ptr, const char *)) ) + { + n += strlen (argv[argc]) + 1; + if (argc >= DIM (argv)-1) + { + if (xmode) + BUG (); + jnlib_set_errno (EINVAL); + return NULL; + } + argc++; + } + n++; + + home = NULL; + if (*first_part == '~') + { + if (first_part[1] == '/' || !first_part[1]) + { + /* This is the "~/" or "~" case. */ + home = getenv("HOME"); + if (!home) + home = home_buffer = get_pwdir (xmode, NULL); + if (home && *home) + n += strlen (home); + } + else + { + /* This is the "~username/" or "~username" case. */ + char *user; + + if (xmode) + user = jnlib_xstrdup (first_part+1); + else + { + user = jnlib_strdup (first_part+1); + if (!user) + return NULL; + } + p = strchr (user, '/'); + if (p) + *p = 0; + skip = 1 + strlen (user); + + home = home_buffer = get_pwdir (xmode, user); + jnlib_free (user); + if (home) + n += strlen (home); + else + skip = 1; + } + } + + if (xmode) + name = jnlib_xmalloc (n); + else + { + name = jnlib_malloc (n); + if (!name) + { + jnlib_free (home_buffer); + return NULL; + } + } + + if (home) + p = stpcpy (stpcpy (name, home), first_part + skip); + else + p = stpcpy (name, first_part); + + jnlib_free (home_buffer); + + for (argc=0; argv[argc]; argc++) + p = stpcpy (stpcpy (p, "/"), argv[argc]); + + return change_slashes (name); +} + +/* Construct a filename from the NULL terminated list of parts. Tilde + expansion is done for the first argument. This function terminates + the process on memory shortage. */ +char * +make_filename (const char *first_part, ... ) +{ + va_list arg_ptr; + char *result; + + va_start (arg_ptr, first_part); + result = do_make_filename (1, first_part, arg_ptr); + va_end (arg_ptr); + return result; +} + +/* Construct a filename from the NULL terminated list of parts. Tilde + expansion is done for the first argument. This function may return + NULL on error. */ +char * +make_filename_try (const char *first_part, ... ) +{ + va_list arg_ptr; + char *result; + + va_start (arg_ptr, first_part); + result = do_make_filename (0, first_part, arg_ptr); + va_end (arg_ptr); + return result; +} + + + +/* Compare whether the filenames are identical. This is a + special version of strcmp() taking the semantics of filenames in + account. Note that this function works only on the supplied names + without considereing any context like the current directory. See + also same_file_p(). */ +int +compare_filenames (const char *a, const char *b) +{ +#ifdef HAVE_DRIVE_LETTERS + for ( ; *a && *b; a++, b++ ) + { + if (*a != *b + && (toupper (*(const unsigned char*)a) + != toupper (*(const unsigned char*)b) ) + && !((*a == '/' && *b == '\\') || (*a == '\\' && *b == '/'))) + break; + } + if ((*a == '/' && *b == '\\') || (*a == '\\' && *b == '/')) + return 0; + else + return (toupper (*(const unsigned char*)a) + - toupper (*(const unsigned char*)b)); +#else + return strcmp(a,b); +#endif +} + + +/* Convert 2 hex characters at S to a byte value. Return this value + or -1 if there is an error. */ +int +hextobyte (const char *s) +{ + int c; + + if ( *s >= '0' && *s <= '9' ) + c = 16 * (*s - '0'); + else if ( *s >= 'A' && *s <= 'F' ) + c = 16 * (10 + *s - 'A'); + else if ( *s >= 'a' && *s <= 'f' ) + c = 16 * (10 + *s - 'a'); + else + return -1; + s++; + if ( *s >= '0' && *s <= '9' ) + c += *s - '0'; + else if ( *s >= 'A' && *s <= 'F' ) + c += 10 + *s - 'A'; + else if ( *s >= 'a' && *s <= 'f' ) + c += 10 + *s - 'a'; + else + return -1; + return c; +} + + +/* Print a BUFFER to stream FP while replacing all control characters + and the characters DELIM and DELIM2 with standard C escape + sequences. Returns the number of characters printed. */ +size_t +print_sanitized_buffer2 (FILE *fp, const void *buffer, size_t length, + int delim, int delim2) +{ + const unsigned char *p = buffer; + size_t count = 0; + + for (; length; length--, p++, count++) + { + if (*p < 0x20 + || *p == 0x7f + || *p == delim + || *p == delim2 + || ((delim || delim2) && *p=='\\')) + { + putc ('\\', fp); + count++; + if (*p == '\n') + { + putc ('n', fp); + count++; + } + else if (*p == '\r') + { + putc ('r', fp); + count++; + } + else if (*p == '\f') + { + putc ('f', fp); + count++; + } + else if (*p == '\v') + { + putc ('v', fp); + count++; + } + else if (*p == '\b') + { + putc ('b', fp); + count++; + } + else if (!*p) + { + putc('0', fp); + count++; + } + else + { + fprintf (fp, "x%02x", *p); + count += 3; + } + } + else + { + putc (*p, fp); + count++; + } + } + + return count; +} + +/* Same as print_sanitized_buffer2 but with just one delimiter. */ +size_t +print_sanitized_buffer (FILE *fp, const void *buffer, size_t length, + int delim) +{ + return print_sanitized_buffer2 (fp, buffer, length, delim, 0); +} + + +size_t +print_sanitized_utf8_buffer (FILE *fp, const void *buffer, + size_t length, int delim) +{ + const char *p = buffer; + size_t i; + + /* We can handle plain ascii simpler, so check for it first. */ + for (i=0; i < length; i++ ) + { + if ( (p[i] & 0x80) ) + break; + } + if (i < length) + { + char *buf = utf8_to_native (p, length, delim); + /*(utf8 conversion already does the control character quoting)*/ + i = strlen (buf); + fputs (buf, fp); + jnlib_free (buf); + return i; + } + else + return print_sanitized_buffer (fp, p, length, delim); +} + + +size_t +print_sanitized_string2 (FILE *fp, const char *string, int delim, int delim2) +{ + return string? print_sanitized_buffer2 (fp, string, strlen (string), + delim, delim2):0; +} + +size_t +print_sanitized_string (FILE *fp, const char *string, int delim) +{ + return string? print_sanitized_buffer (fp, string, strlen (string), delim):0; +} + +size_t +print_sanitized_utf8_string (FILE *fp, const char *string, int delim) +{ + return string? print_sanitized_utf8_buffer (fp, + string, strlen (string), + delim) : 0; +} + +/* Create a string from the buffer P_ARG of length N which is suitable + for printing. Caller must release the created string using xfree. + This function terminates the process on memory shortage. */ +char * +sanitize_buffer (const void *p_arg, size_t n, int delim) +{ + const unsigned char *p = p_arg; + size_t save_n, buflen; + const unsigned char *save_p; + char *buffer, *d; + + /* First count length. */ + for (save_n = n, save_p = p, buflen=1 ; n; n--, p++ ) + { + if ( *p < 0x20 || *p == 0x7f || *p == delim || (delim && *p=='\\')) + { + if ( *p=='\n' || *p=='\r' || *p=='\f' + || *p=='\v' || *p=='\b' || !*p ) + buflen += 2; + else + buflen += 5; + } + else + buflen++; + } + p = save_p; + n = save_n; + /* And now make the string */ + d = buffer = jnlib_xmalloc( buflen ); + for ( ; n; n--, p++ ) + { + if (*p < 0x20 || *p == 0x7f || *p == delim || (delim && *p=='\\')) { + *d++ = '\\'; + if( *p == '\n' ) + *d++ = 'n'; + else if( *p == '\r' ) + *d++ = 'r'; + else if( *p == '\f' ) + *d++ = 'f'; + else if( *p == '\v' ) + *d++ = 'v'; + else if( *p == '\b' ) + *d++ = 'b'; + else if( !*p ) + *d++ = '0'; + else { + sprintf(d, "x%02x", *p ); + d += 3; + } + } + else + *d++ = *p; + } + *d = 0; + return buffer; +} + + +/* Given a string containing an UTF-8 encoded text, return the number + of characters in this string. It differs from strlen in that it + only counts complete UTF-8 characters. Note, that this function + does not take combined characters into account. */ +size_t +utf8_charcount (const char *s) +{ + size_t n; + + for (n=0; *s; s++) + if ( (*s&0xc0) != 0x80 ) /* Exclude continuation bytes: 10xxxxxx */ + n++; + + return n; +} + + +/**************************************************** + ********** W32 specific functions **************** + ****************************************************/ + +#ifdef HAVE_W32_SYSTEM +const char * +w32_strerror (int ec) +{ + static char strerr[256]; + + if (ec == -1) + ec = (int)GetLastError (); +#ifdef HAVE_W32CE_SYSTEM + /* There is only a wchar_t FormatMessage. It does not make much + sense to play the conversion game; we print only the code. */ + snprintf (strerr, sizeof strerr, "ec=%d", (int)GetLastError ()); +#else + FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, ec, + MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), + strerr, DIM (strerr)-1, NULL); +#endif + return strerr; +} +#endif /*HAVE_W32_SYSTEM*/ + + +/**************************************************** + ******** Locale insensitive ctype functions ******** + ****************************************************/ +/* FIXME: replace them by a table lookup and macros */ +int +ascii_isupper (int c) +{ + return c >= 'A' && c <= 'Z'; +} + +int +ascii_islower (int c) +{ + return c >= 'a' && c <= 'z'; +} + +int +ascii_toupper (int c) +{ + if (c >= 'a' && c <= 'z') + c &= ~0x20; + return c; +} + +int +ascii_tolower (int c) +{ + if (c >= 'A' && c <= 'Z') + c |= 0x20; + return c; +} + + +int +ascii_strcasecmp( const char *a, const char *b ) +{ + if (a == b) + return 0; + + for (; *a && *b; a++, b++) { + if (*a != *b && ascii_toupper(*a) != ascii_toupper(*b)) + break; + } + return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b)); +} + +int +ascii_strncasecmp (const char *a, const char *b, size_t n) +{ + const unsigned char *p1 = (const unsigned char *)a; + const unsigned char *p2 = (const unsigned char *)b; + unsigned char c1, c2; + + if (p1 == p2 || !n ) + return 0; + + do + { + c1 = ascii_tolower (*p1); + c2 = ascii_tolower (*p2); + + if ( !--n || c1 == '\0') + break; + + ++p1; + ++p2; + } + while (c1 == c2); + + return c1 - c2; +} + + +int +ascii_memcasecmp (const void *a_arg, const void *b_arg, size_t n ) +{ + const char *a = a_arg; + const char *b = b_arg; + + if (a == b) + return 0; + for ( ; n; n--, a++, b++ ) + { + if( *a != *b && ascii_toupper (*a) != ascii_toupper (*b) ) + return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b)); + } + return 0; +} + +int +ascii_strcmp( const char *a, const char *b ) +{ + if (a == b) + return 0; + + for (; *a && *b; a++, b++) { + if (*a != *b ) + break; + } + return *a == *b? 0 : (*(signed char *)a - *(signed char *)b); +} + + +void * +ascii_memcasemem (const void *haystack, size_t nhaystack, + const void *needle, size_t nneedle) +{ + + if (!nneedle) + return (void*)haystack; /* finding an empty needle is really easy */ + if (nneedle <= nhaystack) + { + const char *a = haystack; + const char *b = a + nhaystack - nneedle; + + for (; a <= b; a++) + { + if ( !ascii_memcasecmp (a, needle, nneedle) ) + return (void *)a; + } + } + return NULL; +} + +/********************************************* + ********** missing string functions ********* + *********************************************/ + +#ifndef HAVE_STPCPY +char * +stpcpy(char *a,const char *b) +{ + while( *b ) + *a++ = *b++; + *a = 0; + + return (char*)a; +} +#endif + +#ifndef HAVE_STRSEP +/* Code taken from glibc-2.2.1/sysdeps/generic/strsep.c. */ +char * +strsep (char **stringp, const char *delim) +{ + char *begin, *end; + + begin = *stringp; + if (begin == NULL) + return NULL; + + /* A frequent case is when the delimiter string contains only one + character. Here we don't need to call the expensive `strpbrk' + function and instead work using `strchr'. */ + if (delim[0] == '\0' || delim[1] == '\0') + { + char ch = delim[0]; + + if (ch == '\0') + end = NULL; + else + { + if (*begin == ch) + end = begin; + else if (*begin == '\0') + end = NULL; + else + end = strchr (begin + 1, ch); + } + } + else + /* Find the end of the token. */ + end = strpbrk (begin, delim); + + if (end) + { + /* Terminate the token and set *STRINGP past NUL character. */ + *end++ = '\0'; + *stringp = end; + } + else + /* No more delimiters; this is the last token. */ + *stringp = NULL; + + return begin; +} +#endif /*HAVE_STRSEP*/ + + +#ifndef HAVE_STRLWR +char * +strlwr(char *s) +{ + char *p; + for(p=s; *p; p++ ) + *p = tolower(*p); + return s; +} +#endif + + +#ifndef HAVE_STRCASECMP +int +strcasecmp( const char *a, const char *b ) +{ + for( ; *a && *b; a++, b++ ) { + if( *a != *b && toupper(*a) != toupper(*b) ) + break; + } + return *(const byte*)a - *(const byte*)b; +} +#endif + + +/**************** + * mingw32/cpd has a memicmp() + */ +#ifndef HAVE_MEMICMP +int +memicmp( const char *a, const char *b, size_t n ) +{ + for( ; n; n--, a++, b++ ) + if( *a != *b && toupper(*(const byte*)a) != toupper(*(const byte*)b) ) + return *(const byte *)a - *(const byte*)b; + return 0; +} +#endif + + +#ifndef HAVE_MEMRCHR +void * +memrchr (const void *buffer, int c, size_t n) +{ + const unsigned char *p = buffer; + + for (p += n; n ; n--) + if (*--p == c) + return (void *)p; + return NULL; +} +#endif /*HAVE_MEMRCHR*/ + + +/* Percent-escape the string STR by replacing colons with '%3a'. If + EXTRA is not NULL all characters in EXTRA are also escaped. */ +static char * +do_percent_escape (const char *str, const char *extra, int die) +{ + int i, j; + char *ptr; + + if (!str) + return NULL; + + for (i=j=0; str[i]; i++) + if (str[i] == ':' || str[i] == '%' || (extra && strchr (extra, str[i]))) + j++; + if (die) + ptr = jnlib_xmalloc (i + 2 * j + 1); + else + { + ptr = jnlib_malloc (i + 2 * j + 1); + if (!ptr) + return NULL; + } + i = 0; + while (*str) + { + if (*str == ':') + { + ptr[i++] = '%'; + ptr[i++] = '3'; + ptr[i++] = 'a'; + } + else if (*str == '%') + { + ptr[i++] = '%'; + ptr[i++] = '2'; + ptr[i++] = '5'; + } + else if (extra && strchr (extra, *str)) + { + ptr[i++] = '%'; + ptr[i++] = tohex_lower ((*str>>4)&15); + ptr[i++] = tohex_lower (*str&15); + } + else + ptr[i++] = *str; + str++; + } + ptr[i] = '\0'; + + return ptr; +} + +/* Percent-escape the string STR by replacing colons with '%3a'. If + EXTRA is not NULL all characters in EXTRA are also escaped. This + function terminates the process on memory shortage. */ +char * +percent_escape (const char *str, const char *extra) +{ + return do_percent_escape (str, extra, 1); +} + +/* Same as percent_escape but return NULL instead of exiting on memory + error. */ +char * +try_percent_escape (const char *str, const char *extra) +{ + return do_percent_escape (str, extra, 0); +} + + + +static char * +do_strconcat (const char *s1, va_list arg_ptr) +{ + const char *argv[48]; + size_t argc; + size_t needed; + char *buffer, *p; + + argc = 0; + argv[argc++] = s1; + needed = strlen (s1); + while (((argv[argc] = va_arg (arg_ptr, const char *)))) + { + needed += strlen (argv[argc]); + if (argc >= DIM (argv)-1) + { + jnlib_set_errno (EINVAL); + return NULL; + } + argc++; + } + needed++; + buffer = jnlib_malloc (needed); + if (buffer) + { + for (p = buffer, argc=0; argv[argc]; argc++) + p = stpcpy (p, argv[argc]); + } + return buffer; +} + + +/* Concatenate the string S1 with all the following strings up to a + NULL. Returns a malloced buffer with the new string or NULL on a + malloc error or if too many arguments are given. */ +char * +strconcat (const char *s1, ...) +{ + va_list arg_ptr; + char *result; + + if (!s1) + result = jnlib_strdup (""); + else + { + va_start (arg_ptr, s1); + result = do_strconcat (s1, arg_ptr); + va_end (arg_ptr); + } + return result; +} + +/* Same as strconcat but terminate the process with an error message + if something goes wrong. */ +char * +xstrconcat (const char *s1, ...) +{ + va_list arg_ptr; + char *result; + + if (!s1) + result = jnlib_xstrdup (""); + else + { + va_start (arg_ptr, s1); + result = do_strconcat (s1, arg_ptr); + va_end (arg_ptr); + } + if (!result) + { + if (errno == EINVAL) + fputs ("\nfatal: too many args for xstrconcat\n", stderr); + else + fputs ("\nfatal: out of memory\n", stderr); + exit (2); + } + return result; +} + diff --git a/common/stringhelp.h b/common/stringhelp.h new file mode 100644 index 000000000..a560b163e --- /dev/null +++ b/common/stringhelp.h @@ -0,0 +1,136 @@ +/* stringhelp.h + * Copyright (C) 1998, 1999, 2000, 2001, 2003, + * 2006, 2007, 2009 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#ifndef LIBJNLIB_STRINGHELP_H +#define LIBJNLIB_STRINGHELP_H + +#include "types.h" + +const char *memistr (const void *buf, size_t buflen, const char *sub); +char *mem2str( char *, const void *, size_t); +char *trim_spaces( char *string ); +char *trim_trailing_spaces( char *string ); +unsigned int trim_trailing_chars( unsigned char *line, unsigned len, + const char *trimchars); +unsigned int trim_trailing_ws( unsigned char *line, unsigned len ); +size_t length_sans_trailing_chars (const unsigned char *line, size_t len, + const char *trimchars ); +size_t length_sans_trailing_ws (const unsigned char *line, size_t len); + + +char *make_basename(const char *filepath, const char *inputpath); +char *make_dirname(const char *filepath); +char *make_filename( const char *first_part, ... ) GNUPG_GCC_A_SENTINEL(0); +char *make_filename_try (const char *first_part, ... ) GNUPG_GCC_A_SENTINEL(0); +int compare_filenames( const char *a, const char *b ); + +int hextobyte (const char *s); + +size_t print_sanitized_buffer (FILE *fp, const void *buffer, size_t length, + int delim); +size_t print_sanitized_buffer2 (FILE *fp, const void *buffer, size_t length, + int delim, int delim2); +size_t print_sanitized_utf8_buffer (FILE *fp, const void *buffer, + size_t length, int delim); +size_t print_sanitized_string (FILE *fp, const char *string, int delim); +size_t print_sanitized_string2 (FILE *fp, const char *string, + int delim, int delim2); +size_t print_sanitized_utf8_string (FILE *fp, const char *string, int delim); +char *sanitize_buffer (const void *p, size_t n, int delim); + + +size_t utf8_charcount (const char *s); + + +#ifdef HAVE_W32_SYSTEM +const char *w32_strerror (int ec); +#endif + + +int ascii_isupper (int c); +int ascii_islower (int c); +int ascii_toupper (int c); +int ascii_tolower (int c); +int ascii_strcasecmp( const char *a, const char *b ); +int ascii_strncasecmp (const char *a, const char *b, size_t n); +int ascii_memcasecmp( const void *a, const void *b, size_t n ); +const char *ascii_memistr ( const void *buf, size_t buflen, const char *sub); +void *ascii_memcasemem (const void *haystack, size_t nhaystack, + const void *needle, size_t nneedle); + + +#ifndef HAVE_MEMICMP +int memicmp( const char *a, const char *b, size_t n ); +#endif +#ifndef HAVE_STPCPY +char *stpcpy(char *a,const char *b); +#endif +#ifndef HAVE_STRSEP +char *strsep (char **stringp, const char *delim); +#endif +#ifndef HAVE_STRLWR +char *strlwr(char *a); +#endif +#ifndef HAVE_STRTOUL +# define strtoul(a,b,c) ((unsigned long)strtol((a),(b),(c))) +#endif +#ifndef HAVE_MEMMOVE +# define memmove(d, s, n) bcopy((s), (d), (n)) +#endif +#ifndef HAVE_STRICMP +# define stricmp(a,b) strcasecmp( (a), (b) ) +#endif +#ifndef HAVE_MEMRCHR +void *memrchr (const void *buffer, int c, size_t n); +#endif + + +#ifndef HAVE_ISASCII +static inline int +isascii (int c) +{ + return (((c) & ~0x7f) == 0); +} +#endif /* !HAVE_ISASCII */ + + +#ifndef STR +# define STR(v) #v +#endif +#define STR2(v) STR(v) + +/* Percent-escape the string STR by replacing colons with '%3a'. If + EXTRA is not NULL, also replace all characters given in EXTRA. The + "try_" variant fails with NULL if not enough memory can be + allocated. */ +char *percent_escape (const char *str, const char *extra); +char *try_percent_escape (const char *str, const char *extra); + + +/* Concatenate the string S1 with all the following strings up to a + NULL. Returns a malloced buffer with the new string or NULL on a + malloc error or if too many arguments are given. */ +char *strconcat (const char *s1, ...) GNUPG_GCC_A_SENTINEL(0); +/* Ditto, but die on error. */ +char *xstrconcat (const char *s1, ...) GNUPG_GCC_A_SENTINEL(0); + + + +#endif /*LIBJNLIB_STRINGHELP_H*/ diff --git a/common/strlist.c b/common/strlist.c new file mode 100644 index 000000000..b31e6213a --- /dev/null +++ b/common/strlist.c @@ -0,0 +1,204 @@ +/* strlist.c - string helpers + * Copyright (C) 1998, 2000, 2001, 2006 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#include +#include +#include +#include +#include + +#include "libjnlib-config.h" +#include "strlist.h" +#ifdef JNLIB_NEED_UTF8CONV +#include "utf8conv.h" +#endif + +void +free_strlist( strlist_t sl ) +{ + strlist_t sl2; + + for(; sl; sl = sl2 ) { + sl2 = sl->next; + jnlib_free(sl); + } +} + + +/* Add STRING to the LIST at the front. This function terminates the + process on memory shortage. */ +strlist_t +add_to_strlist( strlist_t *list, const char *string ) +{ + strlist_t sl; + + sl = jnlib_xmalloc( sizeof *sl + strlen(string)); + sl->flags = 0; + strcpy(sl->d, string); + sl->next = *list; + *list = sl; + return sl; +} + + +/* Add STRING to the LIST at the front. This function returns NULL + and sets ERRNO on memory shortage. */ +strlist_t +add_to_strlist_try (strlist_t *list, const char *string) +{ + strlist_t sl; + + sl = jnlib_malloc (sizeof *sl + strlen (string)); + if (sl) + { + sl->flags = 0; + strcpy (sl->d, string); + sl->next = *list; + *list = sl; + } + return sl; +} + + +/* Same as add_to_strlist() but if IS_UTF8 is *not* set, a conversion + to UTF-8 is done. This function terminates the process on memory + shortage. */ +#ifdef JNLIB_NEED_UTF8CONV +strlist_t +add_to_strlist2( strlist_t *list, const char *string, int is_utf8 ) +{ + strlist_t sl; + + if (is_utf8) + sl = add_to_strlist( list, string ); + else + { + char *p = native_to_utf8( string ); + sl = add_to_strlist( list, p ); + jnlib_free ( p ); + } + return sl; +} +#endif /* JNLIB_NEED_UTF8CONV*/ + + +/* Add STRING to the LIST at the end. This function terminates the + process on memory shortage. */ +strlist_t +append_to_strlist( strlist_t *list, const char *string ) +{ + strlist_t r, sl; + + sl = jnlib_xmalloc( sizeof *sl + strlen(string)); + sl->flags = 0; + strcpy(sl->d, string); + sl->next = NULL; + if( !*list ) + *list = sl; + else { + for( r = *list; r->next; r = r->next ) + ; + r->next = sl; + } + return sl; +} + + +#ifdef JNLIB_NEED_UTF8CONV +strlist_t +append_to_strlist2( strlist_t *list, const char *string, int is_utf8 ) +{ + strlist_t sl; + + if( is_utf8 ) + sl = append_to_strlist( list, string ); + else + { + char *p = native_to_utf8 (string); + sl = append_to_strlist( list, p ); + jnlib_free( p ); + } + return sl; +} +#endif /* JNLIB_NEED_UTF8CONV */ + + +/* Return a copy of LIST. This function terminates the process on + memory shortage.*/ +strlist_t +strlist_copy (strlist_t list) +{ + strlist_t newlist = NULL, sl, *last; + + last = &newlist; + for (; list; list = list->next) + { + sl = jnlib_xmalloc (sizeof *sl + strlen (list->d)); + sl->flags = list->flags; + strcpy(sl->d, list->d); + sl->next = NULL; + *last = sl; + last = &sl; + } + return newlist; +} + + + +strlist_t +strlist_prev( strlist_t head, strlist_t node ) +{ + strlist_t n; + + for(n=NULL; head && head != node; head = head->next ) + n = head; + return n; +} + +strlist_t +strlist_last( strlist_t node ) +{ + if( node ) + for( ; node->next ; node = node->next ) + ; + return node; +} + + +/* Remove the first item from LIST and return its content in an + allocated buffer. This function terminates the process on memory + shortage. */ +char * +strlist_pop (strlist_t *list) +{ + char *str=NULL; + strlist_t sl=*list; + + if(sl) + { + str=jnlib_xmalloc(strlen(sl->d)+1); + strcpy(str,sl->d); + + *list=sl->next; + jnlib_free(sl); + } + + return str; +} + diff --git a/common/strlist.h b/common/strlist.h new file mode 100644 index 000000000..1e2ffa8da --- /dev/null +++ b/common/strlist.h @@ -0,0 +1,50 @@ +/* strlist.h + * Copyright (C) 1998, 2000, 2001, 2006 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#ifndef LIBJNLIB_STRLIST_H +#define LIBJNLIB_STRLIST_H + +struct string_list +{ + struct string_list *next; + unsigned int flags; + char d[1]; +}; +typedef struct string_list *strlist_t; + +void free_strlist (strlist_t sl); +strlist_t add_to_strlist (strlist_t *list, const char *string); +strlist_t add_to_strlist_try (strlist_t *list, const char *string); + +strlist_t add_to_strlist2( strlist_t *list, const char *string, int is_utf8); + +strlist_t append_to_strlist (strlist_t *list, const char *string); +strlist_t append_to_strlist2 (strlist_t *list, const char *string, + int is_utf8); + +strlist_t strlist_copy (strlist_t list); + +strlist_t strlist_prev (strlist_t head, strlist_t node); +strlist_t strlist_last (strlist_t node); +char * strlist_pop (strlist_t *list); + +#define FREE_STRLIST(a) do { free_strlist((a)); (a) = NULL ; } while(0) + + +#endif /*LIBJNLIB_STRLIST_H*/ diff --git a/common/sysutils.h b/common/sysutils.h index fd4340f3d..6f34b9791 100644 --- a/common/sysutils.h +++ b/common/sysutils.h @@ -52,7 +52,7 @@ void gnupg_allow_set_foregound_window (pid_t pid); #ifdef HAVE_W32_SYSTEM -#include "../jnlib/w32help.h" +#include "../common/w32help.h" #endif /*HAVE_W32_SYSTEM*/ diff --git a/common/t-stringhelp.c b/common/t-stringhelp.c new file mode 100644 index 000000000..0c921b03d --- /dev/null +++ b/common/t-stringhelp.c @@ -0,0 +1,414 @@ +/* t-stringhelp.c - Regression tests for stringhelp.c + * Copyright (C) 2007 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#include +#include +#include +#include +#include +#ifdef HAVE_PWD_H +# include +#endif +#include +#include + +#include "stringhelp.h" + +#include "t-support.h" + + +static char *home_buffer; + + +const char * +gethome (void) +{ + if (!home_buffer) + { + char *home = getenv("HOME"); + + if(home) + home_buffer = xstrdup (home); +#if defined(HAVE_GETPWUID) && defined(HAVE_PWD_H) + else + { + struct passwd *pwd; + + pwd = getpwuid (getuid()); + if (pwd) + home_buffer = xstrdup (pwd->pw_dir); + } +#endif + } + return home_buffer; +} + + +static void +test_percent_escape (void) +{ + char *result; + static struct { + const char *extra; + const char *value; + const char *expected; + } tests[] = + { + { NULL, "", "" }, + { NULL, "%", "%25" }, + { NULL, "%%", "%25%25" }, + { NULL, " %", " %25" }, + { NULL, ":", "%3a" }, + { NULL, " :", " %3a" }, + { NULL, ": ", "%3a " }, + { NULL, " : ", " %3a " }, + { NULL, "::", "%3a%3a" }, + { NULL, ": :", "%3a %3a" }, + { NULL, "%:", "%25%3a" }, + { NULL, ":%", "%3a%25" }, + { "\\\n:", ":%", "%3a%25" }, + { "\\\n:", "\\:%", "%5c%3a%25" }, + { "\\\n:", "\n:%", "%0a%3a%25" }, + { "\\\n:", "\xff:%", "\xff%3a%25" }, + { "\\\n:", "\xfe:%", "\xfe%3a%25" }, + { "\\\n:", "\x01:%", "\x01%3a%25" }, + { "\x01", "\x01:%", "%01%3a%25" }, + { "\xfe", "\xfe:%", "%fe%3a%25" }, + { "\xfe", "\xff:%", "\xff%3a%25" }, + + { NULL, NULL, NULL } + }; + int testno; + + result = percent_escape (NULL, NULL); + if (result) + fail (0); + for (testno=0; tests[testno].value; testno++) + { + result = percent_escape (tests[testno].value, tests[testno].extra); + if (!result) + fail (testno); + if (strcmp (result, tests[testno].expected)) + fail (testno); + xfree (result); + } + +} + + +static void +test_compare_filenames (void) +{ + struct { + const char *a; + const char *b; + int result; + } tests[] = { + { "", "", 0 }, + { "", "a", -1 }, + { "a", "", 1 }, + { "a", "a", 0 }, + { "a", "aa", -1 }, + { "aa", "a", 1 }, + { "a", "b", -1 }, + +#ifdef HAVE_W32_SYSTEM + { "a", "A", 0 }, + { "A", "a", 0 }, + { "foo/bar", "foo\\bar", 0 }, + { "foo\\bar", "foo/bar", 0 }, + { "foo\\", "foo/", 0 }, + { "foo/", "foo\\", 0 }, +#endif /*HAVE_W32_SYSTEM*/ + { NULL, NULL, 0} + }; + int testno, result; + + for (testno=0; tests[testno].a; testno++) + { + result = compare_filenames (tests[testno].a, tests[testno].b); + result = result < 0? -1 : result > 0? 1 : 0; + if (result != tests[testno].result) + fail (testno); + } +} + + +static void +test_strconcat (void) +{ + char *out; + + out = strconcat ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", NULL); + if (!out) + fail (0); + else + xfree (out); + out = strconcat ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", "8", NULL); + if (out) + fail (0); + else if (errno != EINVAL) + fail (0); + + out = strconcat ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL); + if (out) + fail (0); + else if (errno != EINVAL) + fail (0); + +#if __GNUC__ < 4 /* gcc 4.0 has a sentinel attribute. */ + out = strconcat (NULL); + if (!out || *out) + fail (1); +#endif + out = strconcat (NULL, NULL); + if (!out || *out) + fail (1); + out = strconcat ("", NULL); + if (!out || *out) + fail (1); + xfree (out); + + out = strconcat ("", "", NULL); + if (!out || *out) + fail (2); + xfree (out); + + out = strconcat ("a", "b", NULL); + if (!out || strcmp (out, "ab")) + fail (3); + xfree (out); + out = strconcat ("a", "b", "c", NULL); + if (!out || strcmp (out, "abc")) + fail (3); + xfree (out); + + out = strconcat ("a", "b", "cc", NULL); + if (!out || strcmp (out, "abcc")) + fail (4); + xfree (out); + out = strconcat ("a1", "b1", "c1", NULL); + if (!out || strcmp (out, "a1b1c1")) + fail (4); + xfree (out); + + out = strconcat ("", " long b ", "", "--even-longer--", NULL); + if (!out || strcmp (out, " long b --even-longer--")) + fail (5); + xfree (out); + + out = strconcat ("", " long b ", "", "--even-longer--", NULL); + if (!out || strcmp (out, " long b --even-longer--")) + fail (5); + xfree (out); +} + +static void +test_xstrconcat (void) +{ + char *out; + + out = xstrconcat ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", NULL); + if (!out) + fail (0); + +#if __GNUC__ < 4 /* gcc 4.0 has a sentinel attribute. */ + out = xstrconcat (NULL); + if (!out) + fail (1); +#endif + out = xstrconcat (NULL, NULL); + if (!out) + fail (1); + out = xstrconcat ("", NULL); + if (!out || *out) + fail (1); + xfree (out); + + out = xstrconcat ("", "", NULL); + if (!out || *out) + fail (2); + xfree (out); + + out = xstrconcat ("a", "b", NULL); + if (!out || strcmp (out, "ab")) + fail (3); + xfree (out); + out = xstrconcat ("a", "b", "c", NULL); + if (!out || strcmp (out, "abc")) + fail (3); + xfree (out); + + out = xstrconcat ("a", "b", "cc", NULL); + if (!out || strcmp (out, "abcc")) + fail (4); + xfree (out); + out = xstrconcat ("a1", "b1", "c1", NULL); + if (!out || strcmp (out, "a1b1c1")) + fail (4); + xfree (out); + + out = xstrconcat ("", " long b ", "", "--even-longer--", NULL); + if (!out || strcmp (out, " long b --even-longer--")) + fail (5); + xfree (out); + + out = xstrconcat ("", " long b ", "", "--even-longer--", NULL); + if (!out || strcmp (out, " long b --even-longer--")) + fail (5); + xfree (out); +} + + +static void +test_make_filename_try (void) +{ + char *out; + const char *home = gethome (); + size_t homelen = home? strlen (home):0; + + out = make_filename_try ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", NULL); + if (out) + fail (0); + else if (errno != EINVAL) + fail (0); + xfree (out); + out = make_filename_try ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", NULL); + if (out) + fail (0); + else if (errno != EINVAL) + fail (0); + xfree (out); + + out = make_filename_try ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", NULL); + if (!out || strcmp (out, + "1/2/3/4/5/6/7/8/9/10/" + "1/2/3/4/5/6/7/8/9/10/" + "1/2/3/4/5/6/7/8/9/10/" + "1/2")) + fail (0); + xfree (out); + + out = make_filename_try ("foo", "~/bar", "baz/cde", NULL); + if (!out || strcmp (out, "foo/~/bar/baz/cde")) + fail (1); + xfree (out); + + out = make_filename_try ("foo", "~/bar", "baz/cde/", NULL); + if (!out || strcmp (out, "foo/~/bar/baz/cde/")) + fail (1); + xfree (out); + + out = make_filename_try ("/foo", "~/bar", "baz/cde/", NULL); + if (!out || strcmp (out, "/foo/~/bar/baz/cde/")) + fail (1); + xfree (out); + + out = make_filename_try ("//foo", "~/bar", "baz/cde/", NULL); + if (!out || strcmp (out, "//foo/~/bar/baz/cde/")) + fail (1); + xfree (out); + + out = make_filename_try ("", "~/bar", "baz/cde", NULL); + if (!out || strcmp (out, "/~/bar/baz/cde")) + fail (1); + xfree (out); + + + out = make_filename_try ("~/foo", "bar", NULL); + if (!out) + fail (2); + if (home) + { + if (strlen (out) < homelen + 7) + fail (2); + if (strncmp (out, home, homelen)) + fail (2); + if (strcmp (out+homelen, "/foo/bar")) + fail (2); + } + else + { + if (strcmp (out, "~/foo/bar")) + fail (2); + } + xfree (out); + + out = make_filename_try ("~", "bar", NULL); + if (!out) + fail (2); + if (home) + { + if (strlen (out) < homelen + 3) + fail (2); + if (strncmp (out, home, homelen)) + fail (2); + if (strcmp (out+homelen, "/bar")) + fail (2); + } + else + { + if (strcmp (out, "~/bar")) + fail (2); + } + xfree (out); +} + + +int +main (int argc, char **argv) +{ + (void)argc; + (void)argv; + + test_percent_escape (); + test_compare_filenames (); + test_strconcat (); + test_xstrconcat (); + test_make_filename_try (); + + xfree (home_buffer); + return 0; +} + diff --git a/common/t-support.c b/common/t-support.c new file mode 100644 index 000000000..bf05c4c06 --- /dev/null +++ b/common/t-support.c @@ -0,0 +1,147 @@ +/* t-support.c - helper functions for the regression tests. + * Copyright (C) 2007 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#include +#include +#include +#include +#include +#include + +#include "t-support.h" + + +/* Replacements for the malloc functions as used here. */ + +static void +out_of_memory (void) +{ + fprintf (stderr,"error: out of core in regression tests: %s\n", + strerror (errno)); + exit (2); +} + + +void * +gcry_malloc (size_t n) +{ + return malloc (n); +} + +void * +gcry_xmalloc (size_t n) +{ + void *p = malloc (n); + if (!p) + out_of_memory (); + return p; +} + +char * +gcry_strdup (const char *string) +{ + char *p = malloc (strlen (string)+1); + if (p) + strcpy (p, string); + return p; +} + + +void * +gcry_realloc (void *a, size_t n) +{ + return realloc (a, n); +} + +void * +gcry_xrealloc (void *a, size_t n) +{ + void *p = realloc (a, n); + if (!p) + out_of_memory (); + return p; +} + + + +void * +gcry_calloc (size_t n, size_t m) +{ + return calloc (n, m); +} + +void * +gcry_xcalloc (size_t n, size_t m) +{ + void *p = calloc (n, m); + if (!p) + out_of_memory (); + return p; +} + + +char * +gcry_xstrdup (const char *string) +{ + void *p = malloc (strlen (string)+1); + if (!p) + out_of_memory (); + strcpy (p, string); + return p; +} + +void +gcry_free (void *a) +{ + if (a) + free (a); +} + + + +/* Stubs for gpg-error functions required because some compilers do + not eliminate the supposed-to-be-unused-inline-functions and thus + require functions called from these inline fucntions. Although we + do not use gpg-error, gpg-error.h may get included via gcrypt.h if + it happens to be used used in libjnlib-config.h. */ +#ifndef GPG_ERROR_H /* Don't do this if gpg-error.h has been included. */ +int +gpg_err_code_from_errno (int err) +{ + (void)err; + assert (!"stub function"); + return -1; +} +#endif /*GPG_ERROR_H*/ + + +/* Retrieve the error code directly from the ERRNO variable. This + returns GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped + (report this) and GPG_ERR_MISSING_ERRNO if ERRNO has the value 0. */ +#ifndef GPG_ERROR_H /* Don't do this if gpg-error.h has been included. */ +int +gpg_err_code_from_syserror (void) +{ + assert (!"stub function"); + return -1; +} +#endif /*GPG_ERROR_H*/ + + + diff --git a/common/t-support.h b/common/t-support.h new file mode 100644 index 000000000..2dfbc0990 --- /dev/null +++ b/common/t-support.h @@ -0,0 +1,60 @@ +/* t-support.h - Helper for the regression tests + * Copyright (C) 2007 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#ifndef LIBJNLIB_T_SUPPORT_H +#define LIBJNLIB_T_SUPPORT_H 1 + +#ifdef GCRYPT_VERSION +#error The regression tests should not include with gcrypt.h +#endif + +#ifdef HAVE_W32CE_SYSTEM +#include /* Defines strerror. */ +#endif + + +#ifndef HAVE_GETENV +# define getenv(a) (NULL) +#endif + + +/* Replacement prototypes. */ +void *gcry_xmalloc (size_t n); +void *gcry_xcalloc (size_t n, size_t m); +void *gcry_xrealloc (void *a, size_t n); +char *gcry_xstrdup (const char * a); +void gcry_free (void *a); + +/* Map the used xmalloc functions to those implemented by t-support.c */ +#define xmalloc(a) gcry_xmalloc ( (a) ) +#define xcalloc(a,b) gcry_xcalloc ( (a), (b) ) +#define xrealloc(a,n) gcry_xrealloc ( (a), (n) ) +#define xstrdup(a) gcry_xstrdup ( (a) ) +#define xfree(a) gcry_free ( (a) ) + + +/* Macros to print the result of a test. */ +#define pass() do { ; } while(0) +#define fail(a) do { fprintf (stderr, "%s:%d: test %d failed\n",\ + __FILE__,__LINE__, (a)); \ + exit (1); \ + } while(0) + + +#endif /*LIBJNLIB_T_SUPPORT_H*/ diff --git a/common/t-timestuff.c b/common/t-timestuff.c new file mode 100644 index 000000000..46816765d --- /dev/null +++ b/common/t-timestuff.c @@ -0,0 +1,145 @@ +/* t-timestuff.c - Regression tests for time functions + * Copyright (C) 2007 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#include +#include +#include +#include +#include +#include + +#include "mischelp.h" + +#include "t-support.h" + + +static int +cmp_time_s (struct tm *a, struct tm *b) +{ + if (a->tm_year != b->tm_year + || a->tm_mon != b->tm_mon + || a->tm_mday != b->tm_mday + || a->tm_hour != b->tm_hour + || a->tm_min != b->tm_min + || a->tm_sec != b->tm_sec + || a->tm_wday != b->tm_wday + || a->tm_yday != b->tm_yday + || !a->tm_isdst != !b->tm_isdst) + return -1; + return 0; +} + + + +static void +test_timegm (void) +{ + static struct { + int year, mon, mday, hour, min, sec; + } tvalues[] = { + { -1 }, + { -2, 1 }, + { -2, 2 }, + { -2, 86399 }, + { -2, 86400 }, + { -2, 0x7ffffffe }, + { -2, 0x7fffffff }, + /* Note: Because we use mktime below we can only start with the + day after Epoch. */ + { 1970, 1, 2, 0, 0 , 1}, + { 1970, 1, 2, 0, 0 , 2}, + { 1970, 1, 2, 12, 0 , 0}, + { 1970, 1, 2, 23, 59 , 59}, + { 1999, 12, 31, 23, 59 , 59}, + { 2000, 1, 1, 0, 0, 0}, + { 2000, 1, 1, 0, 0, 1}, + { 2010, 12, 31, 23, 59 , 59}, + { 2010, 1, 1, 0, 0, 0}, + { 2010, 1, 1, 0, 0, 1}, + /* The date below is about the last time mktime works in CET on + Windows XP; this is a somewhat strange because 32 bit Unices + will happily work along for another month until they reach the + end of all ticks on 20380119T031408 (unless Uli takes + compassion on us and changes time_t to a u64). */ + { 2037, 12, 18, 23, 59, 59} + + }; + int tidx; + time_t now, atime, counter; + struct tm tbuf, tbuf2, *tp; + + counter = 0; + for (tidx=0; tidx < DIM (tvalues); tidx++) + { + if (tvalues[tidx].year == -1) + { + now = time (NULL); + } + else if (tvalues[tidx].year == -2) + { + now = tvalues[tidx].mon; + } + else + { + memset (&tbuf, 0, sizeof tbuf); + tbuf.tm_year = tvalues[tidx].year - 1900; + tbuf.tm_mon = tvalues[tidx].mon; + tbuf.tm_mday = tvalues[tidx].mday; + tbuf.tm_hour = tvalues[tidx].hour; + tbuf.tm_min = tvalues[tidx].min; + tbuf.tm_sec = tvalues[tidx].sec; + now = mktime (&tbuf); + } + if (now == (time_t)(-1)) + fail (tidx); + + tp = gmtime (&now); + if (!tp) + fail (tidx); + tbuf = *tp; + tbuf2 = tbuf; + atime = timegm (&tbuf); + if (atime == (time_t)(-1)) + fail (tidx); + if (atime != now) + fail (tidx); + + tp = gmtime (&atime); + if (!tp) + fail (tidx); + if (cmp_time_s (tp, &tbuf)) + fail (tidx); + if (cmp_time_s (tp, &tbuf2)) + fail (tidx); + } +} + + + +int +main (int argc, char **argv) +{ + (void)argc; + (void)argv; + + test_timegm (); + + return 0; +} + diff --git a/common/t-w32-reg.c b/common/t-w32-reg.c new file mode 100644 index 000000000..f4848cbaa --- /dev/null +++ b/common/t-w32-reg.c @@ -0,0 +1,70 @@ +/* t-w32-reg.c - Regression tests for W32 registry functions + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#include +#include +#include +#include +#include +#include + +#include "mischelp.h" + +#include "t-support.h" +#include "w32help.h" + + +static void +test_read_registry (void) +{ + char *string; + +#ifdef HAVE_W32CE_SYSTEM + string = read_w32_registry_string ("HKEY_CLASSES_ROOT", + "BOOTSTRAP\\CLSID", NULL); + if (!string) + fail (0); + fprintf (stderr, "Bootstrap clsid: %s\n", string); + xfree (string); +#endif + + string = read_w32_registry_string + ("HKEY_CURRENT_USER", + "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", + "User Agent"); + if (!string) + fail (0); + fprintf (stderr, "User agent: %s\n", string); + xfree (string); +} + + + + +int +main (int argc, char **argv) +{ + (void)argc; + (void)argv; + + test_read_registry (); + + return 0; +} + diff --git a/common/ttyio.c b/common/ttyio.c index fc274070c..ec26b06e8 100644 --- a/common/ttyio.c +++ b/common/ttyio.c @@ -48,7 +48,6 @@ #include "util.h" #include "ttyio.h" -#include "estream-printf.h" #include "common-defs.h" #define CONTROL_D ('D' - 'A' + 1) diff --git a/common/types.h b/common/types.h new file mode 100644 index 000000000..62fa0470d --- /dev/null +++ b/common/types.h @@ -0,0 +1,114 @@ +/* types.h - define some extra types + * Copyright (C) 1999, 2000, 2001, 2006 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#ifndef LIBJNLIB_TYPES_H +#define LIBJNLIB_TYPES_H + +/* The AC_CHECK_SIZEOF() in configure fails for some machines. + * we provide some fallback values here */ +#if !SIZEOF_UNSIGNED_SHORT +# undef SIZEOF_UNSIGNED_SHORT +# define SIZEOF_UNSIGNED_SHORT 2 +#endif +#if !SIZEOF_UNSIGNED_INT +# undef SIZEOF_UNSIGNED_INT +# define SIZEOF_UNSIGNED_INT 4 +#endif +#if !SIZEOF_UNSIGNED_LONG +# undef SIZEOF_UNSIGNED_LONG +# define SIZEOF_UNSIGNED_LONG 4 +#endif + + +#include + + +#ifndef HAVE_BYTE_TYPEDEF +# undef byte /* There might be a macro with this name. */ +/* Windows typedefs byte in the rpc headers. Avoid warning about + double definition. */ +#if !(defined(_WIN32) && defined(cbNDRContext)) + typedef unsigned char byte; +#endif +# define HAVE_BYTE_TYPEDEF +#endif + +#ifndef HAVE_USHORT_TYPEDEF +# undef ushort /* There might be a macro with this name. */ + typedef unsigned short ushort; +# define HAVE_USHORT_TYPEDEF +#endif + +#ifndef HAVE_ULONG_TYPEDEF +# undef ulong /* There might be a macro with this name. */ + typedef unsigned long ulong; +# define HAVE_ULONG_TYPEDEF +#endif + +#ifndef HAVE_U16_TYPEDEF +# undef u16 /* There might be a macro with this name. */ +# if SIZEOF_UNSIGNED_INT == 2 + typedef unsigned int u16; +# elif SIZEOF_UNSIGNED_SHORT == 2 + typedef unsigned short u16; +# else +# error no typedef for u16 +# endif +# define HAVE_U16_TYPEDEF +#endif + +#ifndef HAVE_U32_TYPEDEF +# undef u32 /* There might be a macro with this name. */ +# if SIZEOF_UNSIGNED_INT == 4 + typedef unsigned int u32; +# elif SIZEOF_UNSIGNED_LONG == 4 + typedef unsigned long u32; +# else +# error no typedef for u32 +# endif +# define HAVE_U32_TYPEDEF +#endif + +#ifndef HAVE_U64_TYPEDEF +# undef u64 /* There might be a macro with this name. */ +# if SIZEOF_UNSIGNED_INT == 8 + typedef unsigned int u64; +# define HAVE_U64_TYPEDEF +# elif SIZEOF_UNSIGNED_LONG == 8 + typedef unsigned long u64; +# define HAVE_U64_TYPEDEF +# elif __GNUC__ >= 2 || defined(__SUNPRO_C) + typedef unsigned long long u64; +# define HAVE_U64_TYPEDEF +# endif +#endif + + +/* Some GCC attributes. Note that we use also define some in + mischelp.h, but this header and types.h are not always included. + Should eventually be put into one file (e.g. nlib-common.h). */ +#if __GNUC__ >= 4 +# define GNUPG_GCC_A_SENTINEL(a) __attribute__ ((sentinel(a))) +#else +# define GNUPG_GCC_A_SENTINEL(a) +#endif + + + +#endif /*LIBJNLIB_TYPES_H*/ diff --git a/common/utf8conv.c b/common/utf8conv.c new file mode 100644 index 000000000..6cbe4e92c --- /dev/null +++ b/common/utf8conv.c @@ -0,0 +1,813 @@ +/* utf8conf.c - UTF8 character set conversion + * Copyright (C) 1994, 1998, 1999, 2000, 2001, 2003, 2006, + * 2008, 2010 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#include +#include +#include +#include +#include +#ifdef HAVE_LANGINFO_CODESET +#include +#endif +#include +#ifndef HAVE_W32_SYSTEM +# include +#endif + +#include "libjnlib-config.h" +#include "stringhelp.h" +#include "dynload.h" +#include "utf8conv.h" + +#ifndef MB_LEN_MAX +#define MB_LEN_MAX 16 +#endif + +static const char *active_charset_name = "iso-8859-1"; +static int no_translation; /* Set to true if we let simply pass through. */ +static int use_iconv; /* iconv comversion fucntions required. */ + + +/* Under W32 we dlopen the iconv dll and don't require any iconv + related headers at all. However we need to define some stuff. */ +#ifdef HAVE_W32_SYSTEM +typedef void *iconv_t; +#ifndef ICONV_CONST +#define ICONV_CONST +#endif +static iconv_t (* __stdcall iconv_open) (const char *tocode, + const char *fromcode); +static size_t (* __stdcall iconv) (iconv_t cd, + char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft); +static int (* __stdcall iconv_close) (iconv_t cd); + +static int +load_libiconv (void) +{ + static int done; + + if (!done) + { + void *handle; + + done = 1; /* Do it right now because we might get called recursivly + through gettext. */ + + handle = dlopen ("iconv.dll", RTLD_LAZY); + if (handle) + { + iconv_open = dlsym (handle, "libiconv_open"); + if (iconv_open) + iconv = dlsym (handle, "libiconv"); + if (iconv) + iconv_close = dlsym (handle, "libiconv_close"); + } + if (!handle || !iconv_close) + { + log_info (_("error loading `%s': %s\n"), + "iconv.dll", dlerror ()); + log_info (_("please see %s for more information\n"), + "http://www.gnupg.org/download/iconv.html"); + iconv_open = NULL; + iconv = NULL; + iconv_close = NULL; + if (handle) + dlclose (handle); + } + } + return iconv_open? 0: -1; +} +#endif /*HAVE_W32_SYSTEM*/ + + +/* Error handler for iconv failures. This is needed to not clutter the + output with repeated diagnostics about a missing conversion. */ +static void +handle_iconv_error (const char *to, const char *from, int use_fallback) +{ + if (errno == EINVAL) + { + static int shown1, shown2; + int x; + + if (to && !strcmp (to, "utf-8")) + { + x = shown1; + shown1 = 1; + } + else + { + x = shown2; + shown2 = 1; + } + + if (!x) + log_info (_("conversion from `%s' to `%s' not available\n"), + from, to); + } + else + { + static int shown; + + if (!shown) + log_info (_("iconv_open failed: %s\n"), strerror (errno)); + shown = 1; + } + + if (use_fallback) + { + /* To avoid further error messages we fallback to Latin-1 for the + native encoding. This is justified as one can expect that on a + utf-8 enabled system nl_langinfo() will work and thus we won't + never get to here. Thus Latin-1 seems to be a reasonable + default. */ + active_charset_name = "iso-8859-1"; + no_translation = 0; + use_iconv = 0; + } +} + + + +int +set_native_charset (const char *newset) +{ + const char *full_newset; + + if (!newset) + { +#ifdef HAVE_W32_SYSTEM + static char codepage[30]; + unsigned int cpno; + const char *aliases; + + /* We are a console program thus we need to use the + GetConsoleOutputCP function and not the the GetACP which + would give the codepage for a GUI program. Note this is not + a bulletproof detection because GetConsoleCP might return a + different one for console input. Not sure how to cope with + that. If the console Code page is not known we fall back to + the system code page. */ +#ifndef HAVE_W32CE_SYSTEM + cpno = GetConsoleOutputCP (); + if (!cpno) +#endif + cpno = GetACP (); + sprintf (codepage, "CP%u", cpno ); + /* Resolve alias. We use a long string string and not the usual + array to optimize if the code is taken to a DSO. Taken from + libiconv 1.9.2. */ + newset = codepage; + for (aliases = ("CP936" "\0" "GBK" "\0" + "CP1361" "\0" "JOHAB" "\0" + "CP20127" "\0" "ASCII" "\0" + "CP20866" "\0" "KOI8-R" "\0" + "CP21866" "\0" "KOI8-RU" "\0" + "CP28591" "\0" "ISO-8859-1" "\0" + "CP28592" "\0" "ISO-8859-2" "\0" + "CP28593" "\0" "ISO-8859-3" "\0" + "CP28594" "\0" "ISO-8859-4" "\0" + "CP28595" "\0" "ISO-8859-5" "\0" + "CP28596" "\0" "ISO-8859-6" "\0" + "CP28597" "\0" "ISO-8859-7" "\0" + "CP28598" "\0" "ISO-8859-8" "\0" + "CP28599" "\0" "ISO-8859-9" "\0" + "CP28605" "\0" "ISO-8859-15" "\0" + "CP65001" "\0" "UTF-8" "\0"); + *aliases; + aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1) + { + if (!strcmp (codepage, aliases) ||(*aliases == '*' && !aliases[1])) + { + newset = aliases + strlen (aliases) + 1; + break; + } + } + +#else /*!HAVE_W32_SYSTEM*/ + +#ifdef HAVE_LANGINFO_CODESET + newset = nl_langinfo (CODESET); +#else /*!HAVE_LANGINFO_CODESET*/ + /* Try to get the used charset from environment variables. */ + static char codepage[30]; + const char *lc, *dot, *mod; + + strcpy (codepage, "iso-8859-1"); + lc = getenv ("LC_ALL"); + if (!lc || !*lc) + { + lc = getenv ("LC_CTYPE"); + if (!lc || !*lc) + lc = getenv ("LANG"); + } + if (lc && *lc) + { + dot = strchr (lc, '.'); + if (dot) + { + mod = strchr (++dot, '@'); + if (!mod) + mod = dot + strlen (dot); + if (mod - dot < sizeof codepage && dot != mod) + { + memcpy (codepage, dot, mod - dot); + codepage [mod - dot] = 0; + } + } + } + newset = codepage; +#endif /*!HAVE_LANGINFO_CODESET*/ +#endif /*!HAVE_W32_SYSTEM*/ + } + + full_newset = newset; + if (strlen (newset) > 3 && !ascii_memcasecmp (newset, "iso", 3)) + { + newset += 3; + if (*newset == '-' || *newset == '_') + newset++; + } + + /* Note that we silently assume that plain ASCII is actually meant + as Latin-1. This makes sense because many Unix system don't have + their locale set up properly and thus would get annoying error + messages and we have to handle all the "bug" reports. Latin-1 has + always been the character set used for 8 bit characters on Unix + systems. */ + if ( !*newset + || !ascii_strcasecmp (newset, "8859-1" ) + || !ascii_strcasecmp (newset, "646" ) + || !ascii_strcasecmp (newset, "ASCII" ) + || !ascii_strcasecmp (newset, "ANSI_X3.4-1968" ) + ) + { + active_charset_name = "iso-8859-1"; + no_translation = 0; + use_iconv = 0; + } + else if ( !ascii_strcasecmp (newset, "utf8" ) + || !ascii_strcasecmp(newset, "utf-8") ) + { + active_charset_name = "utf-8"; + no_translation = 1; + use_iconv = 0; + } + else + { + iconv_t cd; + +#ifdef HAVE_W32_SYSTEM + if (load_libiconv ()) + return -1; +#endif /*HAVE_W32_SYSTEM*/ + + cd = iconv_open (full_newset, "utf-8"); + if (cd == (iconv_t)-1) + { + handle_iconv_error (full_newset, "utf-8", 0); + return -1; + } + iconv_close (cd); + cd = iconv_open ("utf-8", full_newset); + if (cd == (iconv_t)-1) + { + handle_iconv_error ("utf-8", full_newset, 0); + return -1; + } + iconv_close (cd); + active_charset_name = full_newset; + no_translation = 0; + use_iconv = 1; + } + return 0; +} + +const char * +get_native_charset () +{ + return active_charset_name; +} + +/* Return true if the native charset is utf-8. */ +int +is_native_utf8 (void) +{ + return no_translation; +} + + +/* Convert string, which is in native encoding to UTF8 and return a + new allocated UTF-8 string. This function terminates the process + on memory shortage. */ +char * +native_to_utf8 (const char *orig_string) +{ + const unsigned char *string = (const unsigned char *)orig_string; + const unsigned char *s; + char *buffer; + unsigned char *p; + size_t length = 0; + + if (no_translation) + { + /* Already utf-8 encoded. */ + buffer = jnlib_xstrdup (orig_string); + } + else if (!use_iconv) + { + /* For Latin-1 we can avoid the iconv overhead. */ + for (s = string; *s; s++) + { + length++; + if (*s & 0x80) + length++; + } + buffer = jnlib_xmalloc (length + 1); + for (p = (unsigned char *)buffer, s = string; *s; s++) + { + if ( (*s & 0x80 )) + { + *p++ = 0xc0 | ((*s >> 6) & 3); + *p++ = 0x80 | (*s & 0x3f); + } + else + *p++ = *s; + } + *p = 0; + } + else + { + /* Need to use iconv. */ + iconv_t cd; + const char *inptr; + char *outptr; + size_t inbytes, outbytes; + + cd = iconv_open ("utf-8", active_charset_name); + if (cd == (iconv_t)-1) + { + handle_iconv_error ("utf-8", active_charset_name, 1); + return native_to_utf8 (string); + } + + for (s=string; *s; s++ ) + { + length++; + if ((*s & 0x80)) + length += 5; /* We may need up to 6 bytes for the utf8 output. */ + } + buffer = jnlib_xmalloc (length + 1); + + inptr = string; + inbytes = strlen (string); + outptr = buffer; + outbytes = length; + if ( iconv (cd, (ICONV_CONST char **)&inptr, &inbytes, + &outptr, &outbytes) == (size_t)-1) + { + static int shown; + + if (!shown) + log_info (_("conversion from `%s' to `%s' failed: %s\n"), + active_charset_name, "utf-8", strerror (errno)); + shown = 1; + /* We don't do any conversion at all but use the strings as is. */ + strcpy (buffer, string); + } + else /* Success. */ + { + *outptr = 0; + /* We could realloc the buffer now but I doubt that it makes + much sense given that it will get freed anyway soon + after. */ + } + iconv_close (cd); + } + return buffer; +} + + + +static char * +do_utf8_to_native (const char *string, size_t length, int delim, + int with_iconv) +{ + int nleft; + int i; + unsigned char encbuf[8]; + int encidx; + const unsigned char *s; + size_t n; + char *buffer = NULL; + char *p = NULL; + unsigned long val = 0; + size_t slen; + int resync = 0; + + /* First pass (p==NULL): count the extended utf-8 characters. */ + /* Second pass (p!=NULL): create string. */ + for (;;) + { + for (slen = length, nleft = encidx = 0, n = 0, + s = (const unsigned char *)string; + slen; + s++, slen--) + { + if (resync) + { + if (!(*s < 128 || (*s >= 0xc0 && *s <= 0xfd))) + { + /* Still invalid. */ + if (p) + { + sprintf (p, "\\x%02x", *s); + p += 4; + } + n += 4; + continue; + } + resync = 0; + } + if (!nleft) + { + if (!(*s & 0x80)) + { + /* Plain ascii. */ + if ( delim != -1 + && (*s < 0x20 || *s == 0x7f || *s == delim + || (delim && *s == '\\'))) + { + n++; + if (p) + *p++ = '\\'; + switch (*s) + { + case '\n': n++; if ( p ) *p++ = 'n'; break; + case '\r': n++; if ( p ) *p++ = 'r'; break; + case '\f': n++; if ( p ) *p++ = 'f'; break; + case '\v': n++; if ( p ) *p++ = 'v'; break; + case '\b': n++; if ( p ) *p++ = 'b'; break; + case 0: n++; if ( p ) *p++ = '0'; break; + default: + n += 3; + if (p) + { + sprintf (p, "x%02x", *s); + p += 3; + } + break; + } + } + else + { + if (p) + *p++ = *s; + n++; + } + } + else if ((*s & 0xe0) == 0xc0) /* 110x xxxx */ + { + val = *s & 0x1f; + nleft = 1; + encidx = 0; + encbuf[encidx++] = *s; + } + else if ((*s & 0xf0) == 0xe0) /* 1110 xxxx */ + { + val = *s & 0x0f; + nleft = 2; + encidx = 0; + encbuf[encidx++] = *s; + } + else if ((*s & 0xf8) == 0xf0) /* 1111 0xxx */ + { + val = *s & 0x07; + nleft = 3; + encidx = 0; + encbuf[encidx++] = *s; + } + else if ((*s & 0xfc) == 0xf8) /* 1111 10xx */ + { + val = *s & 0x03; + nleft = 4; + encidx = 0; + encbuf[encidx++] = *s; + } + else if ((*s & 0xfe) == 0xfc) /* 1111 110x */ + { + val = *s & 0x01; + nleft = 5; + encidx = 0; + encbuf[encidx++] = *s; + } + else /* Invalid encoding: print as \xNN. */ + { + if (p) + { + sprintf (p, "\\x%02x", *s); + p += 4; + } + n += 4; + resync = 1; + } + } + else if (*s < 0x80 || *s >= 0xc0) /* Invalid utf-8 */ + { + if (p) + { + for (i = 0; i < encidx; i++) + { + sprintf (p, "\\x%02x", encbuf[i]); + p += 4; + } + sprintf (p, "\\x%02x", *s); + p += 4; + } + n += 4 + 4 * encidx; + nleft = 0; + encidx = 0; + resync = 1; + } + else + { + encbuf[encidx++] = *s; + val <<= 6; + val |= *s & 0x3f; + if (!--nleft) /* Ready. */ + { + if (no_translation) + { + if (p) + { + for (i = 0; i < encidx; i++) + *p++ = encbuf[i]; + } + n += encidx; + encidx = 0; + } + else if (with_iconv) + { + /* Our strategy for using iconv is a bit strange + but it better keeps compatibility with + previous versions in regard to how invalid + encodings are displayed. What we do is to + keep the utf-8 as is and have the real + translation step then at the end. Yes, I + know that this is ugly. However we are short + of the 1.4 release and for this branch we + should not mess too much around with iconv + things. One reason for this is that we don't + know enough about non-GNU iconv + implementation and want to minimize the risk + of breaking the code on too many platforms. */ + if ( p ) + { + for (i=0; i < encidx; i++ ) + *p++ = encbuf[i]; + } + n += encidx; + encidx = 0; + } + else /* Latin-1 case. */ + { + if (val >= 0x80 && val < 256) + { + /* We can simply print this character */ + n++; + if (p) + *p++ = val; + } + else + { + /* We do not have a translation: print utf8. */ + if (p) + { + for (i = 0; i < encidx; i++) + { + sprintf (p, "\\x%02x", encbuf[i]); + p += 4; + } + } + n += encidx * 4; + encidx = 0; + } + } + } + + } + } + if (!buffer) + { + /* Allocate the buffer after the first pass. */ + buffer = p = jnlib_xmalloc (n + 1); + } + else if (with_iconv) + { + /* Note: See above for comments. */ + iconv_t cd; + const char *inptr; + char *outbuf, *outptr; + size_t inbytes, outbytes; + + *p = 0; /* Terminate the buffer. */ + + cd = iconv_open (active_charset_name, "utf-8"); + if (cd == (iconv_t)-1) + { + handle_iconv_error (active_charset_name, "utf-8", 1); + jnlib_free (buffer); + return utf8_to_native (string, length, delim); + } + + /* Allocate a new buffer large enough to hold all possible + encodings. */ + n = p - buffer + 1; + inbytes = n - 1;; + inptr = buffer; + outbytes = n * MB_LEN_MAX; + if (outbytes / MB_LEN_MAX != n) + BUG (); /* Actually an overflow. */ + outbuf = outptr = jnlib_xmalloc (outbytes); + if ( iconv (cd, (ICONV_CONST char **)&inptr, &inbytes, + &outptr, &outbytes) == (size_t)-1) + { + static int shown; + + if (!shown) + log_info (_("conversion from `%s' to `%s' failed: %s\n"), + "utf-8", active_charset_name, strerror (errno)); + shown = 1; + /* Didn't worked out. Try again but without iconv. */ + jnlib_free (buffer); + buffer = NULL; + jnlib_free (outbuf); + outbuf = do_utf8_to_native (string, length, delim, 0); + } + else /* Success. */ + { + *outptr = 0; /* Make sure it is a string. */ + /* We could realloc the buffer now but I doubt that it + makes much sense given that it will get freed + anyway soon after. */ + jnlib_free (buffer); + } + iconv_close (cd); + return outbuf; + } + else /* Not using iconv. */ + { + *p = 0; /* Make sure it is a string. */ + return buffer; + } + } +} + +/* Convert string, which is in UTF-8 to native encoding. Replace + illegal encodings by some "\xnn" and quote all control + characters. A character with value DELIM will always be quoted, it + must be a vanilla ASCII character. A DELIM value of -1 is special: + it disables all quoting of control characters. This function + terminates the process on memory shortage. */ +char * +utf8_to_native (const char *string, size_t length, int delim) +{ + return do_utf8_to_native (string, length, delim, use_iconv); +} + + + + +/* Wrapper function for iconv_open, required for W32 as we dlopen that + library on that system. */ +jnlib_iconv_t +jnlib_iconv_open (const char *tocode, const char *fromcode) +{ +#ifdef HAVE_W32_SYSTEM + if (load_libiconv ()) + return (jnlib_iconv_t)(-1); +#endif /*HAVE_W32_SYSTEM*/ + + return (jnlib_iconv_t)iconv_open (tocode, fromcode); +} + + +/* Wrapper function for iconv, required for W32 as we dlopen that + library on that system. */ +size_t +jnlib_iconv (jnlib_iconv_t cd, + const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + +#ifdef HAVE_W32_SYSTEM + if (load_libiconv ()) + return 0; +#endif /*HAVE_W32_SYSTEM*/ + + return iconv ((iconv_t)cd, (char**)inbuf, inbytesleft, outbuf, outbytesleft); +} + +/* Wrapper function for iconv_close, required for W32 as we dlopen that + library on that system. */ +int +jnlib_iconv_close (jnlib_iconv_t cd) +{ +#ifdef HAVE_W32_SYSTEM + if (load_libiconv ()) + return 0; +#endif /*HAVE_W32_SYSTEM*/ + + return iconv_close ((iconv_t)cd); +} + + +#ifdef HAVE_W32_SYSTEM +/* Return a malloced string encoded in UTF-8 from the wide char input + string STRING. Caller must free this value. Returns NULL and sets + ERRNO on failure. Calling this function with STRING set to NULL is + not defined. */ +char * +wchar_to_utf8 (const wchar_t *string) +{ + int n; + char *result; + + n = WideCharToMultiByte (CP_UTF8, 0, string, -1, NULL, 0, NULL, NULL); + if (n < 0) + { + jnlib_set_errno (EINVAL); + return NULL; + } + + result = jnlib_malloc (n+1); + if (!result) + return NULL; + + n = WideCharToMultiByte (CP_UTF8, 0, string, -1, result, n, NULL, NULL); + if (n < 0) + { + jnlib_free (result); + jnlib_set_errno (EINVAL); + result = NULL; + } + return result; +} + + +/* Return a malloced wide char string from an UTF-8 encoded input + string STRING. Caller must free this value. Returns NULL and sets + ERRNO on failure. Calling this function with STRING set to NULL is + not defined. */ +wchar_t * +utf8_to_wchar (const char *string) +{ + int n; + size_t nbytes; + wchar_t *result; + + n = MultiByteToWideChar (CP_UTF8, 0, string, -1, NULL, 0); + if (n < 0) + { + jnlib_set_errno (EINVAL); + return NULL; + } + + nbytes = (size_t)(n+1) * sizeof(*result); + if (nbytes / sizeof(*result) != (n+1)) + { + jnlib_set_errno (ENOMEM); + return NULL; + } + result = malloc (nbytes); + if (!result) + return NULL; + + n = MultiByteToWideChar (CP_UTF8, 0, string, -1, result, n); + if (n < 0) + { + free (result); + jnlib_set_errno (EINVAL); + result = NULL; + } + return result; +} +#endif /*HAVE_W32_SYSTEM*/ diff --git a/common/utf8conv.h b/common/utf8conv.h new file mode 100644 index 000000000..28dd450dd --- /dev/null +++ b/common/utf8conv.h @@ -0,0 +1,45 @@ +/* utf8conf.h + * Copyright (C) 2003, 2006 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#ifndef LIBJNLIB_UTF8CONF_H +#define LIBJNLIB_UTF8CONF_H + +int set_native_charset (const char *newset); +const char *get_native_charset (void); +int is_native_utf8 (void); + +char *native_to_utf8 (const char *string); +char *utf8_to_native (const char *string, size_t length, int delim); + + +/* Silly wrappers, required for W32 portability. */ +typedef void *jnlib_iconv_t; + +jnlib_iconv_t jnlib_iconv_open (const char *tocode, const char *fromcode); +size_t jnlib_iconv (jnlib_iconv_t cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft); +int jnlib_iconv_close (jnlib_iconv_t cd); + +#ifdef HAVE_W32_SYSTEM +char *wchar_to_utf8 (const wchar_t *string); +wchar_t *utf8_to_wchar (const char *string); +#endif /*HAVE_W32_SYSTEM*/ + + +#endif /*LIBJNLIB_UTF8CONF_H*/ diff --git a/common/util.h b/common/util.h index 56678620b..32d4085e7 100644 --- a/common/util.h +++ b/common/util.h @@ -33,29 +33,30 @@ /* Hash function used with libksba. */ #define HASH_FNC ((void (*)(void *, const void*,size_t))gcry_md_write) +/* Estream replaces most uses of stdio. */ +#include "../common/estream.h" +#include "../common/estream-printf.h" + /* Get all the stuff from jnlib. */ -#include "../jnlib/logging.h" -#include "../jnlib/argparse.h" -#include "../jnlib/stringhelp.h" -#include "../jnlib/mischelp.h" -#include "../jnlib/strlist.h" -#include "../jnlib/dotlock.h" -#include "../jnlib/utf8conv.h" -#include "../jnlib/dynload.h" +#include "../common/logging.h" +#include "../common/argparse.h" +#include "../common/stringhelp.h" +#include "../common/mischelp.h" +#include "../common/strlist.h" +#include "../common/dotlock.h" +#include "../common/utf8conv.h" +#include "../common/dynload.h" #include "init.h" /* Redefine asprintf by our estream version which uses our own memory allocator.. */ -#include "estream-printf.h" #define asprintf estream_asprintf #define vasprintf estream_vasprintf -/* Due to a bug in mingw32's snprintf related to the 'l' modifier we - better use our snprintf. */ -#ifdef HAVE_W32_SYSTEM +/* Due to a bug in mingw32's snprintf related to the 'l' modifier and + for increased portability we use our snprintf on all systems. */ #define snprintf estream_snprintf -#endif /* GCC attributes. */ diff --git a/common/w32-afunix.c b/common/w32-afunix.c new file mode 100644 index 000000000..579621491 --- /dev/null +++ b/common/w32-afunix.c @@ -0,0 +1,138 @@ +/* w32-afunix.c - AF_UNIX emulation for Windows (Client only). + * Copyright (C) 2004, 2006 g10 Code GmbH + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +/* Use of this code is preprecated - you better use the sockt wrappers + from libassuan. */ + +#ifdef _WIN32 +#include +#include +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include + +#include "w32-afunix.h" + + + +/* The buffer for NONCE needs to be at least 16 bytes. Returns 0 on + success. */ +static int +read_port_and_nonce (const char *fname, unsigned short *port, char *nonce) +{ + FILE *fp; + char buffer[50], *p; + size_t nread; + int aval; + + fp = fopen (fname, "rb"); + if (!fp) + return -1; + nread = fread (buffer, 1, sizeof buffer - 1, fp); + fclose (fp); + if (!nread) + { +#warning remove this file + jnlib_set_errno (EIO); + return -1; + } + buffer[nread] = 0; + aval = atoi (buffer); + if (aval < 1 || aval > 65535) + { + jnlib_set_errno (EINVAL); + return -1; + } + *port = (unsigned int)aval; + for (p=buffer; nread && *p != '\n'; p++, nread--) + ; + if (*p != '\n' || nread != 17) + { + jnlib_set_errno (EINVAL); + return -1; + } + p++; nread--; + memcpy (nonce, p, 16); + return 0; +} + + + +int +_w32_close (int fd) +{ + int rc = closesocket (fd); + if (rc && WSAGetLastError () == WSAENOTSOCK) + rc = close (fd); + return rc; +} + + +int +_w32_sock_new (int domain, int type, int proto) +{ + if (domain == AF_UNIX || domain == AF_LOCAL) + domain = AF_INET; + return socket (domain, type, proto); +} + + +int +_w32_sock_connect (int sockfd, struct sockaddr *addr, int addrlen) +{ + struct sockaddr_in myaddr; + struct sockaddr_un *unaddr; + unsigned short port; + char nonce[16]; + int ret; + + (void)addrlen; + + unaddr = (struct sockaddr_un *)addr; + if (read_port_and_nonce (unaddr->sun_path, &port, nonce)) + return -1; + + myaddr.sin_family = AF_INET; + myaddr.sin_port = htons (port); + myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); + + /* Set return values. */ + unaddr->sun_family = myaddr.sin_family; + unaddr->sun_port = myaddr.sin_port; + unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr; + + ret = connect (sockfd, (struct sockaddr *)&myaddr, sizeof myaddr); + if (!ret) + { + /* Send the nonce. */ + ret = send (sockfd, nonce, 16, 0); + if (ret >= 0 && ret != 16) + { + jnlib_set_errno (EIO); + ret = -1; + } + } + return ret; +} + + +#endif /*_WIN32*/ diff --git a/common/w32-afunix.h b/common/w32-afunix.h new file mode 100644 index 000000000..23681ddeb --- /dev/null +++ b/common/w32-afunix.h @@ -0,0 +1,52 @@ +/* w32-afunix.h - AF_UNIX emulation for Windows + * Copyright (C) 2004, 2006 g10 Code GmbH + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#ifdef _WIN32 +#ifndef W32AFUNIX_DEFS_H +#define W32AFUNIX_DEFS_H + +#include +#include +#include +#include + +/* We can easiliy replace this code by the socket wrappers from libassuan. */ +#warning Please do not use this module anymore + +#define DIRSEP_C '\\' + +#define AF_LOCAL AF_UNIX +/* We need to prefix the structure with a sockaddr_in header so we can + use it later for sendto and recvfrom. */ +struct sockaddr_un +{ + short sun_family; + unsigned short sun_port; + struct in_addr sun_addr; + char sun_path[108-2-4]; /* Path name. */ +}; + + +int _w32_close (int fd); +int _w32_sock_new (int domain, int type, int proto); +int _w32_sock_connect (int sockfd, struct sockaddr *addr, int addrlen); + + +#endif /*W32AFUNIX_DEFS_H*/ +#endif /*_WIN32*/ diff --git a/common/w32-reg.c b/common/w32-reg.c new file mode 100644 index 000000000..5809c32bb --- /dev/null +++ b/common/w32-reg.c @@ -0,0 +1,312 @@ +/* w32-reg.c - MS-Windows Registry access + * Copyright (C) 1999, 2002, 2007 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#include +#ifdef HAVE_W32_SYSTEM + /* This module is only used in this environment */ + +#include +#include +#include +#include +#include + +#include "libjnlib-config.h" +#include "utf8conv.h" +#include "w32help.h" + + +static HKEY +get_root_key(const char *root) +{ + HKEY root_key; + + if (!root) + root_key = HKEY_CURRENT_USER; + else if (!strcmp( root, "HKEY_CLASSES_ROOT" ) ) + root_key = HKEY_CLASSES_ROOT; + else if (!strcmp( root, "HKEY_CURRENT_USER" ) ) + root_key = HKEY_CURRENT_USER; + else if (!strcmp( root, "HKEY_LOCAL_MACHINE" ) ) + root_key = HKEY_LOCAL_MACHINE; + else if (!strcmp( root, "HKEY_USERS" ) ) + root_key = HKEY_USERS; + else if (!strcmp( root, "HKEY_PERFORMANCE_DATA" ) ) + root_key = HKEY_PERFORMANCE_DATA; + else if (!strcmp( root, "HKEY_CURRENT_CONFIG" ) ) + root_key = HKEY_CURRENT_CONFIG; + else + return NULL; + + return root_key; +} + + +/* Return a string from the Win32 Registry or NULL in case of error. + Caller must release the return value. A NULL for root is an alias + for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn. */ +char * +read_w32_registry_string (const char *root, const char *dir, const char *name) +{ +#ifdef HAVE_W32CE_SYSTEM + HKEY root_key, key_handle; + DWORD n1, nbytes, type; + char *result = NULL; + wchar_t *wdir, *wname; + + if ( !(root_key = get_root_key(root) ) ) + return NULL; + + wdir = utf8_to_wchar (dir); + if (!wdir) + return NULL; + + if (RegOpenKeyEx (root_key, wdir, 0, KEY_READ, &key_handle) ) + { + if (root) + { + jnlib_free (wdir); + return NULL; /* No need for a RegClose, so return immediately. */ + } + /* It seems to be common practise to fall back to HKLM. */ + if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, wdir, 0, KEY_READ, &key_handle) ) + { + jnlib_free (wdir); + return NULL; /* Still no need for a RegClose. */ + } + } + jnlib_free (wdir); + + if (name) + { + wname = utf8_to_wchar (name); + if (!wname) + goto leave; + } + else + wname = NULL; + + nbytes = 2; + if (RegQueryValueEx (key_handle, wname, 0, NULL, NULL, &nbytes)) + goto leave; + result = jnlib_malloc ((n1=nbytes+2)); + if (!result) + goto leave; + if (RegQueryValueEx (key_handle, wname, 0, &type, result, &n1)) + { + jnlib_free (result); + result = NULL; + goto leave; + } + result[nbytes] = 0; /* Make sure it is a string. */ + result[nbytes+1] = 0; + if (type == REG_SZ || type == REG_EXPAND_SZ) + { + wchar_t *tmp = (void*)result; + result = wchar_to_utf8 (tmp); + jnlib_free (tmp); + } + + leave: + jnlib_free (wname); + RegCloseKey (key_handle); + return result; +#else /*!HAVE_W32CE_SYSTEM*/ + HKEY root_key, key_handle; + DWORD n1, nbytes, type; + char *result = NULL; + + if ( !(root_key = get_root_key(root) ) ) + return NULL; + + if (RegOpenKeyEx (root_key, dir, 0, KEY_READ, &key_handle) ) + { + if (root) + return NULL; /* No need for a RegClose, so return immediately. */ + /* It seems to be common practise to fall back to HKLM. */ + if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) ) + return NULL; /* Still no need for a RegClose. */ + } + + nbytes = 1; + if (RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes ) ) + goto leave; + result = jnlib_malloc ((n1=nbytes+1)); + if (!result) + goto leave; + if (RegQueryValueEx( key_handle, name, 0, &type, result, &n1 )) + { + jnlib_free (result); + result = NULL; + goto leave; + } + result[nbytes] = 0; /* Make sure it is a string. */ + if (type == REG_EXPAND_SZ && strchr (result, '%')) + { + char *tmp; + + n1 += 1000; + tmp = jnlib_malloc (n1+1); + if (!tmp) + goto leave; + nbytes = ExpandEnvironmentStrings (result, tmp, n1); + if (nbytes && nbytes > n1) + { + jnlib_free (tmp); + n1 = nbytes; + tmp = jnlib_malloc (n1 + 1); + if (!tmp) + goto leave; + nbytes = ExpandEnvironmentStrings (result, tmp, n1); + if (nbytes && nbytes > n1) + { + /* Oops - truncated, better don't expand at all. */ + jnlib_free (tmp); + goto leave; + } + tmp[nbytes] = 0; + jnlib_free (result); + result = tmp; + } + else if (nbytes) + { + /* Okay, reduce the length. */ + tmp[nbytes] = 0; + jnlib_free (result); + result = jnlib_malloc (strlen (tmp)+1); + if (!result) + result = tmp; + else + { + strcpy (result, tmp); + jnlib_free (tmp); + } + } + else + { + /* Error - don't expand. */ + jnlib_free (tmp); + } + } + + leave: + RegCloseKey (key_handle); + return result; +#endif /*!HAVE_W32CE_SYSTEM*/ +} + + +/* Note: This code is not well tested. However, it is not used in + GnuPG. */ +int +write_w32_registry_string (const char *root, const char *dir, + const char *name, const char *value) +{ + HKEY root_key, reg_key; +#ifdef HAVE_W32CE_SYSTEM + wchar_t *wdir, *wname, *wvalue; + DWORD disp; + + if ( !(root_key = get_root_key(root) ) ) + return -1; + + wdir = utf8_to_wchar (dir); + if (!wdir) + return -1; + + if (RegOpenKeyEx (root_key, wdir, 0, 0, ®_key)) + { + jnlib_free (wdir); + return -1; + } + jnlib_free (wdir); + + if (name) + { + wname = utf8_to_wchar (name); + if (!wname) + return -1; + } + else + wname = NULL; + + wvalue = utf8_to_wchar (value); + if (wvalue) + { + jnlib_free (wname); + return -1; + } + + if (RegSetValueEx (reg_key, wname, 0, REG_SZ, + (BYTE *)wvalue, wcslen (wvalue)) != ERROR_SUCCESS ) + { + + if (RegCreateKeyEx (root_key, wname, 0, NULL, 0, 0, NULL, + ®_key, &disp) != ERROR_SUCCESS) + { + RegCloseKey(reg_key); + jnlib_free (wname); + jnlib_free (wvalue); + return -1; + } + if (RegSetValueEx (reg_key, wname, 0, REG_SZ, + (BYTE *)wvalue, wcslen (wvalue)) != ERROR_SUCCESS ) + { + RegCloseKey(reg_key); + jnlib_free (wname); + jnlib_free (wvalue); + return -1; + } + } + + jnlib_free (wname); + jnlib_free (wvalue); + RegCloseKey (reg_key); + return 0; +#else /*!HAVE_W32CE_SYSTEM*/ + + if ( !(root_key = get_root_key(root) ) ) + return -1; + + if ( RegOpenKeyEx( root_key, dir, 0, KEY_WRITE, ®_key ) + != ERROR_SUCCESS ) + return -1; + + if ( RegSetValueEx (reg_key, name, 0, REG_SZ, (BYTE *)value, + strlen( value ) ) != ERROR_SUCCESS ) + { + if ( RegCreateKey( root_key, name, ®_key ) != ERROR_SUCCESS ) + { + RegCloseKey(reg_key); + return -1; + } + if ( RegSetValueEx (reg_key, name, 0, REG_SZ, (BYTE *)value, + strlen( value ) ) != ERROR_SUCCESS ) + { + RegCloseKey(reg_key); + return -1; + } + } + + RegCloseKey (reg_key); + return 0; +#endif /*!HAVE_W32CE_SYSTEM*/ +} + +#endif /*HAVE_W32_SYSTEM*/ diff --git a/common/w32help.h b/common/w32help.h new file mode 100644 index 000000000..518d4251c --- /dev/null +++ b/common/w32help.h @@ -0,0 +1,32 @@ +/* w32help.h - W32 speicif functions + * Copyright (C) 2007 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#ifndef LIBJNLIB_W32HELP_H +#define LIBJNLIB_W32HELP_H +#ifdef HAVE_W32_SYSTEM + +/*-- w32-reg.c --*/ +char *read_w32_registry_string (const char *root, + const char *dir, const char *name ); +int write_w32_registry_string (const char *root, const char *dir, + const char *name, const char *value); + + +#endif /*HAVE_W32_SYSTEM*/ +#endif /*LIBJNLIB_MISCHELP_H*/ diff --git a/common/xasprintf.c b/common/xasprintf.c index 9774d06de..f16410dbd 100644 --- a/common/xasprintf.c +++ b/common/xasprintf.c @@ -23,7 +23,6 @@ #include "util.h" #include "iobuf.h" -#include "estream-printf.h" #if !defined(_ESTREAM_PRINTF_MALLOC) || !defined(_ESTREAM_PRINTF_FREE) #error Need to define ESTREAM_PRINTF_MALLOC and _FREE diff --git a/common/xmalloc.c b/common/xmalloc.c new file mode 100644 index 000000000..eb6d5ab11 --- /dev/null +++ b/common/xmalloc.c @@ -0,0 +1,87 @@ +/* xmalloc.c - standard malloc wrappers + * Copyright (C) 1999, 2000, 2001, 2006 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#include +#include +#include +#include + +#include "libjnlib-config.h" +#include "xmalloc.h" + +static void +out_of_core(void) +{ + fputs("\nfatal: out of memory\n", stderr ); + exit(2); +} + + +void * +xmalloc( size_t n ) +{ + void *p = malloc( n ); + if( !p ) + out_of_core(); + return p; +} + +void * +xrealloc( void *a, size_t n ) +{ + void *p = realloc( a, n ); + if( !p ) + out_of_core(); + return p; +} + +void * +xcalloc( size_t n, size_t m ) +{ + void *p = calloc( n, m ); + if( !p ) + out_of_core(); + return p; +} + +char * +xstrdup( const char *string ) +{ + void *p = xmalloc( strlen(string)+1 ); + strcpy( p, string ); + return p; +} + + +char * +xstrcat2( const char *a, const char *b ) +{ + size_t n1; + char *p; + + if( !b ) + return xstrdup( a ); + + n1 = strlen(a); + p = xmalloc( n1 + strlen(b) + 1 ); + memcpy(p, a, n1 ); + strcpy(p+n1, b ); + return p; +} + diff --git a/common/xmalloc.h b/common/xmalloc.h new file mode 100644 index 000000000..8c9c5292b --- /dev/null +++ b/common/xmalloc.h @@ -0,0 +1,30 @@ +/* xmalloc.h + * Copyright (C) 1999, 2000, 2001, 2006 Free Software Foundation, Inc. + * + * This file is part of JNLIB. + * + * JNLIB is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * JNLIB is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#ifndef LIBJNLIB_XMALLOC_H +#define LIBJNLIB_XMALLOC_H + +void *xmalloc( size_t n ); +void *xrealloc( void *a, size_t n ); +void *xcalloc( size_t n, size_t m ); +char *xstrdup( const char *string ); +char *xstrcat2( const char *a, const char *b ); + + +#endif /*LIBJNLIB_XMALLOC_H*/ diff --git a/configure.ac b/configure.ac index 03d41fc19..c02fb1423 100644 --- a/configure.ac +++ b/configure.ac @@ -43,7 +43,7 @@ NEED_LIBGCRYPT_API=1 NEED_LIBGCRYPT_VERSION=1.4.0 NEED_LIBASSUAN_API=2 -NEED_LIBASSUAN_VERSION=1.1.0 +NEED_LIBASSUAN_VERSION=2.0.0 NEED_KSBA_API=1 NEED_KSBA_VERSION=1.0.2 @@ -439,7 +439,7 @@ AH_BOTTOM([ asprintf. */ #define _ESTREAM_PRINTF_MALLOC gcry_malloc #define _ESTREAM_PRINTF_FREE gcry_free -#define _ESTREAM_PRINTF_EXTRA_INCLUDE "util.h" +#define _ESTREAM_PRINTF_EXTRA_INCLUDE "../common/util.h" /* Under Windows we use the gettext code from libgpg-error. */ #define GPG_ERR_ENABLE_GETTEXT_MACROS @@ -633,9 +633,6 @@ AM_PATH_LIBGCRYPT("$NEED_LIBGCRYPT_API:$NEED_LIBGCRYPT_VERSION", AM_PATH_LIBASSUAN("$NEED_LIBASSUAN_API:$NEED_LIBASSUAN_VERSION", have_libassuan=yes,have_libassuan=no) if test "$have_libassuan" = "yes"; then - have_libassuan=no - AM_PATH_LIBASSUAN("$NEED_LIBASSUAN_API:$NEED_LIBASSUAN_VERSION", - have_libassuan=yes,have_libassuan=no) AC_DEFINE_UNQUOTED(GNUPG_LIBASSUAN_VERSION, "$libassuan_version", [version of the libassuan library]) fi @@ -1108,7 +1105,7 @@ AC_CHECK_FUNCS([ttyname rand ftello fsync]) AC_CHECK_TYPES([struct sigaction, sigset_t],,,[#include ]) # -# These are needed by libjnlib - fixme: we should use a jnlib.m4 +# These are needed by the jnlib parts in common. # Note: We already checked pwd.h. AC_CHECK_HEADERS([signal.h]) AC_CHECK_FUNCS([memicmp stpcpy strsep strlwr strtoul memmove stricmp strtol \ @@ -1490,7 +1487,6 @@ Makefile po/Makefile.in gl/Makefile include/Makefile -jnlib/Makefile common/Makefile kbx/Makefile g10/Makefile diff --git a/g10/ChangeLog b/g10/ChangeLog index 121d57356..b77ed8d9c 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,9 @@ +2010-03-10 Werner Koch + + * Makefile.am (needed_libs): Remove libjnlib.a. + + * main.h: Remove "estream.h". + 2010-03-08 Werner Koch * main.h: Include "estream.h" diff --git a/g10/Makefile.am b/g10/Makefile.am index 3a0529293..b89ff8ee6 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -27,7 +27,7 @@ include $(top_srcdir)/am/cmacros.am AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(LIBASSUAN_CFLAGS) $(GPG_ERROR_CFLAGS) -needed_libs = $(libcommon) ../jnlib/libjnlib.a ../gl/libgnu.a +needed_libs = $(libcommon) ../gl/libgnu.a bin_PROGRAMS = gpg2 gpgv2 noinst_PROGRAMS = $(module_tests) diff --git a/g10/main.h b/g10/main.h index f0f1edc7c..ec09124bd 100644 --- a/g10/main.h +++ b/g10/main.h @@ -25,7 +25,6 @@ #include "cipher.h" #include "keydb.h" #include "util.h" -#include "../common/estream.h" /* It could be argued that the default cipher should be 3DES rather than CAST5, and the default compression should be 0 diff --git a/g10/packet.h b/g10/packet.h index a97fe07a3..54f8295c1 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -23,7 +23,7 @@ #include "types.h" #include "../common/iobuf.h" -#include "../jnlib/strlist.h" +#include "../common/strlist.h" #include "cipher.h" #include "filter.h" #include "../common/openpgpdefs.h" diff --git a/g10/rmd160.c b/g10/rmd160.c index f89193707..febfa618a 100644 --- a/g10/rmd160.c +++ b/g10/rmd160.c @@ -35,7 +35,7 @@ #include #include -#include "../jnlib/types.h" +#include "../common/types.h" #include "rmd160.h" /* diff --git a/g13/Makefile.am b/g13/Makefile.am index 84004cb34..362f060de 100644 --- a/g13/Makefile.am +++ b/g13/Makefile.am @@ -40,7 +40,7 @@ g13_SOURCES = \ be-encfs.c be-encfs.h \ be-truecrypt.c be-truecrypt.h -g13_LDADD = $(libcommonpth) ../jnlib/libjnlib.a ../gl/libgnu.a \ +g13_LDADD = $(libcommonpth) ../gl/libgnu.a \ $(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) $(PTH_LIBS) \ $(GPG_ERROR_LIBS) $(LIBINTL) diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog deleted file mode 100644 index 53ceedf27..000000000 --- a/jnlib/ChangeLog +++ /dev/null @@ -1,758 +0,0 @@ -2010-03-01 Werner Koch - - * t-w32-reg.c: New. - - * w32-reg.c (read_w32_registry_string) - (write_w32_registry_string): Support W32CE. - -2010-02-26 Werner Koch - - * t-timestuff.c: New. - - * dynload.h (dlopen, dlsym) [W32CE]: Map to wchar_t. - - * mischelp.c (_jnlib_free): New. - (same_file_p) [W32CE]: Map to wchar_t. - - * utf8conv.c (set_native_charset) [W32CE]: Do not use - GetConsoleOutputCP. - (wchar_to_utf8, utf8_to_wchar) [W32]: New. - - * Makefile.am (t_jnlib_ldadd) [W32CE]: Add gpg-error. - - * t-support.h (getenv) [HAVE_GETENV]: Add getenv stub. - [W32CE]: Include gpg-error.h - * t-support.c (gpg_err_code_from_errno) - (gpg_err_code_from_syserror) [GPG_ERROR_H]: Do not build. - - * t-stringhelp.c (gethome) [!HAVE_GETPWUID]: Keep result of getenv. - - * dotlock.c [!HAVE_SIGNAL_H]: Don't include signal.h. - (create_dotlock) [W32CE]: Map filename top wchar_t. - - * libjnlib-config.h [USE_SIMPLE_GETTEXT]: Include gpg-error.h and - remove w32help.h. - (jnlib_set_errno): New. Use it everywhere to set ERRNO. - (getenv) [!HAVE_GETENV]: New. - (getpid) [W32E]: New. - - * stringhelp.c (get_pwdir) [!HAVE_PWD_H]: Mark unused args. - (w32_strerror) [W32CE]: Use a simple implementation. - - * w32help.h [USE_SIMPLE_GETTEXT]: Remove all definitions; we are - now using the gpg-error included implementation. - * w32-gettext.c: Remove. - - * mischelp.c (same_file_p): Fix bug in case the second file can't - be opened. - -2009-10-19 Werner Koch - - * strlist.c (add_to_strlist_try): New. - -2009-09-22 Werner Koch - - * dotlock.h (DOTLOCK): Rename to dotlock_t. Change all users. - -2009-08-26 Werner Koch - - * stringhelp.c (do_make_filename): Factor some code out to .. - (get_pwdir): .. new. - -2009-08-26 Werner Koch - - * stringhelp.c [HAVE_PWD_H]: Include pwd.h. - (do_make_filename): New. - (make_filename, make_filename_try): Implement using the new - function. - * t-stringhelp.c (test_make_filename_try): New. - * t-support.c (gcry_strdup): Fix. - - * stringhelp.h (make_filename, make_filename_try): Add sentinel - attribute. - -2009-08-25 Werner Koch - - * stringhelp.c: Include errno.h. - (do_strconcat): New. - (strconcat, xstrconcat): New. - * types.h (GNUPG_GCC_A_SENTINEL): New. - * t-stringhelp.c (test_strconcat, test_xstrconcat): New. - (main): Run them. - -2009-07-07 Werner Koch - - * stringhelp.c (make_filename_try): Use jnlib_malloc. - - * dotlock.c (read_lockfile): Replace jnlib_xmalloc by jnlib_malloc. - -2009-06-04 Werner Koch - - * mischelp.h: Include SUN_LEN etc also for W32. - -2009-05-19 Werner Koch - - * mischelp.h: Define PF_LOCAL, AF_LOCAL and SUN_LEN if requested. - * logging.c (fun_writer): Use SUN_LEN to fix a Mac OS X freeze. - -2009-03-25 Werner Koch - - * logging.c (fun_closer): Never close fd 2. - (set_file_fd): Close logstream early. - -2009-02-25 Werner Koch - - * logging.c (get_tid_callback): New. - (do_logv): Use it. - (log_set_get_tid_callback): New. - -2009-01-22 Werner Koch - - * t-support.c (gpg_err_code_from_errno) - (gpg_err_code_from_syserror): New. - -2008-11-20 Werner Koch - - * argparse.c (arg_parse): Fix last change. - -2008-11-11 Werner Koch - - * argparse.h: Add a bunch of macros and constants. - * argparse.c: Use the new macros. Re-indent the code. Change - license back to LGPL 2.1. - -2008-11-04 Werner Koch - - * w32-gettext.c: Merged with code from libgpg-error and rewrote - most parts. - - * Makefile.am (AM_CFLAGS): Add -DJNLIB_IN_JNLIB. - -2008-10-29 Werner Koch - - * stringhelp.c (make_filename): Implement using macros. Factor some - code out to .. - (change_slashes): New. - (make_filename_try): New. - - * w32-gettext.c (gettext): Return if no domain is loaded. - Reported by Tom Pegios. - -2008-10-28 Werner Koch - - * w32-gettext.c (gettext): Try the binary search if the string was - not found in the hash table. - -2008-10-20 Werner Koch - - * w32-afunix.c (_w32_sock_connect): Mark ADDRLEN as unused. - - * dotlock.c (release_dotlock): Do not mix declaration and code. - - * stringhelp.c (make_basename): Silent gcc warning about unused arg. - * argparse.c (store_alias): Ditto. - (find_long_option): - -2008-10-15 Werner Koch - - * logging.c (do_logv) [W32]: Flush the log stream. - -2008-09-29 Werner Koch - - * argparse.c (ARGERR_): Use constants for error values. - (optfile_parse): Prettify. Replace xmalloc and xrealloc by malloc - and realloc. - * libjnlib-config.h (jnlib_strdup, jnlib_realloc): New. - -2008-06-26 Werner Koch - - * stringhelp.c (print_sanitized_buffer2): Loose check for control - characters to better cope with utf-8. The range 0x80..0x9f is - nowadays not anymore accidently used for control charaters. - -2008-06-13 Werner Koch - - * dotlock.c: Reformat code and implement locking for W32. - (create_dotlock): Use snprintf. - -2008-06-11 Werner Koch - - * utf8conv.c: Remove useless variable ACTIVE_CHARSET. Suggested - by Petr Uzel. - -2008-05-26 Werner Koch - - * argparse.c (usage): Make sure to print a trailing LF for usage(1). - -2008-04-08 Werner Koch - - * w32-gettext.c (gettext_select_utf8): New. - (get_string): Support switching encodings. - (load_domain): Allocate space for DATA_NATIVE. - -2008-03-25 Werner Koch - - * w32-gettext.c (_nl_locale_name): New. Taken from - ../common/localename and GNU gettext's localename.c. - (set_gettext_file): Rewritten. - (gettext_localename): New. - -2008-03-17 Werner Koch - - * logging.c (my_funopen_hook_size_t): New. - (fun_writer): Use it to cope with fopencookie/funopen differences. - * dotlock.c (read_lockfile): Initialize PID. Reported by Stéphane - Corthésy. - -2008-02-22 Werner Koch - - * argparse.c (strusage): Set copyright year to 2008. - -2007-11-19 Werner Koch - - * stringhelp.c (percent_escape): Factor code out to - (do_percent_escape): .. new. - (try_percent_escape): New. - -2007-10-01 Werner Koch - - * w32-afunix.c: Only keep the client related code. - (read_port_and_nonce): New. Taken from Assuan. - (_w32_sock_connect): Rewritten. - -2007-08-29 Werner Koch - - * argparse.c (initialize): Make strings translatable and remove - extra LF. - -2007-08-24 Werner Koch - - * mischelp.c (same_file_p): New. - (libjnlib_dummy_mischelp_func): Remove as we now always have one - function. - -2007-08-09 Werner Koch - - * argparse.c (show_help): Expand the @EMAIL@ macro in the package - bug reporting address. - -2007-08-02 Werner Koch - - * t-stringhelp.c (test_compare_filenames): New. - - * stringhelp.c (compare_filenames) [HAVE_DRIVE_LETTERS]: Fixed - comparison to take slash and backslash in account. - (make_filename): Avoid mixing / and \. - -2007-07-04 Werner Koch - - * utf8conv.c (load_libiconv): Remove URL from translatble string. - - Switched JNLIB from LGPLv2.1 to LGPLv3. - -2007-07-01 Werner Koch - - * argparse.c (strusage): Use id 10 for the license string; - default to GPL3+. Change long note to version 3 or later. - (show_version): Print the license info. - -2007-06-19 Werner Koch - - * Makefile.am: Add support for regression tests. - * t-support.h, t-support.c: New. - * t-stringhelp.c: New. - - * stringhelp.c (percent_escape): Add arg EXTRA to make it a more - general function. Changed all callers. - -2007-06-18 Werner Koch - - * w32-afunix.c (_w32_sock_bind): Changed to properly detect an - already used socket. - -2007-06-18 Marcus Brinkmann - - * stringhelp.h (percent_escape): New prototype. - * stringhelp.c (percent_escape): New function. - -2007-06-11 Werner Koch - - * utf8conv.c (jnlib_iconv_open, jnlib_iconv, jnlib_iconv_close): New. - -2007-06-06 Werner Koch - - * w32help.h: New. - * w32-gettext.c: New. Taken from gnupg 1.4, added ngettext, - changed to use jnlib malloc functions and put under the LGPL. - * w32-reg.c: New. Taken from../common/w32reg.c and changed to - LGPL. Changed API to use the jnlib malloc functions. - * Makefile.am (libjnlib_a_SOURCES) [!W32]: Do not build the w32 - specific modules. - - * dotlock.c: Include stringhelp.h for stpcpy prototype. - -2007-06-04 Werner Koch - - * dynload.h: New. Taken from ../common and changed to LGPL. - - * utf8conv.c (load_libiconv): New. Taken from GnuPG 1.4 - -2007-05-30 Werner Koch - - * w32-pth.h, w32-pth.c: Remove. - -2007-04-25 Werner Koch - - * argparse.c (long_opt_strlen): Fixed for utf-8. - -2007-03-07 Werner Koch - - * argparse.c (strusage): Set copyright year to 2007. - -2007-01-25 Werner Koch - - * stringhelp.c (utf8_charcount): New. - -2006-11-29 Werner Koch - - * utf8conv.c (set_native_charset) [HAVE_W32_SYSTEM]: Fixed typo in - macro name. - -2006-11-15 Werner Koch - - * logging.c (my_funopen_hook_ret_t): New. - (fun_writer): Use it. - -2006-10-19 Werner Koch - - * stringhelp.c (memrchr) [!HAVE_MEMRCHR]: Provide a replacement. - -2006-09-27 Werner Koch - - * mischelp.c: New. - (timegm): Copied from gnupg 1.4, changed from GPL to LGPL. Fixed - a memory leak. - - * stringhelp.h (isascii): New. - - * stringhelp.c (strsep): New. Copied from gnupg 1.4.5 - util/strgutil.c. - - * strlist.h (STRLIST): Removed deprecated typedef. - - * types.h: Made cpp commands work with old compilers. Also shows - up nicer with Emacs' font locking. - - * w32-afunix.c (_w32_sock_connect): Set ERRNO for an invalid port. - - Changed license from GPL to LGPL. Note that all code has either - been written by me, David, employees of g10 Code or taken from - glibc. - - * libjnlib-config.h, stringhelp.c, stringhelp.h: - * strlist.c, strlist.h, utf8conv.c, utf8conv.h: - * argparse.c, argparse.h, logging.c, logging.h: - * dotlock.c, dotlock.h, types.h, mischelp.h: - * xmalloc.c, xmalloc.h, w32-pth.c, w32-pth.h: - * w32-afunix.c, w32-afunix.h: Tagged them to be long to jnlib - which is a part of GnuPG but also used by other projetcs. - -2006-09-22 Werner Koch - - * utf8conv.c: Reworked to match the gnupg 1.4.5 code. This now - requires iconv support but this is reasonable for all modern - systems. - -2006-08-29 Werner Koch - - * logging.c (do_logv): Emit a missing LF for fatal errors. - -2006-06-28 Werner Koch - - * dotlock.c (make_dotlock, release_dotlock, read_lockfile) - (maybe_deadlock, destroy_dotlock, create_dotlock): Re-indented. - (create_dotlock): Repalces some log_fatal by log_error as it was - not intended that they should terminate. Write the nodename to - the locking file. Code cleanups. - (read_lockfile): Reworked to read the node name. - (make_dotlock): Test for identical node name and delete lock stale - file. - (release_dotlock): Likewise. - -2006-05-23 Werner Koch - - * libjnlib-config.h (JNLIB_NEED_UTF8CONV): Fixed typo in name. - - * dotlock.c (release_dotlock): Don't act if we don't have any - locks at all. - (destroy_dotlock): New. From 1.4.3. - (dotlock_remove_lockfiles): Make use of destroy function. - -2006-05-19 Werner Koch - - * strlist.c (append_to_strlist2): Enabled. - - * stringhelp.c (print_sanitized_buffer2): New. Changed the rules - to match the behaviour of print_string2 from gnupg 1.4.3. - (print_sanitized_buffer): Use the new function. - (print_sanitized_string2): New. - (hextobyte): New. Taken from gpg 1.4.3. - -2006-04-28 Werner Koch - - * stringhelp.c (print_sanitized_buffer): Fix bug where the count - got wrong for the \xNN representation. - (sanitize_buffer): Fix bug where some control characters lose part - of their \xNN representation. - -2006-04-20 Werner Koch - - * stringhelp.c (make_basename): New arg INPUTPATH for future - riscos compatibility. - -2006-04-18 Werner Koch - - * libjnlib-config.h (JNLIB_NEED_UTF8CONF): Defined. - * strlist.c (add_to_strlist2) [JNLIB_NEED_UTF8CONV]: Enabled. - -2005-06-15 Werner Koch - - * stringhelp.c (sanitize_buffer): Make P a void*. - (ascii_memistr, memistr): Ditto. - (ascii_memcasecmp): Ditto. - * logging.c (writen): Use void * for arg BUFFER. - * stringhelp.c (memistr): Fixed unsigned/signed pointer conflict. - (ascii_memistr): Ditto. - (ascii_memcasemem): Ditto. - * utf8conv.c (utf8_to_native): Ditto. - (utf8_to_native): Ditto. - * argparse.c (show_version): Removed non-required cast. - -2005-01-19 Werner Koch - - * logging.c (fun_writer): Don't fallback to stderr. Print to - stderr only if connected to a tty. - -2004-12-20 Werner Koch - - * w32-pth.c (do_pth_event_free): The events are hold in a ring - buffer. Adjust for that. - (do_pth_event_body): Ditto. - (pth_event_isolate): Ditto. - (do_pth_wait): Ditto. - (_pth_event_count): Renamed to .. - (event_count): .. and adjusted as above. - (pth_init): Define 3 debug levels and change all debug calls to - make use of them. This makes the moule now silent. - -2004-12-19 Werner Koch - - * w32-pth.c (pth_init): Enable debugging depending on env var. - (pth_self): New. - (pth_mutex_release, pth_mutex_acquire): Implemented directly using - the W32 API. - -2004-12-18 Werner Koch - - * w32-pth.c (pth_init): Reverse return values. Use TRUE and FALSE - constants. - (pth_kill, pth_mutex_acquire, pth_attr_set, pth_join, pth_cancel): - Ditto. - -2004-12-15 Werner Koch - - * logging.c [W32]: Don't include unavailable headers. - -2004-12-14 Werner Koch - - * w32-pth.c (_pth_strerror): Renamed to ... - (w32_strerror): .. this. And let callers provide a buffer. - (spawn_helper_thread): Removed HD arg and hardwire the stack size - to 32k. - (do_pth_wait): Removed use of ATTR; not needed for the helper - threads. - (helper_thread): Renamed to .. - (launch_thread): .. this. Release handle if not joinable. - (struct pth_priv_hd_s): Renamed to ... - (struct thread_info_s): .. this. Add member JOINABLE and TH. - -2004-12-14 Timo Schulz - - * w32-pth.c (pth_kill): Just release the crit section if - pth_init was really called. And set all handles to NULL. - (_pth_strerror): New. - (do_pth_wait): Before we enter the loop we check if there - are too much events in the ring. - -2004-12-14 Werner Koch - - * w32-pth.h (pth_event_occured): Removed macro. - * w32-pth.c: Fixed license statement; its under the LGPL. - (enter_pth, leave_pth): Use them to bracket almost all public - functions. - -2004-12-13 Timo Schulz - - * w32-pth.c (enter_pth, leave_pth): New. - (pth_init): Initialize global mutex section. - (pth_kill): Release global mutex section. - (helper_thread): New. - (pth_spawn): Make sure only one thread is running. - -2004-12-13 Werner Koch - - * stringhelp.c (w32_strerror) [W32]: New. - - * w32-pth.c, w32-pth.h: Added real code written by Timo Schulz. - Not finished, though. - -2004-12-07 Werner Koch - - * w32-pth.c, w32-pth.h: New. - -2004-11-26 Werner Koch - - * logging.c [_WIN32]: Don't include socket headers. - -2004-11-30 Timo Schulz - - * w32-afunix.c: New. AF_UNIX emulation for W32. - * w32-afunix.h: Likewise. - -2004-11-22 Werner Koch - - * logging.c (log_test_fd): Add test on LOGSTREAM. Reported by - Barry Schwartz. - -2004-11-18 Werner Koch - - * logging.c: Explicitly include sys/stat.h for the S_I* constants. - -2004-10-21 Werner Koch - - * logging.c (do_logv): Use set_log_stream to setup a default. - (log_set_file): Factored code out to .. - (set_file_fd): .. New function to allow using a file descriptor. - (log_set_fd): Make use of new fucntion. - (fun_writer): Reworked. - -2004-08-18 Werner Koch - - * stringhelp.c (print_sanitized_utf8_string): Actually implement - it. - -2004-06-21 Werner Koch - - * logging.c (log_set_file): Do not close an old logstream if it - used to be stderr or stdout. - -2004-05-05 Werner Koch - - * logging.c (log_set_file): Oops, don't close if LOGSTREAM is NULL. - -2004-04-30 Werner Koch - - * 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 - - * 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 - - * stringhelp.c (print_sanitized_buffer): Don't care about - non-ASCII characaters. - (sanitize_buffer): Ditto. - -2004-02-12 Werner Koch - - * Makefile.am: Replaced INCLUDES by AM_CPPFLAGS. - -2004-01-05 Werner Koch - - * argparse.c (strusage): Changed default copyright year to 2004. - -2003-12-17 Werner Koch - - * argparse.c (initialize): Replaced use of non-literal format - args. Suggested by Florian Weimer. - -2003-12-16 Werner Koch - - * 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 - - * strlist.c (strlist_copy): New. - - * dotlock.c: Define DIRSEP_C et al. if not defined. - -2003-11-06 Werner Koch - - * strlist.h (strlist_t): New. STRLIST is now deprecated. - -2003-06-18 Werner Koch - - * strlist.c (strlist_pop): New. - - * dotlock.c (dotlock_remove_lockfiles): Prefixed with dotlock_ and - made global. - -2003-06-17 Werner Koch - - * 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 - - * 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 - - * mischelp.h (wipememory2,wipememory): New. Taken from GnuPG 1.3.2. - -2002-06-04 Werner Koch - - * stringhelp.c (print_sanitized_utf8_string): New. No real - implementation for now. - (print_sanitized_utf8_buffer): Ditto. - -2002-04-04 Werner Koch - - * logging.c (log_get_prefix): New. - -2002-03-15 Werner Koch - - * argparse.c (optfile_parse): Fixed missing argument handling. - -2002-02-25 Werner Koch - - * stringhelp.c (ascii_memcasemem): New. - -2002-02-14 Werner Koch - - * Makefile.am (INCLUDES): Add cflags for libgcrypt. - -2002-02-07 Werner Koch - - * logging.c (log_set_fd): New. - - * stringhelp.c (print_sanitized_buffer): New. - (print_sanitized_string): New. - -2002-01-24 Werner Koch - - * 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 - - * 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 . - -2002-01-19 Werner Koch - - * logging.c (log_get_stream): New. - -2001-12-05 Werner Koch - - * 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 - - * strlist.c, strlist.h: New. Taken from pgnupg/util/strgutil.c - -2001-08-30 Werner Koch - - * logging.c (log_printf): Don't pass NULL instead of arg_ptr. - -2001-07-19 Werner Koch - - * 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 - - * 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, 2005, 2006, 2007, 2008, - 2010 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/Makefile.am b/jnlib/Makefile.am deleted file mode 100644 index 232aef980..000000000 --- a/jnlib/Makefile.am +++ /dev/null @@ -1,85 +0,0 @@ -# Makefile for the JNLIB part of GnuPG -# Copyright (C) 1999, 2000, 2001, 2004, 2006, -# 2010 Feee Software Soundation, Inc. -# -# This file is part of JNLIB. -# -# JNLIB is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as -# published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# JNLIB is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this program; if not, see . - - -## Process this file with automake to produce Makefile.in - -EXTRA_DIST = README -noinst_PROGRAMS = $(module_tests) -TESTS = $(module_tests) - -AM_CPPFLAGS = -I$(top_srcdir)/intl - -# We need libgcrypt because libjnlib-config includes gcrypt.h -AM_CFLAGS = -DJNLIB_IN_JNLIB $(LIBGCRYPT_CFLAGS) - -noinst_LIBRARIES = libjnlib.a - - -#libjnlib_a_LDFLAGS = -libjnlib_a_SOURCES = \ - libjnlib-config.h \ - stringhelp.c stringhelp.h \ - strlist.c strlist.h \ - utf8conv.c utf8conv.h \ - argparse.c argparse.h \ - logging.c logging.h \ - dotlock.c dotlock.h \ - types.h mischelp.c mischelp.h dynload.h w32help.h - -if HAVE_W32_SYSTEM -libjnlib_a_SOURCES += w32-reg.c w32-afunix.c w32-afunix.h -endif - - -# For GnuPG we don't need the xmalloc stuff. -# xmalloc.c xmalloc.h - - -# -# Module tests. -# -# These tests should only be used at the canonical location of jnlib -# which is the GnuPG package. The reason for this is that t-support.c -# defines replacements for the actual used memory allocation functions -# so that there is no dependency on libgcrypt. -# -module_tests = t-stringhelp t-timestuff -if HAVE_W32_SYSTEM -module_tests += t-w32-reg -endif - -t_jnlib_src = t-support.c t-support.h -t_jnlib_ldadd = libjnlib.a $(LIBINTL) $(LIBICONV) -# For W32 we need libgpg-error because it provides gettext. -if HAVE_W32_SYSTEM -t_jnlib_ldadd += $(GPG_ERROR_LIBS) -endif - -t_stringhelp_SOURCES = t-stringhelp.c $(t_jnlib_src) -t_stringhelp_LDADD = $(t_jnlib_ldadd) - -t_timestuff_SOURCES = t-timestuff.c $(t_jnlib_src) -t_timestuff_LDADD = $(t_jnlib_ldadd) - -if HAVE_W32_SYSTEM -t_w32_reg_SOURCES = t-w32-reg.c $(t_jnlib_src) -t_w32_reg_LDADD = $(t_jnlib_ldadd) -endif - diff --git a/jnlib/README b/jnlib/README deleted file mode 100644 index 5536e1ade..000000000 --- a/jnlib/README +++ /dev/null @@ -1,8 +0,0 @@ -JNLIB - This is a collection of utility function which are too small -to put into a library. The code here is licensed under the LGPL. - -libjnlib-config.h should be be modified for each project to make these -functions fit into the software. Mainly these are memory functions in -case you need another allocator. - - diff --git a/jnlib/argparse.c b/jnlib/argparse.c deleted file mode 100644 index ab88922a4..000000000 --- a/jnlib/argparse.c +++ /dev/null @@ -1,1205 +0,0 @@ -/* [argparse.c wk 17.06.97] Argument Parser for option handling - * Copyright (C) 1998, 1999, 2000, 2001, 2006 - * 2007, 2008 Free Software Foundation, Inc. - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include "libjnlib-config.h" -#include "mischelp.h" -#include "stringhelp.h" -#include "logging.h" -#ifdef JNLIB_NEED_UTF8CONV -#include "utf8conv.h" -#endif -#include "argparse.h" - - - -/********************************* - * @Summary arg_parse - * #include - * - * typedef struct { - * char *argc; pointer to argc (value subject to change) - * char ***argv; pointer to argv (value subject to change) - * unsigned flags; Global flags (DO NOT CHANGE) - * int err; print error about last option - * 1 = warning, 2 = abort - * int r_opt; return option - * int r_type; type of return value (0 = no argument found) - * union { - * int ret_int; - * long ret_long - * ulong ret_ulong; - * char *ret_str; - * } r; Return values - * struct { - * int idx; - * const char *last; - * void *aliases; - * } internal; DO NOT CHANGE - * } ARGPARSE_ARGS; - * - * typedef struct { - * int short_opt; - * const char *long_opt; - * unsigned flags; - * } ARGPARSE_OPTS; - * - * int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts ); - * - * @Description - * This is my replacement for getopt(). See the example for a typical usage. - * Global flags are: - * Bit 0 : Do not remove options form argv - * Bit 1 : Do not stop at last option but return other args - * with r_opt set to -1. - * Bit 2 : Assume options and real args are mixed. - * Bit 3 : Do not use -- to stop option processing. - * Bit 4 : Do not skip the first arg. - * Bit 5 : allow usage of long option with only one dash - * Bit 6 : ignore --version - * all other bits must be set to zero, this value is modified by the - * function, so assume this is write only. - * Local flags (for each option): - * Bit 2-0 : 0 = does not take an argument - * 1 = takes int argument - * 2 = takes string argument - * 3 = takes long argument - * 4 = takes ulong argument - * Bit 3 : argument is optional (r_type will the be set to 0) - * Bit 4 : allow 0x etc. prefixed values. - * Bit 7 : this is a command and not an option - * You stop the option processing by setting opts to NULL, the function will - * then return 0. - * @Return Value - * Returns the args.r_opt or 0 if ready - * r_opt may be -2/-7 to indicate an unknown option/command. - * @See Also - * ArgExpand - * @Notes - * You do not need to process the options 'h', '--help' or '--version' - * because this function includes standard help processing; but if you - * specify '-h', '--help' or '--version' you have to do it yourself. - * The option '--' stops argument processing; if bit 1 is set the function - * continues to return normal arguments. - * To process float args or unsigned args you must use a string args and do - * the conversion yourself. - * @Example - * - * ARGPARSE_OPTS opts[] = { - * { 'v', "verbose", 0 }, - * { 'd', "debug", 0 }, - * { 'o', "output", 2 }, - * { 'c', "cross-ref", 2|8 }, - * { 'm', "my-option", 1|8 }, - * { 500, "have-no-short-option-for-this-long-option", 0 }, - * {0} }; - * ARGPARSE_ARGS pargs = { &argc, &argv, 0 } - * - * while( ArgParse( &pargs, &opts) ) { - * switch( pargs.r_opt ) { - * case 'v': opt.verbose++; break; - * case 'd': opt.debug++; break; - * case 'o': opt.outfile = pargs.r.ret_str; break; - * case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break; - * case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break; - * case 500: opt.a_long_one++; break - * default : pargs.err = 1; break; -- force warning output -- - * } - * } - * if( argc > 1 ) - * log_fatal( "Too many args"); - * - */ - -typedef struct alias_def_s *ALIAS_DEF; -struct alias_def_s { - ALIAS_DEF next; - char *name; /* malloced buffer with name, \0, value */ - const char *value; /* ptr into name */ -}; - -static const char *(*strusage_handler)( int ) = NULL; - -static int set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s); -static void show_help(ARGPARSE_OPTS *opts, unsigned flags); -static void show_version(void); - - -static void -initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno ) -{ - if( !(arg->flags & (1<<15)) ) - { - /* Initialize this instance. */ - arg->internal.idx = 0; - arg->internal.last = NULL; - arg->internal.inarg = 0; - arg->internal.stopped = 0; - arg->internal.aliases = NULL; - arg->internal.cur_alias = NULL; - arg->err = 0; - arg->flags |= 1<<15; /* Mark as initialized. */ - if ( *arg->argc < 0 ) - jnlib_log_bug ("invalid argument for arg_parsee\n"); - } - - - if (arg->err) - { - /* Last option was erroneous. */ - const char *s; - - if (filename) - { - if ( arg->r_opt == ARGPARSE_UNEXPECTED_ARG ) - s = _("argument not expected"); - else if ( arg->r_opt == ARGPARSE_READ_ERROR ) - s = _("read error"); - else if ( arg->r_opt == ARGPARSE_KEYWORD_TOO_LONG ) - s = _("keyword too long"); - else if ( arg->r_opt == ARGPARSE_MISSING_ARG ) - s = _("missing argument"); - else if ( arg->r_opt == ARGPARSE_INVALID_COMMAND ) - s = _("invalid command"); - else if ( arg->r_opt == ARGPARSE_INVALID_ALIAS ) - s = _("invalid alias definition"); - else if ( arg->r_opt == ARGPARSE_OUT_OF_CORE ) - s = _("out of core"); - else - s = _("invalid option"); - jnlib_log_error ("%s:%u: %s\n", filename, *lineno, s); - } - else - { - s = arg->internal.last? arg->internal.last:"[??]"; - - if ( arg->r_opt == ARGPARSE_MISSING_ARG ) - jnlib_log_error (_("missing argument for option \"%.50s\"\n"), s); - else if ( arg->r_opt == ARGPARSE_UNEXPECTED_ARG ) - jnlib_log_error (_("option \"%.50s\" does not expect an " - "argument\n"), s ); - else if ( arg->r_opt == ARGPARSE_INVALID_COMMAND ) - jnlib_log_error (_("invalid command \"%.50s\"\n"), s); - else if ( arg->r_opt == ARGPARSE_AMBIGUOUS_OPTION ) - jnlib_log_error (_("option \"%.50s\" is ambiguous\n"), s); - else if ( arg->r_opt == ARGPARSE_AMBIGUOUS_OPTION ) - jnlib_log_error (_("command \"%.50s\" is ambiguous\n"),s ); - else if ( arg->r_opt == ARGPARSE_OUT_OF_CORE ) - jnlib_log_error ("%s\n", _("out of core\n")); - else - jnlib_log_error (_("invalid option \"%.50s\"\n"), s); - } - if ( arg->err != 1 ) - exit (2); - arg->err = 0; - } - - /* Zero out the return value union. */ - arg->r.ret_str = NULL; - arg->r.ret_long = 0; -} - - -static void -store_alias( ARGPARSE_ARGS *arg, char *name, char *value ) -{ - /* TODO: replace this dummy function with a rea one - * and fix the probelms IRIX has with (ALIAS_DEV)arg.. - * used as lvalue - */ - (void)arg; - (void)name; - (void)value; -#if 0 - ALIAS_DEF a = jnlib_xmalloc( sizeof *a ); - a->name = name; - a->value = value; - a->next = (ALIAS_DEF)arg->internal.aliases; - (ALIAS_DEF)arg->internal.aliases = a; -#endif -} - -/**************** - * Get options from a file. - * Lines starting with '#' are comment lines. - * Syntax is simply a keyword and the argument. - * Valid keywords are all keywords from the long_opt list without - * the leading dashes. The special keywords "help", "warranty" and "version" - * are not valid here. - * The special keyword "alias" may be used to store alias definitions, - * which are later expanded like long options. - * Caller must free returned strings. - * If called with FP set to NULL command line args are parse instead. - * - * Q: Should we allow the syntax - * keyword = value - * and accept for boolean options a value of 1/0, yes/no or true/false? - * Note: Abbreviation of options is here not allowed. - */ -int -optfile_parse (FILE *fp, const char *filename, unsigned *lineno, - ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts) -{ - int state, i, c; - int idx=0; - char keyword[100]; - char *buffer = NULL; - size_t buflen = 0; - int in_alias=0; - - if (!fp) /* Divert to to arg_parse() in this case. */ - return arg_parse (arg, opts); - - initialize (arg, filename, lineno); - - /* Find the next keyword. */ - state = i = 0; - for (;;) - { - c = getc (fp); - if (c == '\n' || c== EOF ) - { - if ( c != EOF ) - ++*lineno; - if (state == -1) - break; - else if (state == 2) - { - keyword[i] = 0; - for (i=0; opts[i].short_opt; i++ ) - { - if (opts[i].long_opt && !strcmp (opts[i].long_opt, keyword)) - break; - } - idx = i; - arg->r_opt = opts[idx].short_opt; - if (!opts[idx].short_opt ) - arg->r_opt = ((opts[idx].flags & ARGPARSE_OPT_COMMAND) - ? ARGPARSE_INVALID_COMMAND - : ARGPARSE_INVALID_OPTION); - else if (!(opts[idx].flags & 7)) - arg->r_type = 0; /* Does not take an arg. */ - else if ((opts[idx].flags & 8) ) - arg->r_type = 0; /* Arg is optional. */ - else - arg->r_opt = ARGPARSE_MISSING_ARG; - - break; - } - else if (state == 3) - { - /* No argument found. */ - if (in_alias) - arg->r_opt = ARGPARSE_MISSING_ARG; - else if (!(opts[idx].flags & 7)) - arg->r_type = 0; /* Does not take an arg. */ - else if ((opts[idx].flags & 8)) - arg->r_type = 0; /* No optional argument. */ - else - arg->r_opt = ARGPARSE_MISSING_ARG; - - break; - } - else if (state == 4) - { - /* Has an argument. */ - if (in_alias) - { - if (!buffer) - arg->r_opt = ARGPARSE_UNEXPECTED_ARG; - else - { - char *p; - - buffer[i] = 0; - p = strpbrk (buffer, " \t"); - if (p) - { - *p++ = 0; - trim_spaces (p); - } - if (!p || !*p) - { - jnlib_free (buffer); - arg->r_opt = ARGPARSE_INVALID_ALIAS; - } - else - { - store_alias (arg, buffer, p); - } - } - } - else if (!(opts[idx].flags & 7)) - arg->r_opt = ARGPARSE_UNEXPECTED_ARG; - else - { - char *p; - - if (!buffer) - { - keyword[i] = 0; - buffer = jnlib_strdup (keyword); - if (!buffer) - arg->r_opt = ARGPARSE_OUT_OF_CORE; - } - else - buffer[i] = 0; - - if (buffer) - { - trim_spaces (buffer); - p = buffer; - if (*p == '"') - { - /* Remove quotes. */ - p++; - if (*p && p[strlen(p)-1] == '\"' ) - p[strlen(p)-1] = 0; - } - if (!set_opt_arg (arg, opts[idx].flags, p)) - jnlib_free(buffer); - } - } - break; - } - else if (c == EOF) - { - if (ferror (fp)) - arg->r_opt = ARGPARSE_READ_ERROR; - else - arg->r_opt = 0; /* EOF. */ - break; - } - state = 0; - i = 0; - } - else if (state == -1) - ; /* Skip. */ - else if (state == 0 && isascii (c) && isspace(c)) - ; /* Skip leading white space. */ - else if (state == 0 && c == '#' ) - state = 1; /* Start of a comment. */ - else if (state == 1) - ; /* Skip comments. */ - else if (state == 2 && isascii (c) && isspace(c)) - { - /* Check keyword. */ - keyword[i] = 0; - for (i=0; opts[i].short_opt; i++ ) - if (opts[i].long_opt && !strcmp (opts[i].long_opt, keyword)) - break; - idx = i; - arg->r_opt = opts[idx].short_opt; - if (!opts[idx].short_opt) - { - if (!strcmp (keyword, "alias")) - { - in_alias = 1; - state = 3; - } - else - { - arg->r_opt = ((opts[idx].flags & ARGPARSE_OPT_COMMAND) - ? ARGPARSE_INVALID_COMMAND - : ARGPARSE_INVALID_OPTION); - state = -1; /* Skip rest of line and leave. */ - } - } - else - state = 3; - } - else if (state == 3) - { - /* Skip leading spaces of the argument. */ - if (!isascii (c) || !isspace(c)) - { - i = 0; - keyword[i++] = c; - state = 4; - } - } - else if (state == 4) - { - /* Collect the argument. */ - if (buffer) - { - if (i < buflen-1) - buffer[i++] = c; - else - { - char *tmp; - size_t tmplen = buflen + 50; - - tmp = jnlib_realloc (buffer, tmplen); - if (tmp) - { - buflen = tmplen; - buffer = tmp; - buffer[i++] = c; - } - else - { - jnlib_free (buffer); - arg->r_opt = ARGPARSE_OUT_OF_CORE; - break; - } - } - } - else if (i < DIM(keyword)-1) - keyword[i++] = c; - else - { - size_t tmplen = DIM(keyword) + 50; - buffer = jnlib_malloc (tmplen); - if (buffer) - { - buflen = tmplen; - memcpy(buffer, keyword, i); - buffer[i++] = c; - } - else - { - arg->r_opt = ARGPARSE_OUT_OF_CORE; - break; - } - } - } - else if (i >= DIM(keyword)-1) - { - arg->r_opt = ARGPARSE_KEYWORD_TOO_LONG; - state = -1; /* Skip rest of line and leave. */ - } - else - { - keyword[i++] = c; - state = 2; - } - } - - return arg->r_opt; -} - - - -static int -find_long_option( ARGPARSE_ARGS *arg, - ARGPARSE_OPTS *opts, const char *keyword ) -{ - int i; - size_t n; - - (void)arg; - - /* Would be better if we can do a binary search, but it is not - possible to reorder our option table because we would mess - up our help strings - What we can do is: Build a nice option - lookup table wehn this function is first invoked */ - if( !*keyword ) - return -1; - for(i=0; opts[i].short_opt; i++ ) - if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) ) - return i; -#if 0 - { - ALIAS_DEF a; - /* see whether it is an alias */ - for( a = args->internal.aliases; a; a = a->next ) { - if( !strcmp( a->name, keyword) ) { - /* todo: must parse the alias here */ - args->internal.cur_alias = a; - return -3; /* alias available */ - } - } - } -#endif - /* not found, see whether it is an abbreviation */ - /* aliases may not be abbreviated */ - n = strlen( keyword ); - for(i=0; opts[i].short_opt; i++ ) { - if( opts[i].long_opt && !strncmp( opts[i].long_opt, keyword, n ) ) { - int j; - for(j=i+1; opts[j].short_opt; j++ ) { - if( opts[j].long_opt - && !strncmp( opts[j].long_opt, keyword, n ) ) - return -2; /* abbreviation is ambiguous */ - } - return i; - } - } - return -1; -} - -int -arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts) -{ - int idx; - int argc; - char **argv; - char *s, *s2; - int i; - - initialize( arg, NULL, NULL ); - argc = *arg->argc; - argv = *arg->argv; - idx = arg->internal.idx; - - if (!idx && argc && !(arg->flags & ARGPARSE_FLAG_ARG0)) - { - /* Skip the first argument. */ - argc--; argv++; idx++; - } - - next_one: - if (!argc) - { - /* No more args. */ - arg->r_opt = 0; - goto leave; /* Ready. */ - } - - s = *argv; - arg->internal.last = s; - - if (arg->internal.stopped && (arg->flags & ARGPARSE_FLAG_ALL)) - { - arg->r_opt = ARGPARSE_IS_ARG; /* Not an option but an argument. */ - arg->r_type = 2; - arg->r.ret_str = s; - argc--; argv++; idx++; /* set to next one */ - } - else if( arg->internal.stopped ) - { - arg->r_opt = 0; - goto leave; /* Ready. */ - } - else if ( *s == '-' && s[1] == '-' ) - { - /* Long option. */ - char *argpos; - - arg->internal.inarg = 0; - if (!s[2] && !(arg->flags & ARGPARSE_FLAG_NOSTOP)) - { - /* Stop option processing. */ - arg->internal.stopped = 1; - argc--; argv++; idx++; - goto next_one; - } - - argpos = strchr( s+2, '=' ); - if ( argpos ) - *argpos = 0; - i = find_long_option ( arg, opts, s+2 ); - if ( argpos ) - *argpos = '='; - - if ( i < 0 && !strcmp ( "help", s+2) ) - show_help (opts, arg->flags); - else if ( i < 0 && !strcmp ( "version", s+2) ) - { - if (!(arg->flags & ARGPARSE_FLAG_NOVERSION)) - { - show_version (); - exit(0); - } - } - else if ( i < 0 && !strcmp( "warranty", s+2)) - { - puts ( strusage (16) ); - exit (0); - } - else if ( i < 0 && !strcmp( "dump-options", s+2) ) - { - for (i=0; opts[i].short_opt; i++ ) - { - if ( opts[i].long_opt ) - printf ("--%s\n", opts[i].long_opt); - } - fputs ("--dump-options\n--help\n--version\n--warranty\n", stdout); - exit (0); - } - - if ( i == -2 ) - arg->r_opt = ARGPARSE_AMBIGUOUS_OPTION; - else if ( i == -1 ) - { - arg->r_opt = ARGPARSE_INVALID_OPTION; - arg->r.ret_str = s+2; - } - else - arg->r_opt = opts[i].short_opt; - if ( i < 0 ) - ; - else if ( (opts[i].flags & 0x07) ) - { - if ( argpos ) - { - s2 = argpos+1; - if ( !*s2 ) - s2 = NULL; - } - else - s2 = argv[1]; - if ( !s2 && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) ) - { - arg->r_type = ARGPARSE_TYPE_NONE; /* Argument is optional. */ - } - else if ( !s2 ) - { - arg->r_opt = ARGPARSE_MISSING_ARG; - } - else if ( !argpos && *s2 == '-' - && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) ) - { - /* The argument is optional and the next seems to be an - option. We do not check this possible option but - assume no argument */ - arg->r_type = ARGPARSE_TYPE_NONE; - } - else - { - set_opt_arg (arg, opts[i].flags, s2); - if ( !argpos ) - { - argc--; argv++; idx++; /* Skip one. */ - } - } - } - else - { - /* Does not take an argument. */ - if ( argpos ) - arg->r_type = ARGPARSE_UNEXPECTED_ARG; - else - arg->r_type = 0; - } - argc--; argv++; idx++; /* Set to next one. */ - } - else if ( (*s == '-' && s[1]) || arg->internal.inarg ) - { - /* Short option. */ - int dash_kludge = 0; - - i = 0; - if ( !arg->internal.inarg ) - { - arg->internal.inarg++; - if ( (arg->flags & ARGPARSE_FLAG_ONEDASH) ) - { - for (i=0; opts[i].short_opt; i++ ) - if ( opts[i].long_opt && !strcmp (opts[i].long_opt, s+1)) - { - dash_kludge = 1; - break; - } - } - } - s += arg->internal.inarg; - - if (!dash_kludge ) - { - for (i=0; opts[i].short_opt; i++ ) - if ( opts[i].short_opt == *s ) - break; - } - - if ( !opts[i].short_opt && ( *s == 'h' || *s == '?' ) ) - show_help (opts, arg->flags); - - arg->r_opt = opts[i].short_opt; - if (!opts[i].short_opt ) - { - arg->r_opt = (opts[i].flags & ARGPARSE_OPT_COMMAND)? - ARGPARSE_INVALID_COMMAND:ARGPARSE_INVALID_OPTION; - arg->internal.inarg++; /* Point to the next arg. */ - arg->r.ret_str = s; - } - else if ( (opts[i].flags & 7) ) - { - if ( s[1] && !dash_kludge ) - { - s2 = s+1; - set_opt_arg (arg, opts[i].flags, s2); - } - else - { - s2 = argv[1]; - if ( !s2 && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) ) - { - arg->r_type = ARGPARSE_TYPE_NONE; - } - else if ( !s2 ) - { - arg->r_opt = ARGPARSE_MISSING_ARG; - } - else if ( *s2 == '-' && s2[1] - && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) ) - { - /* The argument is optional and the next seems to - be an option. We do not check this possible - option but assume no argument. */ - arg->r_type = ARGPARSE_TYPE_NONE; - } - else - { - set_opt_arg (arg, opts[i].flags, s2); - argc--; argv++; idx++; /* Skip one. */ - } - } - s = "x"; /* This is so that !s[1] yields false. */ - } - else - { - /* Does not take an argument. */ - arg->r_type = ARGPARSE_TYPE_NONE; - arg->internal.inarg++; /* Point to the next arg. */ - } - if ( !s[1] || dash_kludge ) - { - /* No more concatenated short options. */ - arg->internal.inarg = 0; - argc--; argv++; idx++; - } - } - else if ( arg->flags & ARGPARSE_FLAG_MIXED ) - { - arg->r_opt = ARGPARSE_IS_ARG; - arg->r_type = 2; - arg->r.ret_str = s; - argc--; argv++; idx++; /* Set to next one. */ - } - else - { - arg->internal.stopped = 1; /* Stop option processing. */ - goto next_one; - } - - leave: - *arg->argc = argc; - *arg->argv = argv; - arg->internal.idx = idx; - return arg->r_opt; -} - - - -static int -set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s) -{ - int base = (flags & 16)? 0 : 10; - - switch ( (arg->r_type = (flags & 7)) ) - { - case ARGPARSE_TYPE_INT: - arg->r.ret_int = (int)strtol(s,NULL,base); - return 0; - case ARGPARSE_TYPE_LONG: - arg->r.ret_long= strtol(s,NULL,base); - return 0; - case ARGPARSE_TYPE_ULONG: - arg->r.ret_ulong= strtoul(s,NULL,base); - return 0; - case ARGPARSE_TYPE_STRING: - default: - arg->r.ret_str = s; - return 1; - } -} - - -static size_t -long_opt_strlen( ARGPARSE_OPTS *o ) -{ - size_t n = strlen (o->long_opt); - - if ( o->description && *o->description == '|' ) - { - const char *s; -#ifdef JNLIB_NEED_UTF8CONV - int is_utf8 = is_native_utf8 (); -#endif - - s=o->description+1; - if ( *s != '=' ) - n++; - /* For a (mostly) correct length calculation we exclude - continuation bytes (10xxxxxx) if we are on a native utf8 - terminal. */ - for (; *s && *s != '|'; s++ ) -#ifdef JNLIB_NEED_UTF8CONV - if ( is_utf8 && (*s&0xc0) != 0x80 ) -#endif - n++; - } - return n; -} - - -/**************** - * Print formatted help. The description string has some special - * meanings: - * - A description string which is "@" suppresses help output for - * this option - * - a description,ine which starts with a '@' and is followed by - * any other characters is printed as is; this may be used for examples - * ans such. - * - A description which starts with a '|' outputs the string between this - * bar and the next one as arguments of the long option. - */ -static void -show_help (ARGPARSE_OPTS *opts, unsigned int flags) -{ - const char *s; - - show_version (); - putchar ('\n'); - s = strusage(41); - puts (s); - if ( opts[0].description ) - { - /* Auto format the option description. */ - int i,j, indent; - - /* Get max. length of long options. */ - for (i=indent=0; opts[i].short_opt; i++ ) - { - if ( opts[i].long_opt ) - if ( !opts[i].description || *opts[i].description != '@' ) - if ( (j=long_opt_strlen(opts+i)) > indent && j < 35 ) - indent = j; - } - - /* Example: " -v, --verbose Viele Sachen ausgeben" */ - indent += 10; - if ( *opts[0].description != '@' ) - puts ("Options:"); - for (i=0; opts[i].short_opt; i++ ) - { - s = _( opts[i].description ); - if ( s && *s== '@' && !s[1] ) /* Hide this line. */ - continue; - if ( s && *s == '@' ) /* Unindented comment only line. */ - { - for (s++; *s; s++ ) - { - if ( *s == '\n' ) - { - if( s[1] ) - putchar('\n'); - } - else - putchar(*s); - } - putchar('\n'); - continue; - } - - j = 3; - if ( opts[i].short_opt < 256 ) - { - printf (" -%c", opts[i].short_opt); - if ( !opts[i].long_opt ) - { - if (s && *s == '|' ) - { - putchar (' '); j++; - for (s++ ; *s && *s != '|'; s++, j++ ) - putchar (*s); - if ( *s ) - s++; - } - } - } - else - fputs(" ", stdout); - if ( opts[i].long_opt ) - { - j += printf ("%c --%s", opts[i].short_opt < 256?',':' ', - opts[i].long_opt ); - if (s && *s == '|' ) - { - if ( *++s != '=' ) - { - putchar(' '); - j++; - } - for ( ; *s && *s != '|'; s++, j++ ) - putchar(*s); - if ( *s ) - s++; - } - fputs (" ", stdout); - j += 3; - } - for (;j < indent; j++ ) - putchar(' '); - if ( s ) - { - if ( *s && j > indent ) - { - putchar('\n'); - for (j=0;j < indent; j++ ) - putchar (' '); - } - for (; *s; s++ ) - { - if ( *s == '\n' ) - { - if ( s[1] ) - { - putchar ('\n'); - for (j=0; j < indent; j++ ) - putchar (' '); - } - } - else - putchar (*s); - } - } - putchar ('\n'); - } - if ( (flags & ARGPARSE_FLAG_ONEDASH) ) - puts ("\n(A single dash may be used instead of the double ones)"); - } - if ( (s=strusage(19)) ) - { - /* bug reports to ... */ - char *s2; - - putchar('\n'); - s2 = strstr (s, "@EMAIL@"); - if (s2) - { - if (s2-s) - fwrite (s, s2-s, 1, stdout); -#ifdef PACKAGE_BUGREPORT - fputs (PACKAGE_BUGREPORT, stdout); -#else - fputs ("bug@example.org", stdout); -#endif - s2 += 7; - if (*s2) - fputs (s2, stdout); - } - else - fputs(s, stdout); - } - fflush(stdout); - exit(0); -} - -static void -show_version () -{ - const char *s; - int i; - - /* Version line. */ - fputs (strusage (11), stdout); - if ((s=strusage (12))) - printf (" (%s)", s ); - printf (" %s\n", strusage (13) ); - /* Additional version lines. */ - for (i=20; i < 30; i++) - if ((s=strusage (i))) - printf ("%s\n", s ); - /* Copyright string. */ - if( (s=strusage (14)) ) - printf("%s\n", s ); - /* Licence string. */ - if( (s=strusage (10)) ) - printf("%s\n", s ); - /* Copying conditions. */ - if ( (s=strusage(15)) ) - fputs (s, stdout); - /* Thanks. */ - if ((s=strusage(18))) - fputs (s, stdout); - /* Additional program info. */ - for (i=30; i < 40; i++ ) - if ( (s=strusage (i)) ) - fputs (s, stdout); - fflush (stdout); -} - - -void -usage (int level) -{ - const char *p; - - if (!level) - { - fprintf(stderr,"%s %s; %s\n", strusage(11), strusage(13), strusage (14)); - fflush (stderr); - } - else if (level == 1) - { - p = strusage (40); - fputs (p, stderr); - if (*p && p[strlen(p)] != '\n') - putc ('\n', stderr); - exit (2); - } - else if (level == 2) - { - puts (strusage(41)); - exit (0); - } -} - -/* Level - * 0: Print copyright string to stderr - * 1: Print a short usage hint to stderr and terminate - * 2: Print a long usage hint to stdout and terminate - * 10: Return license info string - * 11: Return the name of the program - * 12: Return optional name of package which includes this program. - * 13: version string - * 14: copyright string - * 15: Short copying conditions (with LFs) - * 16: Long copying conditions (with LFs) - * 17: Optional printable OS name - * 18: Optional thanks list (with LFs) - * 19: Bug report info - *20..29: Additional lib version strings. - *30..39: Additional program info (with LFs) - * 40: short usage note (with LF) - * 41: long usage note (with LF) - */ -const char * -strusage( int level ) -{ - const char *p = strusage_handler? strusage_handler(level) : NULL; - - if ( p ) - return p; - - switch ( level ) - { - case 10: p = ("License GPLv3+: GNU GPL version 3 or later " - ""); - break; - case 11: p = "foo"; break; - case 13: p = "0.0"; break; - case 14: p = "Copyright (C) 2010 Free Software Foundation, Inc."; break; - case 15: p = -"This is free software: you are free to change and redistribute it.\n" -"There is NO WARRANTY, to the extent permitted by law.\n"; - break; - case 16: p = -"This is free software; you can redistribute it and/or modify\n" -"it under the terms of the GNU General Public License as published by\n" -"the Free Software Foundation; either version 3 of the License, or\n" -"(at your option) any later version.\n\n" -"It is distributed in the hope that it will be useful,\n" -"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" -"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" -"GNU General Public License for more details.\n\n" -"You should have received a copy of the GNU General Public License\n" -"along with this software. If not, see .\n"; - break; - case 40: /* short and long usage */ - case 41: p = ""; break; - } - - return p; -} - -void -set_strusage ( const char *(*f)( int ) ) -{ - strusage_handler = f; -} - - -#ifdef TEST -static struct { - int verbose; - int debug; - char *outfile; - char *crf; - int myopt; - int echo; - int a_long_one; -}opt; - -int -main(int argc, char **argv) -{ - ARGPARSE_OPTS opts[] = { - ARGPARSE_x('v', "verbose", NONE, 0, "Laut sein"), - ARGPARSE_s_n('e', "echo" , ("Zeile ausgeben, damit wir sehen, " - "was wir ein gegeben haben")), - ARGPARSE_s_n('d', "debug", "Debug\nfalls mal etwas\nschief geht"), - ARGPARSE_s_s('o', "output", 0 ), - ARGPARSE_o_s('c', "cross-ref", "cross-reference erzeugen\n" ), - /* Note that on a non-utf8 terminal the ß might garble the output. */ - ARGPARSE_s_n('s', "street","|Straße|set the name of the street to Straße"), - ARGPARSE_o_i('m', "my-option", 0), - ARGPARSE_s_n(500, "a-long-option", 0 ), - ARGPARSE_end - }; - ARGPARSE_ARGS pargs = { &argc, &argv, 2|4|32 }; - int i; - - while( arg_parse ( &pargs, opts) ) { - switch( pargs.r_opt ) { - case -1 : printf( "arg=`%s'\n", pargs.r.ret_str); break; - case 'v': opt.verbose++; break; - case 'e': opt.echo++; break; - case 'd': opt.debug++; break; - case 'o': opt.outfile = pargs.r.ret_str; break; - case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break; - case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break; - case 500: opt.a_long_one++; break; - default : pargs.err = ARGPARSE_PRINT_WARNING; break; - } - } - for(i=0; i < argc; i++ ) - printf("%3d -> (%s)\n", i, argv[i] ); - puts("Options:"); - if( opt.verbose ) - printf(" verbose=%d\n", opt.verbose ); - if( opt.debug ) - printf(" debug=%d\n", opt.debug ); - if( opt.outfile ) - printf(" outfile=`%s'\n", opt.outfile ); - if( opt.crf ) - printf(" crffile=`%s'\n", opt.crf ); - if( opt.myopt ) - printf(" myopt=%d\n", opt.myopt ); - if( opt.a_long_one ) - printf(" a-long-one=%d\n", opt.a_long_one ); - if( opt.echo ) - printf(" echo=%d\n", opt.echo ); - return 0; -} -#endif - -/**** bottom of file ****/ diff --git a/jnlib/argparse.h b/jnlib/argparse.h deleted file mode 100644 index b211e5fdf..000000000 --- a/jnlib/argparse.h +++ /dev/null @@ -1,183 +0,0 @@ -/* argparse.h - Argument parser for option handling. - * Copyright (C) 1998,1999,2000,2001,2006 Free Software Foundation, Inc. - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#ifndef LIBJNLIB_ARGPARSE_H -#define LIBJNLIB_ARGPARSE_H - -#include -#include "types.h" - -typedef struct -{ - int *argc; /* Pointer to ARGC (value subject to change). */ - char ***argv; /* Pointer to ARGV (value subject to change). */ - unsigned int flags; /* Global flags. May be set prior to calling the - parser. The parser may change the value. */ - int err; /* Print error description for last option. - Either 0, ARGPARSE_PRINT_WARNING or - ARGPARSE_PRINT_ERROR. */ - - int r_opt; /* Returns option code. */ - int r_type; /* Returns type of option value. */ - union { - int ret_int; - long ret_long; - unsigned long ret_ulong; - char *ret_str; - } r; /* Return values */ - - struct { - int idx; - int inarg; - int stopped; - const char *last; - void *aliases; - const void *cur_alias; - } internal; /* Private - do not change. */ -} ARGPARSE_ARGS; - -typedef struct -{ - int short_opt; - const char *long_opt; - unsigned int flags; - const char *description; /* Optional option description. */ -} ARGPARSE_OPTS; - - -/* Global flags (ARGPARSE_ARGS). */ -#define ARGPARSE_FLAG_KEEP 1 /* Do not remove options form argv. */ -#define ARGPARSE_FLAG_ALL 2 /* Do not stop at last option but return - remaining args with R_OPT set to -1. */ -#define ARGPARSE_FLAG_MIXED 4 /* Assume options and args are mixed. */ -#define ARGPARSE_FLAG_NOSTOP 8 /* Do not stop processing at "--". */ -#define ARGPARSE_FLAG_ARG0 16 /* Do not skip the first arg. */ -#define ARGPARSE_FLAG_ONEDASH 32 /* Allow long options with one dash. */ -#define ARGPARSE_FLAG_NOVERSION 64 /* No output for "--version". */ - -/* Flags for each option (ARGPARSE_OPTS). The type code may be - ORed with the OPT flags. */ -#define ARGPARSE_TYPE_NONE 0 /* Does not take an argument. */ -#define ARGPARSE_TYPE_INT 1 /* Takes an int argument. */ -#define ARGPARSE_TYPE_STRING 2 /* Takes a string argument. */ -#define ARGPARSE_TYPE_LONG 3 /* Takes a long argument. */ -#define ARGPARSE_TYPE_ULONG 4 /* Takes an unsigned long argument. */ -#define ARGPARSE_OPT_OPTIONAL (1<<3) /* Argument is optional. */ -#define ARGPARSE_OPT_PREFIX (1<<4) /* Allow 0x etc. prefixed values. */ -#define ARGPARSE_OPT_COMMAND (1<<8) /* The argument is a command. */ - -/* A set of macros to make option definitions easier to read. */ -#define ARGPARSE_x(s,l,t,f,d) \ - { (s), (l), ARGPARSE_TYPE_ ## t | (f), (d) } - -#define ARGPARSE_s(s,l,t,d) \ - { (s), (l), ARGPARSE_TYPE_ ## t, (d) } -#define ARGPARSE_s_n(s,l,d) \ - { (s), (l), ARGPARSE_TYPE_NONE, (d) } -#define ARGPARSE_s_i(s,l,d) \ - { (s), (l), ARGPARSE_TYPE_INT, (d) } -#define ARGPARSE_s_s(s,l,d) \ - { (s), (l), ARGPARSE_TYPE_STRING, (d) } -#define ARGPARSE_s_l(s,l,d) \ - { (s), (l), ARGPARSE_TYPE_LONG, (d) } -#define ARGPARSE_s_u(s,l,d) \ - { (s), (l), ARGPARSE_TYPE_ULONG, (d) } - -#define ARGPARSE_o(s,l,t,d) \ - { (s), (l), (ARGPARSE_TYPE_ ## t | ARGPARSE_OPT_OPTIONAL), (d) } -#define ARGPARSE_o_n(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_OPTIONAL), (d) } -#define ARGPARSE_o_i(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_INT | ARGPARSE_OPT_OPTIONAL), (d) } -#define ARGPARSE_o_s(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_STRING | ARGPARSE_OPT_OPTIONAL), (d) } -#define ARGPARSE_o_l(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_LONG | ARGPARSE_OPT_OPTIONAL), (d) } -#define ARGPARSE_o_u(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_ULONG | ARGPARSE_OPT_OPTIONAL), (d) } - -#define ARGPARSE_p(s,l,t,d) \ - { (s), (l), (ARGPARSE_TYPE_ ## t | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_p_n(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_p_i(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_INT | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_p_s(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_STRING | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_p_l(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_LONG | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_p_u(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_ULONG | ARGPARSE_OPT_PREFIX), (d) } - -#define ARGPARSE_op(s,l,t,d) \ - { (s), (l), (ARGPARSE_TYPE_ ## t \ - | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_op_n(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_NONE \ - | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_op_i(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_INT \ - | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_op_s(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_STRING \ - | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_op_l(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_LONG \ - | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_op_u(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_ULONG \ - | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } - -#define ARGPARSE_c(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_COMMAND), (d) } - - -#define ARGPARSE_group(s,d) \ - { (s), NULL, 0, (d) } - -#define ARGPARSE_end() { 0, NULL, 0, NULL } - - -/* Other constants. */ -#define ARGPARSE_PRINT_WARNING 1 -#define ARGPARSE_PRINT_ERROR 2 - - -/* Error values. */ -#define ARGPARSE_IS_ARG (-1) -#define ARGPARSE_INVALID_OPTION (-2) -#define ARGPARSE_MISSING_ARG (-3) -#define ARGPARSE_KEYWORD_TOO_LONG (-4) -#define ARGPARSE_READ_ERROR (-5) -#define ARGPARSE_UNEXPECTED_ARG (-6) -#define ARGPARSE_INVALID_COMMAND (-7) -#define ARGPARSE_AMBIGUOUS_OPTION (-8) -#define ARGPARSE_AMBIGUOUS_COMMAND (-9) -#define ARGPARSE_INVALID_ALIAS (-10) -#define ARGPARSE_OUT_OF_CORE (-11) - - -int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts); -int optfile_parse( FILE *fp, const char *filename, unsigned *lineno, - ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts); -void usage( int level ); -const char *strusage( int level ); -void set_strusage( const char *(*f)( int ) ); - -#endif /*LIBJNLIB_ARGPARSE_H*/ diff --git a/jnlib/dotlock.c b/jnlib/dotlock.c deleted file mode 100644 index 0d5a7bce9..000000000 --- a/jnlib/dotlock.c +++ /dev/null @@ -1,713 +0,0 @@ -/* dotlock.c - dotfile locking - * Copyright (C) 1998, 2000, 2001, 2003, 2004, - * 2005, 2006, 2008 Free Software Foundation, Inc. - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_DOSISH_SYSTEM -# define WIN32_LEAN_AND_MEAN -# include -#else -# include -#endif -#include -#include -#include -#include -#ifdef HAVE_SIGNAL_H -# include -#endif - -#include "libjnlib-config.h" -#include "stringhelp.h" -#include "dotlock.h" -#include "utf8conv.h" - -#if !defined(DIRSEP_C) && !defined(EXTSEP_C) \ - && !defined(DIRSEP_S) && !defined(EXTSEP_S) -#ifdef HAVE_DOSISH_SYSTEM -#define DIRSEP_C '\\' -#define EXTSEP_C '.' -#define DIRSEP_S "\\" -#define EXTSEP_S "." -#else -#define DIRSEP_C '/' -#define EXTSEP_C '.' -#define DIRSEP_S "/" -#define EXTSEP_S "." -#endif -#endif - - -/* The object describing a lock. */ -struct dotlock_handle -{ - struct dotlock_handle *next; - char *lockname; /* Name of the actual lockfile. */ - int locked; /* Lock status. */ - int disable; /* If true, locking is disabled. */ - -#ifdef HAVE_DOSISH_SYSTEM - HANDLE lockhd; /* The W32 handle of the lock file. */ -#else - char *tname; /* Name of the lockfile template. */ - size_t nodename_off; /* Offset in TNAME of the nodename part. */ - size_t nodename_len; /* Length of the nodename part. */ -#endif /* HAVE_DOSISH_SYSTEM */ -}; - - -/* A list of of all lock handles. */ -static volatile dotlock_t all_lockfiles; - -/* If this has the value true all locking is disabled. */ -static int never_lock; - - -/* Local protototypes. */ -#ifndef HAVE_DOSISH_SYSTEM -static int read_lockfile (dotlock_t h, int *same_node); -#endif /*!HAVE_DOSISH_SYSTEM*/ - - - - -/* Entirely disable all locking. This function should be called - before any locking is done. It may be called right at startup of - the process as it only sets a global value. */ -void -disable_dotlock(void) -{ - never_lock = 1; -} - - - -/* Create a lockfile for a file name FILE_TO_LOCK and returns an - object of type dotlock_t which may be used later to actually acquire - the lock. A cleanup routine gets installed to cleanup left over - locks or other files used internally by the lock mechanism. - - Calling this function with NULL does only install the atexit - handler and may thus be used to assure that the cleanup is called - after all other atexit handlers. - - This function creates a lock file in the same directory as - FILE_TO_LOCK using that name and a suffix of ".lock". Note that on - POSIX systems a temporary file ".#lk..pid[.threadid] is - used. - - The function returns an new handle which needs to be released using - destroy_dotlock but gets also released at the termination of the - process. On error NULL is returned. - */ -dotlock_t -create_dotlock (const char *file_to_lock) -{ - static int initialized; - dotlock_t h; -#ifndef HAVE_DOSISH_SYSTEM - int fd = -1; - char pidstr[16]; - const char *nodename; - const char *dirpart; - int dirpartlen; - struct utsname utsbuf; - size_t tnamelen; -#endif - - if ( !initialized ) - { - atexit (dotlock_remove_lockfiles); - initialized = 1; - } - - if ( !file_to_lock ) - return NULL; /* Only initialization was requested. */ - - h = jnlib_calloc (1, sizeof *h); - if (!h) - return NULL; - - if (never_lock) - { - h->disable = 1; -#ifdef _REENTRANT - /* fixme: aquire mutex on all_lockfiles */ -#endif - h->next = all_lockfiles; - all_lockfiles = h; - return h; - } - -#ifndef HAVE_DOSISH_SYSTEM - /* - This is the POSIX version which uses a temporary file and the - link system call to make locking an atomic operation. - */ - - snprintf (pidstr, sizeof pidstr, "%10d\n", (int)getpid() ); - - /* Create a temporary file. */ - if ( uname ( &utsbuf ) ) - nodename = "unknown"; - else - nodename = utsbuf.nodename; - -#ifdef __riscos__ - { - char *iter = (char *) nodename; - for (; iter[0]; iter++) - if (iter[0] == '.') - iter[0] = '/'; - } -#endif /* __riscos__ */ - - if ( !(dirpart = strrchr (file_to_lock, DIRSEP_C)) ) - { - dirpart = EXTSEP_S; - dirpartlen = 1; - } - else - { - dirpartlen = dirpart - file_to_lock; - dirpart = file_to_lock; - } - -#ifdef _REENTRANT - /* fixme: aquire mutex on all_lockfiles */ -#endif - h->next = all_lockfiles; - all_lockfiles = h; - - tnamelen = dirpartlen + 6 + 30 + strlen(nodename) + 10; - h->tname = jnlib_malloc (tnamelen + 1); - if (!h->tname) - { - all_lockfiles = h->next; - jnlib_free (h); - return NULL; - } - h->nodename_len = strlen (nodename); - -#ifndef __riscos__ - snprintf (h->tname, tnamelen, "%.*s/.#lk%p.", dirpartlen, dirpart, h ); - h->nodename_off = strlen (h->tname); - snprintf (h->tname+h->nodename_off, tnamelen - h->nodename_off, - "%s.%d", nodename, (int)getpid ()); -#else /* __riscos__ */ - snprintf (h->tname, tnamelen, "%.*s.lk%p/", dirpartlen, dirpart, h ); - h->nodename_off = strlen (h->tname); - snprintf (h->tname+h->nodename_off, tnamelen - h->modename_off, - "%s/%d", nodename, (int)getpid () ); -#endif /* __riscos__ */ - - do - { - jnlib_set_errno (0); - fd = open (h->tname, O_WRONLY|O_CREAT|O_EXCL, - S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR ); - } - while (fd == -1 && errno == EINTR); - - if ( fd == -1 ) - { - all_lockfiles = h->next; - log_error (_("failed to create temporary file `%s': %s\n"), - h->tname, strerror(errno)); - jnlib_free (h->tname); - jnlib_free (h); - return NULL; - } - if ( write (fd, pidstr, 11 ) != 11 ) - goto write_failed; - if ( write (fd, nodename, strlen (nodename) ) != strlen (nodename) ) - goto write_failed; - if ( write (fd, "\n", 1 ) != 1 ) - goto write_failed; - if ( close (fd) ) - goto write_failed; - -# ifdef _REENTRANT - /* release mutex */ -# endif - h->lockname = jnlib_malloc ( strlen (file_to_lock) + 6 ); - if (!h->lockname) - { - all_lockfiles = h->next; - unlink (h->tname); - jnlib_free (h->tname); - jnlib_free (h); - return NULL; - } - strcpy (stpcpy (h->lockname, file_to_lock), EXTSEP_S "lock"); - return h; - - write_failed: - all_lockfiles = h->next; -# ifdef _REENTRANT - /* fixme: release mutex */ -# endif - log_error ( _("error writing to `%s': %s\n"), h->tname, strerror(errno) ); - close (fd); - unlink (h->tname); - jnlib_free (h->tname); - jnlib_free (h); - return NULL; - -#else /* HAVE_DOSISH_SYSTEM */ - - /* The Windows version does not need a temporary file but uses the - plain lock file along with record locking. We create this file - here so that we later do only need to do the file locking. For - error reporting it is useful to keep the name of the file in the - handle. */ - h->next = all_lockfiles; - all_lockfiles = h; - - h->lockname = jnlib_malloc ( strlen (file_to_lock) + 6 ); - if (!h->lockname) - { - all_lockfiles = h->next; - jnlib_free (h); - return NULL; - } - strcpy (stpcpy(h->lockname, file_to_lock), EXTSEP_S "lock"); - - /* If would be nice if we would use the FILE_FLAG_DELETE_ON_CLOSE - along with FILE_SHARE_DELETE but that does not work due to a race - condition: Despite the OPEN_ALWAYS flag CreateFile may return an - error and we can't reliable create/open the lock file unless we - would wait here until it works - however there are other valid - reasons why a lock file can't be created and thus the process - would not stop as expected but spin til until Windows crashes. - Our solution is to keep the lock file open; that does not - harm. */ - { -#ifdef HAVE_W32CE_SYSTEM - wchar_t *wname = utf8_to_wchar (h->lockname); - - h->lockhd = INVALID_HANDLE_VALUE; - if (wname) - h->lockhd = CreateFile (wname, -#else - h->lockhd = CreateFile (h->lockname, -#endif - GENERIC_READ|GENERIC_WRITE, - FILE_SHARE_READ|FILE_SHARE_WRITE, - NULL, OPEN_ALWAYS, 0, NULL); -#ifdef HAVE_W32CE_SYSTEM - jnlib_free (wname); -#endif - } - if (h->lockhd == INVALID_HANDLE_VALUE) - { - log_error (_("can't create `%s': %s\n"), h->lockname, w32_strerror (-1)); - all_lockfiles = h->next; - jnlib_free (h->lockname); - jnlib_free (h); - return NULL; - } - return h; - -#endif /* HAVE_DOSISH_SYSTEM */ -} - - -/* Destroy the local handle H and release the lock. */ -void -destroy_dotlock (dotlock_t h) -{ - dotlock_t hprev, htmp; - - if ( !h ) - return; - - /* First remove the handle from our global list of all locks. */ - for (hprev=NULL, htmp=all_lockfiles; htmp; hprev=htmp, htmp=htmp->next) - if (htmp == h) - { - if (hprev) - hprev->next = htmp->next; - else - all_lockfiles = htmp->next; - h->next = NULL; - break; - } - - /* Then destroy the lock. */ - if (!h->disable) - { -#ifdef HAVE_DOSISH_SYSTEM - if (h->locked) - { - UnlockFile (h->lockhd, 0, 0, 1, 0); - } - CloseHandle (h->lockhd); -#else /* !HAVE_DOSISH_SYSTEM */ - if (h->locked && h->lockname) - unlink (h->lockname); - if (h->tname) - unlink (h->tname); - jnlib_free (h->tname); -#endif /* HAVE_DOSISH_SYSTEM */ - jnlib_free (h->lockname); - } - jnlib_free(h); -} - - -#ifndef HAVE_DOSISH_SYSTEM -static int -maybe_deadlock (dotlock_t h) -{ - dotlock_t r; - - for ( r=all_lockfiles; r; r = r->next ) - { - if ( r != h && r->locked ) - return 1; - } - return 0; -} -#endif /*!HAVE_DOSISH_SYSTEM*/ - - - -/* Do a lock on H. A TIMEOUT of 0 returns immediately, -1 waits - forever (hopefully not), other values are reserved (should then be - timeouts in milliseconds). Returns: 0 on success */ -int -make_dotlock (dotlock_t h, long timeout) -{ - int backoff = 0; -#ifndef HAVE_DOSISH_SYSTEM - int pid; - const char *maybe_dead=""; - int same_node; -#endif /*!HAVE_DOSISH_SYSTEM*/ - - if ( h->disable ) - return 0; /* Locks are completely disabled. Return success. */ - - if ( h->locked ) - { -#ifndef __riscos__ - log_debug ("Oops, `%s' is already locked\n", h->lockname); -#endif /* !__riscos__ */ - return 0; - } - - for (;;) - { -#ifndef HAVE_DOSISH_SYSTEM -# ifndef __riscos__ - if ( !link(h->tname, h->lockname) ) - { - /* fixme: better use stat to check the link count */ - h->locked = 1; - return 0; /* okay */ - } - if ( errno != EEXIST ) - { - log_error ( "lock not made: link() failed: %s\n", strerror(errno) ); - return -1; - } -# else /* __riscos__ */ - if ( !renamefile(h->tname, h->lockname) ) - { - h->locked = 1; - return 0; /* okay */ - } - if ( errno != EEXIST ) - { - log_error( "lock not made: rename() failed: %s\n", strerror(errno) ); - return -1; - } -# endif /* __riscos__ */ - - if ( (pid = read_lockfile (h, &same_node)) == -1 ) - { - if ( errno != ENOENT ) - { - log_info ("cannot read lockfile\n"); - return -1; - } - log_info( "lockfile disappeared\n"); - continue; - } - else if ( pid == getpid() && same_node ) - { - log_info( "Oops: lock already held by us\n"); - h->locked = 1; - return 0; /* okay */ - } - else if ( same_node && kill (pid, 0) && errno == ESRCH ) - { -# ifndef __riscos__ - log_info (_("removing stale lockfile (created by %d)\n"), pid ); - unlink (h->lockname); - continue; -# else /* __riscos__ */ - /* Under RISCOS we are *pretty* sure that the other task - is dead and therefore we remove the stale lock file. */ - maybe_dead = _(" - probably dead - removing lock"); - unlink(h->lockname); -# endif /* __riscos__ */ - } - - if ( timeout == -1 ) - { - /* Wait until lock has been released. */ - struct timeval tv; - - log_info (_("waiting for lock (held by %d%s) %s...\n"), - pid, maybe_dead, maybe_deadlock(h)? _("(deadlock?) "):""); - - - /* We can't use sleep, cause signals may be blocked. */ - tv.tv_sec = 1 + backoff; - tv.tv_usec = 0; - select(0, NULL, NULL, NULL, &tv); - if ( backoff < 10 ) - backoff++ ; - } - else - return -1; -#else /*HAVE_DOSISH_SYSTEM*/ - int w32err; - - if (LockFile (h->lockhd, 0, 0, 1, 0)) - { - h->locked = 1; - return 0; /* okay */ - } - w32err = GetLastError (); - if (w32err != ERROR_LOCK_VIOLATION) - { - log_error (_("lock `%s' not made: %s\n"), - h->lockname, w32_strerror (w32err)); - return -1; - } - - if ( timeout == -1 ) - { - /* Wait until lock has been released. */ - log_info (_("waiting for lock %s...\n"), h->lockname); - Sleep ((1 + backoff)*1000); - if ( backoff < 10 ) - backoff++ ; - } - else - return -1; -#endif /*HAVE_DOSISH_SYSTEM*/ - } - /*NOTREACHED*/ -} - - -/* Release a lock. Returns 0 on success. */ -int -release_dotlock (dotlock_t h) -{ -#ifndef HAVE_DOSISH_SYSTEM - int pid, same_node; -#endif - - /* To avoid atexit race conditions we first check whether there are - any locks left. It might happen that another atexit handler - tries to release the lock while the atexit handler of this module - already ran and thus H is undefined. */ - if (!all_lockfiles) - return 0; - - if ( h->disable ) - return 0; - - if ( !h->locked ) - { - log_debug("Oops, `%s' is not locked\n", h->lockname); - return 0; - } - -#ifdef HAVE_DOSISH_SYSTEM - if (!UnlockFile (h->lockhd, 0, 0, 1, 0)) - { - log_error ("release_dotlock: error removing lockfile `%s': %s\n", - h->lockname, w32_strerror (-1)); - return -1; - } -#else - - pid = read_lockfile (h, &same_node); - if ( pid == -1 ) - { - log_error( "release_dotlock: lockfile error\n"); - return -1; - } - if ( pid != getpid() || !same_node ) - { - log_error( "release_dotlock: not our lock (pid=%d)\n", pid); - return -1; - } - -#ifndef __riscos__ - if ( unlink( h->lockname ) ) - { - log_error ("release_dotlock: error removing lockfile `%s'\n", - h->lockname); - return -1; - } - /* Fixme: As an extra check we could check whether the link count is - now really at 1. */ -#else /* __riscos__ */ - if ( renamefile (h->lockname, h->tname) ) - { - log_error ("release_dotlock: error renaming lockfile `%s' to `%s'\n", - h->lockname, h->tname); - return -1; - } -#endif /* __riscos__ */ - -#endif /* !HAVE_DOSISH_SYSTEM */ - h->locked = 0; - return 0; -} - - -/* Read the lock file and return the pid, returns -1 on error. True - will be stored in the integer at address SAME_NODE if the lock file - has been created on the same node. */ -#ifndef HAVE_DOSISH_SYSTEM -static int -read_lockfile (dotlock_t h, int *same_node ) -{ - char buffer_space[10+1+70+1]; /* 70 is just an estimated value; node - name are usually shorter. */ - int fd; - int pid = -1; - char *buffer, *p; - size_t expected_len; - int res, nread; - - *same_node = 0; - expected_len = 10 + 1 + h->nodename_len + 1; - if ( expected_len >= sizeof buffer_space) - { - buffer = jnlib_malloc (expected_len); - if (!buffer) - return -1; - } - else - buffer = buffer_space; - - if ( (fd = open (h->lockname, O_RDONLY)) == -1 ) - { - int e = errno; - log_info ("error opening lockfile `%s': %s\n", - h->lockname, strerror(errno) ); - if (buffer != buffer_space) - jnlib_free (buffer); - jnlib_set_errno (e); /* Need to return ERRNO here. */ - return -1; - } - - p = buffer; - nread = 0; - do - { - res = read (fd, p, expected_len - nread); - if (res == -1 && errno == EINTR) - continue; - if (res < 0) - { - log_info ("error reading lockfile `%s'", h->lockname ); - close (fd); - if (buffer != buffer_space) - jnlib_free (buffer); - jnlib_set_errno (0); /* Do not return an inappropriate ERRNO. */ - return -1; - } - p += res; - nread += res; - } - while (res && nread != expected_len); - close(fd); - - if (nread < 11) - { - log_info ("invalid size of lockfile `%s'", h->lockname ); - if (buffer != buffer_space) - jnlib_free (buffer); - jnlib_set_errno (0); /* Better don't return an inappropriate ERRNO. */ - return -1; - } - - if (buffer[10] != '\n' - || (buffer[10] = 0, pid = atoi (buffer)) == -1 -#ifndef __riscos__ - || !pid -#else /* __riscos__ */ - || (!pid && riscos_getpid()) -#endif /* __riscos__ */ - ) - { - log_error ("invalid pid %d in lockfile `%s'", pid, h->lockname ); - if (buffer != buffer_space) - jnlib_free (buffer); - jnlib_set_errno (0); - return -1; - } - - if (nread == expected_len - && !memcmp (h->tname+h->nodename_off, buffer+11, h->nodename_len) - && buffer[11+h->nodename_len] == '\n') - *same_node = 1; - - if (buffer != buffer_space) - jnlib_free (buffer); - return pid; -} -#endif /* !HAVE_DOSISH_SYSTEM */ - - -/* Remove all lockfiles. This is usually called by the atexit handler - installed by this module but may also be called by other - termination handlers. */ -void -dotlock_remove_lockfiles (void) -{ - dotlock_t h, h2; - - h = all_lockfiles; - all_lockfiles = NULL; - - while ( h ) - { - h2 = h->next; - destroy_dotlock (h); - h = h2; - } -} - diff --git a/jnlib/dotlock.h b/jnlib/dotlock.h deleted file mode 100644 index 407a80b37..000000000 --- a/jnlib/dotlock.h +++ /dev/null @@ -1,33 +0,0 @@ -/* dotlock.h - * Copyright (C) 2000, 2001, 2006 Free Software Foundation, Inc. - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#ifndef LIBJNLIB_DOTLOCK_H -#define LIBJNLIB_DOTLOCK_H - -struct dotlock_handle; -typedef struct dotlock_handle *dotlock_t; - -void disable_dotlock (void); -dotlock_t create_dotlock (const char *file_to_lock); -void destroy_dotlock ( dotlock_t h ); -int make_dotlock (dotlock_t h, long timeout); -int release_dotlock (dotlock_t h); -void dotlock_remove_lockfiles (void); - -#endif /*LIBJNLIB_DOTLOCK_H*/ diff --git a/jnlib/dynload.h b/jnlib/dynload.h deleted file mode 100644 index 0c8a3bbaa..000000000 --- a/jnlib/dynload.h +++ /dev/null @@ -1,86 +0,0 @@ -/* dynload.h - Wrapper functions for run-time dynamic loading - * Copyright (C) 2003, 2010 Free Software Foundation, Inc. - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#ifndef LIBJNLIB_DYNLOAD_H -#define LIBJNLIB_DYNLOAD_H - -#ifndef __MINGW32__ -# include -#else -# include -# include "utf8conv.h" -# include "mischelp.h" -# define RTLD_LAZY 0 - -static inline void * -dlopen (const char *name, int flag) -{ - void *hd; -#ifdef HAVE_W32CE_SYSTEM - wchar_t *wname = utf8_to_wchar (name); - hd = wname? LoadLibrary (wname) : NULL; - _jnlib_free (wname); -#else - hd = LoadLibrary (name); -#endif - (void)flag; - return hd; -} - -static inline void * -dlsym (void *hd, const char *sym) -{ - if (hd && sym) - { -#ifdef HAVE_W32CE_SYSTEM - wchar_t *wsym = utf8_to_wchar (sym); - void *fnc = wsym? GetProcAddress (hd, wsym) : NULL; - _jnlib_free (wsym); -#else - void *fnc = GetProcAddress (hd, sym); -#endif - if (!fnc) - return NULL; - return fnc; - } - return NULL; -} - - -static inline const char * -dlerror (void) -{ - static char buf[32]; - snprintf (buf, sizeof buf, "ec=%lu", GetLastError ()); - return buf; -} - - -static inline int -dlclose (void * hd) -{ - if (hd) - { - CloseHandle (hd); - return 0; - } - return -1; -} -# endif /*__MINGW32__*/ -#endif /*LIBJNLIB_DYNLOAD_H*/ diff --git a/jnlib/libjnlib-config.h b/jnlib/libjnlib-config.h deleted file mode 100644 index 621e89feb..000000000 --- a/jnlib/libjnlib-config.h +++ /dev/null @@ -1,99 +0,0 @@ -/* libjnlib-config.h - local configuration of the jnlib functions - * Copyright (C) 2000, 2001, 2006 Free Software Foundation, Inc. - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -/**************** - * This header is to be included only by the files in this directory - * it should not be used by other modules. - */ - -#ifndef LIBJNLIB_CONFIG_H -#define LIBJNLIB_CONFIG_H - -#include /* gcry_malloc & Cie. */ -#include "logging.h" - -/* We require support for utf-8 conversion. */ -#define JNLIB_NEED_UTF8CONV 1 - - - -#if !defined(JNLIB_NEED_UTF8CONV) && defined(HAVE_W32_SYSTEM) -#define JNLIB_NEED_UTF8CONV 1 -#endif - -/* Gettext stuff */ -#ifdef USE_SIMPLE_GETTEXT -# include -# define _(a) gettext (a) -# define N_(a) (a) - -#else -#ifdef HAVE_LOCALE_H -# include -#endif - -#ifdef ENABLE_NLS -# include -# define _(a) gettext (a) -# ifdef gettext_noop -# define N_(a) gettext_noop (a) -# else -# define N_(a) (a) -# endif -#else -# define _(a) (a) -# define N_(a) (a) -#endif -#endif /* !USE_SIMPLE_GETTEXT */ - -/* Malloc functions to be used by jnlib. */ -#define jnlib_malloc(a) gcry_malloc( (a) ) -#define jnlib_calloc(a,b) gcry_calloc( (a), (b) ) -#define jnlib_realloc(a,b) gcry_realloc( (a), (b) ) -#define jnlib_strdup(a) gcry_strdup( (a) ) -#define jnlib_xmalloc(a) gcry_xmalloc( (a) ) -#define jnlib_xcalloc(a,b) gcry_xcalloc( (a), (b) ) -#define jnlib_xrealloc(a,n) gcry_xrealloc( (a), (n) ) -#define jnlib_xstrdup(a) gcry_xstrdup( (a) ) -#define jnlib_free(a) gcry_free( (a) ) - -/* Logging functions to be used by jnlib. */ -#define jnlib_log_debug log_debug -#define jnlib_log_info log_info -#define jnlib_log_error log_error -#define jnlib_log_fatal log_fatal -#define jnlib_log_bug log_bug - -/* Wrapper to set ERRNO. */ -#ifdef HAVE_W32CE_SYSTEM -# define jnlib_set_errno(e) gpg_err_set_errno ((e)) -#else -# define jnlib_set_errno(e) do { errno = (e); } while (0) -#endif - -/* Dummy replacement for getenv. */ -#ifndef HAVE_GETENV -#define getenv(a) (NULL) -#endif - -#ifdef HAVE_W32CE_SYSTEM -#define getpid() GetCurrentProcessId () -#endif - -#endif /*LIBJNUTIL_CONFIG_H*/ diff --git a/jnlib/logging.c b/jnlib/logging.c deleted file mode 100644 index 028697b78..000000000 --- a/jnlib/logging.c +++ /dev/null @@ -1,651 +0,0 @@ -/* logging.c - Useful logging functions - * Copyright (C) 1998, 1999, 2000, 2001, 2003, - * 2004, 2005, 2006, 2009 Free Software Foundation, Inc. - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef HAVE_W32_SYSTEM -#include -#include -#endif /*!HAVE_W32_SYSTEM*/ -#include -#include -#include - - -#define JNLIB_NEED_LOG_LOGV 1 -#define JNLIB_NEED_AFLOCAL 1 -#include "libjnlib-config.h" -#include "logging.h" - -#if defined (HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN) -#define USE_FUNWRITER 1 -#endif - -#ifdef HAVE_FOPENCOOKIE -typedef ssize_t my_funopen_hook_ret_t; -typedef size_t my_funopen_hook_size_t; -#else -typedef int my_funopen_hook_ret_t; -typedef int my_funopen_hook_size_t; -#endif - - -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 unsigned long (*get_tid_callback)(void); -static int running_detached; -static int force_prefixes; - -static int missing_lf; -static int errorcount; - - -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. */ -#ifdef USE_FUNWRITER -struct fun_cookie_s { - int fd; - int quiet; - int want_socket; - int is_socket; - char name[1]; -}; - -/* Write NBYTES of BUFFER to file descriptor FD. */ -static int -writen (int fd, const void *buffer, size_t nbytes) -{ - const char *buf = buffer; - 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 my_funopen_hook_ret_t -fun_writer (void *cookie_arg, const char *buffer, my_funopen_hook_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 because detached - processes often close stderr and by writing to file descriptor 2 - we might send the log message to a file not intended for logging - (e.g. a pipe or network connection). */ - if (cookie->want_socket && cookie->fd == -1) - { - /* Not yet open or meanwhile closed due to an error. */ - cookie->is_socket = 0; - cookie->fd = socket (PF_LOCAL, SOCK_STREAM, 0); - if (cookie->fd == -1) - { - if (!cookie->quiet && !running_detached - && isatty (fileno (stderr))) - fprintf (stderr, "failed to create socket for logging: %s\n", - strerror(errno)); - } - else - { - struct sockaddr_un addr; - size_t addrlen; - - 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 = SUN_LEN (&addr); - - if (connect (cookie->fd, (struct sockaddr *) &addr, addrlen) == -1) - { - if (!cookie->quiet && !running_detached - && isatty (fileno (stderr))) - fprintf (stderr, "can't connect to `%s': %s\n", - cookie->name, strerror(errno)); - close (cookie->fd); - cookie->fd = -1; - } - } - - if (cookie->fd == -1) - { - if (!running_detached) - { - /* Due to all the problems with apps not running - detached but being called with stderr closed or - used for a different purposes, it does not make - sense to switch to stderr. We therefore disable it. */ - if (!cookie->quiet) - { - /* fputs ("switching logging to stderr\n", stderr);*/ - cookie->quiet = 1; - } - cookie->fd = -1; /*fileno (stderr);*/ - } - } - else /* Connection has been established. */ - { - cookie->quiet = 0; - cookie->is_socket = 1; - } - } - - log_socket = cookie->fd; - if (cookie->fd != -1 && !writen (cookie->fd, buffer, size)) - return (my_funopen_hook_ret_t)size; /* Okay. */ - - if (!running_detached && cookie->fd != -1 - && isatty (fileno (stderr))) - { - if (*cookie->name) - fprintf (stderr, "error writing to `%s': %s\n", - cookie->name, strerror(errno)); - else - fprintf (stderr, "error writing to file descriptor %d: %s\n", - cookie->fd, strerror(errno)); - } - if (cookie->is_socket && cookie->fd != -1) - { - close (cookie->fd); - cookie->fd = -1; - log_socket = -1; - } - - return (my_funopen_hook_ret_t)size; -} - -static int -fun_closer (void *cookie_arg) -{ - struct fun_cookie_s *cookie = cookie_arg; - - if (cookie->fd != -1 && cookie->fd != 2) - close (cookie->fd); - jnlib_free (cookie); - log_socket = -1; - return 0; -} -#endif /*USE_FUNWRITER*/ - - - -/* Common function to either set the logging to a file or a file - descriptor. */ -static void -set_file_fd (const char *name, int fd) -{ - FILE *fp; - int want_socket; -#ifdef USE_FUNWRITER - struct fun_cookie_s *cookie; -#endif - - /* Close an open log stream. */ - if (logstream) - { - if (logstream != stderr && logstream != stdout) - fclose (logstream); - logstream = NULL; - } - - /* Figure out what kind of logging we want. */ - if (name && !strcmp (name, "-")) - { - name = NULL; - fd = fileno (stderr); - } - - if (name) - { - want_socket = (!strncmp (name, "socket://", 9) && name[9]); - if (want_socket) - name += 9; - } - else - { - want_socket = 0; - } - - /* Setup a new stream. */ -#ifdef USE_FUNWRITER - /* The xmalloc below is justified because we can expect that this - function is called only during initialization and there is no - easy way out of this error condition. */ - cookie = jnlib_xmalloc (sizeof *cookie + (name? strlen (name):0)); - strcpy (cookie->name, name? name:""); - cookie->quiet = 0; - cookie->is_socket = 0; - cookie->want_socket = want_socket; - if (!name) - cookie->fd = fd; - else if (want_socket) - cookie->fd = -1; - else - { - do - cookie->fd = open (name, O_WRONLY|O_APPEND|O_CREAT, - (S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWGRP|S_IWOTH)); - while (cookie->fd == -1 && errno == EINTR); - } - log_socket = cookie->fd; - -#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 /*!USE_FUNWRITER*/ - - /* The system does not feature custom streams. Thus fallback to - plain stdio. */ - if (want_socket) - { - fprintf (stderr, "system does not support logging to a socket - " - "using stderr\n"); - fp = stderr; - } - else if (name) - fp = fopen (name, "a"); - else if (fd == 1) - fp = stdout; - else if (fd == 2) - fp = stderr; - else - fp = fdopen (fd, "a"); - - log_socket = -1; - -#endif /*!USE_FUNWRITER*/ - - /* On error default to stderr. */ - if (!fp) - { - if (name) - fprintf (stderr, "failed to open log file `%s': %s\n", - name, strerror(errno)); - else - fprintf (stderr, "failed to fdopen file descriptor %d: %s\n", - fd, strerror(errno)); - /* We need to make sure that there is a log stream. We use stderr. */ - fp = stderr; - } - else - setvbuf (fp, NULL, _IOLBF, 0); - - logstream = fp; - - /* We always need to print the prefix and the pid for socket mode, - so that the server reading the socket can do something - meaningful. */ - force_prefixes = want_socket; - - missing_lf = 0; -} - - -/* Set the file to write log to. The special names NULL and "-" may - be used to select stderr and names formatted like - "socket:///home/foo/mylogs" may be used to write the logging to the - socket "/home/foo/mylogs". If the connection to the socket fails - or a write error is detected, the function writes to stderr and - tries the next time again to connect the socket. - */ -void -log_set_file (const char *name) -{ - set_file_fd (name? name: "-", -1); -} - -void -log_set_fd (int fd) -{ - set_file_fd (NULL, fd); -} - - -void -log_set_get_tid_callback (unsigned long (*cb)(void)) -{ - get_tid_callback = cb; -} - - -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 (logstream) - { - int tmp = fileno (logstream); - if ( tmp != -1 && tmp == fd) - return 1; - } - if (log_socket != -1 && log_socket == fd) - return 1; - return 0; -} - -int -log_get_fd () -{ - return fileno(logstream?logstream:stderr); -} - -FILE * -log_get_stream () -{ - /* FIXME: We should not return stderr here but initialize the log - stream properly. This might break more things than using stderr, - though */ - return logstream?logstream:stderr; -} - -static void -do_logv (int level, const char *fmt, va_list arg_ptr) -{ - if (!logstream) - { - log_set_file (NULL); /* Make sure a log stream has been set. */ - assert (logstream); - } - - 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) - { - if (get_tid_callback) - fprintf (logstream, "[%u.%lx]", - (unsigned int)getpid (), get_tid_callback ()); - else - 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; -#ifdef HAVE_W32_SYSTEM - else - fflush (logstream); -#endif - } - - if (level == JNLIB_LOG_FATAL) - { - if (missing_lf) - putc('\n', logstream ); - exit(2); - } - if (level == JNLIB_LOG_BUG) - { - if (missing_lf) - putc('\n', logstream ); - 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 - diff --git a/jnlib/logging.h b/jnlib/logging.h deleted file mode 100644 index 0b96108a8..000000000 --- a/jnlib/logging.h +++ /dev/null @@ -1,88 +0,0 @@ -/* logging.h - * Copyright (C) 1999, 2000, 2001, 2004, 2006 Free Software Foundation, Inc. - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#ifndef LIBJNLIB_LOGGING_H -#define LIBJNLIB_LOGGING_H - -#include -#include "mischelp.h" - -/* Flag values for log_set_prefix. */ -#define JNLIB_LOG_WITH_PREFIX 1 -#define JNLIB_LOG_WITH_TIME 2 -#define JNLIB_LOG_WITH_PID 4 -#define JNLIB_LOG_RUN_DETACHED 256 - -int log_get_errorcount (int clear); -void log_inc_errorcount (void); -void log_set_file( const char *name ); -void log_set_fd (int fd); -void log_set_get_tid_callback (unsigned long (*cb)(void)); -void log_set_prefix (const char *text, unsigned int flags); -const char *log_get_prefix (unsigned int *flags); -int log_test_fd (int fd); -int log_get_fd(void); -FILE *log_get_stream (void); - -#ifdef JNLIB_GCC_M_FUNCTION - void bug_at( const char *file, int line, const char *func ) JNLIB_GCC_A_NR; -# define BUG() bug_at( __FILE__ , __LINE__, __FUNCTION__ ) -#else - void bug_at( const char *file, int line ); -# define BUG() bug_at( __FILE__ , __LINE__ ) -#endif - -/* To avoid mandatory inclusion of stdarg and other stuff, do it only - if explicitly requested to do so. */ -#ifdef JNLIB_NEED_LOG_LOGV -#include -enum jnlib_log_levels { - JNLIB_LOG_BEGIN, - JNLIB_LOG_CONT, - JNLIB_LOG_INFO, - JNLIB_LOG_WARN, - JNLIB_LOG_ERROR, - JNLIB_LOG_FATAL, - JNLIB_LOG_BUG, - JNLIB_LOG_DEBUG -}; -void log_logv (int level, const char *fmt, va_list arg_ptr); -#endif /*JNLIB_NEED_LOG_LOGV*/ - - -void log_bug( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2); -void log_fatal( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2); -void log_error( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); -void log_info( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); -void log_debug( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); -void log_printf( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); - -/* Print a hexdump of BUFFER. With TEXT passes as NULL print just the - raw dump, with TEXT being an empty string, print a trailing - linefeed, otherwise print an entire debug line with TEXT followed - by the hexdump and a final LF. */ -void log_printhex (const char *text, const void *buffer, size_t length); - - -#endif /*LIBJNLIB_LOGGING_H*/ - - - - - diff --git a/jnlib/mischelp.c b/jnlib/mischelp.c deleted file mode 100644 index e06be21f2..000000000 --- a/jnlib/mischelp.c +++ /dev/null @@ -1,197 +0,0 @@ -/* mischelp.c - Miscellaneous helper functions - * Copyright (C) 1998, 2000, 2001, 2006, 2007 Free Software Foundation, Inc. - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#include -#include -#include -#include -#ifdef HAVE_W32_SYSTEM -# define WIN32_LEAN_AND_MEAN -# include -#else /*!HAVE_W32_SYSTEM*/ -# include -# include -# include -#endif /*!HAVE_W32_SYSTEM*/ -#include - -#include "libjnlib-config.h" -#include "stringhelp.h" -#include "utf8conv.h" -#include "mischelp.h" - - -/* Because we can't use our jnlib_free macro in inline functions we - provide this wrapper. */ -void -_jnlib_free (void *p) -{ - if (p) - jnlib_free (p); -} - - -/* Check whether the files NAME1 and NAME2 are identical. This is for - example achieved by comparing the inode numbers of the files. */ -int -same_file_p (const char *name1, const char *name2) -{ - int yes; - - /* First try a shortcut. */ - if (!compare_filenames (name1, name2)) - yes = 1; - else - { -#ifdef HAVE_W32_SYSTEM - HANDLE file1, file2; - BY_HANDLE_FILE_INFORMATION info1, info2; - -#ifdef HAVE_W32CE_SYSTEM - { - wchar_t *wname = utf8_to_wchar (name1); - if (wname) - file1 = CreateFile (wname, 0, 0, NULL, OPEN_EXISTING, 0, NULL); - else - file1 = INVALID_HANDLE_VALUE; - jnlib_free (wname); - } -#else - file1 = CreateFile (name1, 0, 0, NULL, OPEN_EXISTING, 0, NULL); -#endif - if (file1 == INVALID_HANDLE_VALUE) - yes = 0; /* If we can't open the file, it is not the same. */ - else - { -#ifdef HAVE_W32CE_SYSTEM - { - wchar_t *wname = utf8_to_wchar (name2); - if (wname) - file2 = CreateFile (wname, 0, 0, NULL, OPEN_EXISTING, 0, NULL); - else - file2 = INVALID_HANDLE_VALUE; - jnlib_free (wname); - } -#else - file2 = CreateFile (name2, 0, 0, NULL, OPEN_EXISTING, 0, NULL); -#endif - if (file2 == INVALID_HANDLE_VALUE) - yes = 0; /* If we can't open the file, it is not the same. */ - else - { - yes = (GetFileInformationByHandle (file1, &info1) - && GetFileInformationByHandle (file2, &info2) - && info1.dwVolumeSerialNumber==info2.dwVolumeSerialNumber - && info1.nFileIndexHigh == info2.nFileIndexHigh - && info1.nFileIndexLow == info2.nFileIndexLow); - CloseHandle (file2); - } - CloseHandle (file1); - } -#else /*!HAVE_W32_SYSTEM*/ - struct stat info1, info2; - - yes = (!stat (name1, &info1) && !stat (name2, &info2) - && info1.st_dev == info2.st_dev && info1.st_ino == info2.st_ino); -#endif /*!HAVE_W32_SYSTEM*/ - } - return yes; -} - - -/* - timegm() is a GNU function that might not be available everywhere. - It's basically the inverse of gmtime() - you give it a struct tm, - and get back a time_t. It differs from mktime() in that it handles - the case where the struct tm is UTC and the local environment isn't. - - Note, that this replacement implementation might not be thread-safe! - - Some BSDs don't handle the putenv("foo") case properly, so we use - unsetenv if the platform has it to remove environment variables. -*/ -#ifndef HAVE_TIMEGM -time_t -timegm (struct tm *tm) -{ -#ifdef HAVE_W32_SYSTEM - /* This one is thread safe. */ - SYSTEMTIME st; - FILETIME ft; - unsigned long long cnsecs; - - st.wYear = tm->tm_year + 1900; - st.wMonth = tm->tm_mon + 1; - st.wDay = tm->tm_mday; - st.wHour = tm->tm_hour; - st.wMinute = tm->tm_min; - st.wSecond = tm->tm_sec; - st.wMilliseconds = 0; /* Not available. */ - st.wDayOfWeek = 0; /* Ignored. */ - - /* System time is UTC thus the conversion is pretty easy. */ - if (!SystemTimeToFileTime (&st, &ft)) - { - jnlib_set_errno (EINVAL); - return (time_t)(-1); - } - - cnsecs = (((unsigned long long)ft.dwHighDateTime << 32) - | ft.dwLowDateTime); - cnsecs -= 116444736000000000ULL; /* The filetime epoch is 1601-01-01. */ - return (time_t)(cnsecs / 10000000ULL); - -#else /* (Non thread safe implementation!) */ - - time_t answer; - char *zone; - - zone=getenv("TZ"); - putenv("TZ=UTC"); - tzset(); - answer=mktime(tm); - if(zone) - { - static char *old_zone; - - if (!old_zone) - { - old_zone = malloc(3+strlen(zone)+1); - if (old_zone) - { - strcpy(old_zone,"TZ="); - strcat(old_zone,zone); - } - } - if (old_zone) - putenv (old_zone); - } - else -#ifdef HAVE_UNSETENV - unsetenv("TZ"); -#else - putenv("TZ"); -#endif - - tzset(); - return answer; -#endif -} -#endif /*!HAVE_TIMEGM*/ - diff --git a/jnlib/mischelp.h b/jnlib/mischelp.h deleted file mode 100644 index 52781e12f..000000000 --- a/jnlib/mischelp.h +++ /dev/null @@ -1,102 +0,0 @@ -/* mischelp.h - Miscellaneous helper macros and functions - * Copyright (C) 1999, 2000, 2001, 2002, 2003, - * 2006, 2007, 2009 Free Software Foundation, Inc. - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#ifndef LIBJNLIB_MISCHELP_H -#define LIBJNLIB_MISCHHELP_H - - -/* Because we can't use the internal jnlib_free macro in inline - functions we provide a wrapper fucntion as well. */ -void _jnlib_free (void *p); - -/* Check whether the files NAME1 and NAME2 are identical. This is for - example achieved by comparing the inode numbers of the files. */ -int same_file_p (const char *name1, const char *name2); - - -#ifndef HAVE_TIMEGM -#include -time_t timegm (struct tm *tm); -#endif /*!HAVE_TIMEGM*/ - - -#define DIM(v) (sizeof(v)/sizeof((v)[0])) -#define DIMof(type,member) DIM(((type *)0)->member) - - -#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ) -# define JNLIB_GCC_M_FUNCTION 1 -# define JNLIB_GCC_A_NR __attribute__ ((noreturn)) -# define JNLIB_GCC_A_PRINTF( f, a ) __attribute__ ((format (printf,f,a))) -# define JNLIB_GCC_A_NR_PRINTF( f, a ) \ - __attribute__ ((noreturn, format (printf,f,a))) -#else -# define JNLIB_GCC_A_NR -# define JNLIB_GCC_A_PRINTF( f, a ) -# define JNLIB_GCC_A_NR_PRINTF( f, a ) -#endif - - -/* To avoid that a compiler optimizes certain memset calls away, these - macros may be used instead. */ -#define wipememory2(_ptr,_set,_len) do { \ - volatile char *_vptr=(volatile char *)(_ptr); \ - size_t _vlen=(_len); \ - while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \ - } while(0) -#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len) - - -/* Include hacks which are mainly required for Slowaris. */ -#ifdef JNLIB_NEED_AFLOCAL -#ifndef HAVE_W32_SYSTEM -# include -# include -#else -# include -#endif - -#ifndef PF_LOCAL -# ifdef PF_UNIX -# define PF_LOCAL PF_UNIX -# else -# define PF_LOCAL AF_UNIX -# endif -#endif /*PF_LOCAL*/ -#ifndef AF_LOCAL -# define AF_LOCAL AF_UNIX -#endif /*AF_UNIX*/ - -/* We used to avoid this macro in GnuPG and inlined the AF_LOCAL name - length computation directly with the little twist of adding 1 extra - byte. It seems that this was needed once on an old HP/UX box and - there are also rumours that 4.3 Reno and DEC systems need it. This - one-off buglet did not harm any current system until it came to Mac - OS X where the kernel (as of May 2009) exhibited a strange bug: The - systems basically froze in the connect call if the passed name - contained an invalid directory part. Ignore the old Unices. */ -#ifndef SUN_LEN -# define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \ - + strlen ((ptr)->sun_path)) -#endif /*SUN_LEN*/ -#endif /*JNLIB_NEED_AFLOCAL*/ - - -#endif /*LIBJNLIB_MISCHELP_H*/ diff --git a/jnlib/stringhelp.c b/jnlib/stringhelp.c deleted file mode 100644 index 36f96b8ff..000000000 --- a/jnlib/stringhelp.c +++ /dev/null @@ -1,1151 +0,0 @@ -/* stringhelp.c - standard string helper functions - * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005, - * 2006, 2007, 2008, 2009 Free Software Foundation, Inc. - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#include -#include -#include -#include -#include -#include -#ifdef HAVE_PWD_H -# include -#endif -#include -#include -#ifdef HAVE_W32_SYSTEM -# include -#endif - -#include "libjnlib-config.h" -#include "utf8conv.h" -#include "stringhelp.h" - - -#define tohex_lower(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'a')) - -/* Sometimes we want to avoid mixing slashes and backslashes on W32 - and prefer backslashes. There is usual no problem with mixing - them, however a very few W32 API calls can't grok plain slashes. - Printing filenames with mixed slashes also looks a bit strange. - This function has no effext on POSIX. */ -static inline char * -change_slashes (char *name) -{ -#ifdef HAVE_DRIVE_LETTERS - char *p; - - if (strchr (name, '\\')) - { - for (p=name; *p; p++) - if (*p == '/') - *p = '\\'; - } -#endif /*HAVE_DRIVE_LETTERS*/ - return name; -} - - -/* - * Look for the substring SUB in buffer and return a pointer to that - * substring in BUFFER or NULL if not found. - * Comparison is case-insensitive. - */ -const char * -memistr (const void *buffer, size_t buflen, const char *sub) -{ - const unsigned char *buf = buffer; - const unsigned char *t = (const unsigned char *)buffer; - const unsigned char *s = (const unsigned char *)sub; - size_t n = buflen; - - for ( ; n ; t++, n-- ) - { - if ( toupper (*t) == toupper (*s) ) - { - for ( buf=t++, buflen = n--, s++; - n && toupper (*t) == toupper (*s); t++, s++, n-- ) - ; - if (!*s) - return (const char*)buf; - t = buf; - s = (const unsigned char *)sub ; - n = buflen; - } - } - return NULL; -} - -const char * -ascii_memistr ( const void *buffer, size_t buflen, const char *sub ) -{ - const unsigned char *buf = buffer; - const unsigned char *t = (const unsigned char *)buf; - const unsigned char *s = (const unsigned char *)sub; - size_t n = buflen; - - for ( ; n ; t++, n-- ) - { - if (ascii_toupper (*t) == ascii_toupper (*s) ) - { - for ( buf=t++, buflen = n--, s++; - n && ascii_toupper (*t) == ascii_toupper (*s); t++, s++, n-- ) - ; - if (!*s) - return (const char*)buf; - t = (const unsigned char *)buf; - s = (const unsigned char *)sub ; - n = buflen; - } - } - return NULL; -} - -/* This function is similar to strncpy(). However it won't copy more - than N - 1 characters and makes sure that a '\0' is appended. With - N given as 0, nothing will happen. With DEST given as NULL, memory - will be allocated using jnlib_xmalloc (i.e. if it runs out of core - the function terminates). Returns DES or a pointer to the - allocated memory. - */ -char * -mem2str( char *dest , const void *src , size_t n ) -{ - char *d; - const char *s; - - if( n ) { - if( !dest ) - dest = jnlib_xmalloc( n ) ; - d = dest; - s = src ; - for(n--; n && *s; n-- ) - *d++ = *s++; - *d = '\0' ; - } - - return dest ; -} - - -/**************** - * remove leading and trailing white spaces - */ -char * -trim_spaces( char *str ) -{ - char *string, *p, *mark; - - string = str; - /* find first non space character */ - for( p=string; *p && isspace( *(byte*)p ) ; p++ ) - ; - /* move characters */ - for( (mark = NULL); (*string = *p); string++, p++ ) - if( isspace( *(byte*)p ) ) { - if( !mark ) - mark = string ; - } - else - mark = NULL ; - if( mark ) - *mark = '\0' ; /* remove trailing spaces */ - - return str ; -} - -/**************** - * remove trailing white spaces - */ -char * -trim_trailing_spaces( char *string ) -{ - char *p, *mark; - - for( mark = NULL, p = string; *p; p++ ) { - if( isspace( *(byte*)p ) ) { - if( !mark ) - mark = p; - } - else - mark = NULL; - } - if( mark ) - *mark = '\0' ; - - return string ; -} - - -unsigned -trim_trailing_chars( byte *line, unsigned len, const char *trimchars ) -{ - byte *p, *mark; - unsigned n; - - for(mark=NULL, p=line, n=0; n < len; n++, p++ ) { - if( strchr(trimchars, *p ) ) { - if( !mark ) - mark = p; - } - else - mark = NULL; - } - - if( mark ) { - *mark = 0; - return mark - line; - } - return len; -} - -/**************** - * remove trailing white spaces and return the length of the buffer - */ -unsigned -trim_trailing_ws( byte *line, unsigned len ) -{ - return trim_trailing_chars( line, len, " \t\r\n" ); -} - -size_t -length_sans_trailing_chars (const unsigned char *line, size_t len, - const char *trimchars ) -{ - const unsigned char *p, *mark; - size_t n; - - for( mark=NULL, p=line, n=0; n < len; n++, p++ ) - { - if (strchr (trimchars, *p )) - { - if( !mark ) - mark = p; - } - else - mark = NULL; - } - - if (mark) - return mark - line; - return len; -} - -/* - * Return the length of line ignoring trailing white-space. - */ -size_t -length_sans_trailing_ws (const unsigned char *line, size_t len) -{ - return length_sans_trailing_chars (line, len, " \t\r\n"); -} - - - -/* - * Extract from a given path the filename component. This function - * terminates the process on memory shortage. - */ -char * -make_basename(const char *filepath, const char *inputpath) -{ -#ifdef __riscos__ - return riscos_make_basename(filepath, inputpath); -#else - char *p; - - (void)inputpath; /* Only required for riscos. */ - - if ( !(p=strrchr(filepath, '/')) ) -#ifdef HAVE_DRIVE_LETTERS - if ( !(p=strrchr(filepath, '\\')) ) - if ( !(p=strrchr(filepath, ':')) ) -#endif - { - return jnlib_xstrdup(filepath); - } - - return jnlib_xstrdup(p+1); -#endif -} - - - -/* - * Extract from a given filename the path prepended to it. If there - * isn't a path prepended to the filename, a dot is returned ('.'). - * This function terminates the process on memory shortage. - */ -char * -make_dirname(const char *filepath) -{ - char *dirname; - int dirname_length; - char *p; - - if ( !(p=strrchr(filepath, '/')) ) -#ifdef HAVE_DRIVE_LETTERS - if ( !(p=strrchr(filepath, '\\')) ) - if ( !(p=strrchr(filepath, ':')) ) -#endif - { - return jnlib_xstrdup("."); - } - - dirname_length = p-filepath; - dirname = jnlib_xmalloc(dirname_length+1); - strncpy(dirname, filepath, dirname_length); - dirname[dirname_length] = 0; - - return dirname; -} - - - -static char * -get_pwdir (int xmode, const char *name) -{ - char *result = NULL; -#ifdef HAVE_PWD_H - struct passwd *pwd = NULL; - - if (name) - { -#ifdef HAVE_GETPWNAM - /* Fixme: We should use getpwnam_r if available. */ - pwd = getpwnam (name); -#endif - } - else - { -#ifdef HAVE_GETPWUID - /* Fixme: We should use getpwuid_r if available. */ - pwd = getpwuid (getuid()); -#endif - } - if (pwd) - { - if (xmode) - result = jnlib_xstrdup (pwd->pw_dir); - else - result = jnlib_strdup (pwd->pw_dir); - } -#else /*!HAVE_PWD_H*/ - /* No support at all. */ - (void)xmode; - (void)name; -#endif /*HAVE_PWD_H*/ - return result; -} - -static char * -do_make_filename (int xmode, const char *first_part, va_list arg_ptr) -{ - const char *argv[32]; - int argc; - size_t n; - int skip = 1; - char *home_buffer = NULL; - char *name, *home, *p; - - n = strlen (first_part) + 1; - argc = 0; - while ( (argv[argc] = va_arg (arg_ptr, const char *)) ) - { - n += strlen (argv[argc]) + 1; - if (argc >= DIM (argv)-1) - { - if (xmode) - BUG (); - jnlib_set_errno (EINVAL); - return NULL; - } - argc++; - } - n++; - - home = NULL; - if (*first_part == '~') - { - if (first_part[1] == '/' || !first_part[1]) - { - /* This is the "~/" or "~" case. */ - home = getenv("HOME"); - if (!home) - home = home_buffer = get_pwdir (xmode, NULL); - if (home && *home) - n += strlen (home); - } - else - { - /* This is the "~username/" or "~username" case. */ - char *user; - - if (xmode) - user = jnlib_xstrdup (first_part+1); - else - { - user = jnlib_strdup (first_part+1); - if (!user) - return NULL; - } - p = strchr (user, '/'); - if (p) - *p = 0; - skip = 1 + strlen (user); - - home = home_buffer = get_pwdir (xmode, user); - jnlib_free (user); - if (home) - n += strlen (home); - else - skip = 1; - } - } - - if (xmode) - name = jnlib_xmalloc (n); - else - { - name = jnlib_malloc (n); - if (!name) - { - jnlib_free (home_buffer); - return NULL; - } - } - - if (home) - p = stpcpy (stpcpy (name, home), first_part + skip); - else - p = stpcpy (name, first_part); - - jnlib_free (home_buffer); - - for (argc=0; argv[argc]; argc++) - p = stpcpy (stpcpy (p, "/"), argv[argc]); - - return change_slashes (name); -} - -/* Construct a filename from the NULL terminated list of parts. Tilde - expansion is done for the first argument. This function terminates - the process on memory shortage. */ -char * -make_filename (const char *first_part, ... ) -{ - va_list arg_ptr; - char *result; - - va_start (arg_ptr, first_part); - result = do_make_filename (1, first_part, arg_ptr); - va_end (arg_ptr); - return result; -} - -/* Construct a filename from the NULL terminated list of parts. Tilde - expansion is done for the first argument. This function may return - NULL on error. */ -char * -make_filename_try (const char *first_part, ... ) -{ - va_list arg_ptr; - char *result; - - va_start (arg_ptr, first_part); - result = do_make_filename (0, first_part, arg_ptr); - va_end (arg_ptr); - return result; -} - - - -/* Compare whether the filenames are identical. This is a - special version of strcmp() taking the semantics of filenames in - account. Note that this function works only on the supplied names - without considereing any context like the current directory. See - also same_file_p(). */ -int -compare_filenames (const char *a, const char *b) -{ -#ifdef HAVE_DRIVE_LETTERS - for ( ; *a && *b; a++, b++ ) - { - if (*a != *b - && (toupper (*(const unsigned char*)a) - != toupper (*(const unsigned char*)b) ) - && !((*a == '/' && *b == '\\') || (*a == '\\' && *b == '/'))) - break; - } - if ((*a == '/' && *b == '\\') || (*a == '\\' && *b == '/')) - return 0; - else - return (toupper (*(const unsigned char*)a) - - toupper (*(const unsigned char*)b)); -#else - return strcmp(a,b); -#endif -} - - -/* Convert 2 hex characters at S to a byte value. Return this value - or -1 if there is an error. */ -int -hextobyte (const char *s) -{ - int c; - - if ( *s >= '0' && *s <= '9' ) - c = 16 * (*s - '0'); - else if ( *s >= 'A' && *s <= 'F' ) - c = 16 * (10 + *s - 'A'); - else if ( *s >= 'a' && *s <= 'f' ) - c = 16 * (10 + *s - 'a'); - else - return -1; - s++; - if ( *s >= '0' && *s <= '9' ) - c += *s - '0'; - else if ( *s >= 'A' && *s <= 'F' ) - c += 10 + *s - 'A'; - else if ( *s >= 'a' && *s <= 'f' ) - c += 10 + *s - 'a'; - else - return -1; - return c; -} - - -/* Print a BUFFER to stream FP while replacing all control characters - and the characters DELIM and DELIM2 with standard C escape - sequences. Returns the number of characters printed. */ -size_t -print_sanitized_buffer2 (FILE *fp, const void *buffer, size_t length, - int delim, int delim2) -{ - const unsigned char *p = buffer; - size_t count = 0; - - for (; length; length--, p++, count++) - { - if (*p < 0x20 - || *p == 0x7f - || *p == delim - || *p == delim2 - || ((delim || delim2) && *p=='\\')) - { - putc ('\\', fp); - count++; - if (*p == '\n') - { - putc ('n', fp); - count++; - } - else if (*p == '\r') - { - putc ('r', fp); - count++; - } - else if (*p == '\f') - { - putc ('f', fp); - count++; - } - else if (*p == '\v') - { - putc ('v', fp); - count++; - } - else if (*p == '\b') - { - putc ('b', fp); - count++; - } - else if (!*p) - { - putc('0', fp); - count++; - } - else - { - fprintf (fp, "x%02x", *p); - count += 3; - } - } - else - { - putc (*p, fp); - count++; - } - } - - return count; -} - -/* Same as print_sanitized_buffer2 but with just one delimiter. */ -size_t -print_sanitized_buffer (FILE *fp, const void *buffer, size_t length, - int delim) -{ - return print_sanitized_buffer2 (fp, buffer, length, delim, 0); -} - - -size_t -print_sanitized_utf8_buffer (FILE *fp, const void *buffer, - size_t length, int delim) -{ - const char *p = buffer; - size_t i; - - /* We can handle plain ascii simpler, so check for it first. */ - for (i=0; i < length; i++ ) - { - if ( (p[i] & 0x80) ) - break; - } - if (i < length) - { - char *buf = utf8_to_native (p, length, delim); - /*(utf8 conversion already does the control character quoting)*/ - i = strlen (buf); - fputs (buf, fp); - jnlib_free (buf); - return i; - } - else - return print_sanitized_buffer (fp, p, length, delim); -} - - -size_t -print_sanitized_string2 (FILE *fp, const char *string, int delim, int delim2) -{ - return string? print_sanitized_buffer2 (fp, string, strlen (string), - delim, delim2):0; -} - -size_t -print_sanitized_string (FILE *fp, const char *string, int delim) -{ - return string? print_sanitized_buffer (fp, string, strlen (string), delim):0; -} - -size_t -print_sanitized_utf8_string (FILE *fp, const char *string, int delim) -{ - return string? print_sanitized_utf8_buffer (fp, - string, strlen (string), - delim) : 0; -} - -/* Create a string from the buffer P_ARG of length N which is suitable - for printing. Caller must release the created string using xfree. - This function terminates the process on memory shortage. */ -char * -sanitize_buffer (const void *p_arg, size_t n, int delim) -{ - const unsigned char *p = p_arg; - size_t save_n, buflen; - const unsigned char *save_p; - char *buffer, *d; - - /* First count length. */ - for (save_n = n, save_p = p, buflen=1 ; n; n--, p++ ) - { - if ( *p < 0x20 || *p == 0x7f || *p == delim || (delim && *p=='\\')) - { - if ( *p=='\n' || *p=='\r' || *p=='\f' - || *p=='\v' || *p=='\b' || !*p ) - buflen += 2; - else - buflen += 5; - } - else - buflen++; - } - p = save_p; - n = save_n; - /* And now make the string */ - d = buffer = jnlib_xmalloc( buflen ); - for ( ; n; n--, p++ ) - { - if (*p < 0x20 || *p == 0x7f || *p == delim || (delim && *p=='\\')) { - *d++ = '\\'; - if( *p == '\n' ) - *d++ = 'n'; - else if( *p == '\r' ) - *d++ = 'r'; - else if( *p == '\f' ) - *d++ = 'f'; - else if( *p == '\v' ) - *d++ = 'v'; - else if( *p == '\b' ) - *d++ = 'b'; - else if( !*p ) - *d++ = '0'; - else { - sprintf(d, "x%02x", *p ); - d += 3; - } - } - else - *d++ = *p; - } - *d = 0; - return buffer; -} - - -/* Given a string containing an UTF-8 encoded text, return the number - of characters in this string. It differs from strlen in that it - only counts complete UTF-8 characters. Note, that this function - does not take combined characters into account. */ -size_t -utf8_charcount (const char *s) -{ - size_t n; - - for (n=0; *s; s++) - if ( (*s&0xc0) != 0x80 ) /* Exclude continuation bytes: 10xxxxxx */ - n++; - - return n; -} - - -/**************************************************** - ********** W32 specific functions **************** - ****************************************************/ - -#ifdef HAVE_W32_SYSTEM -const char * -w32_strerror (int ec) -{ - static char strerr[256]; - - if (ec == -1) - ec = (int)GetLastError (); -#ifdef HAVE_W32CE_SYSTEM - /* There is only a wchar_t FormatMessage. It does not make much - sense to play the conversion game; we print only the code. */ - snprintf (strerr, sizeof strerr, "ec=%d", (int)GetLastError ()); -#else - FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, ec, - MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), - strerr, DIM (strerr)-1, NULL); -#endif - return strerr; -} -#endif /*HAVE_W32_SYSTEM*/ - - -/**************************************************** - ******** Locale insensitive ctype functions ******** - ****************************************************/ -/* FIXME: replace them by a table lookup and macros */ -int -ascii_isupper (int c) -{ - return c >= 'A' && c <= 'Z'; -} - -int -ascii_islower (int c) -{ - return c >= 'a' && c <= 'z'; -} - -int -ascii_toupper (int c) -{ - if (c >= 'a' && c <= 'z') - c &= ~0x20; - return c; -} - -int -ascii_tolower (int c) -{ - if (c >= 'A' && c <= 'Z') - c |= 0x20; - return c; -} - - -int -ascii_strcasecmp( const char *a, const char *b ) -{ - if (a == b) - return 0; - - for (; *a && *b; a++, b++) { - if (*a != *b && ascii_toupper(*a) != ascii_toupper(*b)) - break; - } - return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b)); -} - -int -ascii_strncasecmp (const char *a, const char *b, size_t n) -{ - const unsigned char *p1 = (const unsigned char *)a; - const unsigned char *p2 = (const unsigned char *)b; - unsigned char c1, c2; - - if (p1 == p2 || !n ) - return 0; - - do - { - c1 = ascii_tolower (*p1); - c2 = ascii_tolower (*p2); - - if ( !--n || c1 == '\0') - break; - - ++p1; - ++p2; - } - while (c1 == c2); - - return c1 - c2; -} - - -int -ascii_memcasecmp (const void *a_arg, const void *b_arg, size_t n ) -{ - const char *a = a_arg; - const char *b = b_arg; - - if (a == b) - return 0; - for ( ; n; n--, a++, b++ ) - { - if( *a != *b && ascii_toupper (*a) != ascii_toupper (*b) ) - return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b)); - } - return 0; -} - -int -ascii_strcmp( const char *a, const char *b ) -{ - if (a == b) - return 0; - - for (; *a && *b; a++, b++) { - if (*a != *b ) - break; - } - return *a == *b? 0 : (*(signed char *)a - *(signed char *)b); -} - - -void * -ascii_memcasemem (const void *haystack, size_t nhaystack, - const void *needle, size_t nneedle) -{ - - if (!nneedle) - return (void*)haystack; /* finding an empty needle is really easy */ - if (nneedle <= nhaystack) - { - const char *a = haystack; - const char *b = a + nhaystack - nneedle; - - for (; a <= b; a++) - { - if ( !ascii_memcasecmp (a, needle, nneedle) ) - return (void *)a; - } - } - return NULL; -} - -/********************************************* - ********** missing string functions ********* - *********************************************/ - -#ifndef HAVE_STPCPY -char * -stpcpy(char *a,const char *b) -{ - while( *b ) - *a++ = *b++; - *a = 0; - - return (char*)a; -} -#endif - -#ifndef HAVE_STRSEP -/* Code taken from glibc-2.2.1/sysdeps/generic/strsep.c. */ -char * -strsep (char **stringp, const char *delim) -{ - char *begin, *end; - - begin = *stringp; - if (begin == NULL) - return NULL; - - /* A frequent case is when the delimiter string contains only one - character. Here we don't need to call the expensive `strpbrk' - function and instead work using `strchr'. */ - if (delim[0] == '\0' || delim[1] == '\0') - { - char ch = delim[0]; - - if (ch == '\0') - end = NULL; - else - { - if (*begin == ch) - end = begin; - else if (*begin == '\0') - end = NULL; - else - end = strchr (begin + 1, ch); - } - } - else - /* Find the end of the token. */ - end = strpbrk (begin, delim); - - if (end) - { - /* Terminate the token and set *STRINGP past NUL character. */ - *end++ = '\0'; - *stringp = end; - } - else - /* No more delimiters; this is the last token. */ - *stringp = NULL; - - return begin; -} -#endif /*HAVE_STRSEP*/ - - -#ifndef HAVE_STRLWR -char * -strlwr(char *s) -{ - char *p; - for(p=s; *p; p++ ) - *p = tolower(*p); - return s; -} -#endif - - -#ifndef HAVE_STRCASECMP -int -strcasecmp( const char *a, const char *b ) -{ - for( ; *a && *b; a++, b++ ) { - if( *a != *b && toupper(*a) != toupper(*b) ) - break; - } - return *(const byte*)a - *(const byte*)b; -} -#endif - - -/**************** - * mingw32/cpd has a memicmp() - */ -#ifndef HAVE_MEMICMP -int -memicmp( const char *a, const char *b, size_t n ) -{ - for( ; n; n--, a++, b++ ) - if( *a != *b && toupper(*(const byte*)a) != toupper(*(const byte*)b) ) - return *(const byte *)a - *(const byte*)b; - return 0; -} -#endif - - -#ifndef HAVE_MEMRCHR -void * -memrchr (const void *buffer, int c, size_t n) -{ - const unsigned char *p = buffer; - - for (p += n; n ; n--) - if (*--p == c) - return (void *)p; - return NULL; -} -#endif /*HAVE_MEMRCHR*/ - - -/* Percent-escape the string STR by replacing colons with '%3a'. If - EXTRA is not NULL all characters in EXTRA are also escaped. */ -static char * -do_percent_escape (const char *str, const char *extra, int die) -{ - int i, j; - char *ptr; - - if (!str) - return NULL; - - for (i=j=0; str[i]; i++) - if (str[i] == ':' || str[i] == '%' || (extra && strchr (extra, str[i]))) - j++; - if (die) - ptr = jnlib_xmalloc (i + 2 * j + 1); - else - { - ptr = jnlib_malloc (i + 2 * j + 1); - if (!ptr) - return NULL; - } - i = 0; - while (*str) - { - if (*str == ':') - { - ptr[i++] = '%'; - ptr[i++] = '3'; - ptr[i++] = 'a'; - } - else if (*str == '%') - { - ptr[i++] = '%'; - ptr[i++] = '2'; - ptr[i++] = '5'; - } - else if (extra && strchr (extra, *str)) - { - ptr[i++] = '%'; - ptr[i++] = tohex_lower ((*str>>4)&15); - ptr[i++] = tohex_lower (*str&15); - } - else - ptr[i++] = *str; - str++; - } - ptr[i] = '\0'; - - return ptr; -} - -/* Percent-escape the string STR by replacing colons with '%3a'. If - EXTRA is not NULL all characters in EXTRA are also escaped. This - function terminates the process on memory shortage. */ -char * -percent_escape (const char *str, const char *extra) -{ - return do_percent_escape (str, extra, 1); -} - -/* Same as percent_escape but return NULL instead of exiting on memory - error. */ -char * -try_percent_escape (const char *str, const char *extra) -{ - return do_percent_escape (str, extra, 0); -} - - - -static char * -do_strconcat (const char *s1, va_list arg_ptr) -{ - const char *argv[48]; - size_t argc; - size_t needed; - char *buffer, *p; - - argc = 0; - argv[argc++] = s1; - needed = strlen (s1); - while (((argv[argc] = va_arg (arg_ptr, const char *)))) - { - needed += strlen (argv[argc]); - if (argc >= DIM (argv)-1) - { - jnlib_set_errno (EINVAL); - return NULL; - } - argc++; - } - needed++; - buffer = jnlib_malloc (needed); - if (buffer) - { - for (p = buffer, argc=0; argv[argc]; argc++) - p = stpcpy (p, argv[argc]); - } - return buffer; -} - - -/* Concatenate the string S1 with all the following strings up to a - NULL. Returns a malloced buffer with the new string or NULL on a - malloc error or if too many arguments are given. */ -char * -strconcat (const char *s1, ...) -{ - va_list arg_ptr; - char *result; - - if (!s1) - result = jnlib_strdup (""); - else - { - va_start (arg_ptr, s1); - result = do_strconcat (s1, arg_ptr); - va_end (arg_ptr); - } - return result; -} - -/* Same as strconcat but terminate the process with an error message - if something goes wrong. */ -char * -xstrconcat (const char *s1, ...) -{ - va_list arg_ptr; - char *result; - - if (!s1) - result = jnlib_xstrdup (""); - else - { - va_start (arg_ptr, s1); - result = do_strconcat (s1, arg_ptr); - va_end (arg_ptr); - } - if (!result) - { - if (errno == EINVAL) - fputs ("\nfatal: too many args for xstrconcat\n", stderr); - else - fputs ("\nfatal: out of memory\n", stderr); - exit (2); - } - return result; -} - diff --git a/jnlib/stringhelp.h b/jnlib/stringhelp.h deleted file mode 100644 index a560b163e..000000000 --- a/jnlib/stringhelp.h +++ /dev/null @@ -1,136 +0,0 @@ -/* stringhelp.h - * Copyright (C) 1998, 1999, 2000, 2001, 2003, - * 2006, 2007, 2009 Free Software Foundation, Inc. - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#ifndef LIBJNLIB_STRINGHELP_H -#define LIBJNLIB_STRINGHELP_H - -#include "types.h" - -const char *memistr (const void *buf, size_t buflen, const char *sub); -char *mem2str( char *, const void *, size_t); -char *trim_spaces( char *string ); -char *trim_trailing_spaces( char *string ); -unsigned int trim_trailing_chars( unsigned char *line, unsigned len, - const char *trimchars); -unsigned int trim_trailing_ws( unsigned char *line, unsigned len ); -size_t length_sans_trailing_chars (const unsigned char *line, size_t len, - const char *trimchars ); -size_t length_sans_trailing_ws (const unsigned char *line, size_t len); - - -char *make_basename(const char *filepath, const char *inputpath); -char *make_dirname(const char *filepath); -char *make_filename( const char *first_part, ... ) GNUPG_GCC_A_SENTINEL(0); -char *make_filename_try (const char *first_part, ... ) GNUPG_GCC_A_SENTINEL(0); -int compare_filenames( const char *a, const char *b ); - -int hextobyte (const char *s); - -size_t print_sanitized_buffer (FILE *fp, const void *buffer, size_t length, - int delim); -size_t print_sanitized_buffer2 (FILE *fp, const void *buffer, size_t length, - int delim, int delim2); -size_t print_sanitized_utf8_buffer (FILE *fp, const void *buffer, - size_t length, int delim); -size_t print_sanitized_string (FILE *fp, const char *string, int delim); -size_t print_sanitized_string2 (FILE *fp, const char *string, - int delim, int delim2); -size_t print_sanitized_utf8_string (FILE *fp, const char *string, int delim); -char *sanitize_buffer (const void *p, size_t n, int delim); - - -size_t utf8_charcount (const char *s); - - -#ifdef HAVE_W32_SYSTEM -const char *w32_strerror (int ec); -#endif - - -int ascii_isupper (int c); -int ascii_islower (int c); -int ascii_toupper (int c); -int ascii_tolower (int c); -int ascii_strcasecmp( const char *a, const char *b ); -int ascii_strncasecmp (const char *a, const char *b, size_t n); -int ascii_memcasecmp( const void *a, const void *b, size_t n ); -const char *ascii_memistr ( const void *buf, size_t buflen, const char *sub); -void *ascii_memcasemem (const void *haystack, size_t nhaystack, - const void *needle, size_t nneedle); - - -#ifndef HAVE_MEMICMP -int memicmp( const char *a, const char *b, size_t n ); -#endif -#ifndef HAVE_STPCPY -char *stpcpy(char *a,const char *b); -#endif -#ifndef HAVE_STRSEP -char *strsep (char **stringp, const char *delim); -#endif -#ifndef HAVE_STRLWR -char *strlwr(char *a); -#endif -#ifndef HAVE_STRTOUL -# define strtoul(a,b,c) ((unsigned long)strtol((a),(b),(c))) -#endif -#ifndef HAVE_MEMMOVE -# define memmove(d, s, n) bcopy((s), (d), (n)) -#endif -#ifndef HAVE_STRICMP -# define stricmp(a,b) strcasecmp( (a), (b) ) -#endif -#ifndef HAVE_MEMRCHR -void *memrchr (const void *buffer, int c, size_t n); -#endif - - -#ifndef HAVE_ISASCII -static inline int -isascii (int c) -{ - return (((c) & ~0x7f) == 0); -} -#endif /* !HAVE_ISASCII */ - - -#ifndef STR -# define STR(v) #v -#endif -#define STR2(v) STR(v) - -/* Percent-escape the string STR by replacing colons with '%3a'. If - EXTRA is not NULL, also replace all characters given in EXTRA. The - "try_" variant fails with NULL if not enough memory can be - allocated. */ -char *percent_escape (const char *str, const char *extra); -char *try_percent_escape (const char *str, const char *extra); - - -/* Concatenate the string S1 with all the following strings up to a - NULL. Returns a malloced buffer with the new string or NULL on a - malloc error or if too many arguments are given. */ -char *strconcat (const char *s1, ...) GNUPG_GCC_A_SENTINEL(0); -/* Ditto, but die on error. */ -char *xstrconcat (const char *s1, ...) GNUPG_GCC_A_SENTINEL(0); - - - -#endif /*LIBJNLIB_STRINGHELP_H*/ diff --git a/jnlib/strlist.c b/jnlib/strlist.c deleted file mode 100644 index b31e6213a..000000000 --- a/jnlib/strlist.c +++ /dev/null @@ -1,204 +0,0 @@ -/* strlist.c - string helpers - * Copyright (C) 1998, 2000, 2001, 2006 Free Software Foundation, Inc. - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#include -#include -#include -#include -#include - -#include "libjnlib-config.h" -#include "strlist.h" -#ifdef JNLIB_NEED_UTF8CONV -#include "utf8conv.h" -#endif - -void -free_strlist( strlist_t sl ) -{ - strlist_t sl2; - - for(; sl; sl = sl2 ) { - sl2 = sl->next; - jnlib_free(sl); - } -} - - -/* Add STRING to the LIST at the front. This function terminates the - process on memory shortage. */ -strlist_t -add_to_strlist( strlist_t *list, const char *string ) -{ - strlist_t sl; - - sl = jnlib_xmalloc( sizeof *sl + strlen(string)); - sl->flags = 0; - strcpy(sl->d, string); - sl->next = *list; - *list = sl; - return sl; -} - - -/* Add STRING to the LIST at the front. This function returns NULL - and sets ERRNO on memory shortage. */ -strlist_t -add_to_strlist_try (strlist_t *list, const char *string) -{ - strlist_t sl; - - sl = jnlib_malloc (sizeof *sl + strlen (string)); - if (sl) - { - sl->flags = 0; - strcpy (sl->d, string); - sl->next = *list; - *list = sl; - } - return sl; -} - - -/* Same as add_to_strlist() but if IS_UTF8 is *not* set, a conversion - to UTF-8 is done. This function terminates the process on memory - shortage. */ -#ifdef JNLIB_NEED_UTF8CONV -strlist_t -add_to_strlist2( strlist_t *list, const char *string, int is_utf8 ) -{ - strlist_t sl; - - if (is_utf8) - sl = add_to_strlist( list, string ); - else - { - char *p = native_to_utf8( string ); - sl = add_to_strlist( list, p ); - jnlib_free ( p ); - } - return sl; -} -#endif /* JNLIB_NEED_UTF8CONV*/ - - -/* Add STRING to the LIST at the end. This function terminates the - process on memory shortage. */ -strlist_t -append_to_strlist( strlist_t *list, const char *string ) -{ - strlist_t r, sl; - - sl = jnlib_xmalloc( sizeof *sl + strlen(string)); - sl->flags = 0; - strcpy(sl->d, string); - sl->next = NULL; - if( !*list ) - *list = sl; - else { - for( r = *list; r->next; r = r->next ) - ; - r->next = sl; - } - return sl; -} - - -#ifdef JNLIB_NEED_UTF8CONV -strlist_t -append_to_strlist2( strlist_t *list, const char *string, int is_utf8 ) -{ - strlist_t sl; - - if( is_utf8 ) - sl = append_to_strlist( list, string ); - else - { - char *p = native_to_utf8 (string); - sl = append_to_strlist( list, p ); - jnlib_free( p ); - } - return sl; -} -#endif /* JNLIB_NEED_UTF8CONV */ - - -/* Return a copy of LIST. This function terminates the process on - memory shortage.*/ -strlist_t -strlist_copy (strlist_t list) -{ - strlist_t newlist = NULL, sl, *last; - - last = &newlist; - for (; list; list = list->next) - { - sl = jnlib_xmalloc (sizeof *sl + strlen (list->d)); - sl->flags = list->flags; - strcpy(sl->d, list->d); - sl->next = NULL; - *last = sl; - last = &sl; - } - return newlist; -} - - - -strlist_t -strlist_prev( strlist_t head, strlist_t node ) -{ - strlist_t n; - - for(n=NULL; head && head != node; head = head->next ) - n = head; - return n; -} - -strlist_t -strlist_last( strlist_t node ) -{ - if( node ) - for( ; node->next ; node = node->next ) - ; - return node; -} - - -/* Remove the first item from LIST and return its content in an - allocated buffer. This function terminates the process on memory - shortage. */ -char * -strlist_pop (strlist_t *list) -{ - char *str=NULL; - strlist_t sl=*list; - - if(sl) - { - str=jnlib_xmalloc(strlen(sl->d)+1); - strcpy(str,sl->d); - - *list=sl->next; - jnlib_free(sl); - } - - return str; -} - diff --git a/jnlib/strlist.h b/jnlib/strlist.h deleted file mode 100644 index 1e2ffa8da..000000000 --- a/jnlib/strlist.h +++ /dev/null @@ -1,50 +0,0 @@ -/* strlist.h - * Copyright (C) 1998, 2000, 2001, 2006 Free Software Foundation, Inc. - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#ifndef LIBJNLIB_STRLIST_H -#define LIBJNLIB_STRLIST_H - -struct string_list -{ - struct string_list *next; - unsigned int flags; - char d[1]; -}; -typedef struct string_list *strlist_t; - -void free_strlist (strlist_t sl); -strlist_t add_to_strlist (strlist_t *list, const char *string); -strlist_t add_to_strlist_try (strlist_t *list, const char *string); - -strlist_t add_to_strlist2( strlist_t *list, const char *string, int is_utf8); - -strlist_t append_to_strlist (strlist_t *list, const char *string); -strlist_t append_to_strlist2 (strlist_t *list, const char *string, - int is_utf8); - -strlist_t strlist_copy (strlist_t list); - -strlist_t strlist_prev (strlist_t head, strlist_t node); -strlist_t strlist_last (strlist_t node); -char * strlist_pop (strlist_t *list); - -#define FREE_STRLIST(a) do { free_strlist((a)); (a) = NULL ; } while(0) - - -#endif /*LIBJNLIB_STRLIST_H*/ diff --git a/jnlib/t-stringhelp.c b/jnlib/t-stringhelp.c deleted file mode 100644 index 0c921b03d..000000000 --- a/jnlib/t-stringhelp.c +++ /dev/null @@ -1,414 +0,0 @@ -/* t-stringhelp.c - Regression tests for stringhelp.c - * Copyright (C) 2007 Free Software Foundation, Inc. - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#include -#include -#include -#include -#include -#ifdef HAVE_PWD_H -# include -#endif -#include -#include - -#include "stringhelp.h" - -#include "t-support.h" - - -static char *home_buffer; - - -const char * -gethome (void) -{ - if (!home_buffer) - { - char *home = getenv("HOME"); - - if(home) - home_buffer = xstrdup (home); -#if defined(HAVE_GETPWUID) && defined(HAVE_PWD_H) - else - { - struct passwd *pwd; - - pwd = getpwuid (getuid()); - if (pwd) - home_buffer = xstrdup (pwd->pw_dir); - } -#endif - } - return home_buffer; -} - - -static void -test_percent_escape (void) -{ - char *result; - static struct { - const char *extra; - const char *value; - const char *expected; - } tests[] = - { - { NULL, "", "" }, - { NULL, "%", "%25" }, - { NULL, "%%", "%25%25" }, - { NULL, " %", " %25" }, - { NULL, ":", "%3a" }, - { NULL, " :", " %3a" }, - { NULL, ": ", "%3a " }, - { NULL, " : ", " %3a " }, - { NULL, "::", "%3a%3a" }, - { NULL, ": :", "%3a %3a" }, - { NULL, "%:", "%25%3a" }, - { NULL, ":%", "%3a%25" }, - { "\\\n:", ":%", "%3a%25" }, - { "\\\n:", "\\:%", "%5c%3a%25" }, - { "\\\n:", "\n:%", "%0a%3a%25" }, - { "\\\n:", "\xff:%", "\xff%3a%25" }, - { "\\\n:", "\xfe:%", "\xfe%3a%25" }, - { "\\\n:", "\x01:%", "\x01%3a%25" }, - { "\x01", "\x01:%", "%01%3a%25" }, - { "\xfe", "\xfe:%", "%fe%3a%25" }, - { "\xfe", "\xff:%", "\xff%3a%25" }, - - { NULL, NULL, NULL } - }; - int testno; - - result = percent_escape (NULL, NULL); - if (result) - fail (0); - for (testno=0; tests[testno].value; testno++) - { - result = percent_escape (tests[testno].value, tests[testno].extra); - if (!result) - fail (testno); - if (strcmp (result, tests[testno].expected)) - fail (testno); - xfree (result); - } - -} - - -static void -test_compare_filenames (void) -{ - struct { - const char *a; - const char *b; - int result; - } tests[] = { - { "", "", 0 }, - { "", "a", -1 }, - { "a", "", 1 }, - { "a", "a", 0 }, - { "a", "aa", -1 }, - { "aa", "a", 1 }, - { "a", "b", -1 }, - -#ifdef HAVE_W32_SYSTEM - { "a", "A", 0 }, - { "A", "a", 0 }, - { "foo/bar", "foo\\bar", 0 }, - { "foo\\bar", "foo/bar", 0 }, - { "foo\\", "foo/", 0 }, - { "foo/", "foo\\", 0 }, -#endif /*HAVE_W32_SYSTEM*/ - { NULL, NULL, 0} - }; - int testno, result; - - for (testno=0; tests[testno].a; testno++) - { - result = compare_filenames (tests[testno].a, tests[testno].b); - result = result < 0? -1 : result > 0? 1 : 0; - if (result != tests[testno].result) - fail (testno); - } -} - - -static void -test_strconcat (void) -{ - char *out; - - out = strconcat ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", - "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", - "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", - "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", - "1", "2", "3", "4", "5", "6", "7", NULL); - if (!out) - fail (0); - else - xfree (out); - out = strconcat ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", - "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", - "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", - "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", - "1", "2", "3", "4", "5", "6", "7", "8", NULL); - if (out) - fail (0); - else if (errno != EINVAL) - fail (0); - - out = strconcat ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", - "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", - "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", - "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", - "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL); - if (out) - fail (0); - else if (errno != EINVAL) - fail (0); - -#if __GNUC__ < 4 /* gcc 4.0 has a sentinel attribute. */ - out = strconcat (NULL); - if (!out || *out) - fail (1); -#endif - out = strconcat (NULL, NULL); - if (!out || *out) - fail (1); - out = strconcat ("", NULL); - if (!out || *out) - fail (1); - xfree (out); - - out = strconcat ("", "", NULL); - if (!out || *out) - fail (2); - xfree (out); - - out = strconcat ("a", "b", NULL); - if (!out || strcmp (out, "ab")) - fail (3); - xfree (out); - out = strconcat ("a", "b", "c", NULL); - if (!out || strcmp (out, "abc")) - fail (3); - xfree (out); - - out = strconcat ("a", "b", "cc", NULL); - if (!out || strcmp (out, "abcc")) - fail (4); - xfree (out); - out = strconcat ("a1", "b1", "c1", NULL); - if (!out || strcmp (out, "a1b1c1")) - fail (4); - xfree (out); - - out = strconcat ("", " long b ", "", "--even-longer--", NULL); - if (!out || strcmp (out, " long b --even-longer--")) - fail (5); - xfree (out); - - out = strconcat ("", " long b ", "", "--even-longer--", NULL); - if (!out || strcmp (out, " long b --even-longer--")) - fail (5); - xfree (out); -} - -static void -test_xstrconcat (void) -{ - char *out; - - out = xstrconcat ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", - "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", - "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", - "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", - "1", "2", "3", "4", "5", "6", "7", NULL); - if (!out) - fail (0); - -#if __GNUC__ < 4 /* gcc 4.0 has a sentinel attribute. */ - out = xstrconcat (NULL); - if (!out) - fail (1); -#endif - out = xstrconcat (NULL, NULL); - if (!out) - fail (1); - out = xstrconcat ("", NULL); - if (!out || *out) - fail (1); - xfree (out); - - out = xstrconcat ("", "", NULL); - if (!out || *out) - fail (2); - xfree (out); - - out = xstrconcat ("a", "b", NULL); - if (!out || strcmp (out, "ab")) - fail (3); - xfree (out); - out = xstrconcat ("a", "b", "c", NULL); - if (!out || strcmp (out, "abc")) - fail (3); - xfree (out); - - out = xstrconcat ("a", "b", "cc", NULL); - if (!out || strcmp (out, "abcc")) - fail (4); - xfree (out); - out = xstrconcat ("a1", "b1", "c1", NULL); - if (!out || strcmp (out, "a1b1c1")) - fail (4); - xfree (out); - - out = xstrconcat ("", " long b ", "", "--even-longer--", NULL); - if (!out || strcmp (out, " long b --even-longer--")) - fail (5); - xfree (out); - - out = xstrconcat ("", " long b ", "", "--even-longer--", NULL); - if (!out || strcmp (out, " long b --even-longer--")) - fail (5); - xfree (out); -} - - -static void -test_make_filename_try (void) -{ - char *out; - const char *home = gethome (); - size_t homelen = home? strlen (home):0; - - out = make_filename_try ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", - "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", - "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", - "1", "2", "3", NULL); - if (out) - fail (0); - else if (errno != EINVAL) - fail (0); - xfree (out); - out = make_filename_try ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", - "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", - "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", - "1", "2", "3", "4", NULL); - if (out) - fail (0); - else if (errno != EINVAL) - fail (0); - xfree (out); - - out = make_filename_try ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", - "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", - "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", - "1", "2", NULL); - if (!out || strcmp (out, - "1/2/3/4/5/6/7/8/9/10/" - "1/2/3/4/5/6/7/8/9/10/" - "1/2/3/4/5/6/7/8/9/10/" - "1/2")) - fail (0); - xfree (out); - - out = make_filename_try ("foo", "~/bar", "baz/cde", NULL); - if (!out || strcmp (out, "foo/~/bar/baz/cde")) - fail (1); - xfree (out); - - out = make_filename_try ("foo", "~/bar", "baz/cde/", NULL); - if (!out || strcmp (out, "foo/~/bar/baz/cde/")) - fail (1); - xfree (out); - - out = make_filename_try ("/foo", "~/bar", "baz/cde/", NULL); - if (!out || strcmp (out, "/foo/~/bar/baz/cde/")) - fail (1); - xfree (out); - - out = make_filename_try ("//foo", "~/bar", "baz/cde/", NULL); - if (!out || strcmp (out, "//foo/~/bar/baz/cde/")) - fail (1); - xfree (out); - - out = make_filename_try ("", "~/bar", "baz/cde", NULL); - if (!out || strcmp (out, "/~/bar/baz/cde")) - fail (1); - xfree (out); - - - out = make_filename_try ("~/foo", "bar", NULL); - if (!out) - fail (2); - if (home) - { - if (strlen (out) < homelen + 7) - fail (2); - if (strncmp (out, home, homelen)) - fail (2); - if (strcmp (out+homelen, "/foo/bar")) - fail (2); - } - else - { - if (strcmp (out, "~/foo/bar")) - fail (2); - } - xfree (out); - - out = make_filename_try ("~", "bar", NULL); - if (!out) - fail (2); - if (home) - { - if (strlen (out) < homelen + 3) - fail (2); - if (strncmp (out, home, homelen)) - fail (2); - if (strcmp (out+homelen, "/bar")) - fail (2); - } - else - { - if (strcmp (out, "~/bar")) - fail (2); - } - xfree (out); -} - - -int -main (int argc, char **argv) -{ - (void)argc; - (void)argv; - - test_percent_escape (); - test_compare_filenames (); - test_strconcat (); - test_xstrconcat (); - test_make_filename_try (); - - xfree (home_buffer); - return 0; -} - diff --git a/jnlib/t-support.c b/jnlib/t-support.c deleted file mode 100644 index bf05c4c06..000000000 --- a/jnlib/t-support.c +++ /dev/null @@ -1,147 +0,0 @@ -/* t-support.c - helper functions for the regression tests. - * Copyright (C) 2007 Free Software Foundation, Inc. - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#include -#include -#include -#include -#include -#include - -#include "t-support.h" - - -/* Replacements for the malloc functions as used here. */ - -static void -out_of_memory (void) -{ - fprintf (stderr,"error: out of core in regression tests: %s\n", - strerror (errno)); - exit (2); -} - - -void * -gcry_malloc (size_t n) -{ - return malloc (n); -} - -void * -gcry_xmalloc (size_t n) -{ - void *p = malloc (n); - if (!p) - out_of_memory (); - return p; -} - -char * -gcry_strdup (const char *string) -{ - char *p = malloc (strlen (string)+1); - if (p) - strcpy (p, string); - return p; -} - - -void * -gcry_realloc (void *a, size_t n) -{ - return realloc (a, n); -} - -void * -gcry_xrealloc (void *a, size_t n) -{ - void *p = realloc (a, n); - if (!p) - out_of_memory (); - return p; -} - - - -void * -gcry_calloc (size_t n, size_t m) -{ - return calloc (n, m); -} - -void * -gcry_xcalloc (size_t n, size_t m) -{ - void *p = calloc (n, m); - if (!p) - out_of_memory (); - return p; -} - - -char * -gcry_xstrdup (const char *string) -{ - void *p = malloc (strlen (string)+1); - if (!p) - out_of_memory (); - strcpy (p, string); - return p; -} - -void -gcry_free (void *a) -{ - if (a) - free (a); -} - - - -/* Stubs for gpg-error functions required because some compilers do - not eliminate the supposed-to-be-unused-inline-functions and thus - require functions called from these inline fucntions. Although we - do not use gpg-error, gpg-error.h may get included via gcrypt.h if - it happens to be used used in libjnlib-config.h. */ -#ifndef GPG_ERROR_H /* Don't do this if gpg-error.h has been included. */ -int -gpg_err_code_from_errno (int err) -{ - (void)err; - assert (!"stub function"); - return -1; -} -#endif /*GPG_ERROR_H*/ - - -/* Retrieve the error code directly from the ERRNO variable. This - returns GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped - (report this) and GPG_ERR_MISSING_ERRNO if ERRNO has the value 0. */ -#ifndef GPG_ERROR_H /* Don't do this if gpg-error.h has been included. */ -int -gpg_err_code_from_syserror (void) -{ - assert (!"stub function"); - return -1; -} -#endif /*GPG_ERROR_H*/ - - - diff --git a/jnlib/t-support.h b/jnlib/t-support.h deleted file mode 100644 index 2dfbc0990..000000000 --- a/jnlib/t-support.h +++ /dev/null @@ -1,60 +0,0 @@ -/* t-support.h - Helper for the regression tests - * Copyright (C) 2007 Free Software Foundation, Inc. - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#ifndef LIBJNLIB_T_SUPPORT_H -#define LIBJNLIB_T_SUPPORT_H 1 - -#ifdef GCRYPT_VERSION -#error The regression tests should not include with gcrypt.h -#endif - -#ifdef HAVE_W32CE_SYSTEM -#include /* Defines strerror. */ -#endif - - -#ifndef HAVE_GETENV -# define getenv(a) (NULL) -#endif - - -/* Replacement prototypes. */ -void *gcry_xmalloc (size_t n); -void *gcry_xcalloc (size_t n, size_t m); -void *gcry_xrealloc (void *a, size_t n); -char *gcry_xstrdup (const char * a); -void gcry_free (void *a); - -/* Map the used xmalloc functions to those implemented by t-support.c */ -#define xmalloc(a) gcry_xmalloc ( (a) ) -#define xcalloc(a,b) gcry_xcalloc ( (a), (b) ) -#define xrealloc(a,n) gcry_xrealloc ( (a), (n) ) -#define xstrdup(a) gcry_xstrdup ( (a) ) -#define xfree(a) gcry_free ( (a) ) - - -/* Macros to print the result of a test. */ -#define pass() do { ; } while(0) -#define fail(a) do { fprintf (stderr, "%s:%d: test %d failed\n",\ - __FILE__,__LINE__, (a)); \ - exit (1); \ - } while(0) - - -#endif /*LIBJNLIB_T_SUPPORT_H*/ diff --git a/jnlib/t-timestuff.c b/jnlib/t-timestuff.c deleted file mode 100644 index 46816765d..000000000 --- a/jnlib/t-timestuff.c +++ /dev/null @@ -1,145 +0,0 @@ -/* t-timestuff.c - Regression tests for time functions - * Copyright (C) 2007 Free Software Foundation, Inc. - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#include -#include -#include -#include -#include -#include - -#include "mischelp.h" - -#include "t-support.h" - - -static int -cmp_time_s (struct tm *a, struct tm *b) -{ - if (a->tm_year != b->tm_year - || a->tm_mon != b->tm_mon - || a->tm_mday != b->tm_mday - || a->tm_hour != b->tm_hour - || a->tm_min != b->tm_min - || a->tm_sec != b->tm_sec - || a->tm_wday != b->tm_wday - || a->tm_yday != b->tm_yday - || !a->tm_isdst != !b->tm_isdst) - return -1; - return 0; -} - - - -static void -test_timegm (void) -{ - static struct { - int year, mon, mday, hour, min, sec; - } tvalues[] = { - { -1 }, - { -2, 1 }, - { -2, 2 }, - { -2, 86399 }, - { -2, 86400 }, - { -2, 0x7ffffffe }, - { -2, 0x7fffffff }, - /* Note: Because we use mktime below we can only start with the - day after Epoch. */ - { 1970, 1, 2, 0, 0 , 1}, - { 1970, 1, 2, 0, 0 , 2}, - { 1970, 1, 2, 12, 0 , 0}, - { 1970, 1, 2, 23, 59 , 59}, - { 1999, 12, 31, 23, 59 , 59}, - { 2000, 1, 1, 0, 0, 0}, - { 2000, 1, 1, 0, 0, 1}, - { 2010, 12, 31, 23, 59 , 59}, - { 2010, 1, 1, 0, 0, 0}, - { 2010, 1, 1, 0, 0, 1}, - /* The date below is about the last time mktime works in CET on - Windows XP; this is a somewhat strange because 32 bit Unices - will happily work along for another month until they reach the - end of all ticks on 20380119T031408 (unless Uli takes - compassion on us and changes time_t to a u64). */ - { 2037, 12, 18, 23, 59, 59} - - }; - int tidx; - time_t now, atime, counter; - struct tm tbuf, tbuf2, *tp; - - counter = 0; - for (tidx=0; tidx < DIM (tvalues); tidx++) - { - if (tvalues[tidx].year == -1) - { - now = time (NULL); - } - else if (tvalues[tidx].year == -2) - { - now = tvalues[tidx].mon; - } - else - { - memset (&tbuf, 0, sizeof tbuf); - tbuf.tm_year = tvalues[tidx].year - 1900; - tbuf.tm_mon = tvalues[tidx].mon; - tbuf.tm_mday = tvalues[tidx].mday; - tbuf.tm_hour = tvalues[tidx].hour; - tbuf.tm_min = tvalues[tidx].min; - tbuf.tm_sec = tvalues[tidx].sec; - now = mktime (&tbuf); - } - if (now == (time_t)(-1)) - fail (tidx); - - tp = gmtime (&now); - if (!tp) - fail (tidx); - tbuf = *tp; - tbuf2 = tbuf; - atime = timegm (&tbuf); - if (atime == (time_t)(-1)) - fail (tidx); - if (atime != now) - fail (tidx); - - tp = gmtime (&atime); - if (!tp) - fail (tidx); - if (cmp_time_s (tp, &tbuf)) - fail (tidx); - if (cmp_time_s (tp, &tbuf2)) - fail (tidx); - } -} - - - -int -main (int argc, char **argv) -{ - (void)argc; - (void)argv; - - test_timegm (); - - return 0; -} - diff --git a/jnlib/t-w32-reg.c b/jnlib/t-w32-reg.c deleted file mode 100644 index f4848cbaa..000000000 --- a/jnlib/t-w32-reg.c +++ /dev/null @@ -1,70 +0,0 @@ -/* t-w32-reg.c - Regression tests for W32 registry functions - * Copyright (C) 2010 Free Software Foundation, Inc. - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#include -#include -#include -#include -#include -#include - -#include "mischelp.h" - -#include "t-support.h" -#include "w32help.h" - - -static void -test_read_registry (void) -{ - char *string; - -#ifdef HAVE_W32CE_SYSTEM - string = read_w32_registry_string ("HKEY_CLASSES_ROOT", - "BOOTSTRAP\\CLSID", NULL); - if (!string) - fail (0); - fprintf (stderr, "Bootstrap clsid: %s\n", string); - xfree (string); -#endif - - string = read_w32_registry_string - ("HKEY_CURRENT_USER", - "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", - "User Agent"); - if (!string) - fail (0); - fprintf (stderr, "User agent: %s\n", string); - xfree (string); -} - - - - -int -main (int argc, char **argv) -{ - (void)argc; - (void)argv; - - test_read_registry (); - - return 0; -} - diff --git a/jnlib/types.h b/jnlib/types.h deleted file mode 100644 index 62fa0470d..000000000 --- a/jnlib/types.h +++ /dev/null @@ -1,114 +0,0 @@ -/* types.h - define some extra types - * Copyright (C) 1999, 2000, 2001, 2006 Free Software Foundation, Inc. - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#ifndef LIBJNLIB_TYPES_H -#define LIBJNLIB_TYPES_H - -/* The AC_CHECK_SIZEOF() in configure fails for some machines. - * we provide some fallback values here */ -#if !SIZEOF_UNSIGNED_SHORT -# undef SIZEOF_UNSIGNED_SHORT -# define SIZEOF_UNSIGNED_SHORT 2 -#endif -#if !SIZEOF_UNSIGNED_INT -# undef SIZEOF_UNSIGNED_INT -# define SIZEOF_UNSIGNED_INT 4 -#endif -#if !SIZEOF_UNSIGNED_LONG -# undef SIZEOF_UNSIGNED_LONG -# define SIZEOF_UNSIGNED_LONG 4 -#endif - - -#include - - -#ifndef HAVE_BYTE_TYPEDEF -# undef byte /* There might be a macro with this name. */ -/* Windows typedefs byte in the rpc headers. Avoid warning about - double definition. */ -#if !(defined(_WIN32) && defined(cbNDRContext)) - typedef unsigned char byte; -#endif -# define HAVE_BYTE_TYPEDEF -#endif - -#ifndef HAVE_USHORT_TYPEDEF -# undef ushort /* There might be a macro with this name. */ - typedef unsigned short ushort; -# define HAVE_USHORT_TYPEDEF -#endif - -#ifndef HAVE_ULONG_TYPEDEF -# undef ulong /* There might be a macro with this name. */ - typedef unsigned long ulong; -# define HAVE_ULONG_TYPEDEF -#endif - -#ifndef HAVE_U16_TYPEDEF -# undef u16 /* There might be a macro with this name. */ -# if SIZEOF_UNSIGNED_INT == 2 - typedef unsigned int u16; -# elif SIZEOF_UNSIGNED_SHORT == 2 - typedef unsigned short u16; -# else -# error no typedef for u16 -# endif -# define HAVE_U16_TYPEDEF -#endif - -#ifndef HAVE_U32_TYPEDEF -# undef u32 /* There might be a macro with this name. */ -# if SIZEOF_UNSIGNED_INT == 4 - typedef unsigned int u32; -# elif SIZEOF_UNSIGNED_LONG == 4 - typedef unsigned long u32; -# else -# error no typedef for u32 -# endif -# define HAVE_U32_TYPEDEF -#endif - -#ifndef HAVE_U64_TYPEDEF -# undef u64 /* There might be a macro with this name. */ -# if SIZEOF_UNSIGNED_INT == 8 - typedef unsigned int u64; -# define HAVE_U64_TYPEDEF -# elif SIZEOF_UNSIGNED_LONG == 8 - typedef unsigned long u64; -# define HAVE_U64_TYPEDEF -# elif __GNUC__ >= 2 || defined(__SUNPRO_C) - typedef unsigned long long u64; -# define HAVE_U64_TYPEDEF -# endif -#endif - - -/* Some GCC attributes. Note that we use also define some in - mischelp.h, but this header and types.h are not always included. - Should eventually be put into one file (e.g. nlib-common.h). */ -#if __GNUC__ >= 4 -# define GNUPG_GCC_A_SENTINEL(a) __attribute__ ((sentinel(a))) -#else -# define GNUPG_GCC_A_SENTINEL(a) -#endif - - - -#endif /*LIBJNLIB_TYPES_H*/ diff --git a/jnlib/utf8conv.c b/jnlib/utf8conv.c deleted file mode 100644 index 6cbe4e92c..000000000 --- a/jnlib/utf8conv.c +++ /dev/null @@ -1,813 +0,0 @@ -/* utf8conf.c - UTF8 character set conversion - * Copyright (C) 1994, 1998, 1999, 2000, 2001, 2003, 2006, - * 2008, 2010 Free Software Foundation, Inc. - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#include -#include -#include -#include -#include -#ifdef HAVE_LANGINFO_CODESET -#include -#endif -#include -#ifndef HAVE_W32_SYSTEM -# include -#endif - -#include "libjnlib-config.h" -#include "stringhelp.h" -#include "dynload.h" -#include "utf8conv.h" - -#ifndef MB_LEN_MAX -#define MB_LEN_MAX 16 -#endif - -static const char *active_charset_name = "iso-8859-1"; -static int no_translation; /* Set to true if we let simply pass through. */ -static int use_iconv; /* iconv comversion fucntions required. */ - - -/* Under W32 we dlopen the iconv dll and don't require any iconv - related headers at all. However we need to define some stuff. */ -#ifdef HAVE_W32_SYSTEM -typedef void *iconv_t; -#ifndef ICONV_CONST -#define ICONV_CONST -#endif -static iconv_t (* __stdcall iconv_open) (const char *tocode, - const char *fromcode); -static size_t (* __stdcall iconv) (iconv_t cd, - char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft); -static int (* __stdcall iconv_close) (iconv_t cd); - -static int -load_libiconv (void) -{ - static int done; - - if (!done) - { - void *handle; - - done = 1; /* Do it right now because we might get called recursivly - through gettext. */ - - handle = dlopen ("iconv.dll", RTLD_LAZY); - if (handle) - { - iconv_open = dlsym (handle, "libiconv_open"); - if (iconv_open) - iconv = dlsym (handle, "libiconv"); - if (iconv) - iconv_close = dlsym (handle, "libiconv_close"); - } - if (!handle || !iconv_close) - { - log_info (_("error loading `%s': %s\n"), - "iconv.dll", dlerror ()); - log_info (_("please see %s for more information\n"), - "http://www.gnupg.org/download/iconv.html"); - iconv_open = NULL; - iconv = NULL; - iconv_close = NULL; - if (handle) - dlclose (handle); - } - } - return iconv_open? 0: -1; -} -#endif /*HAVE_W32_SYSTEM*/ - - -/* Error handler for iconv failures. This is needed to not clutter the - output with repeated diagnostics about a missing conversion. */ -static void -handle_iconv_error (const char *to, const char *from, int use_fallback) -{ - if (errno == EINVAL) - { - static int shown1, shown2; - int x; - - if (to && !strcmp (to, "utf-8")) - { - x = shown1; - shown1 = 1; - } - else - { - x = shown2; - shown2 = 1; - } - - if (!x) - log_info (_("conversion from `%s' to `%s' not available\n"), - from, to); - } - else - { - static int shown; - - if (!shown) - log_info (_("iconv_open failed: %s\n"), strerror (errno)); - shown = 1; - } - - if (use_fallback) - { - /* To avoid further error messages we fallback to Latin-1 for the - native encoding. This is justified as one can expect that on a - utf-8 enabled system nl_langinfo() will work and thus we won't - never get to here. Thus Latin-1 seems to be a reasonable - default. */ - active_charset_name = "iso-8859-1"; - no_translation = 0; - use_iconv = 0; - } -} - - - -int -set_native_charset (const char *newset) -{ - const char *full_newset; - - if (!newset) - { -#ifdef HAVE_W32_SYSTEM - static char codepage[30]; - unsigned int cpno; - const char *aliases; - - /* We are a console program thus we need to use the - GetConsoleOutputCP function and not the the GetACP which - would give the codepage for a GUI program. Note this is not - a bulletproof detection because GetConsoleCP might return a - different one for console input. Not sure how to cope with - that. If the console Code page is not known we fall back to - the system code page. */ -#ifndef HAVE_W32CE_SYSTEM - cpno = GetConsoleOutputCP (); - if (!cpno) -#endif - cpno = GetACP (); - sprintf (codepage, "CP%u", cpno ); - /* Resolve alias. We use a long string string and not the usual - array to optimize if the code is taken to a DSO. Taken from - libiconv 1.9.2. */ - newset = codepage; - for (aliases = ("CP936" "\0" "GBK" "\0" - "CP1361" "\0" "JOHAB" "\0" - "CP20127" "\0" "ASCII" "\0" - "CP20866" "\0" "KOI8-R" "\0" - "CP21866" "\0" "KOI8-RU" "\0" - "CP28591" "\0" "ISO-8859-1" "\0" - "CP28592" "\0" "ISO-8859-2" "\0" - "CP28593" "\0" "ISO-8859-3" "\0" - "CP28594" "\0" "ISO-8859-4" "\0" - "CP28595" "\0" "ISO-8859-5" "\0" - "CP28596" "\0" "ISO-8859-6" "\0" - "CP28597" "\0" "ISO-8859-7" "\0" - "CP28598" "\0" "ISO-8859-8" "\0" - "CP28599" "\0" "ISO-8859-9" "\0" - "CP28605" "\0" "ISO-8859-15" "\0" - "CP65001" "\0" "UTF-8" "\0"); - *aliases; - aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1) - { - if (!strcmp (codepage, aliases) ||(*aliases == '*' && !aliases[1])) - { - newset = aliases + strlen (aliases) + 1; - break; - } - } - -#else /*!HAVE_W32_SYSTEM*/ - -#ifdef HAVE_LANGINFO_CODESET - newset = nl_langinfo (CODESET); -#else /*!HAVE_LANGINFO_CODESET*/ - /* Try to get the used charset from environment variables. */ - static char codepage[30]; - const char *lc, *dot, *mod; - - strcpy (codepage, "iso-8859-1"); - lc = getenv ("LC_ALL"); - if (!lc || !*lc) - { - lc = getenv ("LC_CTYPE"); - if (!lc || !*lc) - lc = getenv ("LANG"); - } - if (lc && *lc) - { - dot = strchr (lc, '.'); - if (dot) - { - mod = strchr (++dot, '@'); - if (!mod) - mod = dot + strlen (dot); - if (mod - dot < sizeof codepage && dot != mod) - { - memcpy (codepage, dot, mod - dot); - codepage [mod - dot] = 0; - } - } - } - newset = codepage; -#endif /*!HAVE_LANGINFO_CODESET*/ -#endif /*!HAVE_W32_SYSTEM*/ - } - - full_newset = newset; - if (strlen (newset) > 3 && !ascii_memcasecmp (newset, "iso", 3)) - { - newset += 3; - if (*newset == '-' || *newset == '_') - newset++; - } - - /* Note that we silently assume that plain ASCII is actually meant - as Latin-1. This makes sense because many Unix system don't have - their locale set up properly and thus would get annoying error - messages and we have to handle all the "bug" reports. Latin-1 has - always been the character set used for 8 bit characters on Unix - systems. */ - if ( !*newset - || !ascii_strcasecmp (newset, "8859-1" ) - || !ascii_strcasecmp (newset, "646" ) - || !ascii_strcasecmp (newset, "ASCII" ) - || !ascii_strcasecmp (newset, "ANSI_X3.4-1968" ) - ) - { - active_charset_name = "iso-8859-1"; - no_translation = 0; - use_iconv = 0; - } - else if ( !ascii_strcasecmp (newset, "utf8" ) - || !ascii_strcasecmp(newset, "utf-8") ) - { - active_charset_name = "utf-8"; - no_translation = 1; - use_iconv = 0; - } - else - { - iconv_t cd; - -#ifdef HAVE_W32_SYSTEM - if (load_libiconv ()) - return -1; -#endif /*HAVE_W32_SYSTEM*/ - - cd = iconv_open (full_newset, "utf-8"); - if (cd == (iconv_t)-1) - { - handle_iconv_error (full_newset, "utf-8", 0); - return -1; - } - iconv_close (cd); - cd = iconv_open ("utf-8", full_newset); - if (cd == (iconv_t)-1) - { - handle_iconv_error ("utf-8", full_newset, 0); - return -1; - } - iconv_close (cd); - active_charset_name = full_newset; - no_translation = 0; - use_iconv = 1; - } - return 0; -} - -const char * -get_native_charset () -{ - return active_charset_name; -} - -/* Return true if the native charset is utf-8. */ -int -is_native_utf8 (void) -{ - return no_translation; -} - - -/* Convert string, which is in native encoding to UTF8 and return a - new allocated UTF-8 string. This function terminates the process - on memory shortage. */ -char * -native_to_utf8 (const char *orig_string) -{ - const unsigned char *string = (const unsigned char *)orig_string; - const unsigned char *s; - char *buffer; - unsigned char *p; - size_t length = 0; - - if (no_translation) - { - /* Already utf-8 encoded. */ - buffer = jnlib_xstrdup (orig_string); - } - else if (!use_iconv) - { - /* For Latin-1 we can avoid the iconv overhead. */ - for (s = string; *s; s++) - { - length++; - if (*s & 0x80) - length++; - } - buffer = jnlib_xmalloc (length + 1); - for (p = (unsigned char *)buffer, s = string; *s; s++) - { - if ( (*s & 0x80 )) - { - *p++ = 0xc0 | ((*s >> 6) & 3); - *p++ = 0x80 | (*s & 0x3f); - } - else - *p++ = *s; - } - *p = 0; - } - else - { - /* Need to use iconv. */ - iconv_t cd; - const char *inptr; - char *outptr; - size_t inbytes, outbytes; - - cd = iconv_open ("utf-8", active_charset_name); - if (cd == (iconv_t)-1) - { - handle_iconv_error ("utf-8", active_charset_name, 1); - return native_to_utf8 (string); - } - - for (s=string; *s; s++ ) - { - length++; - if ((*s & 0x80)) - length += 5; /* We may need up to 6 bytes for the utf8 output. */ - } - buffer = jnlib_xmalloc (length + 1); - - inptr = string; - inbytes = strlen (string); - outptr = buffer; - outbytes = length; - if ( iconv (cd, (ICONV_CONST char **)&inptr, &inbytes, - &outptr, &outbytes) == (size_t)-1) - { - static int shown; - - if (!shown) - log_info (_("conversion from `%s' to `%s' failed: %s\n"), - active_charset_name, "utf-8", strerror (errno)); - shown = 1; - /* We don't do any conversion at all but use the strings as is. */ - strcpy (buffer, string); - } - else /* Success. */ - { - *outptr = 0; - /* We could realloc the buffer now but I doubt that it makes - much sense given that it will get freed anyway soon - after. */ - } - iconv_close (cd); - } - return buffer; -} - - - -static char * -do_utf8_to_native (const char *string, size_t length, int delim, - int with_iconv) -{ - int nleft; - int i; - unsigned char encbuf[8]; - int encidx; - const unsigned char *s; - size_t n; - char *buffer = NULL; - char *p = NULL; - unsigned long val = 0; - size_t slen; - int resync = 0; - - /* First pass (p==NULL): count the extended utf-8 characters. */ - /* Second pass (p!=NULL): create string. */ - for (;;) - { - for (slen = length, nleft = encidx = 0, n = 0, - s = (const unsigned char *)string; - slen; - s++, slen--) - { - if (resync) - { - if (!(*s < 128 || (*s >= 0xc0 && *s <= 0xfd))) - { - /* Still invalid. */ - if (p) - { - sprintf (p, "\\x%02x", *s); - p += 4; - } - n += 4; - continue; - } - resync = 0; - } - if (!nleft) - { - if (!(*s & 0x80)) - { - /* Plain ascii. */ - if ( delim != -1 - && (*s < 0x20 || *s == 0x7f || *s == delim - || (delim && *s == '\\'))) - { - n++; - if (p) - *p++ = '\\'; - switch (*s) - { - case '\n': n++; if ( p ) *p++ = 'n'; break; - case '\r': n++; if ( p ) *p++ = 'r'; break; - case '\f': n++; if ( p ) *p++ = 'f'; break; - case '\v': n++; if ( p ) *p++ = 'v'; break; - case '\b': n++; if ( p ) *p++ = 'b'; break; - case 0: n++; if ( p ) *p++ = '0'; break; - default: - n += 3; - if (p) - { - sprintf (p, "x%02x", *s); - p += 3; - } - break; - } - } - else - { - if (p) - *p++ = *s; - n++; - } - } - else if ((*s & 0xe0) == 0xc0) /* 110x xxxx */ - { - val = *s & 0x1f; - nleft = 1; - encidx = 0; - encbuf[encidx++] = *s; - } - else if ((*s & 0xf0) == 0xe0) /* 1110 xxxx */ - { - val = *s & 0x0f; - nleft = 2; - encidx = 0; - encbuf[encidx++] = *s; - } - else if ((*s & 0xf8) == 0xf0) /* 1111 0xxx */ - { - val = *s & 0x07; - nleft = 3; - encidx = 0; - encbuf[encidx++] = *s; - } - else if ((*s & 0xfc) == 0xf8) /* 1111 10xx */ - { - val = *s & 0x03; - nleft = 4; - encidx = 0; - encbuf[encidx++] = *s; - } - else if ((*s & 0xfe) == 0xfc) /* 1111 110x */ - { - val = *s & 0x01; - nleft = 5; - encidx = 0; - encbuf[encidx++] = *s; - } - else /* Invalid encoding: print as \xNN. */ - { - if (p) - { - sprintf (p, "\\x%02x", *s); - p += 4; - } - n += 4; - resync = 1; - } - } - else if (*s < 0x80 || *s >= 0xc0) /* Invalid utf-8 */ - { - if (p) - { - for (i = 0; i < encidx; i++) - { - sprintf (p, "\\x%02x", encbuf[i]); - p += 4; - } - sprintf (p, "\\x%02x", *s); - p += 4; - } - n += 4 + 4 * encidx; - nleft = 0; - encidx = 0; - resync = 1; - } - else - { - encbuf[encidx++] = *s; - val <<= 6; - val |= *s & 0x3f; - if (!--nleft) /* Ready. */ - { - if (no_translation) - { - if (p) - { - for (i = 0; i < encidx; i++) - *p++ = encbuf[i]; - } - n += encidx; - encidx = 0; - } - else if (with_iconv) - { - /* Our strategy for using iconv is a bit strange - but it better keeps compatibility with - previous versions in regard to how invalid - encodings are displayed. What we do is to - keep the utf-8 as is and have the real - translation step then at the end. Yes, I - know that this is ugly. However we are short - of the 1.4 release and for this branch we - should not mess too much around with iconv - things. One reason for this is that we don't - know enough about non-GNU iconv - implementation and want to minimize the risk - of breaking the code on too many platforms. */ - if ( p ) - { - for (i=0; i < encidx; i++ ) - *p++ = encbuf[i]; - } - n += encidx; - encidx = 0; - } - else /* Latin-1 case. */ - { - if (val >= 0x80 && val < 256) - { - /* We can simply print this character */ - n++; - if (p) - *p++ = val; - } - else - { - /* We do not have a translation: print utf8. */ - if (p) - { - for (i = 0; i < encidx; i++) - { - sprintf (p, "\\x%02x", encbuf[i]); - p += 4; - } - } - n += encidx * 4; - encidx = 0; - } - } - } - - } - } - if (!buffer) - { - /* Allocate the buffer after the first pass. */ - buffer = p = jnlib_xmalloc (n + 1); - } - else if (with_iconv) - { - /* Note: See above for comments. */ - iconv_t cd; - const char *inptr; - char *outbuf, *outptr; - size_t inbytes, outbytes; - - *p = 0; /* Terminate the buffer. */ - - cd = iconv_open (active_charset_name, "utf-8"); - if (cd == (iconv_t)-1) - { - handle_iconv_error (active_charset_name, "utf-8", 1); - jnlib_free (buffer); - return utf8_to_native (string, length, delim); - } - - /* Allocate a new buffer large enough to hold all possible - encodings. */ - n = p - buffer + 1; - inbytes = n - 1;; - inptr = buffer; - outbytes = n * MB_LEN_MAX; - if (outbytes / MB_LEN_MAX != n) - BUG (); /* Actually an overflow. */ - outbuf = outptr = jnlib_xmalloc (outbytes); - if ( iconv (cd, (ICONV_CONST char **)&inptr, &inbytes, - &outptr, &outbytes) == (size_t)-1) - { - static int shown; - - if (!shown) - log_info (_("conversion from `%s' to `%s' failed: %s\n"), - "utf-8", active_charset_name, strerror (errno)); - shown = 1; - /* Didn't worked out. Try again but without iconv. */ - jnlib_free (buffer); - buffer = NULL; - jnlib_free (outbuf); - outbuf = do_utf8_to_native (string, length, delim, 0); - } - else /* Success. */ - { - *outptr = 0; /* Make sure it is a string. */ - /* We could realloc the buffer now but I doubt that it - makes much sense given that it will get freed - anyway soon after. */ - jnlib_free (buffer); - } - iconv_close (cd); - return outbuf; - } - else /* Not using iconv. */ - { - *p = 0; /* Make sure it is a string. */ - return buffer; - } - } -} - -/* Convert string, which is in UTF-8 to native encoding. Replace - illegal encodings by some "\xnn" and quote all control - characters. A character with value DELIM will always be quoted, it - must be a vanilla ASCII character. A DELIM value of -1 is special: - it disables all quoting of control characters. This function - terminates the process on memory shortage. */ -char * -utf8_to_native (const char *string, size_t length, int delim) -{ - return do_utf8_to_native (string, length, delim, use_iconv); -} - - - - -/* Wrapper function for iconv_open, required for W32 as we dlopen that - library on that system. */ -jnlib_iconv_t -jnlib_iconv_open (const char *tocode, const char *fromcode) -{ -#ifdef HAVE_W32_SYSTEM - if (load_libiconv ()) - return (jnlib_iconv_t)(-1); -#endif /*HAVE_W32_SYSTEM*/ - - return (jnlib_iconv_t)iconv_open (tocode, fromcode); -} - - -/* Wrapper function for iconv, required for W32 as we dlopen that - library on that system. */ -size_t -jnlib_iconv (jnlib_iconv_t cd, - const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft) -{ - -#ifdef HAVE_W32_SYSTEM - if (load_libiconv ()) - return 0; -#endif /*HAVE_W32_SYSTEM*/ - - return iconv ((iconv_t)cd, (char**)inbuf, inbytesleft, outbuf, outbytesleft); -} - -/* Wrapper function for iconv_close, required for W32 as we dlopen that - library on that system. */ -int -jnlib_iconv_close (jnlib_iconv_t cd) -{ -#ifdef HAVE_W32_SYSTEM - if (load_libiconv ()) - return 0; -#endif /*HAVE_W32_SYSTEM*/ - - return iconv_close ((iconv_t)cd); -} - - -#ifdef HAVE_W32_SYSTEM -/* Return a malloced string encoded in UTF-8 from the wide char input - string STRING. Caller must free this value. Returns NULL and sets - ERRNO on failure. Calling this function with STRING set to NULL is - not defined. */ -char * -wchar_to_utf8 (const wchar_t *string) -{ - int n; - char *result; - - n = WideCharToMultiByte (CP_UTF8, 0, string, -1, NULL, 0, NULL, NULL); - if (n < 0) - { - jnlib_set_errno (EINVAL); - return NULL; - } - - result = jnlib_malloc (n+1); - if (!result) - return NULL; - - n = WideCharToMultiByte (CP_UTF8, 0, string, -1, result, n, NULL, NULL); - if (n < 0) - { - jnlib_free (result); - jnlib_set_errno (EINVAL); - result = NULL; - } - return result; -} - - -/* Return a malloced wide char string from an UTF-8 encoded input - string STRING. Caller must free this value. Returns NULL and sets - ERRNO on failure. Calling this function with STRING set to NULL is - not defined. */ -wchar_t * -utf8_to_wchar (const char *string) -{ - int n; - size_t nbytes; - wchar_t *result; - - n = MultiByteToWideChar (CP_UTF8, 0, string, -1, NULL, 0); - if (n < 0) - { - jnlib_set_errno (EINVAL); - return NULL; - } - - nbytes = (size_t)(n+1) * sizeof(*result); - if (nbytes / sizeof(*result) != (n+1)) - { - jnlib_set_errno (ENOMEM); - return NULL; - } - result = malloc (nbytes); - if (!result) - return NULL; - - n = MultiByteToWideChar (CP_UTF8, 0, string, -1, result, n); - if (n < 0) - { - free (result); - jnlib_set_errno (EINVAL); - result = NULL; - } - return result; -} -#endif /*HAVE_W32_SYSTEM*/ diff --git a/jnlib/utf8conv.h b/jnlib/utf8conv.h deleted file mode 100644 index 28dd450dd..000000000 --- a/jnlib/utf8conv.h +++ /dev/null @@ -1,45 +0,0 @@ -/* utf8conf.h - * Copyright (C) 2003, 2006 Free Software Foundation, Inc. - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#ifndef LIBJNLIB_UTF8CONF_H -#define LIBJNLIB_UTF8CONF_H - -int set_native_charset (const char *newset); -const char *get_native_charset (void); -int is_native_utf8 (void); - -char *native_to_utf8 (const char *string); -char *utf8_to_native (const char *string, size_t length, int delim); - - -/* Silly wrappers, required for W32 portability. */ -typedef void *jnlib_iconv_t; - -jnlib_iconv_t jnlib_iconv_open (const char *tocode, const char *fromcode); -size_t jnlib_iconv (jnlib_iconv_t cd, const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft); -int jnlib_iconv_close (jnlib_iconv_t cd); - -#ifdef HAVE_W32_SYSTEM -char *wchar_to_utf8 (const wchar_t *string); -wchar_t *utf8_to_wchar (const char *string); -#endif /*HAVE_W32_SYSTEM*/ - - -#endif /*LIBJNLIB_UTF8CONF_H*/ diff --git a/jnlib/w32-afunix.c b/jnlib/w32-afunix.c deleted file mode 100644 index 579621491..000000000 --- a/jnlib/w32-afunix.c +++ /dev/null @@ -1,138 +0,0 @@ -/* w32-afunix.c - AF_UNIX emulation for Windows (Client only). - * Copyright (C) 2004, 2006 g10 Code GmbH - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -/* Use of this code is preprecated - you better use the sockt wrappers - from libassuan. */ - -#ifdef _WIN32 -#include -#include -#define WIN32_LEAN_AND_MEAN -#include -#include -#include -#include -#include - -#include "w32-afunix.h" - - - -/* The buffer for NONCE needs to be at least 16 bytes. Returns 0 on - success. */ -static int -read_port_and_nonce (const char *fname, unsigned short *port, char *nonce) -{ - FILE *fp; - char buffer[50], *p; - size_t nread; - int aval; - - fp = fopen (fname, "rb"); - if (!fp) - return -1; - nread = fread (buffer, 1, sizeof buffer - 1, fp); - fclose (fp); - if (!nread) - { -#warning remove this file - jnlib_set_errno (EIO); - return -1; - } - buffer[nread] = 0; - aval = atoi (buffer); - if (aval < 1 || aval > 65535) - { - jnlib_set_errno (EINVAL); - return -1; - } - *port = (unsigned int)aval; - for (p=buffer; nread && *p != '\n'; p++, nread--) - ; - if (*p != '\n' || nread != 17) - { - jnlib_set_errno (EINVAL); - return -1; - } - p++; nread--; - memcpy (nonce, p, 16); - return 0; -} - - - -int -_w32_close (int fd) -{ - int rc = closesocket (fd); - if (rc && WSAGetLastError () == WSAENOTSOCK) - rc = close (fd); - return rc; -} - - -int -_w32_sock_new (int domain, int type, int proto) -{ - if (domain == AF_UNIX || domain == AF_LOCAL) - domain = AF_INET; - return socket (domain, type, proto); -} - - -int -_w32_sock_connect (int sockfd, struct sockaddr *addr, int addrlen) -{ - struct sockaddr_in myaddr; - struct sockaddr_un *unaddr; - unsigned short port; - char nonce[16]; - int ret; - - (void)addrlen; - - unaddr = (struct sockaddr_un *)addr; - if (read_port_and_nonce (unaddr->sun_path, &port, nonce)) - return -1; - - myaddr.sin_family = AF_INET; - myaddr.sin_port = htons (port); - myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); - - /* Set return values. */ - unaddr->sun_family = myaddr.sin_family; - unaddr->sun_port = myaddr.sin_port; - unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr; - - ret = connect (sockfd, (struct sockaddr *)&myaddr, sizeof myaddr); - if (!ret) - { - /* Send the nonce. */ - ret = send (sockfd, nonce, 16, 0); - if (ret >= 0 && ret != 16) - { - jnlib_set_errno (EIO); - ret = -1; - } - } - return ret; -} - - -#endif /*_WIN32*/ diff --git a/jnlib/w32-afunix.h b/jnlib/w32-afunix.h deleted file mode 100644 index 23681ddeb..000000000 --- a/jnlib/w32-afunix.h +++ /dev/null @@ -1,52 +0,0 @@ -/* w32-afunix.h - AF_UNIX emulation for Windows - * Copyright (C) 2004, 2006 g10 Code GmbH - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#ifdef _WIN32 -#ifndef W32AFUNIX_DEFS_H -#define W32AFUNIX_DEFS_H - -#include -#include -#include -#include - -/* We can easiliy replace this code by the socket wrappers from libassuan. */ -#warning Please do not use this module anymore - -#define DIRSEP_C '\\' - -#define AF_LOCAL AF_UNIX -/* We need to prefix the structure with a sockaddr_in header so we can - use it later for sendto and recvfrom. */ -struct sockaddr_un -{ - short sun_family; - unsigned short sun_port; - struct in_addr sun_addr; - char sun_path[108-2-4]; /* Path name. */ -}; - - -int _w32_close (int fd); -int _w32_sock_new (int domain, int type, int proto); -int _w32_sock_connect (int sockfd, struct sockaddr *addr, int addrlen); - - -#endif /*W32AFUNIX_DEFS_H*/ -#endif /*_WIN32*/ diff --git a/jnlib/w32-reg.c b/jnlib/w32-reg.c deleted file mode 100644 index 5809c32bb..000000000 --- a/jnlib/w32-reg.c +++ /dev/null @@ -1,312 +0,0 @@ -/* w32-reg.c - MS-Windows Registry access - * Copyright (C) 1999, 2002, 2007 Free Software Foundation, Inc. - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#include -#ifdef HAVE_W32_SYSTEM - /* This module is only used in this environment */ - -#include -#include -#include -#include -#include - -#include "libjnlib-config.h" -#include "utf8conv.h" -#include "w32help.h" - - -static HKEY -get_root_key(const char *root) -{ - HKEY root_key; - - if (!root) - root_key = HKEY_CURRENT_USER; - else if (!strcmp( root, "HKEY_CLASSES_ROOT" ) ) - root_key = HKEY_CLASSES_ROOT; - else if (!strcmp( root, "HKEY_CURRENT_USER" ) ) - root_key = HKEY_CURRENT_USER; - else if (!strcmp( root, "HKEY_LOCAL_MACHINE" ) ) - root_key = HKEY_LOCAL_MACHINE; - else if (!strcmp( root, "HKEY_USERS" ) ) - root_key = HKEY_USERS; - else if (!strcmp( root, "HKEY_PERFORMANCE_DATA" ) ) - root_key = HKEY_PERFORMANCE_DATA; - else if (!strcmp( root, "HKEY_CURRENT_CONFIG" ) ) - root_key = HKEY_CURRENT_CONFIG; - else - return NULL; - - return root_key; -} - - -/* Return a string from the Win32 Registry or NULL in case of error. - Caller must release the return value. A NULL for root is an alias - for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn. */ -char * -read_w32_registry_string (const char *root, const char *dir, const char *name) -{ -#ifdef HAVE_W32CE_SYSTEM - HKEY root_key, key_handle; - DWORD n1, nbytes, type; - char *result = NULL; - wchar_t *wdir, *wname; - - if ( !(root_key = get_root_key(root) ) ) - return NULL; - - wdir = utf8_to_wchar (dir); - if (!wdir) - return NULL; - - if (RegOpenKeyEx (root_key, wdir, 0, KEY_READ, &key_handle) ) - { - if (root) - { - jnlib_free (wdir); - return NULL; /* No need for a RegClose, so return immediately. */ - } - /* It seems to be common practise to fall back to HKLM. */ - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, wdir, 0, KEY_READ, &key_handle) ) - { - jnlib_free (wdir); - return NULL; /* Still no need for a RegClose. */ - } - } - jnlib_free (wdir); - - if (name) - { - wname = utf8_to_wchar (name); - if (!wname) - goto leave; - } - else - wname = NULL; - - nbytes = 2; - if (RegQueryValueEx (key_handle, wname, 0, NULL, NULL, &nbytes)) - goto leave; - result = jnlib_malloc ((n1=nbytes+2)); - if (!result) - goto leave; - if (RegQueryValueEx (key_handle, wname, 0, &type, result, &n1)) - { - jnlib_free (result); - result = NULL; - goto leave; - } - result[nbytes] = 0; /* Make sure it is a string. */ - result[nbytes+1] = 0; - if (type == REG_SZ || type == REG_EXPAND_SZ) - { - wchar_t *tmp = (void*)result; - result = wchar_to_utf8 (tmp); - jnlib_free (tmp); - } - - leave: - jnlib_free (wname); - RegCloseKey (key_handle); - return result; -#else /*!HAVE_W32CE_SYSTEM*/ - HKEY root_key, key_handle; - DWORD n1, nbytes, type; - char *result = NULL; - - if ( !(root_key = get_root_key(root) ) ) - return NULL; - - if (RegOpenKeyEx (root_key, dir, 0, KEY_READ, &key_handle) ) - { - if (root) - return NULL; /* No need for a RegClose, so return immediately. */ - /* It seems to be common practise to fall back to HKLM. */ - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) ) - return NULL; /* Still no need for a RegClose. */ - } - - nbytes = 1; - if (RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes ) ) - goto leave; - result = jnlib_malloc ((n1=nbytes+1)); - if (!result) - goto leave; - if (RegQueryValueEx( key_handle, name, 0, &type, result, &n1 )) - { - jnlib_free (result); - result = NULL; - goto leave; - } - result[nbytes] = 0; /* Make sure it is a string. */ - if (type == REG_EXPAND_SZ && strchr (result, '%')) - { - char *tmp; - - n1 += 1000; - tmp = jnlib_malloc (n1+1); - if (!tmp) - goto leave; - nbytes = ExpandEnvironmentStrings (result, tmp, n1); - if (nbytes && nbytes > n1) - { - jnlib_free (tmp); - n1 = nbytes; - tmp = jnlib_malloc (n1 + 1); - if (!tmp) - goto leave; - nbytes = ExpandEnvironmentStrings (result, tmp, n1); - if (nbytes && nbytes > n1) - { - /* Oops - truncated, better don't expand at all. */ - jnlib_free (tmp); - goto leave; - } - tmp[nbytes] = 0; - jnlib_free (result); - result = tmp; - } - else if (nbytes) - { - /* Okay, reduce the length. */ - tmp[nbytes] = 0; - jnlib_free (result); - result = jnlib_malloc (strlen (tmp)+1); - if (!result) - result = tmp; - else - { - strcpy (result, tmp); - jnlib_free (tmp); - } - } - else - { - /* Error - don't expand. */ - jnlib_free (tmp); - } - } - - leave: - RegCloseKey (key_handle); - return result; -#endif /*!HAVE_W32CE_SYSTEM*/ -} - - -/* Note: This code is not well tested. However, it is not used in - GnuPG. */ -int -write_w32_registry_string (const char *root, const char *dir, - const char *name, const char *value) -{ - HKEY root_key, reg_key; -#ifdef HAVE_W32CE_SYSTEM - wchar_t *wdir, *wname, *wvalue; - DWORD disp; - - if ( !(root_key = get_root_key(root) ) ) - return -1; - - wdir = utf8_to_wchar (dir); - if (!wdir) - return -1; - - if (RegOpenKeyEx (root_key, wdir, 0, 0, ®_key)) - { - jnlib_free (wdir); - return -1; - } - jnlib_free (wdir); - - if (name) - { - wname = utf8_to_wchar (name); - if (!wname) - return -1; - } - else - wname = NULL; - - wvalue = utf8_to_wchar (value); - if (wvalue) - { - jnlib_free (wname); - return -1; - } - - if (RegSetValueEx (reg_key, wname, 0, REG_SZ, - (BYTE *)wvalue, wcslen (wvalue)) != ERROR_SUCCESS ) - { - - if (RegCreateKeyEx (root_key, wname, 0, NULL, 0, 0, NULL, - ®_key, &disp) != ERROR_SUCCESS) - { - RegCloseKey(reg_key); - jnlib_free (wname); - jnlib_free (wvalue); - return -1; - } - if (RegSetValueEx (reg_key, wname, 0, REG_SZ, - (BYTE *)wvalue, wcslen (wvalue)) != ERROR_SUCCESS ) - { - RegCloseKey(reg_key); - jnlib_free (wname); - jnlib_free (wvalue); - return -1; - } - } - - jnlib_free (wname); - jnlib_free (wvalue); - RegCloseKey (reg_key); - return 0; -#else /*!HAVE_W32CE_SYSTEM*/ - - if ( !(root_key = get_root_key(root) ) ) - return -1; - - if ( RegOpenKeyEx( root_key, dir, 0, KEY_WRITE, ®_key ) - != ERROR_SUCCESS ) - return -1; - - if ( RegSetValueEx (reg_key, name, 0, REG_SZ, (BYTE *)value, - strlen( value ) ) != ERROR_SUCCESS ) - { - if ( RegCreateKey( root_key, name, ®_key ) != ERROR_SUCCESS ) - { - RegCloseKey(reg_key); - return -1; - } - if ( RegSetValueEx (reg_key, name, 0, REG_SZ, (BYTE *)value, - strlen( value ) ) != ERROR_SUCCESS ) - { - RegCloseKey(reg_key); - return -1; - } - } - - RegCloseKey (reg_key); - return 0; -#endif /*!HAVE_W32CE_SYSTEM*/ -} - -#endif /*HAVE_W32_SYSTEM*/ diff --git a/jnlib/w32help.h b/jnlib/w32help.h deleted file mode 100644 index 518d4251c..000000000 --- a/jnlib/w32help.h +++ /dev/null @@ -1,32 +0,0 @@ -/* w32help.h - W32 speicif functions - * Copyright (C) 2007 Free Software Foundation, Inc. - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#ifndef LIBJNLIB_W32HELP_H -#define LIBJNLIB_W32HELP_H -#ifdef HAVE_W32_SYSTEM - -/*-- w32-reg.c --*/ -char *read_w32_registry_string (const char *root, - const char *dir, const char *name ); -int write_w32_registry_string (const char *root, const char *dir, - const char *name, const char *value); - - -#endif /*HAVE_W32_SYSTEM*/ -#endif /*LIBJNLIB_MISCHELP_H*/ diff --git a/jnlib/xmalloc.c b/jnlib/xmalloc.c deleted file mode 100644 index eb6d5ab11..000000000 --- a/jnlib/xmalloc.c +++ /dev/null @@ -1,87 +0,0 @@ -/* xmalloc.c - standard malloc wrappers - * Copyright (C) 1999, 2000, 2001, 2006 Free Software Foundation, Inc. - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#include -#include -#include -#include - -#include "libjnlib-config.h" -#include "xmalloc.h" - -static void -out_of_core(void) -{ - fputs("\nfatal: out of memory\n", stderr ); - exit(2); -} - - -void * -xmalloc( size_t n ) -{ - void *p = malloc( n ); - if( !p ) - out_of_core(); - return p; -} - -void * -xrealloc( void *a, size_t n ) -{ - void *p = realloc( a, n ); - if( !p ) - out_of_core(); - return p; -} - -void * -xcalloc( size_t n, size_t m ) -{ - void *p = calloc( n, m ); - if( !p ) - out_of_core(); - return p; -} - -char * -xstrdup( const char *string ) -{ - void *p = xmalloc( strlen(string)+1 ); - strcpy( p, string ); - return p; -} - - -char * -xstrcat2( const char *a, const char *b ) -{ - size_t n1; - char *p; - - if( !b ) - return xstrdup( a ); - - n1 = strlen(a); - p = xmalloc( n1 + strlen(b) + 1 ); - memcpy(p, a, n1 ); - strcpy(p+n1, b ); - return p; -} - diff --git a/jnlib/xmalloc.h b/jnlib/xmalloc.h deleted file mode 100644 index 8c9c5292b..000000000 --- a/jnlib/xmalloc.h +++ /dev/null @@ -1,30 +0,0 @@ -/* xmalloc.h - * Copyright (C) 1999, 2000, 2001, 2006 Free Software Foundation, Inc. - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#ifndef LIBJNLIB_XMALLOC_H -#define LIBJNLIB_XMALLOC_H - -void *xmalloc( size_t n ); -void *xrealloc( void *a, size_t n ); -void *xcalloc( size_t n, size_t m ); -char *xstrdup( const char *string ); -char *xstrcat2( const char *a, const char *b ); - - -#endif /*LIBJNLIB_XMALLOC_H*/ diff --git a/kbx/ChangeLog b/kbx/ChangeLog index ea4fef8e7..d88500a0e 100644 --- a/kbx/ChangeLog +++ b/kbx/ChangeLog @@ -1,3 +1,10 @@ +2010-03-10 Werner Koch + + * Makefile.am (kbxutil_LDADD, $(PROGRAMS)): Remove libjnlib.a. + + * keybox-search.c, keybox-init.c, keybox-defs.h, kbxutil.c: + Replace "jnlib" include file part by "common". + 2010-03-08 Werner Koch Use macros for iobuf_ioctl commands. diff --git a/kbx/Makefile.am b/kbx/Makefile.am index 14e8fa5e2..81a7d3f24 100644 --- a/kbx/Makefile.am +++ b/kbx/Makefile.am @@ -46,8 +46,8 @@ libkeybox_a_SOURCES = $(common_sources) # requires it - although we don't actually need it. It is easier # to do it this way. kbxutil_SOURCES = kbxutil.c $(common_sources) -kbxutil_LDADD = ../common/libcommon.a ../jnlib/libjnlib.a ../gl/libgnu.a \ +kbxutil_LDADD = ../common/libcommon.a ../gl/libgnu.a \ $(KSBA_LIBS) $(LIBGCRYPT_LIBS) \ $(GPG_ERROR_LIBS) $(LIBINTL) $(LIBICONV) $(W32SOCKLIBS) -$(PROGRAMS) : ../common/libcommon.a ../jnlib/libjnlib.a ../gl/libgnu.a +$(PROGRAMS) : ../common/libcommon.a ../gl/libgnu.a diff --git a/kbx/kbxutil.c b/kbx/kbxutil.c index 459281110..592f7d467 100644 --- a/kbx/kbxutil.c +++ b/kbx/kbxutil.c @@ -29,10 +29,10 @@ #include #define JNLIB_NEED_LOG_LOGV -#include "../jnlib/logging.h" -#include "../jnlib/argparse.h" -#include "../jnlib/stringhelp.h" -#include "../jnlib/utf8conv.h" +#include "../common/logging.h" +#include "../common/argparse.h" +#include "../common/stringhelp.h" +#include "../common/utf8conv.h" #include "i18n.h" #include "init.h" #include "keybox-defs.h" @@ -433,7 +433,7 @@ main( int argc, char **argv ) /*create_dotlock(NULL); register locking cleanup */ - /* We need to use the gcry malloc function because jnlib does use them */ + /* We need to use the gcry malloc function because jnlib uses them. */ keybox_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free ); diff --git a/kbx/keybox-defs.h b/kbx/keybox-defs.h index 626f3e5c3..98d23b326 100644 --- a/kbx/keybox-defs.h +++ b/kbx/keybox-defs.h @@ -34,9 +34,9 @@ owns here. This will not allow us build KBX in a standalone way but there is currently no need for it anyway. Same goes for stringhelp.h which for example provides a replacement for stpcpy - - fixme: Better the LIBOBJ mechnism. */ -#include "../jnlib/types.h" -#include "../jnlib/stringhelp.h" + fixme: Better use the LIBOBJ mechnism. */ +#include "../common/types.h" +#include "../common/stringhelp.h" #include "keybox.h" diff --git a/kbx/keybox-dump.c b/kbx/keybox-dump.c index b671089a0..4be8501a1 100644 --- a/kbx/keybox-dump.c +++ b/kbx/keybox-dump.c @@ -472,7 +472,7 @@ open_file (const char **filename, FILE *outfp) { int save_errno = errno; fprintf (outfp, "can't open `%s': %s\n", *filename, strerror(errno)); - errno = save_errno; + gpg_err_set_errno (save_errno); } return fp; } diff --git a/kbx/keybox-init.c b/kbx/keybox-init.c index e4138647e..c364277e3 100644 --- a/kbx/keybox-init.c +++ b/kbx/keybox-init.c @@ -24,7 +24,7 @@ #include #include -#include "../jnlib/mischelp.h" +#include "../common/mischelp.h" #include "keybox-defs.h" static KB_NAME kb_names; diff --git a/kbx/keybox-search.c b/kbx/keybox-search.c index be4ca4579..96c873dbe 100644 --- a/kbx/keybox-search.c +++ b/kbx/keybox-search.c @@ -24,7 +24,7 @@ #include #include -#include "../jnlib/stringhelp.h" /* ascii_xxxx() */ +#include "../common/stringhelp.h" /* ascii_xxxx() */ #include "keybox-defs.h" #include diff --git a/keyserver/Makefile.am b/keyserver/Makefile.am index 96cd8d1c2..fd046cfc0 100644 --- a/keyserver/Makefile.am +++ b/keyserver/Makefile.am @@ -37,12 +37,12 @@ libexec_PROGRAMS = $(GPGKEYS_LDAP) $(GPGKEYS_HKP) $(GPGKEYS_FINGER) \ libexec_SCRIPTS = $(GPGKEYS_MAILTO) noinst_SCRIPTS = gpg2keys_test -common_libs = ../gl/libgnu.a ../common/libcommon.a ../jnlib/libjnlib.a +common_libs = ../gl/libgnu.a ../common/libcommon.a other_libs = $(LIBICONV) $(LIBINTL) $(CAPLIBS) gpg2keys_ldap_SOURCES = gpgkeys_ldap.c ksutil.c ksutil.h no-libgcrypt.c gpg2keys_ldap_CPPFLAGS = $(LDAP_CPPFLAGS) $(AM_CPPFLAGS) -gpg2keys_ldap_LDADD = ../jnlib/libjnlib.a $(LDAPLIBS) $(GPG_ERROR_LIBS) \ +gpg2keys_ldap_LDADD = $(common_libs) $(LDAPLIBS) $(GPG_ERROR_LIBS) \ $(NETLIBS) $(other_libs) gpg2keys_finger_SOURCES = gpgkeys_finger.c ksutil.c ksutil.h no-libgcrypt.c diff --git a/po/POTFILES.in b/po/POTFILES.in index f31d10993..cac69a4a6 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -21,6 +21,12 @@ common/audit.c common/helpfile.c common/gettime.c +common/argparse.c +common/logging.c +common/utf8conv.c +common/dotlock.c + + g10/armor.c g10/build-packet.c g10/call-agent.c @@ -65,11 +71,6 @@ g10/textfilter.c g10/trustdb.c g10/verify.c -jnlib/argparse.c -jnlib/logging.c -jnlib/utf8conv.c -jnlib/dotlock.c - kbx/kbxutil.c scd/app-nks.c diff --git a/scd/ChangeLog b/scd/ChangeLog index 91694a056..44497364d 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,7 @@ +2010-03-10 Werner Koch + + * Makefile.am (scdaemon_LDADD): Remove libjnlib.a. + 2009-12-15 Werner Koch * iso7816.c (do_generate_keypair): s/readonly/read_only/ because diff --git a/scd/Makefile.am b/scd/Makefile.am index ae623ace8..923ebfee0 100644 --- a/scd/Makefile.am +++ b/scd/Makefile.am @@ -41,7 +41,7 @@ scdaemon_SOURCES = \ app.c app-common.h app-help.c $(card_apps) -scdaemon_LDADD = $(libcommonpth) ../jnlib/libjnlib.a ../gl/libgnu.a \ +scdaemon_LDADD = $(libcommonpth) ../gl/libgnu.a \ $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) $(PTH_LIBS) \ $(LIBUSB_LIBS) $(GPG_ERROR_LIBS) \ $(LIBINTL) $(DL_LIBS) $(NETLIBS) $(LIBICONV) diff --git a/sm/ChangeLog b/sm/ChangeLog index ba5047a82..104f6caaf 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,9 @@ +2010-03-10 Werner Koch + + * Makefile.am (common_libs): Remove libjnlib.a. Change order. + + * gpgsm.h: Remove "estream.h". + 2010-03-08 Werner Koch * certreqgen.c (gpgsm_genkey): Change OUT_FP to an estream_t diff --git a/sm/Makefile.am b/sm/Makefile.am index 2bbdd1b59..ba194811d 100644 --- a/sm/Makefile.am +++ b/sm/Makefile.am @@ -52,8 +52,7 @@ gpgsm_SOURCES = \ qualified.c -common_libs = $(libcommon) ../kbx/libkeybox.a ../jnlib/libjnlib.a \ - ../gl/libgnu.a +common_libs = ../kbx/libkeybox.a $(libcommon) ../gl/libgnu.a gpgsm_LDADD = $(common_libs) ../common/libgpgrl.a \ $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) \ diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 7e0353060..542c292ac 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -31,7 +31,6 @@ #include #include "../common/util.h" #include "../common/status.h" -#include "../common/estream.h" #include "../common/audit.h" #include "../common/session-env.h" diff --git a/tools/ChangeLog b/tools/ChangeLog index 24196fa32..048c1685a 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,7 @@ +2010-03-10 Werner Koch + + * Makefile.am (common_libs): Remove libjnlib.a. + 2010-03-08 Werner Koch * no-libgcrypt.c (gcry_create_nonce): New. diff --git a/tools/Makefile.am b/tools/Makefile.am index 1d04964c0..ea066e67b 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -53,7 +53,7 @@ endif noinst_PROGRAMS = clean-sat mk-tdata make-dns-cert gpgsplit -common_libs = $(libcommon) ../jnlib/libjnlib.a ../gl/libgnu.a +common_libs = $(libcommon) ../gl/libgnu.a pwquery_libs = ../common/libsimple-pwquery.a gpgsplit_LDADD = $(common_libs) \ @@ -62,7 +62,7 @@ gpgsplit_LDADD = $(common_libs) \ gpgconf_SOURCES = gpgconf.c gpgconf.h gpgconf-comp.c no-libgcrypt.c -# jnlib/common sucks in gpg-error, will they, nil they (some compilers +# common sucks in gpg-error, will they, nil they (some compilers # do not eliminate the supposed-to-be-unused-inline-functions). gpgconf_LDADD = $(common_libs) \ $(LIBINTL) $(GPG_ERROR_LIBS) $(LIBICONV) $(W32SOCKLIBS) @@ -86,7 +86,7 @@ gpg_connect_agent_LDADD = ../common/libgpgrl.a $(common_libs) \ gpgkey2ssh_SOURCES = gpgkey2ssh.c gpgkey2ssh_CFLAGS = $(LIBGCRYPT_CFLAGS) $(GPG_ERROR_CFLAGS) -# common sucks in jnlib, via use of BUG() in an inline function, which +# common via use of BUG() in an inline function, which # some compilers do not eliminate. gpgkey2ssh_LDADD = $(common_libs) \ $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) $(LIBINTL) $(LIBICONV) -- cgit v1.2.3